User:TheJC/monobook.js

function addlilink(tabs, url, name, id, title, key){ var na = document.createElement('a'); na.href = url; na.appendChild(document.createTextNode(name)); var li = document.createElement('li'); if(id) li.id = id; li.appendChild(na); tabs.appendChild(li); if(id) { if(key && title) { ta[id] = [key, title]; } else if(key) { ta[id] = [key, '']; } else if(title) { ta[id] = ['', title]; } }  // re-render the title and accesskeys from existing code in wikibits.js  akeytt; return li; }

// STATUS CHANGER $(function { var user = document.getElementById( 'pt-userpage' ).firstChild.firstChild.data;  var subpage = "/Status";  var scheme = "/StatusTemplate";  var linkprefix = "http://en.wikibooks.org/w/index.php?title=User:";  var contribs = document.getElementById( 'pt-mycontris' );  //Add the links  addlilink(contribs, linkprefix+user+subpage+"&action=edit&newstatus=in", "In", "pt-status-in", "I'm in!", "");  addlilink(contribs, linkprefix+user+subpage+"&action=edit&newstatus=busy", "Busy", "pt-status-busy", "I'm busy!", "");  addlilink(contribs, linkprefix+user+subpage+"&action=edit&newstatus=out", "Out", "pt-status-out", "I'm out!", "");  if (location.href.indexOf("User:"+user+subpage+"&action=edit&newstatus=") == -1) return; //Are we here to auto-edit the status?  //Get new status  status = location.href.split("=");  status = status[status.length-1];  //Modify the form  document.getElementById('wpTextbox1').value = ""; document.getElementById('wpSummary').value = "Status: "+status; document.getElementById('wpMinoredit').checked = 'checked'; //Submit it! // document.getElementById('editform').submit; });

// see http://paperlined.org/apps/wikipedia/Tool2/ for instructions on adding this to your monobook.js

// To run this tool on other servers: //	1. copy this script to the target server (this is required because of javascript cross-site security restrictions)

//	2. update the following URL //		for example: "User:Interiot/Tool2/code.js" var tool2_url = "User:Interiot/Tool2/code.js";

//	3. update this namespace list, extracted from something like http://en.wikiquote.org/wiki/Special:Export// //			These *should not* have colons after them. var namespaces = [ "Talk", "User", "User talk", "Wikiquote", "Wikiquote talk", "Image", "Image talk", "MediaWiki", "MediaWiki talk", "Template", "Template talk", "Help", "Help talk", "Category", "Category talk", // 3b. these two project project entries are not added by Special:Export, and might or might not need to be updated "Wikipedia", "Wikipedia talk" ];

namespaces[100] = "Portal"; namespaces[101] = "Portal talk";

//	4. update this date-parser to match the format and language of your specific wiki. Feel free to contact Interiot regarding this, if you can't find another //		copy of this script that uses the same language. // input: a text string from Special:Contributions. output: a javascript Date object // documentation: http://www.quirksmode.org/js/introdate.html#parse, http://www.elated.com/tutorials/programming/javascript/dates/ function date_parse(text) { var matches = text.match(/^([0-9:]+), +([0-9]+) +([a-z]+) +([0-9]+)$/i); if (!matches) { //dump_text("XXX");			// for debugging return matches; }

parseme = matches[3] + ", " + matches[2] + " " + matches[4] + " " + matches[1] + ":00";

//dump_text(parseme);				// for debugging

var dt = new Date; dt.setTime( Date.parse(parseme));

//dump_text(dt.toLocaleString);		// for debugging

return dt; }

// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ end of server-specific configuration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

// TODO: //	- the current document.location method doesn't work when the page is accessed sans-mod_rewrite //	- test with non-ASCII characters //		- non-ascii usernames //		- ??

var prefix = ""; var params = parse_params;

addOnloadFunction(function { var path_len = document.location.pathname.length;  // trigger once we view the right page  if (document.location.pathname.substring(path_len - tool2_url.length, path_len) == tool2_url) {    // get the prefix (needs to be fixed to work sans-mod_rewrite prefix = document.location.protocol + "//" + document.location.host + "/" + document.location.pathname.substring(1, path_len - tool2_url.length);

// blank the inner contents of the page var bodyContent = document.getElementById("bodyContent"); while (bodyContent.childNodes.length > 0) bodyContent.removeChild(bodyContent.lastChild);

if (document.location.search.length == 0) { generate_input_form(bodyContent); } else { generate_main_report(bodyContent); } } });

