User:Supadawg/secedit.js

/////////////////////////////////////////

// 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§ion="+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>/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(/\<\;/gi, "<");

content = content.replace(/\>\;/gi, ">");

content = content.replace(/\"\;/gi, "\"");

content = content.replace(/\&\;/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§ion="+(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 );