diff -r c72b545f1304 -r 67bd3121a12e includes/clientside/static/editor.js --- a/includes/clientside/static/editor.js Wed Dec 26 00:37:26 2007 -0500 +++ b/includes/clientside/static/editor.js Thu Dec 27 22:09:33 2007 -0500 @@ -1,16 +1,32 @@ // Javascript routines for the page editor +if ( document.getElementById('mdgCss') ) +{ + var css_url = document.getElementById('mdgCss').href; +} +else +{ + var css_url = scriptPath + '/includes/clientside/css/enano_shared.css'; +} + +var do_popups = ( is_Safari ) ? '' : ',inlinepopups'; +var _skin = ( typeof(tinymce_skin) == 'string' ) ? tinymce_skin : 'default'; + var enano_tinymce_options = { - mode : "exact", - elements : '', - plugins : 'table', + mode : "none", + plugins : 'table,save,safari,pagebreak,style,layer,advhr,insertdatetime,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras' + do_popups, + theme : 'advanced', + skin : _skin, theme_advanced_resize_horizontal : false, theme_advanced_resizing : true, theme_advanced_toolbar_location : "top", theme_advanced_toolbar_align : "left", - theme_advanced_buttons1_add : "fontselect,fontsizeselect", + theme_advanced_buttons1 : "save,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,forecolor,backcolor,|,formatselect,|,fontselect,fontsizeselect", theme_advanced_buttons3_add_before : "tablecontrols,separator", - theme_advanced_statusbar_location : 'bottom' + theme_advanced_buttons3_add_after : "|,fullscreen", + theme_advanced_statusbar_location : 'bottom', + noneditable_noneditable_class : 'mce_readonly', + content_css : css_url }; var initTinyMCE = function(e) @@ -25,3 +41,585 @@ } addOnloadHook(initTinyMCE); +var editor_open = false; + +function ajaxEditor() +{ + if ( KILL_SWITCH ) + return true; + if ( editor_open ) + return true; + selectButtonMinor('edit'); + selectButtonMajor('article'); + setAjaxLoading(); + ajaxGet(stdAjaxPrefix + '&_mode=getsource', function() + { + if ( ajax.readyState == 4 ) + { + unsetAjaxLoading(); + + var response = String(ajax.responseText + ''); + if ( response.substr(0, 1) != '{' ) + { + handle_invalid_json(response); + return false; + } + + response = parseJSON(response); + if ( response.mode == 'error' ) + { + unselectAllButtonsMinor(); + new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_server'), response.error); + return false; + } + + if ( !response.auth_view_source ) + { + unselectAllButtonsMinor(); + new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_access_denied_title'), $lang.get('editor_err_access_denied_body')); + return false; + } + + ajaxBuildEditor(response.src, (!response.auth_edit), response.time); + } + }); +} + +function ajaxBuildEditor(content, readonly, timestamp) +{ + // Set flags + // We don't want the fancy confirmation framework to trigger if the user is only viewing the page source + if ( !readonly ) + { + editor_open = true; + disableUnload(); + } + + // Destroy existing contents of page container + var edcon = document.getElementById('ajaxEditContainer'); + for ( var i = edcon.childNodes.length - 1; i >= 0; i-- ) + { + edcon.removeChild(edcon.childNodes[i]); + } + + // + // BUILD EDITOR + // + + // Plaintext/wikitext toggler + + var toggler = document.createElement('p'); + toggler.style.marginLeft = '0'; + + var span_wiki = document.createElement('span'); + var span_mce = document.createElement('span'); + span_wiki.id = 'enano_edit_btn_pt'; + span_mce.id = 'enano_edit_btn_mce'; + if ( readCookie('enano_editor_mode') == 'tinymce' ) + { + // Current selection is TinyMCE - make span_wiki have the link and span_mce be plaintext + var a = document.createElement('a'); + a.href = '#'; + a.onclick = function() { + ajaxSetEditorPlain(); + return false; + }; + a.appendChild(document.createTextNode($lang.get('editor_btn_wikitext'))); + span_wiki.appendChild(a); + toggler.appendChild(span_wiki); + toggler.appendChild(document.createTextNode(' | ')); + span_mce.appendChild(document.createTextNode($lang.get('editor_btn_graphical'))); + toggler.appendChild(span_mce); + } + else + { + // Current selection is wikitext - set span_wiki to plaintext and span_mce to link + span_wiki.appendChild(document.createTextNode($lang.get('editor_btn_wikitext'))); + toggler.appendChild(span_wiki); + toggler.appendChild(document.createTextNode(' | ')); + var a = document.createElement('a'); + a.href = '#'; + a.onclick = function() { + ajaxSetEditorMCE(); + return false; + }; + a.appendChild(document.createTextNode($lang.get('editor_btn_graphical'))); + span_mce.appendChild(a); + toggler.appendChild(span_mce); + } + + // Form (to allow submits from MCE to trigger a real save) + var form = document.createElement('form'); + form.action = 'javascript:void(0);'; + form.onsubmit = function() + { + ajaxEditorSave(); + return false; + } + + // Preview holder + var preview_anchor = document.createElement('a'); + preview_anchor.name = 'ajax_preview'; + preview_anchor.id = 'ajax_preview'; + var preview_container = document.createElement('div'); + preview_container.id = 'enano_editor_preview'; + + // Textarea containing the content + var ta_wrapper = document.createElement('div'); + ta_wrapper.style.margin = '10px 0'; + var textarea = document.createElement('textarea'); + textarea.value = content; + textarea._edTimestamp = timestamp; + textarea.id = 'ajaxEditArea'; + textarea.rows = '20'; + textarea.cols = '60'; + textarea.style.width = '98.7%'; + if ( readonly ) + { + textarea.className = 'mce_readonly'; + textarea.setAttribute('readonly', 'readonly'); + } + ta_wrapper.appendChild(textarea); + + // Revision metadata controls + var tblholder = document.createElement('div'); + tblholder.className = 'tblholder'; + var metatable = document.createElement('table'); + metatable.setAttribute('border', '0'); + metatable.setAttribute('cellspacing', '1'); + metatable.setAttribute('cellpadding', '4'); + + if ( readonly ) + { + // Close Viewer button + var tr3 = document.createElement('tr'); + var td3 = document.createElement('th'); + td3.setAttribute('colspan', '2'); + td3.className = 'subhead'; + + var btn_cancel = document.createElement('input'); + btn_cancel.type = 'button'; + btn_cancel.value = $lang.get('editor_btn_closeviewer'); + btn_cancel.onclick = function() { ajaxReset(true); return false; }; + td3.appendChild(btn_cancel); + tr3.appendChild(td3); + + metatable.appendChild(tr3); + } + else + { + // First row: edit summary + var tr1 = document.createElement('tr'); + var td1_1 = document.createElement('td'); + var td1_2 = document.createElement('td'); + td1_1.className = 'row2'; + td1_2.className = 'row1'; + td1_2.style.width = '70%'; + td1_1.appendChild(document.createTextNode($lang.get('editor_lbl_edit_summary'))); + td1_1.appendChild(document.createElement('br')); + var small = document.createElement('small'); + small.appendChild(document.createTextNode($lang.get('editor_lbl_edit_summary_explain'))); + td1_1.appendChild(small); + + var field_es = document.createElement('input'); + field_es.id = 'enano_editor_field_summary'; + field_es.type = 'text'; + field_es.size = '40'; + field_es.style.width = '96%'; + td1_2.appendChild(field_es); + + tr1.appendChild(td1_1); + tr1.appendChild(td1_2); + + // Second row: minor edit + var tr2 = document.createElement('tr'); + var td2_1 = document.createElement('td'); + var td2_2 = document.createElement('td'); + td2_1.className = 'row2'; + td2_2.className = 'row1'; + td2_1.appendChild(document.createTextNode($lang.get('editor_lbl_minor_edit'))); + td2_1.appendChild(document.createElement('br')); + var small = document.createElement('small'); + small.appendChild(document.createTextNode($lang.get('editor_lbl_minor_edit_explain'))); + td2_1.appendChild(small); + + var label = document.createElement('label'); + var field_mi = document.createElement('input'); + field_mi.id = 'enano_editor_field_minor'; + field_mi.type = 'checkbox'; + label.appendChild(field_mi); + label.appendChild(document.createTextNode(' ')); + label.appendChild(document.createTextNode($lang.get('editor_lbl_minor_edit_field'))); + td2_2.appendChild(label); + + tr2.appendChild(td2_1); + tr2.appendChild(td2_2); + + // Third row: controls + var tr3 = document.createElement('tr'); + var td3 = document.createElement('th'); + td3.setAttribute('colspan', '2'); + td3.className = 'subhead'; + + var btn_save = document.createElement('input'); + btn_save.type = 'button'; + btn_save.value = $lang.get('editor_btn_save'); + btn_save.onclick = function() { ajaxEditorSave(); return false; }; + td3.appendChild(btn_save); + + td3.appendChild(document.createTextNode(' ')); + + var btn_preview = document.createElement('input'); + btn_preview.type = 'button'; + btn_preview.value = $lang.get('editor_btn_preview'); + btn_preview.onclick = function() { ajaxEditorGenPreview(); return false; }; + td3.appendChild(btn_preview); + + td3.appendChild(document.createTextNode(' ')); + + var btn_revert = document.createElement('input'); + btn_revert.type = 'button'; + btn_revert.value = $lang.get('editor_btn_revert'); + btn_revert.onclick = function() { ajaxEditorRevertToLatest(); return false; }; + td3.appendChild(btn_revert); + + td3.appendChild(document.createTextNode(' ')); + + var btn_diff = document.createElement('input'); + btn_diff.type = 'button'; + btn_diff.value = $lang.get('editor_btn_diff'); + btn_diff.onclick = function() { ajaxEditorShowDiffs(); return false; }; + td3.appendChild(btn_diff); + + td3.appendChild(document.createTextNode(' ')); + + var btn_cancel = document.createElement('input'); + btn_cancel.type = 'button'; + btn_cancel.value = $lang.get('editor_btn_cancel'); + btn_cancel.onclick = function() { ajaxEditorCancel(); return false; }; + td3.appendChild(btn_cancel); + tr3.appendChild(td3); + + metatable.appendChild(tr1); + metatable.appendChild(tr2); + metatable.appendChild(tr3); + } + tblholder.appendChild(metatable); + + // Edit disclaimer/notice + if ( editNotice ) // This is set globally in {JS_DYNAMIC_VARS}. + { + var en_div = document.createElement('div'); + en_div.innerHTML = editNotice; + en_div.className = 'usermessage'; + en_div.style.margin = '10px 0 0 0'; + } + + // Put it all together... + form.appendChild(toggler); + form.appendChild(preview_anchor); + form.appendChild(preview_container); + form.appendChild(ta_wrapper); + form.appendChild(tblholder); + edcon.appendChild(form); + + if ( editNotice && !readonly ) + { + edcon.appendChild(en_div); + } + + // If the editor preference is tinymce, switch the editor to TinyMCE now + if ( readCookie('enano_editor_mode') == 'tinymce' ) + { + $dynano('ajaxEditArea').switchToMCE(); + } +} + +function ajaxEditorSave() +{ + ajaxSetEditorLoading(); + var ta_content = $('ajaxEditArea').getContent(); + var edit_summ = $('enano_editor_field_summary').object.value; + if ( !edit_summ ) + edit_summ = ''; + var is_minor = ( $('enano_editor_field_minor').object.checked ) ? 1 : 0; + var timestamp = $('ajaxEditArea').object._edTimestamp; + + var json_packet = { + src: ta_content, + summary: edit_summ, + minor_edit: is_minor, + time: timestamp + }; + json_packet = ajaxEscape(toJSONString(json_packet)); + ajaxPost(stdAjaxPrefix + '&_mode=savepage_json', 'r=' + json_packet, function() + { + if ( ajax.readyState == 4 ) + { + ajaxUnSetEditorLoading(); + var response = String(ajax.responseText + ''); + if ( response.substr(0, 1) != '{' ) + { + handle_invalid_json(response); + return false; + } + + response = parseJSON(response); + // This will only be used if there was a lower-level error. + if ( response.mode == 'error' ) + { + new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_server'), response.error); + return false; + } + // This will be used if the PageProcessor generated errors (usually security/permissions related) + if ( response.mode == 'errors' ) + { + var errors = ''; + new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_save_title'), $lang.get('editor_err_save_body') + errors); + return false; + } + // If someone else got to the page first, warn the user + if ( response.mode == 'obsolete' ) + { + // Update the local timestamp to allow override + $('ajaxEditArea').object._edTimestamp = response.time; + new messagebox(MB_OK | MB_ICONEXCLAMATION, $lang.get('editor_err_obsolete_title'), $lang.get('editor_err_obsolete_body', { author: response.author, timestamp: response.date_string, page_url: makeUrl(title, false, true) })); + return false; + } + if ( response.mode == 'success' ) + { + // The save was successful; reset flags and make another request for the new page content + setAjaxLoading(); + editor_open = false; + enableUnload(); + ajaxGet(stdAjaxPrefix + '&_mode=getpage&noheaders', function() + { + if ( ajax.readyState == 4 ) + { + unsetAjaxLoading(); + document.getElementById('ajaxEditContainer').innerHTML = '
' + $lang.get('editor_msg_saved') + '
' + ajax.responseText; + selectButtonMajor('article'); + unselectAllButtonsMinor(); + } + }); + } + } + }, true); + +} + +function ajaxEditorGenPreview() +{ + ajaxSetEditorLoading(); + var ta_content = $('ajaxEditArea').getContent(); + ta_content = ajaxEscape(ta_content); + if ( $('enano_editor_preview').object.innerHTML != '' ) + { + opacity('enano_editor_preview', 100, 0, 500); + } + ajaxPost(stdAjaxPrefix + '&_mode=preview', 'text=' + ta_content, function() + { + if ( ajax.readyState == 4 ) + { + ajaxUnSetEditorLoading(); + changeOpac(0, 'enano_editor_preview'); + $('enano_editor_preview').object.innerHTML = ajax.responseText; + window.location.hash = '#ajax_preview'; + opacity('enano_editor_preview', 0, 100, 500); + } + }, true); +} + +function ajaxEditorRevertToLatest() +{ + var mb = new messagebox(MB_YESNO | MB_ICONQUESTION, $lang.get('editor_msg_revert_confirm_title'), $lang.get('editor_msg_revert_confirm_body')); + mb.onclick['Yes'] = function() + { + setTimeout('ajaxEditorRevertToLatestReal();', 750); + } +} + +function ajaxEditorRevertToLatestReal() +{ + ajaxSetEditorLoading(); + ajaxGet(stdAjaxPrefix + '&_mode=getsource', function() + { + if ( ajax.readyState == 4 ) + { + ajaxUnSetEditorLoading(); + + var response = String(ajax.responseText + ''); + if ( response.substr(0, 1) != '{' ) + { + handle_invalid_json(response); + return false; + } + + response = parseJSON(response); + if ( response.mode == 'error' ) + { + unselectAllButtonsMinor(); + new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_server'), response.error); + return false; + } + + if ( !response.auth_view_source ) + { + unselectAllButtonsMinor(); + new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_access_denied_title'), $lang.get('editor_err_access_denied_body')); + return false; + } + + var ed = tinyMCE.get('ajaxEditArea'); + if ( ed ) + { + ed.setContent(response.src); + } + else + { + $('ajaxEditArea').object.value = response.src; + } + } + }, true); +} + +function ajaxEditorShowDiffs() +{ + ajaxSetEditorLoading(); + var ta_content = $('ajaxEditArea').getContent(); + ta_content = ajaxEscape(ta_content); + if ( $('enano_editor_preview').object.innerHTML != '' ) + { + opacity('enano_editor_preview', 100, 0, 500); + } + ajaxPost(stdAjaxPrefix + '&_mode=diff_cur', 'text=' + ta_content, function() + { + if ( ajax.readyState == 4 ) + { + ajaxUnSetEditorLoading(); + changeOpac(0, 'enano_editor_preview'); + $('enano_editor_preview').object.innerHTML = ajax.responseText; + window.location.hash = '#ajax_preview'; + opacity('enano_editor_preview', 0, 100, 500); + } + }, true); +} + +function ajaxEditorCancel() +{ + var mb = new messagebox(MB_YESNO | MB_ICONQUESTION, $lang.get('editor_msg_cancel_confirm_title'), $lang.get('editor_msg_cancel_confirm_body')); + mb.onclick['Yes'] = function() + { + setAjaxLoading(); + editor_open = false; + enableUnload(); + setTimeout('ajaxReset();', 750); + } +} + +function ajaxSetEditorMCE() +{ + if ( editor_loading ) + return false; + + // Clear out existing buttons + var span_wiki = $dynano('enano_edit_btn_pt').object; + var span_mce = $dynano('enano_edit_btn_mce').object; + span_wiki.removeChild(span_wiki.firstChild); + span_mce.removeChild(span_mce.firstChild); + + // Rebuild control + var a = document.createElement('a'); + a.href = '#'; + a.onclick = function() { + ajaxSetEditorPlain(); + return false; + }; + a.appendChild(document.createTextNode($lang.get('editor_btn_wikitext'))); + span_wiki.appendChild(a); + span_mce.appendChild(document.createTextNode($lang.get('editor_btn_graphical'))); + + // Swap editor + $dynano('ajaxEditArea').switchToMCE(); + + // Remember the setting + createCookie('enano_editor_mode', 'tinymce', 365); +} + +function ajaxSetEditorPlain() +{ + if ( editor_loading ) + return false; + + // Clear out existing buttons + var span_wiki = $dynano('enano_edit_btn_pt').object; + var span_mce = $dynano('enano_edit_btn_mce').object; + span_wiki.removeChild(span_wiki.firstChild); + span_mce.removeChild(span_mce.firstChild); + + // Rebuild control + span_wiki.appendChild(document.createTextNode($lang.get('editor_btn_wikitext'))); + var a = document.createElement('a'); + a.href = '#'; + a.onclick = function() { + ajaxSetEditorMCE(); + return false; + }; + a.appendChild(document.createTextNode($lang.get('editor_btn_graphical'))); + span_mce.appendChild(a); + + // Swap editor + $dynano('ajaxEditArea').destroyMCE(); + + // Remember the setting + createCookie('enano_editor_mode', 'text', 365); +} + +var editor_loading = false; + +function ajaxSetEditorLoading() +{ + var ed = tinyMCE.get('ajaxEditArea'); + editor_loading = true; + if ( ed ) + { + ed.setProgressState(1); + } + else + { + ed = document.getElementById('ajaxEditArea'); + var blackout = document.createElement('div'); + blackout.style.position = 'absolute'; + blackout.style.top = $('ajaxEditArea').Top() + 'px'; + blackout.style.left = $('ajaxEditArea').Left() + 'px'; + blackout.style.width = $('ajaxEditArea').Width() + 'px'; + blackout.style.height = $('ajaxEditArea').Height() + 'px'; + blackout.style.backgroundColor = '#FFFFFF'; + domObjChangeOpac(60, blackout); + blackout.style.backgroundImage = 'url(' + scriptPath + '/includes/clientside/tinymce/themes/advanced/skins/default/img/progress.gif)'; + blackout.style.backgroundPosition = 'center center'; + blackout.style.backgroundRepeat = 'no-repeat'; + blackout.id = 'enano_editor_blackout'; + blackout.style.zIndex = getHighestZ() + 2; + + var body = document.getElementsByTagName('body')[0]; + body.appendChild(blackout); + } +} + +function ajaxUnSetEditorLoading() +{ + editor_loading = false; + var ed = tinyMCE.get('ajaxEditArea'); + if ( ed ) + { + ed.setProgressState(0); + } + else + { + var blackout = document.getElementById('enano_editor_blackout'); + var body = document.getElementsByTagName('body')[0]; + body.removeChild(blackout); + } +} +