function generate_input_form(bodyContent) { if (navigator.userAgent.toLowerCase.indexOf('msie')+1) { bodyContent.innerHTML = "This counter does not currently work in Internet Explorer.  Please get Firefox or use Flcelloguy's Tool instead."; } else { bodyContent.innerHTML = " ";

var form = bodyContent.getElementsByTagName("form")[0]; form.method = "get"; form.action = document.location;

document.getElementById("username").focus; } }

function generate_main_report { fetch_data(params["username"].replace(/\+/g, " "),		"", output_main_report, 0, []); }

function add_stats_row(left_col, right_col) { var row = document.createElement("tr"); var left = document.createElement("td"); var right = document.createElement("td"); document.getElementById("basic_stats").appendChild(row); row.appendChild(left); row.appendChild(right); //left.innerHTML = left_col; left.appendChild( document.createTextNode(left_col) ); right.appendChild( document.createTextNode(right_col) ); return row; }

function output_main_report(history) { // -- generate summary statistics var unique_articles = new Array; var namespace_numedits = new Array; for (var i=0; i<namespaces.length; i++) { namespace_numedits[ namespaces[i] ] = 0; }	namespace_numedits[""] = 0; for (var i=0; i<history.length; i++) { var h = history[i]; unique_articles[ h["title"] ]++; namespace_numedits[ h["namespace"] ]++; }	var unique_articles_keys = keys(unique_articles);

// -- output report var table = document.createElement("table"); table.id = "basic_stats"; document.getElementById("bodyContent").appendChild(table);

add_stats_row("Username", params["username"].replace(/\+/g, " ")); add_stats_row("Total edits", history.length); add_stats_row("Distinct pages edited", unique_articles_keys.length); add_stats_row("Average edits/page", new Number(history.length / unique_articles_keys.length).toFixed(3)); add_stats_row("First edit", history[ history.length-1 ]["date_text"] );

// add a blank row add_stats_row("", "").childNodes[0].style.height = "1em";

add_stats_row("(main)", namespace_numedits[""]); for (var i=0; i<namespaces.length; i++) { var nmspc = namespaces[i]; if (namespace_numedits[nmspc]) { add_stats_row(nmspc, namespace_numedits[nmspc]); }	} }

// ===================================== HTML-scraping backend =========================================

function add_loading_notice { if (document.getElementById("loading_notice")) return; var loading = document.createElement("div"); loading.id = "loading_notice"; loading.innerHTML = " Retrieving data ... "; document.getElementById("bodyContent").appendChild(loading); } function remove_loading_notice { var loading = document.getElementById("loading_notice"); if (!loading) return; loading.parentNode.removeChild(loading); }

var offset_regexp = /href="[^"]+:Contributions[^"]+offset=(\d+)/gi; function fetch_data(username, end_date, handler, offset, page_list) {	add_loading_notice;	var url = prefix + "Special:Contributions/" + username + "?offset=" + offset + "&limit=5000";	loadXMLDoc(url, 		function (request) {			var next_offset = 0;			if (request.readyState != 4)  return;			if (request.status == 200) {				page_list.push(request.responseText);				//dump_text(request.responseText);

// see if there's another pageful to get var matches = map( function(p){						return p.match( /(\d+)$/ )[0];					}, request.responseText.match( offset_regexp ) ); for (var i=0; i<matches.length; i++) { var v = matches[i] * 1; if (v != 0 && (offset == 0 || v < offset)) { next_offset = v;						break; }				}			}

//next_offset = 0;			// for testing only, retrieve just the first page of results

if (next_offset == 0) { parse_data(page_list, handler); } else { // tail recurse fetch_data(username, end_date, handler, next_offset, page_list); }		}); }

// input: a list of strings, each string containing the HTML from a single page // output: a list, where each individual entry is a specific edit from history function parse_data(page_list, handler) { //var total_len = 0; //for (var i=0; i[^(]+\(([^(<]+)/i )[1]					.replace( / +$/, "");			history_entry["date"] = date_parse( history_entry["date_text"] );			history_entry["title"] = history_text.match( /title="([^"]+)"/i )[1]					.replace( /&quot;/g, "\"")					.replace( /&amp;/g, "&");			var find_comment = history_text.replace(/ .*?<\/span> ?/, "");			history_entry["comment"] = ifmatch(find_comment.match( / (.*?)<\/span>/ ))					.replace(/^\((.*)\)$/, "$1");			history_entry["minor"] = /<span class="minor"/.test(history_text);			history_entry["oldid"] = ifmatch(history_text.match(/oldid=([0-9]+)/i));

history_entry["namespace"] = ""; for (var nmspc_ctr=0; nmspc_ctr<namespaces.length; nmspc_ctr++) { var nmspc = namespaces[nmspc_ctr] + ":"; if (history_entry["title"].substring(0, nmspc.length) == nmspc) { history_entry["namespace"] = namespaces[nmspc_ctr]; break; }			}

//dump_object(history_entry);

if (history_entry["title"] != last_history_ent["title"] || history_entry["oldid"] != last_history_ent["oldid"]) edit_history.push(history_entry); last_history_ent = history_entry; }	}

