User:Achille~enwiki/allquarls3.js

Source: Wikipedia, the free encyclopedia.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/ User:Quarl/util.js - miscellaneous utility functions for Wikipedia user scripts

// quarl 2006-01-09 initial version

// <pre><nowiki>

/////////////////////////////////////////////////////////////
// STRING UTILITY FUNCTIONS

function trimspaces(s) {
    if (!s) return s;
    s = s.replace(/^ +/,'');
    s = s.replace(/ +$/,'');
    return s;
}

function string_quote_escape(str) {
    if (!str) return str;
    return "'" + str.replace(/\'/g, '\\\'').replace(/\%27/g, '\\\'') + "'";
}

// wiki article name escaping
function wpaescape(s) {
    // Need to escape '+'; don't escape ':'
    return escape(s.replace(/ /g,'_')).replace(/[+]/g, '%2B').replace(/%3A/,':');
}

function url_getpath(s) {
    return s.replace(/^http:\/\/[^/]+/, '');
}

////////////////////////////////////////////////////////////
// DOM UTILITY FUNCTIONS
function getElementsByClass(searchClass,node,tag) {
/* This script and many more are available free online at
The JavaScript Source :: http://javascript.internet.com
Created by: Dustin Diaz :: http://www.dustindiaz.com/ */
  var classElements = new Array();
  if (node == null)
    node = document;
  if (tag == null)
    tag = '*';
  var els = node.getElementsByTagName(tag);
  var elsLen = els.length;
  var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
  for (i = 0, j = 0; i < elsLen; i++) {
    if (pattern.test(els[i].className) ) {
      classElements[j] = els[i];
      j++;
    }
  }
  return classElements;
}

function add_before(node, newnode) {
    node.parentNode.insertBefore(newnode, node);
    return newnode;
}

function add_after(node, newnode) {
    node.parentNode.insertBefore(newnode, node.nextSibling);
    return newnode;
}

function findHref(href) {
    href = escape(href);
    var links=document.links;
    for(i=0;i<links.length;++i) {
        // unescape and reescape to ensure canonical escaping
        if (escape(unescape(links[i].href)) == href) return links[i];
    }
    return null;
}

function insertNode(node, newNode) {
    if (!node) return null;

    node.parentNode.replaceChild(newNode, node);
    newNode.appendChild(node);
    return newNode;
}

function hookEventObj(obj, hookName, hookFunct) {
    if (!obj) return;

    if (obj.addEventListener)
        obj.addEventListener(hookName, hookFunct, false);
    else if (obj.attachEvent)
        obj.attachEvent("on" + hookName, hookFunct);
}

// AJAX functions

function HTTPClient() {
    var http;
    if(window.XMLHttpRequest) {
        http = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        try {
            http = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                http = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (E) {
                http = false;
            }
        }
    }
    return http;
}

function asyncDownloadXML(url, callback) {
    var xmlhttp = HTTPClient();
    if (!xmlhttp) return null;
    // add optional arguments
    for (var i = 2; i+1 < arguments.length; i += 2) {
        xmlhttp[arguments[i]] = arguments[i+1];
    }
    xmlhttp.open("GET", url, true);
    xmlhttp.overrideMimeType('text/xml');
    // using onload instead of onreadystatechange allows multiple asynchronous requests
    xmlhttp.onload = function(event) { 
        var req = event.target;
        if (req.readyState == 4) callback(req);
    };
    xmlhttp.send(null);
    return xmlhttp;
}

//

// </nowiki></pre>








// User:Quarl/md5.js

// md5 functions, factored from godmode-light.js

// <nowiki><pre>

// -----------------------------------------------------------------------------
// MD5 hash calculator
// -----------------------------------------------------------------------------
// Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
// Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
// Distributed under the BSD License
// See http://pajhome.org.uk/crypt/md5 for more info.
// -----------------------------------------------------------------------------
var hexcase = 0;
var b64pad  = "";
var chrsz   = 8;

function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}

function core_md5(x, len)
{
  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;

  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;

    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819); b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426); c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416); d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); c = md5_ff(c, d, a, b, x[i+10], 17, -42063); b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682); d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); c = md5_gg(c, d, a, b, x[i+11], 14,  643717713); b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083); c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438); d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501); a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473); b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562); b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353); c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174); d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189); a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); c = md5_hh(c, d, a, b, x[i+15], 16,  530742520); b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415); c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571); d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359); d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649); a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259); b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
  }
  return Array(a, b, c, d);

}

function md5_cmn(q, a, b, x, s, t) { return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); }
function md5_ff(a, b, c, d, x, s, t) { return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); }
function md5_gg(a, b, c, d, x, s, t) { return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); }
function md5_hh(a, b, c, d, x, s, t) { return md5_cmn(b ^ c ^ d, a, b, x, s, t); }
function md5_ii(a, b, c, d, x, s, t) { return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); }

function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

function bit_rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

function str2binl(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
  return bin;
}

function binl2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
  }
  return str;
}


// </nowiki></pre>






// based on http://en.wikipedia.org/wiki/Wikipedia:WikiProject_User_scripts/Scripts/Add_LI_link

// <pre>

function getTabActions() {
    return document.getElementById('p-cactions').getElementsByTagName('ul')[0];
}

function getToolbox() {
    return document.getElementById('p-tb').getElementsByTagName('ul')[0];
}

function addTab(url, name, id, title, key) {
    addlilink(getTabActions(), url, name, id, title, key);
}

function addToolboxLink(url, name, id, title, key) {
    addlilink(getToolbox(), url, name, id, title, key);
}

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 && (key || title)) {
        ta[id] = [(key||''), (title||'')];
    }
    // re-render the title and accesskeys from existing code in wikibits.js
    akeytt();
    return li;
}

// </pre>


// User:Quarl/wikipage.js - "WikiPage" class for page name, etc. functionality

// requires: util.js

// Suppose we are editing [[Template talk:Foo bar 'blah']].
//   editingP:             true;

// wikiPage is a pre-initialized global variable using the current page's canonical URL.
// It uses the "Retrieved from" page hyperlink which is robust against redirections, editing, special characters, special pages.
//
//   wikiPage.url:         "http://en.wikipedia.org/wiki/Template_talk:Foo_bar_%27blah%27"
//   wikiPage.qurl:        "http://en.wikipedia.org/w/index.php?title=Template_talk:Foo_bar_%27blah%27"
//   wikiPage.page:        "Template talk:Foo bar 'blah'"
//   wikiPage.article:     "Foo bar 'blah'"
//   wikiPage.namespace:   "Template talk"
//   wikiPage.namespaceNT: "Template"
//   wikiPage.talkP:       true
//   wikiPage.nsTemplateP: true
//   wikiPage.nsMainP:     false
//   wikiPage.nsUserP:     false
//   wikiPage.nsCategoryP: false
//   wikiPage.nsSpecialP:  false
//   wikiPage.nsProjectP:  false    // (namespace "Wikipedia")

// To create new WikiPage object from a URL:
//   var wp = new WikiPage("http://en.wikipedia.org/wiki/Article_Name");
// To create a new WikiPage object from a page name:
//   var wp = new WikiPage(null, 'Article Name');

// <pre><nowiki>

/*
<div class="printfooter">
Retrieved from "<a href="http://en.wikipedia.org/wiki/Albert_Einstein">http://en.wikipedia.org/wiki/Albert_Einstein</a>"</div>
*/

// the "retrieved from" text contains the canonical article URL (even if we're looking at an edit or history page)
function getCanonPageURL0() {
    return getElementsByClass("printfooter", null, 'div')[0].getElementsByTagName('a')[0].href;
}

function getUsername0() {
    // read username from pt-userpage link.
    // <li id="pt-userpage"><a href="/wiki/User:Quarl">Quarl</a></li>
    return document.getElementById('pt-userpage').getElementsByTagName('a')[0].text;
}

