User:Supadawg/secedit.js

From OpenWetWare
Jump to: navigation, search
/////////////////////////////////////////
// By Alek Storm
// Please see talk page for instructions
/////////////////////////////////////////

var body; // shortcut for body node
var xmlhttp; // XMLHTTPRequest object
var startNode; // div that includes section header and edit link
var editSec; // edit link
var editForm; // spliced edit form
var preview; // spliced preview or diff content
var oldContent; // original content of section
var xmlhttpDone = false; // kludge to prevent multiple calls to callback

importScript("User:Supadawg/util.js");

function inc(path) {
  var lt = String.fromCharCode(60);
  var gt = String.fromCharCode(62);
  document.writeln(lt+'script type="text/javascript" src="/w/index.php?title='+path+'&action=raw&ctype=text/javascript&dontcountme=s"'+gt+lt+'/script'+gt);
}

function initSecEdit()
{
  body = document.getElementsByTagName("body")[0];

  // apply to all divs of class "editsection"
  var editSecs = document.getElementsByTagName("span");
  var secCount = 1;
  var pagetitleRe=/\/(wiki\/|w\/index\.php\?title=)([^&?]*)/; // from [Wikipedia:WikiProject User scripts/Techniques]
  for ( var i = 0; i < editSecs.length; i++ ) {
    if ( editSecs[i].getAttribute("class") == "editsection" ) {
      for ( var k = 0; k < editSecs[i].childNodes.length; k++ ) {
        if ( editSecs[i].childNodes[k].nodeName == "A" ) {
          // grab editing uri, escape it, then put it back in
          var editURI = "http://en.wikipedia.org/w/index.php?title="+encodeURIComponent2(pagetitleRe.exec(decodeURI(editSecs[i].childNodes[k].getAttribute("href")))[2]).replace(/\"/gi, "%22").replace(/\'/gi, "%27")+"&action=edit&section="+secCount;
          // give it a unique id
          editSecs[i].childNodes[k].setAttribute( "id", "editSection"+secCount );
          // swap the href with a function call, passing the original href as the second parameter
          editSecs[i].childNodes[k].setAttribute( "href", "javascript:editSection( document.getElementById('editSection" + secCount + "'), '"+editURI+"' );" );
          secCount++;
        }
      }
    }
  }
}

// called on click of section edit link
function editSection( elem, editURI )
{
  cancelEdit(); // get rid of any other sections being edited
  editSec = elem;
  startNode = elem.parentNode.parentNode;

  // initiate xmlhttprequest for section edit page
  xmlhttpDone = false;
  xmlhttp = null // kludge
  xmlhttp = createXMLHTTP( "GET", editURI, stateChange );
}

// put raw input returned from XMLHTTPRequest into a div so we can grab specific elements
function makeDiv( rawHTML )
{
  var div = createNode( body, "div", {style: "visibility: hidden; position: absolute;"} );
  div.innerHTML = rawHTML.replace(/<script[^>]*><\/script>/gi, ""); // if script tags are placed into the DOM, they force reload of files, and nasty things happen
  return div;
}

function isHTag( node )
{
  return node.nodeName.charAt(0) == 'H' && !isNaN( parseInt( node.nodeName.charAt(1) ) );
}

// callback for onclick of an edit link
function stateChange()
{
  if ( xmlhttp && xmlhttp.readyState == 4 ) {
    if ( xmlhttp.status == 200 ) {
      if ( xmlhttpDone )
        return;
      xmlhttpDone = true;

      // store old content of section - loop until we hit header of same spot in hierarchy
      if ( !oldContent ) {
        oldContent = makeDiv("");
        var curElem = startNode.nextSibling;
        while ( curElem ) {
          var hitSiblingSection = false;
          if ( isHTag( curElem ) ) {
            for ( var i = 0; i < curElem.childNodes.length; i++ ) {
              if ( curElem.childNodes[i].nodeName == "SPAN"
                   && curElem.childNodes[i].getAttribute("class") == "editsection"
                   && parseInt( curElem.nodeName.charAt(1) ) <= parseInt( startNode.nodeName.charAt(1) ) )
                  hitSiblingSection = true;
            }
          }
          else if ( curElem.nodeName == "DIV" && curElem.getAttribute("class") == "printfooter" )
            break;

          if ( hitSiblingSection )
            break;
          var nextElem = curElem.nextSibling;
          oldContent.appendChild( curElem );
          curElem = nextElem;
        }
      }
      else
        removeNode( oldContent );

      var div = makeDiv( xmlhttp.responseText );
      editForm = $("editform");
      // change onclick of preview and diff buttons to our function
      $("wpPreview").setAttribute( "type", "button" );
      $("wpPreview").setAttribute( "onclick", "javascript:getEditData( previewChanged, $('wpPreview') );" );
      $("wpDiff").setAttribute( "type", "button" );
      $("wpDiff").setAttribute( "onclick", "javascript:getEditData( diffChanged, $('wpDiff') );" );
      insertAfter( editForm, startNode );
      removeNode( div );

      editSec.setAttribute( "oldHref", editSec.getAttribute("href") );
      editSec.setAttribute( "href", "javascript:cancelEdit();" );
      editSec.innerHTML = "cancel";
    }
    else
      alert("Problem retrieving data - status: "+xmlhttp.status);
  }
}

// firefox hack, not sure if this is a problem in other browsers
function encodeURIComponent2( content )
{
  // from [http://en.wikipedia.org/wiki/User:Topaz/wputil.js]
  content = content.replace(/\&lt\;/gi, "<");
  content = content.replace(/\&gt\;/gi, ">");
  content = content.replace(/\&quot\;/gi, "\"");
  content = content.replace(/\&amp\;/gi, "&");
  return encodeURIComponent( content );
}

// encode differently based on type of form element
function field2Post( node, allowButton )
{
  var reqBody = "";
  switch ( node.nodeName ) {
    case "TEXTAREA":
      reqBody += "&"+node.getAttribute("name")+"="+encodeURIComponent2( node.value );
      break;
    case "INPUT":
      var inputType = node.getAttribute("type");
      if ( inputType == "checkbox" ) {
        if ( node.checked )
          reqBody += "&"+node.getAttribute("name")+"=on"
      }
      else if ( allowButton || (inputType != "submit" && inputType != "button") )
        reqBody += "&"+node.getAttribute("name")+"="+encodeURIComponent2( node.value );
      break;
    case "DIV":
      reqBody += form2Post( node, false );
      break;
  }
  return reqBody;
}

// manually encodes a form element for XMLHTTPRequest
function form2Post( node )
{
  var reqBody = "";
  for ( var i = 0; i < node.childNodes.length; i++ )
    reqBody += field2Post( node.childNodes[i], false );
  return reqBody;
}

// get preview or diff data
function getEditData( callback, clickedBut )
{
  xmlhttpDone = false;
  xmlhttp = null; // kludge
  var action = editForm.getAttribute("action");
  xmlhttp = createXMLHTTP( "POST", "http://en.wikipedia.org"+action, callback, {
    body: form2Post( editForm ) + field2Post( clickedBut, true ),
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      "Referer": "http://en.wikipedia.org" + action.substring( 0, action.indexOf('&') ) + "&action=edit&section="+(parseInt(editSec.getAttribute("id").substring(11))+1)
    }
  } );
}