remove_loading_notice;

handler(edit_history); }

// ===================================== test/debug functions =========================================

function dump_text(text) { //alert("dump_text, with text of size " + text.length);

var pre = document.createElement("pre");

var div = document.createElement("div"); div.style.width = "60em"; div.style.maxHeight = "40em"; div.style.overflow = "auto";

pre.appendChild(document.createTextNode(text)); div.appendChild(pre); document.getElementById("bodyContent").appendChild(div); }

function dump_lines(ary) { dump_text("--> " + ary.join("\n--> ")); }

function dump_object(obj) { var toString = ""; for (var prop in obj) { toString += prop + ": " + obj[prop] + "\n"; }	dump_text(toString); }

// ===================================== utility functions =========================================

function addOnloadFunction(f) { if (window.addEventListener) window.addEventListener("load",f,false); else if (window.attachEvent) window.attachEvent("onload",f); else { var oldOnload='_old_onload_'+addOnloadFunction.uid; addOnloadFunction[oldOnload] = window.onload ? window.onload : function {}; window.onload = function { addOnloadFunction[oldOnload]; f; } ++addOnloadFunction.uid; } }

function parse_params { var pairs = document.location.search.substring(1).split("&"); var ret = []; for (var i=0; i < pairs.length; i++) { var values = pairs[i].split("="); ret[values[0]] = unescape(values[1]); } return ret; }