function WikiPage(url,page) {
    if (!(this instanceof WikiPage)) return new WikiPage(url,page);
    if (url) {
        this.url = "" + url;
        if (this.url.match(/^(?:http:\/\/en.wikipedia.org)\/wiki\//)) {
            this.pageQuoted = RegExp.rightContext;
        } else if (this.url.match(/^(?:http:\/\/en.wikipedia.org)\/w\/index.php\?title=([^&]+)/)) {
            this.pageQuoted = RegExp.$1;
        } else {
            alert("WikiPage: Couldn't parse page name from url '"+url+"'"); 
            return;
        }
        this.page = unescape(this.pageQuoted).replace(/_/g,' ');
    } else if (page) {
        this.page = page.replace(/_/g, ' ');
        this.pageQuoted = wpaescape(page);
        this.url = 'http://en.wikipedia.org/wiki/' + this.pageQuoted;
    } else {
        alert("WikiPage: must specify url or page"); return; 
    }

    this.qurl = 'http://en.wikipedia.org/w/index.php?title=' + this.pageQuoted;

    if (this.page.match(/:/)) {
        this.namespace = RegExp.leftContext;
        this.article = RegExp.rightContext;
    } else {
        this.namespace = ''; // (main)
        this.article = this.page;
    }

    if (this.namespace == 'Talk') {
        this.talkP = true;
        this.namespaceNT = '';
    } else if (this.namespace.match(/ talk$/)) {
        this.talkP = true;
        this.namespaceNT = RegExp.leftContext;
    } else {
        this.talkP = false;
        this.namespaceNT = this.namespace;
    }

    if (this.article.match(/\//)) {
        this.superarticle = RegExp.leftContext;
        this.subarticle = RegExp.rightContext;
    } else {
        this.superarticle = this.article;
        this.subarticle = '';
    }

    this.nsMainP = (this.namespaceNT == '');
    this.nsSpecialP = (this.namespaceNT == 'Special');
    this.nsUserP = (this.namespaceNT == 'User');
    this.nsTemplateP = (this.namespaceNT == 'Template');
    this.nsCategoryP = (this.namespaceNT == 'Category');
    this.nsProjectP = (this.namespaceNT == 'Wikipedia');
    this.nsHelpP = (this.namespaceNT == 'Help');
    this.nsImageP = (this.namespaceNT == 'Image');
    this.nsCategoryP = (this.namespaceNT == 'Category');

    this.talkPage = function() {
        if (this.talkP) { return this; }
        else if (this.namespaceNT == '') { return new WikiPage(null, 'Talk:'+this.article); }
        else { return new WikiPage(null, this.namespaceNT+' talk:'+this.article); }
    }

    this.notalkPage = function() {
        if (!this.talkP) { return this; }
        else if (this.namespaceNT == '') { return new WikiPage(null, this.article); }
        else { return new WikiPage(null, this.namespaceNT+':'+this.article); }
    }
}

// from automod.js
function getQueryVars0(){ 
     var res = new Array();
     var pairs = location.search.substring(1).split("&"); 
     for(var i=0; i < pairs.length; i++){ 
         var pair = pairs[i].split("=");
         res[unescape(pair[0])] = unescape(pair[1]).replace(/\+/g, ' ');
     }
     return res; 
}

function initWikiPage() {
    window.wikiPage = new WikiPage(getCanonPageURL0());
    window.username = getUsername0();
    window.editingP = Boolean(document.forms.editform);    //document.title.match(/^Editing /) 
    window.movepageP = Boolean(document.forms.movepage);
    window.previewP = Boolean(document.getElementById("wikiPreview"));
    window.historyP = Boolean(document.getElementById("pagehistory"));
    window.queryVars = getQueryVars0();
}

// DEPRECATED:
function getPname() { return wikiPage.page; }
function getPnameNS() { return wikiPage.namespace; }
function getPnameNoNS() { return wikiPage.article; }
function pageIsSpecial() { return wikiPage.nsSpecialP; }
function get_query_vars() { return queryVars; }

addOnloadHook(initWikiPage);

// obsolete method 1:
/*function getPname0() {
    var z=document.getElementById("content").childNodes;
    for (var n=0;n<z.length;n++) { 
        if (z[n].className=="firstHeading") return z[n].textContent;
    }
}

function getPname1() {
    var t = getPname0();
    t = t.replace(/^Editing /,'');
    t = t.replace(/ \(section\)$/,'');

    return t;
}*/

// obsolete method 2:
/* 
    return document.title.substr(0, document.title.lastIndexOf(' - Wikipedia, the free'));
*/

//</nowiki></pre>



// <pre>

function LZ(x) { return (x>=10||x<0?"":"0") + x }

function datestampUTCISO() {
    var d=new Date();
    return ""+d.getUTCFullYear()+"-"+LZ(d.getUTCMonth()+1)+"-"+LZ(d.getUTCDate());
}

function timestampUTCISO() {
    var d=new Date();
    return LZ(d.getUTCHours())+":"+LZ(d.getUTCMinutes());
}

monthnames = new Array( "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");

function datestampYYYYMonthD() {
    var d = new Date();
    return ""+d.getUTCFullYear() + ' ' + monthnames[d.getUTCMonth()] + ' ' + d.getUTCDate();
}

function datestampMonthYYYY() {
    var d = new Date();
    return ""+monthnames[d.getUTCMonth()] + ' ' + d.getUTCFullYear();
}

//</pre>


// User:Quarl/autoreplace.js - provides capability to replace strings (regular expressions) in edit boxes on submission.
//    Strings between <nowiki> ... </nowiki> are not replaced.

// external entry points:
//    autoreplace_add("string", "replacement" || replacement_function);

// quarl 2006-01-04 initial version

// test:
//   javascript:alert(autoreplace_replace_string_nonowiki("2 x 3 <nowiki> 4 x 5 </nowiki> 6", "x", "XXX"))
//   javascript:alert(autoreplace_replace_strings("a ~~"+"~~ foo <nowiki>~~"+"~~</nowiki>"))

// <pre><nowiki>

autoreplace_on = true;

//autoreplace_on_save = true;
//autoreplace_on_preview = false;
//autoreplace_on_diff = false;

autoreplace_replacements = Array();

function autoreplaceEntry() {
/*
    if (autoreplace_on_save)
        hookEventObj(document.getElementById('wpSave'), 'click', autoreplace_execute);
    if (autoreplace_on_preview)
        hookEventObj(document.getElementById('wpPreview'), 'click', autoreplace_execute);
    if (autoreplace_on_diff)
        hookEventObj(document.getElementById('wpDiff'), 'click', autoreplace_execute);
*/
    hookEventObj(document.editform, 'submit', autoreplace_execute);
}

function hookEventObj(obj, hookName, hookFunct) {
    if (!obj) return;

    if (obj.addEventListener)
        obj.addEventListener(hookName, hookFunct, false);
    else if (obj.attachEvent)
        obj.attachEvent("on" + hookName, hookFunct);
}

function autoreplace_add(str, replacement) {
    autoreplace_replacements.push([str,replacement]);
}

function autoreplace_f_to_str(t) {
    if (typeof t == 'function') t = t();
    return ""+t;
}

function autoreplace_replace_string(text, str, replacement) {
    return text.replace(new RegExp(str,'g'), replacement);
}

function autoreplace_replace_string_nonowiki(text, str, replacement) {
    var rtext = '';
    while ( text.match(/<nowiki>(?:.|\n)*?<\/nowiki>/) ) {
        // save these before they get clobbered!
        var left = RegExp.leftContext;
        var match = RegExp.lastMatch;
        var right = RegExp.rightContext;

        rtext += autoreplace_replace_string(left, str, replacement) + match;
        text = right;
    }
    rtext += autoreplace_replace_string(text, str, replacement)
    return rtext;
}

function autoreplace_replace_strings(text) {
    if (!text) return text;
    for (i in autoreplace_replacements) {
        r = autoreplace_replacements[i];
        text = autoreplace_replace_string_nonowiki(text, r[0], autoreplace_f_to_str(r[1]));
    }
    return text;
}

function autoreplace_execute() {
    if (!autoreplace_on) return;

    textbox = document.getElementById("wpTextbox1");
    if (!textbox) return;
    textbox.value = autoreplace_replace_strings(textbox.value);

    // Since we're submitting a form, we shouldn't get here again.  Disable in case of recurring bugs.
    autoreplace_on = false;
}

addOnloadHook(autoreplaceEntry);

// </nowiki></pre>




// User:Quarl/automod.js

// requires: wikipage.js, util.js

// based on http://en.wikipedia.org/wiki/User:Jnothman/automod.js

// - added 'amnocreate'
// - fixed escape '+' bug

//<pre><nowiki>

if ((typeof auto_mod_loaded == 'undefined')
    || !auto_mod_loaded) {
auto_mod_loaded = true;
auto_mod_exectd = false;

function am_make_url(title, before, after, summary) {
    return 'http://en.wikipedia.org/w/index.php?title='+wpaescape(title)+
        '&action=edit'+
        '&amaddbefore='+escape(before)+'&amaddafter='+escape(after)+
        '&amsummary='+escape(summary);
}

function auto_mod() {
    if (auto_mod_exectd)
        return false;
    auto_mod_exectd = true;

    if (queryVars['action']=='edit') {
      if (queryVars['amnull']) {
        document.getElementById('editform').submit();
        return true;
      }
      if (queryVars['amaddafter'] || queryVars['amaddbefore'] || queryVars['amreplace']) {
        var summ_el = document.getElementById('wpSummary');
        if (summ_el.value != '' && summ_el.value.substr(summ_el.value.length - 3, 3) != '*/ ') {
            // have already added summary
            return true;
        }
        var text = document.getElementById('wpTextbox1');
        if (queryVars['amnocreate'] && ! text.value) {
            alert("Error!  Page is empty; refusing to create.");
            return false;
        }
        if (queryVars['amclear'])
            text.value = '';
        if (queryVars['amfind'] && queryVars['amreplace'])
            text.value = text.value.replace(new RegExp(queryVars['amfind'], "g"), queryVars['amreplace']);
        if (queryVars['amaddafter']) {
            if (text.value.charAt(text.value.length-1) != '\n')
                text.value += '\n';
            text.value += queryVars['amaddafter'];
        }
        if (queryVars['amaddbefore']) {
            if (text.value.charAt(0) != '\n')
                text.value = '\n' + text.value;
            text.value = queryVars['amaddbefore'] + text.value;
        }
        summ_el.value += (queryVars['amsummary'] || ' ');
        document.getElementById('editform').submit();
      }
      return true;
    }
    return false;
}

addOnloadHook(auto_mod);

} // end if auto_mod_loaded

// </nowiki></pre>

// <pre><nowiki>

// User:Quarl/advanced_sig.js - allows advanced custom signatures.
//
//   - "~~~~" is replaced by anything you want (any string or function) when you hit 'submit'
//   - Defaults to nicely-formatted and [[ISO 8061]] timestamp
//       - Wiki-linked timestamp enables date preferences
//       - Uses <span class="user-Username"> tags around entire signature (including timestamp) - see [[User:HorsePunchKid]]
//   - the toolbar "--~~~~" button is replaced by anything you want
//
//   - You could even use this to vary your signature based on the article or namespace
//     (for example an extra link on AFD pages)

// Requires: datetime.js, autoreplace.js

///////////////////////////////////////////////////////////////
// EXTERNAL ENTRY POINTS
//
// makeSignature():     Returns the custom signature.
//

///////////////////////////////////////////////////////////////
// USER-CONFIGURABLE SETTINGS

// signature:           This is your signature. (can be string or function)
//
//                      To emulate normal behavior:
//                          signature = '~~~~';
//
//                      Default:
//                          signature = build_default_signature;
//
//                      Other examples:
//                          signature = function() { return '--~~~ ' + wikiTimestampISO() }
//                          signature = '<i>&mdash;[[User:Quarl|Quarl]] ~~~~~</i>';
//
//
// toolbar_signature:   What the "signature" toolbar button inserts. (can be string or function)
//                      I recommend removing the '--' (or &mdash;) and having it instead be part of the signature.
//
//                      To emulate normal behavior:
//                          toolbar_signature = '--~~~~';
//
//                      Default:
//                          toolbar_signature = '~~~~';
//
//                      Other examples:
//                          toolbar_signature = makeSignature;
//                          toolbar_signature = '&mdash;~~~~';
//

//
// The following are used by build_default_signature.
//
// sig_username:        Used by build_default_signature as username in CSS span tag class name.
//                      Result is <span user-Quarl> for sig_user='Quarl'.  (can be string or function)
//
//                      Default (should work for most people):
//                          sig_username = getUsername; // read from Wikipedia page
//
//                      Other examples:
//                          sig_username = 'QuarlXYZ';
//
// signature_user:      Used by build_default_signature for username wiki link. (can be string or function)
//                      I recommend embedding the &mdash; so you don't have to type it every time.
//
//                      To emulate normal behavior:
//                          signature_user = '~~~';
//
//                      Default:
//                          signature_user = '&mdash;~~~';
//
//                      Other examples:
//                          signature_user = '[[User:Quarl|Quarl]] <sup>([[User talk:quarl|talk]])</sup>';
//
// signature_timestamp: Used by build_default_signature for timestamp (can be string or function).
//                      I recommend using wikiTimestampISO since I love [[ISO 8601]] time format, and
//                      this would allow everyone to see their preferred time format.
//
//                      To emulate normal behavior:
//                          signature_timestamp = '~~~~~';
//
//                      Default:
//                          signature_timestamp = wikiTimestampISO;
//

// To allow use of advanced_sig.js in other scripts but not require it, use the following:
//      if(typeof window.makeSignature=='undefined')makeSignature=function(){return "~~~~"};

// quarl 2005-12-30 initial version
// quarl 2006-01-04 add feature to replace "~~~~" in text; factored it so it's easy to customize

function getUsername() {
    // read username from pt-userpage link.
    // <li id="pt-userpage"><a href="/wiki/User:Quarl">Quarl</a></li>
    return document.getElementById('pt-userpage').getElementsByTagName('a')[0].text;
}

function wikiTimestampISO() {
    return "[["+datestampUTCISO()+"]]&nbsp;"+timestampUTCISO()+"[[ISO 8601|Z]]";
}

function spansig(user, sigUser, sigTimestamp) {
    return " <span class=\"user-sig user-"+user+"\"><i>" + sigUser +  " <small>"+sigTimestamp+"</small></i></span>"
}

function build_default_signature() {
    return spansig(getSigUsername(), getSignatureUser(), getSignatureTimestamp());
}

// sig_newOption, originally based on newOption from Lupin's popups.js
//     this should expand to something like
//     if (typeof window.foo=='undefined') { window.foo=null; }; window.dfoo = 0.5;
function sig_newOption(x, def) {
    var a='window.'  + x;
    var b='window.default_' + x;
    eval('if (typeof '+ a + '==\'undefined\') {' + a + '=null; }; ' + b + '=' + def + ';');
    return sig_makeGetterFunction(x);
};

function sig_makeGetterFunction(varName) {
    return eval(
             'function() { '+
                 'return sig_evalParam("'+varName+'",'+
                                     '(window.'+varName+' || window.default_'+varName+')); }');
}

function sig_evalParam(varName, v) {
    if (typeof v == 'string') return v;
    if (typeof v == 'function') return v();
    if (v == null) alert("ERROR! Variable '"+varName+"' cannot be null.");
    else alert("ERROR! Variable '"+varName+"' cannot be of type '"+(typeof v)+"'; must be string or function.");
    return ""+v;
}

///////////////////////////////////////////////////////////////
// user-configurable settings (see top of page for commentary)

makeSignature = sig_newOption('signature', 'build_default_signature');

getSigUsername        = sig_newOption('sig_username', 'getUsername');
getSignatureUser      = sig_newOption('signature_user', '"&mdash;~~~"');
getSignatureTimestamp = sig_newOption('signature_timestamp', 'wikiTimestampISO');
getToolbarSignature   = sig_newOption('toolbar_signature', '"~~~~"');

function replaceSignatureButton() {
    // Note: a slightly more complicated version is required to replace the signature with the evaluation of getToolbarSignature() at the time of pressing the button rather than time of page load, but it doesn't matter if you are just replacing it with ~~~~ and using autoreplace as below.
    var toolbar = document.getElementById('toolbar');
    if (!toolbar) return;
    var links = toolbar.getElementsByTagName('a');
    for (var i = 0; i < links.length; i++) {
        links[i].href = links[i].href.replace(/--~~~~/, getToolbarSignature());
    }
}

function replaceSignatureOnSubmit() {
    autoreplace_add('~~~~', makeSignature);
}

addOnloadHook(replaceSignatureButton);
addOnloadHook(replaceSignatureOnSubmit);

// </nowiki></pre>


// User:quarl/rollback.js - rollback button.

// requires wikipage.js, util.js, md5.js

// based on http://sam.zoy.org/wikipedia/godmode-light.js
//   - more robust (works with Popups, etc)
//   - factored code

// <pre><nowiki>

// -----------------------------------------------------------------------------
// God-like Monobook skin
// (c) 2005 Sam Hocevar <[email protected]>
// $Id: godmode-light.js 980 2005-11-12 01:51:51Z sam $
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// Language support, taken from phase3/languages/*
// -----------------------------------------------------------------------------
var rollbacklink = 'rollback';
var cantrollback = 'Cannot revert edit; last contributor is only author of this page.';
var alreadyrolled = 'Cannot rollback last edit of [[$1]] by [[User:$2|$2]] ([[User talk:$2|Talk]]); someone else has edited or rolled back the page already. Last edit was by [[User:$3|$3]] ([[User talk:$3|Talk]]). ';
var revertpage = 'Reverted edits by [[User:$2|$2]] ([[User talk:$2|t]]) ([[Special:Contributions/$2|c]]) to last version by $1';

// -----------------------------------------------------------------------------
// Our nice Revert functions
// -----------------------------------------------------------------------------
var gml_vandal, gml_editor;

function rollback_Revert() {
    if (queryVars['fakeaction'] != 'rollback') return;

    var token = queryVars['token'];
    gml_vandal = queryVars['vandal'];

    document.cont = document.getElementById('bodyContent');

    document.cont.innerHTML = 'Please wait, reverting edits by ' + gml_vandal + '...';
    // Avoid XSS kiddies by using a special token
    if (!token || token != rollback_mkToken(wikiPage, gml_vandal)) {
        document.cont.innerHTML += 'ERROR: Bad authentication token!';
        return;
    }

    document.getElementById('bodyContent').innerHTML += '<br />Getting article history...';
    asyncDownloadXML(wikiPage.qurl + '&action=history&limit=50', rollback_Revert2);
}

function rollback_Revert2(xmlhttp) {
    var l;
    var oldid;
    // Get the vandal and new editor names
    gml_editor = null;
    doc = xmlhttp.responseXML;
    l = doc.getElementById('pagehistory').getElementsByTagName('li');
    for (i = 0; i < l.length; i++) {
        var name = l[i].getElementsByTagName('span')[0].getElementsByTagName('a')[0].innerHTML.replace(/_/g,' ');
        if (!name) continue;
        if (i == 0) {
            if (name != gml_vandal) {
                document.cont.innerHTML += '<br />Error: Last editor is ' + name + ', not ' + gml_vandal + '!';
                return;
            }
        } else {
            if (name != gml_vandal) {
                oldid = l[i].getElementsByTagName('input')[0].value;
                gml_editor = name;
                break;
            }
        }
    }
    if (!gml_editor) {
        document.cont.innerHTML += '<br />Error: ' + gml_vandal + ' is the only editor!';
        return;
    }

    var url = wikiPage.qurl + '&action=edit&oldid=' + oldid;
    document.cont.innerHTML += '<br />Getting article edit form...';
    asyncDownloadXML(wikiPage.qurl + '&action=history&limit=50', rollback_Revert3);
}

function rollback_Revert3(xmlhttp) {
    var form, newform, l;
    // Insert the downloaded form in our current page, using
    // only hidden form inputs.
    doc = xmlhttp.responseXML;
    form = doc.getElementById('editform');
    newform = document.createElement('form');
    l = form.getElementsByTagName('textarea');
    for (i = l.length; i--; ) {
        var t = document.createElement('input');
        t.type = 'hidden';
        t.name = l[i].name;
        t.value = l[i].value;
        newform.appendChild(t);
    }
    l = form.getElementsByTagName('input');
    for (i = l.length; i--; ) {
        if (l[i].name == 'wpSummary') {
            l[i].value = revertpage.replace(/\$1/g, gml_editor).replace(/\$2/g, gml_vandal);
        } else if (l[i].name == 'wpMinoredit') {
            l[i].value = '1';
        } else if (l[i].name == 'wpWatchthis') {
            if (!l[i].checked)
            continue; // Don't touch the "watch" status
            l[i].value = "on";
        } else if (l[i].name == 'wpPreview') {
            continue;
        } else if (l[i].name == 'wpDiff') {
            continue;
        }
        l[i].type = 'hidden';
        newform.appendChild(l[i]);
     }
     newform.name = form.name;
     newform.method = form.method;
     newform.id = form.id;
     newform.action = form.action;
     document.cont.innerHTML += '<br />Submitting form...';
     document.cont.appendChild(newform);
     newform.submit();  // Submit the form
}

function rollback_link_to_username(link) {
    return link && (new WikiPage(link)).article;
}

function rollback_mkToken(wp, vandal) {
    return hex_md5(wp.page + '%' + vandal + '%' + document.cookie);
}

function rollback_mkUrl(wp, vandal) {
    return url_getpath(wp.qurl + '&fakeaction=rollback&vandal=' + 
                       escape(vandal) + '&token=' + escape(rollback_mkToken(wp, vandal)));
}

// -----------------------------------------------------------------------------
// Add revert buttons to the page
// -----------------------------------------------------------------------------
function rollback_AddButtonDiff() {
    var difftag = getElementsByClass('diff-ntitle',document.getElementById('bodyContent'),'td')[0];
    if (!difftag) return;

    // if toplink has an oldid then this is not a diff against current revision.
    var toplink = difftag.getElementsByTagName('a')[0].href;
    if (toplink.match(/oldid=/)) return;

    var vandal = rollback_link_to_username(difftag.getElementsByTagName('a')[1]);
    if (!vandal) { alert("Couldn't parse username in diff page!"); return; }

    var url = rollback_mkUrl(wikiPage,vandal);
    var newtext = ' &nbsp;&nbsp;&nbsp;<strong>[<a href="' + url + '">' + rollbacklink + '</a>]</strong> ';

    difftag.innerHTML = difftag.innerHTML.replace(/(<\/a>\))( *<br)/i, '$1'+newtext+'$2');
}

function rollback_AddButtonContributions() {
    if (wikiPage.page != 'Special:Contributions') return;

    var vandal = rollback_link_to_username(document.getElementById('contentSub').getElementsByTagName('a')[0]);
    if (!vandal) { alert("Couldn't parse user for Special:Contributions page"); return; }

    var l = document.getElementById('bodyContent').getElementsByTagName('li');
    for (i = 0; i < l.length; i++) {
        var t = l[i].innerHTML;
        // If we are already a sysop on this wiki, abort
        if (t.match(/>rollback<\/a>]/)) return;

        if (t.match(/<strong> \(/)) {
            var wp = new WikiPage(l[i].getElementsByTagName('a')[0].href);
            var url = rollback_mkUrl(wp,vandal);
            l[i].innerHTML += ' [<a href="' + url + '">' + rollbacklink + '</a>]';
        }
    }
}

function rollback_Load() {
    rollback_Revert();
    rollback_AddButtonDiff();
    rollback_AddButtonContributions();
}

addOnloadHook(rollback_Load);

// </nowiki></pre>







// User:Quarl/autoafd.js

// requires: wikipage.js, addilink.js
// enhanced by: advanced_sig.js

// TODO: merge with afd_helper's version that uses automod.js?
// TODO: auto-submit the tag and log pages?

// TODO: allow afd from non-edit page

// TODO: only allow from project space

// TODO: just open the [[AFD/article]] page, and asynchronously submit the other two.

// <pre><nowiki>

if(typeof window.makeSignature=='undefined')makeSignature=function(){return "~~~~"};

function autoafd()
{
  document.editform.wpTextbox1.value = '{{subst:afd}}\n' + document.editform.wpTextbox1.value;
  document.editform.wpSummary.value = 'Nominate for AFD';

  var wpAFD = new WikiPage(null,'Wikipedia:Articles for deletion/'+wikiPage.article);

  window.open(wpAFD.qurl + '&action=edit&fakeaction=afdsub&faketarget=' + escape(wikiPage.page),
              'Afd ' + wikiPage.page,
              'status,toolbar,location,menubar,directories,resizeable,scrollbars');

  var wpLog = new WikiPage(null,'Wikipedia:Articles_for_deletion/Log/' + datestampYYYYMonthD());

  window.open(wpLog.qurl + '&action=edit&fakeaction=afdlist&faketarget=' + escape(wikiPage.article),
              'AfdLog ' + wikiPage.page,
              'status,toolbar,location,menubar,directories,resizeable,scrollbars');
}

function autoafdEntry()
{
  if (editingP)
    {
      var action = queryVars['fakeaction'];
      var target = queryVars['faketarget'];

      if (action == 'afdlist')
        {
          document.editform.wpTextbox1.value += '{{' + 'Wikipedia:Articles for deletion/' + target + '}}\n';
          document.editform.wpSummary.value = '[[Wikipedia:Articles for deletion/' + target + ']]';
        }
      else if (action == 'afdsub')
        {
          if (document.editform.wpTextbox1.value.length > 0)
            {
              window.alert("There's an old AFD at the default location already.\n\n" +
                           'Please either move it out of the way (and update existing links to it), or file the afd by hand in another location (such as [[' + wikiPage.page + ' (2)]]).');
            }
          else
            document.editform.wpTextbox1.value += '===[[' + target + ']]===\n' +
              "Nomination.  '''Delete''' " + makeSignature() + "\n*\n*\n*\n";
        }
      else if (wikiPage.nsMainP)
        addTab('javascript:autoafd()', 'Afd', 'ca-autoafd', 'Nominate for deletion');
    }
}

addOnloadHook(autoafdEntry);

// </nowiki></pre>






// User:Quarl/afd_helper.js, based on User:Jnothman/afd_helper.js

// requires: automod.js, wikipage.js, util.js, datestamp.js
// enhanced by: advanced_sig.js

// based on http://en.wikipedia.org/wiki/User:Jnothman/afd_helper/script.js
// [[User:Jnothman/afd_helper/script.js]]

//  - huge list of shortcut expansions and other shortcut features
//  - more "vote" buttons such as in original article
//  - escaping bugs ('&&', '+', etc) fixed
//  - refuse to create AFD pages (in case of more escaping bugs)

//<pre><nowiki>

if(typeof window.makeSignature=='undefined')makeSignature=function(){return "~~~~"};

/************* afd Helper ************/
// see User:Jnothman/afd_helper

afdh_summaryprompt = true;

afdh_vote_shortcuts = Array();
afdh_vote_shortcuts['D']   = 'Delete';
afdh_vote_shortcuts['DA']  = 'Delete all';
afdh_vote_shortcuts['K']   = 'Keep';
afdh_vote_shortcuts['M']   = 'Merge';
afdh_vote_shortcuts['MV']  = 'Move';
afdh_vote_shortcuts['R,RD']   = 'Redirect';
afdh_vote_shortcuts['RW']  = 'Rewrite';
afdh_vote_shortcuts['T']   = 'Transwiki';
afdh_vote_shortcuts['WD']  = 'Weak delete';
afdh_vote_shortcuts['SD']  = 'Strong delete';
afdh_vote_shortcuts['SP']  = 'Speedy delete';
afdh_vote_shortcuts['SK']  = 'Strong keep';
afdh_vote_shortcuts['SM']  = 'Slight merge';
afdh_vote_shortcuts['WK']  = 'Weak keep';
//afdh_vote_shortcuts['SPK'] = '[[Wikipedia:Speedy keep|Speedy keep]]';
afdh_vote_shortcuts['SPK'] = 'Speedy keep';
afdh_vote_shortcuts['C']   = 'Comment';
afdh_vote_shortcuts['MC']  = 'Metacomment';
afdh_vote_shortcuts['BJAODN,BJ'] = 'BJAODN'; // avoids querying for summary

// If the subsitution ends with a space, it is not displayed in the alert box.
// The spaces are removed before posting.
afdh_comment_shortcuts = Array();
afdh_comment_shortcuts['PN']                         = 'per nomination';
afdh_comment_shortcuts['NN']                         = '[[WP:N|non-notable]]';
afdh_comment_shortcuts['V,VAIN,VANITY']              = '[[WP:VAIN|vanity]]';
afdh_comment_shortcuts['NNBIO']                      = '[[WP:BIO|non-notable biography]]';
afdh_comment_shortcuts['NNVBIO']                     = '[[WP:BIO|non-notable vanity biography]]';
afdh_comment_shortcuts['NNWEB']                      = '[[WP:WEB|non-notable website]]';
afdh_comment_shortcuts['NNWEBCOMIC ']                = '[[WP:WEB|non-notable webcomic]]';
afdh_comment_shortcuts['NNBLOG,NNWEBLOG']            = '[[WP:WEB|non-notable weblog]] ';
afdh_comment_shortcuts['NNFORUM','NNWEBFORUM']       = '[[WP:WEB|non-notable web forum]] ';
afdh_comment_shortcuts['NNCORP,NNCOMPANY']           = '[[WP:CORP|non-notable corporation]]';
afdh_comment_shortcuts['NNMUSIC']                    = '[[WP:MUSIC|non-notable musical group]]';
afdh_comment_shortcuts['NNBAND']                     = '[[WP:MUSIC|non-notable band]]';
afdh_comment_shortcuts['NNUNEO']                     = '[[Wikipedia:Avoid_neologisms|non-notable unstable neologism, i.e. protologism]]';
afdh_comment_shortcuts['NNUUNEO']                    = '[[Wikipedia:Avoid_neologisms|non-notable unverifiable unstable neologism, i.e. protologism]]';
afdh_comment_shortcuts['NNFICT,NNFICTION']           = '[[WP:FICT|non-notable reference to fictional work]]';
afdh_comment_shortcuts['NNFICTC,NNFICTCHAR,NNCHAR']  = '[[WP:FICT|non-notable character from fictional work]] ';
afdh_comment_shortcuts['FANCRUFT,NNFAN']             = '[[Wikipedia:Fancruft|fancruft]]';
afdh_comment_shortcuts['NNFANFIC']                   = '[[Wikipedia:Fancruft|non-notable fan fiction]]';
afdh_comment_shortcuts['NNGAME']                     = '[[WP:N|non-notable]] online gaming group';
afdh_comment_shortcuts['U']                          = '[[WP:V|unverifiable]]';
afdh_comment_shortcuts['UPH']                        = '[[WP:V|unverifiable]], possible [[WP:HOAX|hoax]]';
afdh_comment_shortcuts['OR']                         = '[[WP:NOR|original research]]';
afdh_comment_shortcuts['UOR']                        = '[[WP:V|unverifiable]] and/or [[WP:NOR|original research]]';
afdh_comment_shortcuts['H']                          = '[[WP:HOAX|hoax]]';
afdh_comment_shortcuts['HSANC,HSANCT,HSANCTION']     = '[[WP:HOAX|hoax]], and sanction article author';
afdh_comment_shortcuts['ATTACK']                     = '[[WP:CSD|attack page]]';
afdh_comment_shortcuts['WISHSP,WISHEXPAND']          = 'I wish for expansion of [[WP:CSD]] so that this kind of article could be speedy-deleted when no notability is asserted ';
afdh_comment_shortcuts['NOT']                        = '[[WP:NOT|Wikipedia is not]]';
afdh_comment_shortcuts['NOTADVERT']                  = '[[WP:NOT|Wikipedia is not a vehicle for advertising]] ';
afdh_comment_shortcuts['NOTBALL,NOTCRYSTAL']         = '[[WP:NOT|Wikipedia is not a crystal ball]] ';
afdh_comment_shortcuts['NOTCRUFT']                   = '[[WP:NOT|Wikipedia is not an indiscriminate collection of information]] ';
afdh_comment_shortcuts['NOTDICT,NOTDIC']             = '[[WP:NOT|Wikipedia is not a dictionary]] (but [[Wiktionary]] is) ';
afdh_comment_shortcuts['NOTMEMORIAL']                = '[[WP:NOT|Wikipedia is not a memorial]] ';
afdh_comment_shortcuts['NOTOR,NOTORIGINAL']          = '[[WP:NOT|Wikipedia is not a publisher of original thought]] ';
afdh_comment_shortcuts['NOTSOAPBOX']                 = '[[WP:NOT|Wikipedia is not a soapbox]] ';
afdh_comment_shortcuts['NOTSW,NOTSWDIR']             = '[[WP:NOT|Wikipedia is not a software directory]] ';
afdh_comment_shortcuts['NOTWEBHOST,NOTFREEHOST']     = '[[WP:NOT|Wikipedia is not a free host or webspace provider]] ';
afdh_comment_shortcuts['NOTWEBDIR']                  = '[[WP:NOT|Wikipedia is not a web directory]] ';
afdh_comment_shortcuts['NFT,NOTSCHDAY,NOTSCH,NOT1SCHDAY,NOT1DAY'] = '[[WP:NFT|Wikipedia is not for things made up in school one day]] ';
afdh_comment_shortcuts['XBIO,BIOX']                  = 'Recommend the article author see [http://www.wikime.org/ WikiMe] for writing biographies and/or [http://www.wikitree.org WikiTree] for writing genealogies ';
afdh_comment_shortcuts['XUSERFY,USERFYX']            = 'Article author may want to consider moving the content to his [[Wikipedia:User page|user page]] ';
afdh_comment_shortcuts['XPROTO,XPROTOLOGISM,PROTOX'] = 'Protologisms may deserve listing at [[Wiktionary:List_of_protologisms]] ';
afdh_comment_shortcuts['BALLS,BALL'] = '[[WP:BALLS|Complete bollocks]]';

function afdh_expand_shortcuts(input) {
    var result = new Array();
    for (k in input) {
        var keys = k.split(',');
        result[keys[0]] = input[k];
        for (var i=1; i < keys.length; ++i) {
            result[keys[i]] = input[k] + ' ';
        }
    }
    return result;
}

afdh_vote_shortcuts = afdh_expand_shortcuts(afdh_vote_shortcuts);
afdh_comment_shortcuts = afdh_expand_shortcuts(afdh_comment_shortcuts);


function copyArray(a) {
    var r = new Array();
    for (var i=0; i < a.length; i++)
        r[i] = a[i];
    return r;
}

function afd_helper() {
    if (wikiPage.page.match(/^Wikipedia:Articles for deletion\//)) {

        if (!wikiPage.page.match(/^Wikipedia:Articles for deletion\/Log/)) {
            addTab('javascript:afd_vote_this_page()', 'vote', 'ca-vote', "Vote on this AFD");
        }

        afd_annotate_afd();
    } else {
        afd_annotate_article();

        if (wikiPage.nsMainP) 
            addToolboxLink('javascript:afd_nominate()', 'Nominate AFD', '', 'Nominate this article for deletion');
    }
}

function afd_annotate_article() {
    // is this a regular article that has an AFD notice?

    var afd = document.getElementById('afd');
    if (!afd) return;

    var href = 'javascript:afd_vote_this_page()';
    var anchors = copyArray(afd.getElementsByTagName('a'));

    for (i in anchors) {
        if (anchors[i].text == "this article's entry" &&
            anchors[i].href.match(/Wikipedia:Articles_for_deletion\/.*/))
        {
            add_after(anchors[i], document.createTextNode("] "));
            add_after(anchors[i], afdh_create_vote_link(getPname(), href));
            add_after(anchors[i], document.createTextNode(" ["));
            break;
        }
    }

    addTab(href, 'vote', 'ca-vote', 'Vote on AFD for this page');
}

function afd_annotate_afd() {
    var anchors = copyArray(document.getElementById('bodyContent').getElementsByTagName('a'));

    var url_re = /(\/w\/index.php\?title=Wikipedia:Articles_for_deletion\/([^&]+))&action=edit&/;
    var url, matches;
    for (var i=0; i < anchors.length; i++) {
        if (!( anchors[i].text == "edit"
               && (matches = anchors[i].href.match(url_re))
               && (matches[2].substr(0, 4) != 'Log/')) )
            continue;
        var afd_href = matches[1];
        var title = ""+unescape(matches[2]).replace(/_/g,' ');
        var vote_href = "javascript:afd_vote_page("+string_quote_escape(title)+")";
        add_after(anchors[i], afdh_create_vote_link(title, vote_href));
        add_after(anchors[i], document.createTextNode("] ["));
        add_before(anchors[i], afdh_create_afd_link(title, afd_href));
        add_before(anchors[i], document.createTextNode("] ["));
    }
}

function afdh_create_vote_link(title, href) {
    var a = document.createElement('a');
    a.href = href;
    a.title = "Vote on deletion of "+title;
    a.appendChild(document.createTextNode('vote'));

    //var sup = document.createElement('sup');
    //sup.appendChild(a);

    return a;
}

function afdh_create_afd_link(title, href) {
    var a = document.createElement('a');
    a.href = href;
    a.title = title;
    a.appendChild(document.createTextNode('afd'));
    return a;
}

function shortcut_msg(shortcuts) {
    var msg = 'Shortcuts available:\n';
    for (var key in shortcuts) {
        if (shortcuts[key].match(/ $/)) continue;
        msg += key + ': ' + shortcuts[key] + '\n';
    }
    return msg;
}

/* This version replaces only the first word and doesn't require uppercase */
function subst_shortcut1(msg,shortcuts) {
    if (!msg) return msg;
    var m = msg.match(/^([a-zA-Z]+)(.*)$/);
    if (m) {
        return subst_word(m[1],shortcuts) + m[2];
    }
    return msg;
}

function subst_word(word,shortcuts) {
    return trimspaces(shortcuts[word.toUpperCase()]) || word;
}

/* This version replaces all uppercase words */
function subst_shortcut(msg,shortcuts) {
    if (!msg) return msg;
    var ret = '';
    var m;
    while (msg && (m = msg.match(/^(.*?)\b([A-Z]+)\b(.*)$/)) ) {
        ret += m[1] + subst_word(m[2],shortcuts);
        msg = m[3];
    }

    ret += msg;
    return ret;
}

// return true if string ends with period (can also have symbols such as closing paren after period)
function ends_with_period(str) {
    return Boolean(str.match(/[.?!][^a-zA-Z]*$/));
}

// return true if comment needs to be prefixed by 'as '
function afdh_comment_needs_as(comment) {
    var m = comment.match(/^([a-zA-Z]+)(.*)$/);
    if (!m) return false;
    if (m[1] == 'or') return false; // special case for 'or'
    var word1 = m[1].toUpperCase();
    return Boolean(word1 != 'PN' && afdh_comment_shortcuts[word1]);
}

function afdh_expand_vote(vote) {
    vote = subst_shortcut(vote, afdh_vote_shortcuts);
    vote = subst_shortcut1(vote, afdh_vote_shortcuts);
    return vote;
}

function afdh_expand_comment(vote, comment) {
    // if first word is a shortcut other than 'per nomination', prefix with 'as'

    var need_as = afdh_comment_needs_as(comment);

    comment = subst_shortcut(comment,afdh_comment_shortcuts);
    if (!comment.match(/^or /)) {
        // "or" is too common as first word... use uppercase "OR" if that's intended.
        comment = subst_shortcut1(comment,afdh_comment_shortcuts);
    }

    if (need_as) {
        comment = 'as ' + comment;
    }

    if (!ends_with_period(comment)) {
        comment += ".";
    }

    // prefix with space if necessary
    if (!comment.match(/^[.,:; ]/)) {
        comment = " " + comment;
        if (vote == 'Comment') comment = ":" + comment;
    }

    return comment;
}

function afdh_comment_possibly_unexpanded(comment) {
    // did user typo one of the shortcuts?
    return comment.match(/[A-Z][A-Z][A-Z]+(?![\]A-Z\|])/);
}

function afd_vote_this_page() {
    afd_vote_page(wikiPage.page);
}

function afd_vote_page(page) {
    if (!page.match(/^Wikipedia:Articles.for.deletion\//)) {
        if (page.match(/:/)) { alert("Bad page name: '"+page+"'"); return; }
        page = 'Wikipedia:Articles for deletion/' + page;
    }
    afd_vote(new WikiPage(null,page));
}

function afd_vote(wp) {
    var vote0 = window.prompt("Enter your vote.   " + shortcut_msg(afdh_vote_shortcuts));
    if (!vote0) return;
    var vote = afdh_expand_vote(vote0);
    var vote_used_shortcut = (vote != vote0);

    var comment0prev;
    var comment0 = '';
    var comment;
    var pr = "Enter your comment.  ";

    while(true) {
        comment0 = window.prompt(pr + shortcut_msg(afdh_comment_shortcuts), comment0);
        if (typeof comment0 != 'string') return;
        comment = afdh_expand_comment(vote, comment0);

        if (comment0 != comment0prev &&
            afdh_comment_possibly_unexpanded(comment))
        {
            comment0prev = comment0;
            pr = "Did you really mean '"+RegExp.lastMatch+"'?  Correct if you want.  ";
            continue;
        }
        break;
    }

    var default_summary = "vote '"+vote+"'";
    var summary;

    if (afdh_summaryprompt && !vote_used_shortcut) {
        summary = window.prompt("Enter the edit summary:", default_summary);
        if (typeof summary != 'string') return;
    }
    summary = summary || default_summary;

    var newtext = "* '''"+vote+"'''"+comment+" " + makeSignature();

    var url = wp.qurl + '&action=edit' + '&amaddafter='+escape(newtext) + '&amsummary='+escape(summary) + '&amnocreate=1';

    // are we at a log page?  (Note that 'window.location.href' is not as good as wikiPage because of shortcut redirects such as [[WP:AFD/Today]])
    if (wikiPage.page.match(/\/Log\//))
        window.open(url, "afd_helper_vote");
    else
        window.location.href = url;
}

function afd_nominate() {
    var title = wikiPage.page;
    var log_date = datestampYYYYMonthD();
    var reason = window.prompt("Please justify your AFD nomination of "+title+":");
    if (!reason)
        return;
    window.open(am_make_url(title, '{{'+'subst:afd}}', '', 'nomination for [[WP:AFD|deletion]]'), 'afdhn1');
    window.open(am_make_url('Wikipedia:Articles for deletion/Log/'+log_date, '', '{{'+'subst:afd3|pg='+title+'}}', 'Nominating [['+title+']] for deletion'), 'afdhn3');
    window.location.href = am_make_url('Wikipedia:Articles for deletion/'+title, '', '{{'+'subst:afd2|pg='+title+'|text='+reason+' '+makeSignature()+'}}', 'nominated for deletion');
}

addOnloadHook(afd_helper);

//</nowiki></pre>








// User:Quarl/autotag.js - automatically add custom tags to article

// requires: wikipage.js, automod.js, addlilink.js, datetime.js

// quarl 2006-01-03 initial version

//<pre><nowiki>

// TODO: sort the tags by this order (note that these are primary names of tags since they all have many aliases;
// subsituted tags such as afd are tricky; support piped data such as db|reason)

//autotag_order = 'delete,afd,hoax,original research,npov,cleanup,importance'.split(',');

//autotag_mark_minor = false;

function autotag_load() {
    if (wikiPage.nsSpecialP) return;

    if (auto_mod()) return;

    addTab('javascript:autotag_query()', 'tag', 'ca-autotag', "Add tag(s)");
}

function autotag_query() {
    var tags = window.prompt("Enter tags to add, separated by commas. Example: hoax, not verified, original research, npov, mergeto|another article, cleanup");
    autotag(tags);
}

function autotag_iscat(s) {
    return Boolean(s.match(/^category:/i));
}

function autotag_remove_braces(s) {
    // remove any brackets or braces
    s = s.replace(/^\{\{(.*)\}\}$/, '$1');
    s = s.replace(/^\[\[(.*)\]\]$/, '$1');
    return s;
}

function autotag_add_braces(s) {
    if (autotag_iscat(s)) {
        return '[['+s+']]';
    } else {
        return '{{'+s+'}}';
    }
}

function autotag_expand_shortcuts(s) {
    // TODO: write expansions in dialog box
    // TODO: more expansions
    if (s == 'cleanup') s = 'cleanup-date|' + datestampMonthYYYY();
    if (s == 'or') s = 'original research';
    s = s.replace(/^cat:/i, 'Category:');
    return s;
}

function autotag_tagAtTopP(t) {
    if (autotag_iscat(t)) return false;
    if (t.match(/stub$/)) return false; 
    return true;
}

function autotag(tags) {
    tags = tags.split(',');
    var ntags = Array();
    var ttags = Array();
    var ttags_top = Array();
    var ttags_bot = Array();
    for (i in tags) {
        var tag = tags[i];
        tag = autotag_expand_shortcuts(autotag_remove_braces(trimspaces(tag)));
        if (!tag) continue;
        var btag = autotag_add_braces(tag);
        ntags.push(tag);
        ttags.push(btag);
        if (autotag_tagAtTopP(tag)) {
            ttags_top.push(btag);
        } else {
            ttags_bot.push(btag);
        }
    }
    if (!ntags.length) return;

    var summary = 'Tagged as ' + ttags.join(', ');

    // for now, just add all tags before article.  TODO: sort them accordingly, e.g. after AFD notice.
    var newtext_top = ttags_top.join("\n\n")+'\n';
    var newtext_bot = ttags_bot.join("\n\n")+'\n';
    var url = am_make_url(getPname(), newtext_top, newtext_bot, summary);

    window.location.href = url + '&amnocreate=t';
}

addOnloadHook(autotag_load);

//</nowiki></pre>





// User:Quarl/autocopyvio.js - add copyvio tag and add entry to 'copyright problems' page

// requires: wikipage.js, addlilink.js

// based on http://en.wikipedia.org/wiki/Wikipedia:WikiProject_User_scripts/Scripts/Autocopyvio.js
  // AutoCopyvio - Adds copyright violation notice to article and adds entry to Copyright Problems page
  // Created by Bmicomp from modified AutoVFD(by Korath)

// <pre><nowiki>
  
  function copyvio()
  {
    document.editform.wpTextbox1.value = '{' + '{' + 'copyvio|url=}}';
    document.editform.wpSummary.value = 'copyvio';

    var wpLog = new WikiPage(null,'Wikipedia:Copyright problems/' + datestampYYYYMonthD());

    window.open(wpLog.qurl + '&action=edit&fakeaction=copyviolist&faketarget=' + escape(wikiPage.article), 'status,toolbar,location,menubar,directories,resizeable,scrollbars');
  }
  
  function autocopyvio()
  {
    if (editingP)
      {
        if (queryVars['fakeaction'] == 'copyviolist')
          {
              var target = queryVars['faketarget'];
              document.editform.wpTextbox1.value += '*[[' + target + ']] <span class="plainlinks">([http://en.wikipedia.org/{{localurl:' + target + '|action=history}} history] · [http://en.wikipedia.org/{{localurl:' + target + '|diff=0}} last edit])</span>' + ' from [' + '] ~' + '~~' + '~';
              document.editform.wpSummary.value = 'Copyvio ' + '[[' + target + ']]';
          }
        else
          addTab('javascript:copyvio()', 'copyvio', 'ca-copyvio', 'Tag for copyright violation');
      }
  }
  
  addOnloadHook(autocopyvio)
 /**/

// </nowiki></pre>




// User:Quarl/edit_top_link.js

// requires: wikipage.js

// based on http://en.wikipedia.org/wiki/Wikipedia:WikiProject_User_scripts/Scripts/Add_Edit_Top_Link

// This will add an [edit top] link at the top of all pages except preview pages
// by User:Pile0nades

function editTopLink() {
  // if this is preview page or generated page, stop
  if (previewP || wikiPage.nsSpecialP) return;

  // get the page title
  var pageTitle = wikiPage.page;
  var editURL = wikiPage.qurl + '&action=edit&section=0';

  // create div and set innerHTML to link
  var divContainer = document.createElement("div");
  divContainer.innerHTML = '<div class="editsection" style="float:right;margin-left:5px;margin-top:3px;">[<a href="'+editURL+' title="'+pageTitle+'">edit top</a>]</div>';

  // insert divContainer into the DOM before the h1
  document.getElementById("content").insertBefore(divContainer, document.getElementsByTagName("h1")[0]);
}

addOnloadHook(editTopLink);




// User:Quarl/show_diff_since.js - add 'since' tab to show change since I last edited
//    Compared to JesseW's, this is an asynchronous version that doesn't first open the history page

// requires: wikipage.js, addlilink.js

// based on http://en.wikipedia.org/wiki/Wikipedia:WikiProject_User_scripts/Scripts/Changes_since_I_last_edited
// from http://en.wikipedia.org/w/index.php?title=User:JesseW/monobook.js&oldid=20755510

// quarl 2006-01-16 rewritten to asynchronously download history page

// <pre><nowiki>

function addTab_DiffSince() {
    if (wikiPage.nsSpecialP) return;

    var url;
    if (historyP) {
        // already looking at history page
        url = 'javascript:show_diff_since_thisHistoryPage()';
    } else {
        // not yet a history page -- asynchronously download it first
        url = 'javascript:show_diff_since_thisPage()';
    }

    addTab(url, 'since', 'ca-since', "Show changes since I last edited");
}

function show_diff_since_thisPage() {
    show_diff_since(wikiPage, document.getElementById('ca-since'), ' <b>since...</b> ');
}

function show_diff_since(wp, statusnode, statustext) {
    var url = wp.qurl + '&action=history';
    var req = new XMLHttpRequest();

    if (statusnode) {
        // change the button to show the user we're doing something and prevent another click
        req.statusnode = statusnode;
        req.save_text = statusnode.innerHTML;
        statusnode.innerHTML = statustext;
    }

    req.onload = show_diff_since_handleHistoryPage;
    req.overrideMimeType('text/xml');
    req.open("GET", url, true);
    req.send(null);
}

function show_diff_since_handleHistoryPage(event) {
    var req = event.target;
    if (req.readyState == 4) {
        // restore button in case this fails, so user can click again
        if (req.statusnode) {
            req.statusnode.innerHTML = req.save_text;
        }

        if (req.status == 200) {
            show_diff_since_examineTree(req.responseXML);
        } else {
            alert("Error downloading history page!");
        }
    }
}

function show_diff_since_thisHistoryPage() {
    show_diff_since_examineTree(document);
}

function show_diff_since_examineTree(doc) {
    if (!doc) { alert ("## no doc?!"); return; }
    var hists = doc.getElementById("pagehistory").childNodes;
    if (!hists) { alert("Couldn't parse history from page"); return; }
    for (n=0;n<hists.length;n++) {
        // window.username is defined in wikipage.js
        if (hists[n].getElementsByTagName && hists[n].getElementsByTagName("span")[0].textContent==window.username) {
            document.location = hists[n].childNodes[1].href; 
            return;
        }
    }

    alert("Couldn't find your entry in the history page!");
    // TODO: perhaps retry with a larger limit
}

addOnloadHook(addTab_DiffSince);

// </nowiki></pre>






// User:Quarl/show_diff_last.js - add "last" tab to do most recent diff

// requres: wikipage.js, addlilink.js

// based on http://en.wikipedia.org/wiki/Wikipedia:WikiProject_User_scripts/Scripts/Show_last_diff

// based on raylu's abbreviation of http://en.wikipedia.org/w/index.php?title=User:JesseW/monobook.js&oldid=20755510

// <pre>

function addTab_DiffLast() {
    if (wikiPage.nsSpecialP) return;

    var nurl = wikiPage.qurl + "&diff=cur&oldid=prev";
    addTab(nurl, 'last', 'ca-last', "Show most recent diff");
}

addOnloadHook(addTab_DiffLast);

// </pre>





// User:Quarl/auto_testn.js - adds "tN" tabs for autotagging 'test'.

// requires wikipage.js, automod.js, addilink.js
// enhanced by: advanced_sig.js

// based on http://en.wikipedia.org/wiki/Wikipedia:WikiProject_User_scripts/Scripts/test-n.js
//    Can be used from non-edit pages, and automatically submits the changes.

// <pre><nowiki>

if(typeof window.makeSignature=='undefined')makeSignature=function(){return "~~~~"};

function testn(number)
{
    var page = prompt("Vandalism to which article? (Empty to use {{test}} instead of {{test-n}})")
    if (typeof page != 'string') return;

    var text; var summary;

    if (page) {
        text = '{{subst:' + 'test' + number + '-n|' + page + '}} ';
        summary = "Vandalism to [[" + page + "]] - warning " + number;
    } else {
        text = '{{subst:' + 'test' + number + '}} ';
        summary = "Vandalism - warning " + number;
    }
    text = '\n\n' + text + ' ' + makeSignature() + '\n\n';

    url = am_make_url(wikiPage.page, '', text, summary);
    window.location.href = url;
}

function auto_testn_init() {
    if (auto_mod()) return false;

    // Only add tab to User talk pages.
    if (wikiPage.namespace != 'User talk') return;

    // don't bother with subpages
    if (wikiPage.article.match('/')) return;

    auto_testn_addTabs();
}

function auto_testn_addTabs()
{
    var tabs = getTabActions();
    addlilink(tabs,'javascript:testn("1")',"t1",'testn1','Vandalism warning 1');
    addlilink(tabs,'javascript:testn("2")',"t2",'testn2','Vandalism warning 2');
    addlilink(tabs,'javascript:testn("2a")',"t2a",'testn2a','Vandalism warning 2a');
    addlilink(tabs,'javascript:testn("3")',"t3",'testn3','Vandalism warning 3');
    addlilink(tabs,'javascript:testn("4")',"t4",'testn4','Vandalism warning 4');
}

addOnloadHook(auto_testn_init);

//

// </nowiki></pre>






// User:Quarl/hide_own.js - change the "my watchlist" navigation button to default to hide own.

// based on http://en.wikipedia.org/wiki/Wikipedia:WikiProject_User_scripts/Scripts/hideOwn.js

// <pre><nowiki>

function hideOwn () {
  for (var i=0; i<document.links.length; ++i) {
    l = document.links[i];
    // note: text *is* capitalized in source, but rendered lowercase
    if (l.text == 'My watchlist' && l.href.indexOf('Special:Watchlist')>0) {
      l.href+='?hideOwn=1';
      break;
    }
  }
}

addOnloadHook(hideOwn);

// </nowiki></pre>







// User:Quarl/unwatch.js

// add 'un' links to unwatch directly from watchlist.  Do so asynchronously and modify current page by crossing out the unwatched page.

// quarl 2006-01-09 added asynchronous feature.

// requires: wikipage.js, util.js

// originally based on http://en.wikipedia.org/wiki/User:Omegatron/monobook.js
// see also http://en.wikipedia.org/wiki/User:Matthewmayer/monobook.js

// Workaround for Bug 424 http://bugzilla.wikipedia.org/show_bug.cgi?id=424

// TODO: make the normal watch&unwatch tabs AJAX too!

// <pre><nowiki>

// if true, then clicking 'un' uses AJAX to unwatch without opening a new window/tab.
// if false, it is a regular hyperlink (use middle-click to open new tab).
var unwatchAsynchronously = true;

function unwatchMakeUrl(wp) {
    return wp.qurl + '&action=unwatch';
}

function unwatchMakeLink(wp) {
    if (!wp) return "";
    wp = wp.notalkPage();
    if (unwatchAsynchronously) {
        return "javascript:unwatchAsync("+string_quote_escape(wp.page)+")";
    } else {
        return unwatchMakeUrl(article_title);
    }
}

function unwatchAsync(page) {
    var wp = new WikiPage(null, page);
    var url = unwatchMakeUrl(wp);
    asyncDownloadXML(url, unwatchRequestHelper, 'article_title', article_title);
}

function addStrikeThrough(node) {
    return insertNode(node, document.createElement('s'));
}

function unwatchRequestHelper(unwatchReq) {
    var m1; var m2;
    if ((unwatchReq.status == 200) && 
        (m1= unwatchReq.responseText.match(/The page "(.*?)" has been removed from your watchlist/)) &&
        (m2= unwatchReq.responseText.match(/<p>Return to <a href="(\/wiki\/[^"]+)"/)))
    {
        // for some reason, request.article_title is "null" randomly 10% of the time
        //var article = unwatchReq.article_title;
        //var article = unwatch_remove_talk_ns(m1[1]);

        var wp = new WikiPage(m2[1]);
        var qUrl1 = wp.notalkPage().url;
        var qUrl2 = wp.talkPage().url;

        var n1 = addStrikeThrough(findHref(pUrl1));
        var n2 = addStrikeThrough(findHref(pUrl2));
        if (!n1 && !n2) {
            alert("Unwatched article '"+wp.page+"', but couldn't annotate current page.");
            return;
        }
    } else {
        alert("Unwatch '"+unwatchReq.article_title+"'failed!");
    }
}


function unwatch_load(){
    if (wikiPage.page != "Special:Watchlist") return;

    var links = document.links;
    re = /action=history$/;
    for(i=0;i<links.length;++i) {
        var link = links[i];
        if (re.test(link.href)) {
            var wp = new WikiPage(link.href);
            var newUnwatchLink = document.createElement('a');
            newUnwatchLink.href = unwatchMakeLink(wp);
            newUnwatchLink.title = "Unwatch "+wp.page;
            newUnwatchLink.innerHTML = "un";
            add_after(link, newUnwatchLink);
            add_after(link, document.createTextNode("; "));
        }
    }
}

addOnloadHook(unwatch_load);

// </nowiki></pre>




// autofocus.js - Auto-focus the cursor to appropriate edit fields.

// Edit page: focus the main edit area.
// Move page: focus the new page title.

// quarl 2006-01-03 initial version

// requires: wikipage.js

function autofocus() {
    if (editingP && !previewP) {
        document.forms.editform.wpTextbox1.focus();
        return;
    }

    if (movepageP) {
        document.forms.movepage.wpNewTitle.focus();
        return;
    }
}

addOnloadHook(autofocus);





// requires: automod.js, addlilink.js, get_page_name.js, advanced_signature.js

// quarl 2006-01-04 initial version

//<pre><nowiki>

function autocloseafd_load() {
    if (auto_mod())
       return;

    if (getPname().indexOf('Wikipedia:Articles for deletion/')==0) {
        addTab('javascript:autoclose_query()', 'close', 'ca-autoclose', "Close this AFD discussion");
    }
}

function autoclose_query() {
    autoclose(window.prompt("Enter closing comment.  Example: '''Delete''' as non-notable band."));
}

function autoclose(comment) {
    if (!comment) return;

    var add_before = "{{subst:afd top}} " + comment + " " + makeSignature() + "\n\n";
    var add_after = "\n\n{{subst:afd bottom}}\n";

    var summary = 'AFD closed, result: ' + comment;

    url = am_make_url(getPname(), add_before, add_after, summary);
    window.location.href = url;
}

addOnloadHook(autocloseafd_load);

//</nowiki></pre>


// based on http://en.wikipedia.org/wiki/Wikipedia:WikiProject_User_scripts/Scripts/Logs_link

// adds a 'logs for this page' link to the navigation bar
// if the page is a user's page, talk page (but not subpage), the link will go to logs for the user instead
// if the page is a special page, then no link is displayed

// <pre><nowiki>

function addLogsLink() {
    var url;
    var show;
    if (wikiPage.nsUserP && !wikiPage.subarticle) {
        // if this is a user (and not a subpage), show the logs for the user rather than the page
        url = "http://en.wikipedia.org/w/index.php?title=Special%3ALog&user=" + wikiPage.article;
        show = "User " + wikiPage.article;
    } else if (wikiPage.nsSpecialP) {
        // don't display link for special pages
        return;
    } else {
        url = "http://en.wikipedia.org/w/index.php?title=Special%3ALog&page=" + wikiPage.page;
        show = wikiPage.page;
    }

    var title = "Show logs for " + show;
    addToolboxLink(url, "Logs", "pt-logs", title);
}

addOnloadHook(addLogsLink);

// </nowiki></pre>



// toolbox_afd.js - add AFD/Today and AFD/Yesterday links to Toolbox

// quarl 2006-01-03 initial version

// <pre><nowiki>

function addToolboxAFD() {
    addToolboxLink('/wiki/WP:AFD/Today', "AFD/Today", "pt-afd-today", "Show today's AFD log");
    addToolboxLink('/wiki/WP:AFD/Yesterday', "AFD/Yesterday", "pt-afd-yesterday", "Show yesterday's AFD log");
}

addOnloadHook(addToolboxAFD);

// </nowiki></pre>



// User:Quarl/alexafy.js - adds "alexa" links to external links

// requires addlilink.js, util.js

// quarl 2005-01-10 new AJAX version that annotates page asynchronously with rank

// I tried to create a version that automatically downloads the Alexa rank and annotates the page, but I think it's disallowed because it's not from the same domain.  So it would be impossible without a server-side helper script on en.wikipedia.org.

// based on http://en.wikipedia.org/wiki/User:Matthewmayer/monobook.js

//add Alexafy link to toolbar
function addToolboxAlexafy() { 
    addToolboxLink('javascript:alexafyLinks()','Alexa-fy links','alexafyLinks')
}

function alexafyWhitelistedP(url) {
    if (url.match(/wikipedia.org/)) return true;
    return false;
}

function alexafyLinks() {
    var content=document.getElementById('content');
    var externallinks=getElementsByClass('external',content,'a');
    for (i in externallinks) {
        var alink=externallinks[i];
        if (alexafyWhitelistedP(alink.href)) continue;

        alexafy_asyncAnnotateLink(alink);
    }
}

function alexafy_asyncAnnotateLink(alink) {
    var alexaUrl = makeAlexaTrafficUrl(alink.href);
    var dnode = document.createElement('span');
    dnode.innerHTML = ' [<a href="'+alexaUrl+'">Alexa</a>]';
    add_after(alink, dnode);

    // XXX this doesn't work because of permissions.  see top.
    //alexafy_asyncGetRank(dnode,alexaUrl);
}

function makeAlexaTrafficUrl(url) {
    return 'http://www.alexa.com/data/details/traffic_details?q=&url=' + url;
}

function alexafy_asyncGetRank(dnode, alexaUrl) {
    var req = new XMLHttpRequest();
    req.dnode = dnode;
    // using onload instead of onreadystatechange allows multiple asynchronous requests
    req.onload = alexafy_asyncReqCont;
    req.open("GET", alexaUrl, true);
    req.send(null);
}

function alexafy_asyncReqCont(event) {
    req = event.target;
    if (req.readyState!=4) return;
    if (req.status == 200) {
        if (req.responseText.match(/<span.*?Traffic Rank for\t*(.*?):<\/span><span.*?-->([0-9,]+)<\/span>/)) {
            var domain = RegExp.$1;
            var rank = RegExp.$2;
            alexafy_annotateDoc(req.dnode, domain, rank);
            return;
         //<span class="body"> Traffic Rank for  example.org:</span><span class="descBold">	&nbsp;<!--Did you know? Alexa offers this data programmatically.  Visit http://webservices.amazon.com/ for more information about the Alexa Web Information Service.-->123,456</span>
        }
        if (req.responseText.match(/<span.*?Traffic Rank for.*?No Data/)) {
            //<span class="body"> Traffic Rank for :</span>&nbsp;No Data<br>
            alexafy_annotateDoc(req.dnode, null, 'No data');
            return;
        }
    }
    alexafy_annotateDoc(req.dnode, null, 'Error');
}

function alexafy_annotateDoc(dnode, domain, rank)
{
    var msg;
    if (rank == 'Error') {
        msg = "couldn't get Alexa rank";
    } else if (rank == 'No data') {
        msg = "no traffic data";
    } else {
        msg = "traffic rank for "+domain+" is "+rank;
    }
    dnode.innerHTML = dnode.innerHTML.substr(0,dnode.innerHTML.length-1) + msg + "]";
}

addOnloadHook(addToolboxAlexafy);




// User:Quarl/userscript.js - utilities to help develop user scripts

// - adds "raw" tab to user script pages
// - adds "refresh" tab to user script pages (refresh the raw script)

// - TODO: automatically refreshes the raw version when you save a user script page

// requires wikipage.js, addlilink.js

// quarl 2006-01-10 initial version

function userscriptMakeUrl(wp) {
    // note: wp.qurl is parsed from source and is not the same as blindly escaping the input!  String
    // has to exactly match what the user is using, e.g. "User:Quarl/script", not "User%3AQuarl/script"!
    return wp.qurl + '&action=raw&ctype=text/javascript&dontcountme=s';
}

function addTab_UserScriptRaw() {
    if (wikiPage.article.match(/[.]js$/)) {
        addTab(userscriptMakeUrl(wikiPage), 'raw', 'ca-raw', "Show raw version of user script");
    }
}

function addTab_UserScriptRefresh() {
    if (wikiPage.article.match(/[.]js$/)) {
        addTab('javascript:userscript_DoRefresh()', 'refresh', 'ca-refresh', "Force browser to refresh the raw version of this script");
    }
}

/*function userscript_AutoRefresh_Load() {
    if (queryVars['refresh'] == 'userscript') {
        userscript_DoRefresh();
    }
    userscript_ModifyPageRefreshOnSave();
}*/

function userscript_DoRefresh() {
    force_refresh(userscriptMakeUrl(wikiPage));
}

function force_refresh(url) {
    // We can't do frm.location.reload() right now because frm.location will still be "about:blank", but if we complete this event and start a new one, it works.

    //frm.location.replace(url);
    //frm.location.href = url;
    document.getElementById('userscript_refresher').src = url;
    setTimeout('force_refresh_cont_1()', 0);
}

function force_refresh_cont_1() {
    var frm = window.frames['userscript_refresher'];
    frm.location.reload();
}

/*function userscript_ModifyPageRefreshOnSave() {
    document.editform.action += '&refresh=userscript';
}*/

addOnloadHook(addTab_UserScriptRaw);
addOnloadHook(addTab_UserScriptRefresh);
//addOnloadHook(userscript_AutoRefresh_Load);

// hidden iframe
document.write('<div style="position:absolute;left:0px;top:0px;visibility:hidden;" id="hidden_userscript_iframe_div"><iframe src="about:blank" height="0" width="0" name="userscript_refresher" id="userscript_refresher"></iframe></div>');





// User:Quarl/newmessages.js - change the "You have new messages" alert to add "diff since" and "hist" links.

// requires: wikipage.js, show_diff_since.js, util.js

// quarl 2006-01-16 initial version

// <pre><nowiki>

function newmessages_Load() {
    var talkmessagebox = getElementsByClass('usermessage',document.getElementById('bodyContent'),'div')[0];
    if (!talkmessagebox || talkmessagebox.textContent != "You have new messages (diff).") return;

    var wpTalk = window.wpTalk = new WikiPage(null,'User talk:' + window.username);
    var histUrl = wpTalk.qurl + '&action=history';

    talkmessagebox.className += ' plainlinks';

    var t = ' (<span id="newmessages-diffsince"><a href="javascript:newmessages_show_diff_since()">diff since</a></span>)' + 
            ' (<a href="'+histUrl+'">history</a>)';

    // insert before final period
    talkmessagebox.innerHTML = talkmessagebox.innerHTML.replace(/(?=[.]$)/, t);
}

function newmessages_show_diff_since() {
    show_diff_since(wpTalk, document.getElementById('newmessages-diffsince'), '<b>diff since...</b>');
}

addOnloadHook(newmessages_Load);

// </nowki></pre></nowiki></pre>





// <pre>

function LZ(x) { return (x>=10||x<0?"":"0") + x }

function datestampUTCISO() {
    var d=new Date();
    return ""+d.getUTCFullYear()+"-"+LZ(d.getUTCMonth()+1)+"-"+LZ(d.getUTCDate());
}

function timestampUTCISO() {
    var d=new Date();
    return LZ(d.getUTCHours())+":"+LZ(d.getUTCMinutes());
}

monthnames = new Array( "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");

function datestampYYYYMonthD() {
    var d = new Date();
    return ""+d.getUTCFullYear() + ' ' + monthnames[d.getUTCMonth()] + ' ' + d.getUTCDate();
}

function datestampMonthYYYY() {
    var d = new Date();
    return ""+monthnames[d.getUTCMonth()] + ' ' + d.getUTCFullYear();
}

//</pre>



// User:Quarl/autotag.js - automatically add custom tags to article

// requires: wikipage.js, automod.js, addlilink.js, datetime.js

// quarl 2006-01-03 initial version

//<pre><nowiki>

// TODO: sort the tags by this order (note that these are primary names of tags since they all have many aliases;
// subsituted tags such as afd are tricky; support piped data such as db|reason)

//autotag_order = 'delete,afd,hoax,original research,npov,cleanup,importance'.split(',');

//autotag_mark_minor = false;

function autotag_load() {
    if (wikiPage.nsSpecialP) return;

    if (auto_mod()) return;

    addTab('javascript:autotag_query()', 'tag', 'ca-autotag', "Add tag(s)");
}

function autotag_query() {
    var tags = window.prompt("Enter tags to add, separated by commas. Example: hoax, not verified, original research, npov, mergeto|another article, cleanup");
    autotag(tags);
}

function autotag_iscat(s) {
    return Boolean(s.match(/^category:/i));
}

function autotag_remove_braces(s) {
    // remove any brackets or braces
    s = s.replace(/^\{\{(.*)\}\}$/, '$1');
    s = s.replace(/^\[\[(.*)\]\]$/, '$1');
    return s;
}

function autotag_add_braces(s) {
    if (autotag_iscat(s)) {
        return '[['+s+']]';
    } else {
        return '{{'+s+'}}';
    }
}

function autotag_expand_shortcuts(s) {
    // TODO: write expansions in dialog box
    // TODO: more expansions
    if (s == 'cleanup') s = 'cleanup-date|' + datestampMonthYYYY();
    if (s == 'or') s = 'original research';
    s = s.replace(/^cat:/i, 'Category:');
    return s;
}

function autotag_tagAtTopP(t) {
    if (autotag_iscat(t)) return false;
    if (t.match(/stub$/)) return false; 
    return true;
}

function autotag(tags) {
    tags = tags.split(',');
    var ntags = Array();
    var ttags = Array();
    var ttags_top = Array();
    var ttags_bot = Array();
    for (i in tags) {
        var tag = tags[i];
        tag = autotag_expand_shortcuts(autotag_remove_braces(trimspaces(tag)));
        if (!tag) continue;
        var btag = autotag_add_braces(tag);
        ntags.push(tag);
        ttags.push(btag);
        if (autotag_tagAtTopP(tag)) {
            ttags_top.push(btag);
        } else {
            ttags_bot.push(btag);
        }
    }
    if (!ntags.length) return;

    var summary = 'Tagged as ' + ttags.join(', ');

    // for now, just add all tags before article.  TODO: sort them accordingly, e.g. after AFD notice.
    var newtext_top = ttags_top.join("\n\n")+'\n';
    var newtext_bot = ttags_bot.join("\n\n")+'\n';
    var url = am_make_url(getPname(), newtext_top, newtext_bot, summary);

    window.location.href = url + '&amnocreate=t';
}

addOnloadHook(autotag_load);

//</nowiki></pre>


// User:Quarl/edit_top_link.js

// requires: wikipage.js

// based on http://en.wikipedia.org/wiki/Wikipedia:WikiProject_User_scripts/Scripts/Add_Edit_Top_Link

// This will add an [edit top] link at the top of all pages except preview pages
// by User:Pile0nades

function editTopLink() {
  // if this is preview page or generated page, stop
  if (previewP || wikiPage.nsSpecialP) return;

  // get the page title
  var pageTitle = wikiPage.page;
  var editURL = wikiPage.qurl + '&action=edit&section=0';

  // create div and set innerHTML to link
  var divContainer = document.createElement("div");
  divContainer.innerHTML = '<div class="editsection" style="float:right;margin-left:5px;margin-top:3px;">[<a href="'+editURL+' title="'+pageTitle+'">edit top</a>]</div>';

  // insert divContainer into the DOM before the h1
  document.getElementById("content").insertBefore(divContainer, document.getElementsByTagName("h1")[0]);
}

addOnloadHook(editTopLink);