// callback for preview data
function previewChanged()
{
  if ( xmlhttp && xmlhttp.readyState == 4 ) {
    if ( xmlhttp.status == 200 ) {
      if ( xmlhttpDone )
        return;
      xmlhttpDone = true;
      var div = makeDiv( xmlhttp.responseText );
      if ( preview )
        removeNode( preview );
      preview = $("wikiPreview");
      insertAfter( preview, startNode );
      removeNode( div );
    }
    else
      alert("Problem retrieving data - status: "+xmlhttp.status);
  }
}

// callback for diff data
function diffChanged()
{
  if ( xmlhttp && xmlhttp.readyState == 4 ) {
    if ( xmlhttp.status == 200 ) {
      if ( xmlhttpDone )
        return;
      xmlhttpDone = true;
      var div = makeDiv( xmlhttp.responseText );
      if ( preview )
        removeNode( preview );
      preview = $("wikiDiff");
      insertAfter( preview, startNode );
      removeNode( div );
    }
    else
      alert("Problem retrieving data - status: "+xmlhttp.status);
  }
}

// remove form and preview or diff data
function cancelEdit()
{
  if ( preview )
    removeNode( preview );
  preview = null;
  if ( editForm )
    removeNode( editForm );
  editForm = null;
  if ( oldContent ) {
    oldContent.setAttribute( "style", "position: static; visibility: visible;" );
    insertAfter( oldContent, startNode );
  }
  oldContent = null;
  if ( editSec ) {
    editSec.setAttribute( "href", editSec.getAttribute("oldHref") );
    editSec.innerHTML = "edit";
  }
}

addEventListener( "load", initSecEdit, false );