includes/clientside/static/editor.js
changeset 335 67bd3121a12e
parent 117 7cfdbb2fd17a
child 336 bfa2e9c23f03
--- 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 = '<ul><li>' + implode('</li><li>', response.errors) + '</li></ul>';
+          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 = '<div class="usermessage">' + $lang.get('editor_msg_saved') + '</div>' + 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);
+  }
+}
+