function loadXMLDoc(url, handler) {   // branch for native XMLHttpRequest object if (window.XMLHttpRequest) { req = new XMLHttpRequest; req.onreadystatechange = function {handler(req)}; req.open("GET", url, true); req.send(null); // branch for IE/Windows ActiveX version } else if (window.ActiveXObject) { req = new ActiveXObject("Microsoft.XMLHTTP"); if (req) { req.onreadystatechange = function {handler(req)}; req.open("GET", url, true); req.send; }   } }

// see http://search.cpan.org/dist/perl/pod/perlfunc.pod#map function map (handler, list) { var ret = new Array; for (var i=0; i= 2) { return ary[1]; } else { return ""; } }

//

// Below (unsigned2.js version 1.2,) by Invitatious. Dual-licensed under the terms of the GFDL v1.2 or the GPL v2. // New features in this version: you can now choose an edit from the last 16. function addSigWikiCode { // From revision 28011729 of en:Wikipedia:WikiProject_User_scripts/Scripts/Get_tidy_title function aswcGet_tidy_title { var editlk = document.getElementById('ca-edit').getElementsByTagName('a')[0].href; // cut everything up to "title=" from the start and everything past "&action=edit" from the end editlk = editlk.substring(editlk.indexOf('title=') + 6, editlk.lastIndexOf('&action=edit')); return editlk; } // LOCALIZABLE STRINGS START. var lsMonth_names = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; var lsConflict = "Edit conflict." var lsDialog1 = "Please select an edit below:\n\n"; var lsDialog2 = "Unsigned edit number:"; var lsInvalid1 = "Please enter a valid number or cancel this operation."; var lsInvalid2 = "This is not a valid choice. Please choose another option."; var lsNoRev = "No revisions found. Does the page exist?" var lsNoXMLHTTP = "Couldn't get XMLHTTP!"; // LOCALIZABLE STRINGS END var x = window.XMLHttpRequest ? new XMLHttpRequest : window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : false; // Get XMLHTTP if (x) { x.open("GET", "/w/query.php?format=xml&what=revisions&rvlimit=16&rvcomments&titles=" + aswcGet_tidy_title, false); // Get timestamp, user, summary of last 16 edits x.send(null); var revisions = x.responseXML.documentElement.getElementsByTagName("rv"); // Get the revisions if (revisions.length > 0) { var t = revisions[0].getAttribute("timestamp").replace(/[^0-9]/g, ""); // Get rid of non-numeric characters in timestamp if(t != document.editform.wpEdittime.value) { // Detect an edit conflict alert(lsConflict); return; }     var dialog_text = lsDialog1; var edit_data = []; for (var n = 0; n < revisions.length; n++) { // Extract edit data and build dialog text edit_data[n] = { timestamp: revisions[n].getAttribute("timestamp").replace(/[^0-9]/g, ""), user: revisions[n].getAttribute("user"), comment: revisions[n].getAttribute("comment") }; dialog_text += ("[" + n.toString(16).toUpperCase + "] " + edit_data[n].timestamp + " " +        edit_data[n].user + ": " + edit_data[n].comment).substring(0, 80) + "\n"; }     while (true) { alert(dialog_text); // for IE or other var unsigned_edit = prompt(lsDialog2, "0"); // for IE or other // var unsigned_edit = prompt(dialog_text + "\n" + lsDialog2, "0"); // for Mozilla if (unsigned_edit == null) { // Cancel button return; } else if (isNaN(unsigned_edit = parseInt(unsigned_edit, 16))) { // Non-numeric input alert(lsInvalid1); }       else if (!(unsigned_edit = edit_data[unsigned_edit])) { // Non-existent edit alert(lsInvalid2); } else { t = unsigned_edit.timestamp; // So the full name doesn't have to be used // LOCALIZABLE STRINGS START insertTags("" + t.substring(8, 10) + ":" + t.substring(10, 12) + ", " + (t.substring(6, 8) - 0) + " " + lsMonth_names[t.substring(4, 6) - 1] + " " + t.substring(0, 4) + "", "", ""); // Format and insert the tag. The data returned by query.php is UTC already. FetchTimezone is not needed. document.getElementById('wpSummary').value = "Signed unsigned comment by: "+ unsigned_edit.user; document.getElementById('wpMinoredit').checked = 'checked'; // LOCALIZABLE STRINGS END return; }     }    } else { // No revisions alert(lsNoRev); } } else { alert(lsNoXMLHTTP); // No XMLHTTP return; } } $(function{ // From revision 28011435 of en:Wikipedia:WikiProject_User_scripts/Scripts/Add_LI_link  function aswcAddlilink(tabs, url, name, id, title, key) {    var na = document.createElement('a');    na.href = url;    na.appendChild(document.createTextNode(name));    var li = document.createElement('li');    if(id) li.id = id;    li.appendChild(na);    tabs.appendChild(li);    if(id)    {        if(key && title)        {            ta[id] = [key, title];        }        else if(key)        {            ta[id] = [key, ];        }        else if(title)        {            ta[id] = [, title];        }    }    // re-render the title and accesskeys from existing code in wikibits.js    akeytt;    return li; } //  if (/[&?]action=edit/.test(location.search)) {    aswcAddlilink(document.getElementById('p-cactions').getElementsByTagName('ul')[0], "javascript:addSigWikiCode;", /* LOCALIZABLE STRINGS START */ "unsigned2", "ca-unsigned2", "Mark unsigned comment", "" /* LOCALIZABLE STRINGS END */); } }); // Above by Invitatious. Dual-licensed under the terms of the GFDL v1.2 or the GPL v2. //