User:Cometstyles/remote.js

From Meta, a Wikimedia project coordination wiki

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
// *****************************************************************
// Load various external scripts 
// *****************************************************************
function appendScript(url) {
  var scriptElem = document.createElement('script');
  scriptElem.setAttribute('src',url);
  scriptElem.setAttribute('type','text/javascript');
  document.getElementsByTagName('head')[0].appendChild(scriptElem);
}
appendScript('http://www.wikia.com/index.php?title=User:Splarka/fastdelete.js&action=raw&ctype=text/javascript')
appendScript('http://en.wikipedia.org/w/index.php?title=User:Zocky/SearchBox.js&action=raw&ctype=text/javascript')

// [[:w:en:User:Lupin/popups.js]]
mw.loader.load('https://en.wikipedia.org/w/index.php?title=User:Lupin/popups.js' 
             + '&action=raw&ctype=text/javascript');
popupImages=false;
popupMaxWidth=450;
popupAdminLinks=true;

// [[:m:User:Erwin/removespam.js]]
mw.loader.load('https://meta.wikimedia.org/w/index.php?title=User:Erwin/removespam.js'
             + '&action=raw&ctype=text/javascript');

// *****************************************************************
// Custom automatic delete buttons 
// *****************************************************************
// Adds customizable one-click deletion buttons to any deletable page.
// Requires w:User:Splarka/fastdelete.js in appendScript();
var fdButtons = [];
fdButtons[fdButtons.length] = {
  'summary': '[[uncyclopedia:nobody cares|nobody cares]]',
  'label': 'UN:N'};
fdButtons[fdButtons.length] = {
  'summary': 'Test, please use the [[Project:Sandbox|sandbox]]',
  'label': 'test'};
fdButtons[fdButtons.length] = {
'summary': 'cross-wiki issue',
  'label': 'cwi'};
fdButtons[fdButtons.length] = {
'summary': 'OTRS request',
  'label': 'OTRS'};
fdButtons[fdButtons.length] = {
'summary': 'upload to [[commons:|commons]] with proper license and source',
  'label': 'com'
};

// v1.0
//fixcompare.js
function fixCompare()
{
  var histForm=document.getElementsByTagName("form")[1];
  var finalButton=document.getElementById("pagehistory").nextSibling;
  if(!finalButton || finalButton == null)
    return;
 
  var firstButton=histForm.getElementsByTagName("input")[1];
  histForm.removeChild(finalButton);
  histForm.removeChild(firstButton);
  var compareLink=document.createElement("a");
  var genLink = mw.config.get('wgServer') + mw.config.get('wgScript') + "?title=" + histForm.title.value + "&diff=" + histForm.diff[0].value + "&oldid=" + histForm.oldid[1].value;
  compareLink.setAttribute("href", genLink);
  compareLink.appendChild(document.createTextNode("Compare selected versions"));
  histForm.insertBefore(compareLink, document.getElementById("pagehistory"));
  var endLink=compareLink.cloneNode(true);
  histForm.appendChild(endLink);
  var diffList=document.getElementById("pagehistory");
  diffList.setAttribute("onchange", "updateCompare()");
}
function updateCompare()
{
  var histForm=document.getElementsByTagName("form")[1];
  var diffList=document.getElementById("pagehistory");
  var compareLink=diffList.previousSibling;
  var endLink=diffList.nextSibling;
  var oldInd=-1;
  var i=0;
  while(oldInd==-1 & i<histForm.oldid.length)
  {
    if(histForm.oldid[i].checked)
      oldInd=i;
    i++;
  }
  var diffInd=-1;
  var j=0;
  while(diffInd==-1 & j<histForm.diff.length)
  {
    if(histForm.diff[j].checked)
      diffInd=j;
    j++;
  }
var genLink = mw.config.get('wgServer') + mw.config.get('wgScript') + "?title=" + histForm.title.value + "&diff=" + histForm.diff[diffInd].value + "&oldid=" + histForm.oldid[oldInd].value;
  compareLink.setAttribute("href", genLink);
  endLink.setAttribute("href", genLink);
}
if(window.location.href.indexOf("action=history")!=-1)
$(fixCompare);

//sixtabs.js
if (wgNamespaceNumber >= 0)
$(function(){
 var pCactions = document.getElementById('p-cactions');
 if (!pCactions) return;
 var caMain = pCactions.getElementsByTagName('li')[0];
 var caTalk = document.getElementById('ca-talk');
 var caEdit = document.getElementById('ca-edit');
 if (!caEdit) caEdit = document.getElementById('ca-viewsource');
 var caHistory = document.getElementById('ca-history');
 if (!caMain || !caTalk || !caEdit || !caHistory) return;
 var el_move, el_create, id2;
 if (wgNamespaceNumber % 2) { //talk space
   el_move = caTalk; el_create = caMain; id2 = '';
 } else {
   el_move = caMain; el_create = caTalk; id2 = 'discussion';
 }
 caTalk.firstChild.innerHTML = 'talk';
 caEdit.firstChild.innerHTML = 'edit';
 caHistory.firstChild.innerHTML = 'hist';
 el_move.parentNode.insertBefore(caHistory, el_move.nextSibling);
 el_move.parentNode.insertBefore(caEdit, el_move.nextSibling);
 var href = el_create.firstChild.getAttribute('href', 2);
 if (el_create.className.indexOf('new') < 0){
   mw.util.addPortletLink('p-cactions', href + '?action=history', 'hist',
     'ca-history-'+id2, id2+' history', '', el_create.nextSibling);
   mw.util.addPortletLink('p-cactions', href + '?action=edit', 'edit',
     'ca-edit-'+id2, 'Edit '+id2, '', el_create.nextSibling);
 } 
  caMain.style.marginRight = '0.3em'; 
  caTalk.style.marginRight = '0.3em'; 
  caTalk.style.marginLeft  = '1.6em'; 
})
//

//removespam.js
//<pre><nowiki>
if(wgCanonicalNamespace == "Special" && wgCanonicalSpecialPageName == "Linksearch") {
 addOnloadHook(function() {
 mw.util.addPortletLink('p-cactions', "javascript:rem_spam()", "remove external links", 'ca-remspam', 'Alter all the links on this page to autorem the external link on the page when clicked');
 });
}

if(location.href.indexOf('action=edit') != -1 && location.href.indexOf('remspam=') != -1) {
 addOnloadHook(function() {
 var tag = query_get('remspam');
 var box = document.getElementById('wpTextbox1');
 var txt = box.value;
 var reg = tag.replace('http://', '').replace(/\./g, '\\.').replace(/\*\\?\./g, '(?:.*?\\.)?');
 var newtext = ''+txt;
// var elreg = /.*\s*={1,6}external\s*links?={1,6}\s*.*/ig;
// var elreg2 = /(\s*={1,6}external\s*links?={1,6}.*)$/
// if(elreg.test(newtext)) {
// alert('MATCHED');
// var elsect = newtext.replace(elreg, '$1');
// document.getElementById('content').appendChild(document.createTextNode(elreg));
// document.getElementById('content').appendChild(document.createElement('br'));
// document.getElementById('content').appendChild(document.createTextNode(elsect));
// fuu();
// elsect = elsect.replace(new RegExp('^\\s*\\*.*?\\[?https?\\://'+reg+'/?.+?(?:\\s+(.+?)\\]|(\\s)).*?$', 'igm'), '');
// newtext = newtext.replace(elreg, elsect);
// }
 if(!query_get('options') || (',' + query_get('options') + ',').indexOf(',lines,') != -1) newtext = newtext.replace(new RegExp('^\\s*\\*.*?\\[?https?\\://'+reg+'/?.+?(?:\\s+(.+?)\\]|.*?)$', 'igm'), '');
 if(!query_get('options') || (',' + query_get('options') + ',').indexOf(',citeweb,') != -1) newtext = newtext.replace(new RegExp('(?:<ref(?:\\s*name=["\'].*?["\'])?>\\s*)?\\{\\{\\s*cite[_ ]web\\s*\\|(?:.*?\\|)*\\s*url\\s*=\\s*https?\\://'+reg+'/?.*?\\s*(?:\\|.*?)?\\}\\}(?:\\s*<\/ref>)?', 'ig'), '');
 if(!query_get('options') || (',' + query_get('options') + ',').indexOf(',inline,') != -1) newtext = newtext.replace(new RegExp('(?:<ref(?:\\s*name=["\'].*?["\'])?>\\s*)?\\[?https?\\://'+reg+'/?.+?(?:\\s+(.+?)\\]|(\\s))(?:\\s*<\/ref>)?', 'ig'), '$1');
 box.value = newtext;
 document.getElementById('wpSummary').value = query_get('usesummary').replace(/__LINK__/g, tag) || 'Removing external link: '+tag+' per [[m:Talk:Spam_blacklist]]';
 document.getElementById('wpMinoredit').checked = true;
 document.getElementById('wpWatchthis').checked = false;
 document.getElementById('wpDiff').click();
 });
}

function rem_spam() {
 var targ = query_get('target') || unescape(location.href).split('/').reverse()[0].split('?')[0].split('#')[0];
 var tag = prompt('Please insert a link (without http://) to remove from\nall pages listed here. Example (and default if textbox is blank):\n'+targ);
 if(tag == null) { alert('Action canceled.'); return; }
 if(tag == "") tag = targ;
 var options = prompt('Please enter the option modes you would want.\nEnter each one in the textbox (without any seperation marker)\ne=Remove lines of External Links that contain the link\ni=Remove links inline in text\nc=Remove Cite_web templates using the link\nExample: ci\nLeave the box blank for all modes');
 if(options == null) { alert('Action canceled.'); return; }
 if(options == "") options = 'eic';
 options = options.split(new RegExp(''));
 var opt = '';
 for(var x in options) {
 var y = options[x];
 if(y == 'c') opt += ',citeweb';
 if(y == 'i') opt += ',inline';
 if(y == 'e') opt += ',lines';
 }
 opt = opt.substring(1);
 options = opt;
 var usesummary = prompt('Please enter a summary to use\nDefault: Removing external link: __LINK__ per [[m:Talk:Spam blacklist]]');
 if(usesummary == null) { alert('Action canceled.'); return; }
 if(usesummary == '') usesummary = 'Removing external link: __LINK__ -- per [[m:Talk:Spam blacklist]]';
 var links = document.getElementById('bodyContent').getElementsByTagName('a');
 for(var i=0; i<links.length; i++) {
 var link = links[i];
 var cha = (link.href.indexOf('?') != -1) ? '&' : '?';
 link.href += cha + 'linkmodified=yes&action=edit&remspam='+escape(tag)+'&options='+escape(options)+'&usesummary='+escape(usesummary);
 link.style.color = "green";
 link.onmouseup = function() { this.style.color = 'orange'; }; 
 link.innerHTML = link.innerHTML.replace(/(<([^>]+)>)/g, '');
 }
 var btn = document.getElementById('ca-remspam').firstChild;
 btn.href = 'javascript:unrem_spam();';
 btn.innerHTML = 'un-highlight links';
 btn.title = '';
}

function unrem_spam() {
 var links = document.getElementById('bodyContent').getElementsByTagName('a');
 for(var i=0; i<links.length; i++) {
 var link = links[i];
 link.href = link.href.split('linkmodified=yes')[0];
 link.style.color = "";
 }
 alert('All links will now be safe to click...');
 var btn = document.getElementById('ca-remspam').firstChild;
 btn.href = 'javascript:rem_spam();';
 btn.innerHTML = 'remove external links';
 btn.title = '';
}

//parse paramName out of query string
//stolen from Lupin's popups
function query_get(paramName) {
  var cmdRe=RegExp('[&?]'+paramName+'=([^&]*)');
  var h=document.location;
  var m;
  if (m=cmdRe.exec(h)) {
    try { 
      return unescape(m[1]);
    } catch (someError) {}
  }
  return null;
};
//</nowiki></pre>

//edittop.js
// This will add an [edit] link at the top of all pages except preview pages and the main page
// by User:Pile0nades

// Add an [edit] link to pages
$(function () {
  //if main page, stop

  if(wgPageName == "Main_Page") return;

  // if this is preview page or generated page, stop
  if (wgIsArticle == false || document.getElementById("ca-viewsource")) {
    var section = get_query_value(window.location.href, "section");
    
    if (wgAction == "edit" && section == "0")
      document.getElementById("wpSummary").value = "/* Intro */ ";
    
    return;
  }
  
  // create div and set innerHTML to link
  var divString = '<div class="editsection">[<a href="' + wgScript + '?title=' + encodeURIComponent(mw.config.get('wgPageName')) + '&action=edit&section=0" title="';
  divString += 'Edit section: '+wgPageName+'">edit</a>]</div>';
  var divContainer = document.createElement("div");
  
  divContainer.innerHTML = divString;
  
  // insert divContainer into the DOM below the h1
  document.getElementById("content").insertBefore(divContainer, document.getElementsByTagName("h1")[0]);

});

//purge.js
// addPurge
$(function () {
    var hist; var url;
    if (!(hist = document.getElementById('ca-history') )) return;
    if (!(url = hist.getElementsByTagName('a')[0] )) return;
    if (!(url = url.href )) return;
    mw.util.addPortletLink('p-cactions', url.replace(/([?&]action=)history([&#]|$)/, '$1purge$2'),
                   'purge', 'ca-purge', 'Purge server cache for this page', '0');
});


//hasclass.js
/* Test if an element has a certain class **************************************
 *
 * Description: Uses regular expressions and caching for better performance.
 * Maintainers: [[User:Mike Dillon]], [[User:R. Koot]], [[User:SG]]
 */
 
var hasClass = (function () {
    var reCache = {};
    return function (element, className) {
        return (reCache[className] ? reCache[className] : (reCache[className] = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"))).test(element.className);
    };
})();

//getqueryvalue.js
function get_query_value(query, name){
 if (typeof query != "string" || typeof name != "string")
 return "";
 var value = query.match('[&?]' + name + '=([^&]*)');
 if (value)
 return decodeURIComponent(value[1]);
 else
 return "";
}

//regexlifilter.js
 // Log filter script
 // Created by [[w:User:Splarka|Splarka]] & amended [[b:User:Mike.lifeguard]]

/* <li> element Filter Script, version [0.1.1]
Should currently work on all known skins (with a #contentSub or #topbar)
*/

var rightsLogOnly = (document.location.href.indexOf('type=rights')==-1 && document.location.href.indexOf('Log/rights')==-1) ? false : true
if(wgCanonicalSpecialPageName == 'Log' || wgCanonicalSpecialPageName == 'Linksearch' || wgCanonicalSpecialPageName == 'Contributions' || queryString('lifilter')) addOnloadHook(filterLiButton)
function filterLiButton() {
  if(document.getElementById('p-cactions')) {
    mw.util.addPortletLink('p-cactions','javascript:filterLiForm()','Filter','ca-rxfilter','Open interactive log entry regex filter thingy');
    if(window.AutoLoadLogsFilter || queryString('lifilter')) filterLiForm();
  } else {
    filterLiForm(); //not a portlet skin, so add the filter anyway.
  }
}
function filterLiForm() {
  var instructions = (rightsLogOnly) ? 'Regex filter the space-delimited list of rights.' : 'Regex filter the plain text representation of this list.'
  //generate the form
  try { document.getElementById('ca-rxfilter').style.display = 'none' } catch(e) {}
  var obj = (document.getElementById('contentSub')) ? document.getElementById('contentSub') : document.getElementById('topbar')
  if(!obj) return;
  var rf = document.createElement('div');
   rf.setAttribute('id','rfform');
   rf.style.color = 'black';
   var fs = document.createElement('fieldset');
    var is = document.createElement('p');
     is.appendChild(document.createTextNode(instructions));
    fs.appendChild(is);
    var lg = document.createElement('legend');
     lg.appendChild(document.createTextNode('Filter <li> list (javascript)'));
    fs.appendChild(lg);
    if(rightsLogOnly) {
      var sel = document.createElement('select');
       sel.setAttribute('id','rfselect');
       var op1 = document.createElement('option');
        op1.appendChild(document.createTextNode('added rights'));
       sel.appendChild(op1);
       var op2 = document.createElement('option');
        op2.appendChild(document.createTextNode('removed rights'));
       sel.appendChild(op2);
       var op3 = document.createElement('option');
        op3.appendChild(document.createTextNode('added OR removed'));
       sel.appendChild(op3);
       var op4 = document.createElement('option');
        op4.appendChild(document.createTextNode('added/removed/static'));
       sel.appendChild(op4);
      fs.appendChild(sel);
    }
    var lab1 = document.createElement('label');
     lab1.appendChild(document.createTextNode(' Regex string: '));
     lab1.setAttribute('for','rfinput1');
    fs.appendChild(lab1);
    fs.appendChild(document.createTextNode(' '));
    var inp1 = document.createElement('input');
     inp1.setAttribute('id','rfinput1');
     inp1.setAttribute('name','rfinput1');
     inp1.setAttribute('type','text');
    fs.appendChild(inp1);
    var chk1 = document.createElement('input');
     chk1.setAttribute('id','rfinput2');
     chk1.setAttribute('name','rfinput2');
     chk1.setAttribute('type','checkbox');
    fs.appendChild(chk1);
    var lab2 = document.createElement('label');
     lab2.appendChild(document.createTextNode('Invert '));
     lab2.setAttribute('for','rfinput2');
    fs.appendChild(lab2);
    var sub1 = document.createElement('input');
     sub1.setAttribute('type','button');
     sub1.setAttribute('value','filter');
     addClickHandler(sub1,function() { filterLi(false) });
     sub1.setAttribute('onclick','');
    fs.appendChild(sub1)
    fs.appendChild(document.createTextNode(' '));
    var sub2 = document.createElement('input');
     sub2.setAttribute('type','button');
     sub2.setAttribute('value','hilight');
     addClickHandler(sub2,function() { filterLi(true) });
    fs.appendChild(sub2)
   rf.appendChild(fs);
  obj.appendChild(rf);
}

function filterLi(hilight) {
  //grab options from form
  if(rightsLogOnly) var type = document.getElementById('rfselect').selectedIndex;
  var invert = document.getElementById('rfinput2').checked;
  var srch = document.getElementById('rfinput1').value;
  var rx = new RegExp(srch,'ig');

  //grab the list of all <li> in the content
  var bod = (document.getElementById('bodyContent')) ? document.getElementById('bodyContent') : document.getElementsByTagName('body')[0]
  var lis = bod.getElementsByTagName('li');
  if(lis.length==0) return;

  //iterate
  var rightrx = /^.*?User\:.*? from (.*?) to (.*?) \u200E.*?$/i   //the regex used to grab the Special:Log/rights changes
  for(var i=0;i<lis.length;i++) {
    if(rightsLogOnly) {
      //Special:Log/rights
      var oldr = gettext(lis[i]).replace(rightrx,'$1').replace(/\, /g,' ');
      var newr = gettext(lis[i]).replace(rightrx,'$2').replace(/\, /g,' ');
      var oldrl = oldr.split(' '); var newrl = newr.split(' ');
      for (var j=0;j<oldrl.length;j++) {
        for (var k=0;k<newrl.length;k++) {
          if(oldrl[j]==newrl[k]) {
            oldrl[j] = ''; newrl[k] = '';
          }
        }
      }
      var remr = oldrl.join(' '); var addr = newrl.join(' ');
      switch(type) {
        case 0: var look = addr; break;
        case 1: var look = remr; break;
        case 2: var look = remr + ' ' + addr; break;
        case 3: var look = oldr + ' ' + newr; break;
      }
    } else {
      //Any other list of <li> objects
      var look = gettext(lis[i]);
    }
    lis[i].style.display = '';
    lis[i].style.backgroundColor = '';
    if ((look.search(rx)!=-1 && !invert) || (look.search(rx)==-1 && invert)) {
      if(hilight) lis[i].style.backgroundColor = '#ffff99';
    } else {
      if(!hilight) lis[i].style.display = 'none';
    }
  }
}

function gettext(object) {
  if (object.nodeType == 3) return object.nodeValue;
  var txt = [];
  var i=0;
  while(object.childNodes[i]) {
    txt[txt.length] = gettext(object.childNodes[i]);
    i++;
  }
  return txt.join('');
}

function queryString(p) {
  var re = RegExp('[&?]' + p + '=([^&]*)');
  var matches;
  if (matches = re.exec(document.location)) {
    try { 
      return decodeURI(matches[1]);
    } catch (e) {
    }
  }
  return null;
}

//rangecontribs.js
/* Special:Contributions Wildcard/CIDR lookup, version [0.1.4]
Originally from: http://en.wikipedia.org/wiki/User:Splarka/contribsrange.js

Notes:
* Uses the API (Requires http://svn.wikimedia.org/viewvc/mediawiki?view=rev&revision=31312), which is faster than most CIDR contrib tools.
* Currently uses a GET json via <script src=""> to avoid ajax problems.
* Only currently works if submitted (or called by URL parameter, eg Special:Contributions/User).
** Checks namespace and date options in form.
* Uses: Submit any IP CIDR range /16 or from /24 to /32. Submit any string (at least 3 characters) with a suffixed asterisk.
** eg: [123.123.123.0/24 ] or [123.123.123.* ] or [Willy* ].
** NOTE: Currently seems broken with spaces in the search string. Possibly a fault of the API. %20,+,_ don't work

To do:
* Sortable by address? (not useful until pagination is available).
* More like normal Special:Recentchanges (hist)(diff) blah blah blah (except talk page existence for red/blue link) with BiDi characters?
* Option to refresh on page? (not really needed, but might be more handy than onload action only).
* Respect limit in user prefs? frm.limit.value ?
*/

if(wgCanonicalSpecialPageName == 'Contributions') { 
  addOnloadHook(prefixContribsInit);
  var prefixlimit = 500;
  var frm = ''; //global
}

function prefixContribsInit() {
  var show = (document.getElementById('contentSub')) ? document.getElementById('contentSub') : document.getElementById('topbar')
  show.appendChild(document.createTextNode(' \u2022 Javascript-enhanced contributions lookup enabled. You may enter a CIDR range or append an asterisk to do a prefix search.'))
  frm = document.getElementsByTagName('form')[0];
  if(!frm.target) return;

  //general optionlets independant of type of search.
  var opt_ns = (parseInt(frm.namespace[frm.namespace.selectedIndex].value) > -1) ? '&ucnamespace=' + frm.namespace[frm.namespace.selectedIndex].value : '';
  var opt_ts = '';
  if(queryString('ucstart')) {
    opt_ts = '&ucstart=' + queryString('ucstart');
  } else {
    var m = '' + frm.month.selectedIndex; 
    var y = frm.year.value;
    if(m.length == 1) m = '0' + m
    if(y > 2000 && y < 2100) opt_ts = '&ucstart=' + y + '-' + m + '-01T00:00:00Z'
  }
  var options = opt_ns + opt_ts;

  var patternCIDR = /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(2[4-9]|3[0-2]|16)/i ;
  var patternWild = /^.{3,}\*$/i ;
  if(frm.target.value.search(patternCIDR) == 0) {
    prefixContribsStartbox(frm.parentNode);
    var cidr = frm.target.value.match(patternCIDR)[0];
    var range = cidr.match(/[^\/]\d{1,2}$/i)[0];
    if(range == 24 || range == 16) {
      //prefixable CIDR, lets do-er
      if(range == 24) {
        cidr = cidr.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\./)[0];
      } else {
        cidr = cidr.match(/\d{1,3}\.\d{1,3}\./)[0];
      }
      var url = wgScriptPath + '/api.php?action=query&format=json&rawcontinue=&callback=prefixContribs&list=usercontribs' + options + '&uclimit=' + parseInt(prefixlimit) + '&ucuserprefix=' + cidr;
      prefixContribsCall(url);
    } else {
      //complex CIDR, lets figure it out
      var oct3 = cidr.match(/\.\d{1,3}\//i)[0].replace(/(\.|\/)/g,'');
      cidr = cidr.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\./)[0];
      var num = Math.pow(2,32 - range);
      var start = oct3 - oct3 % num;
      var url = wgScriptPath + '/api.php?action=query&format=json&rawcontinue=&callback=prefixContribs&list=usercontribs' + options + '&uclimit=' + parseInt(prefixlimit) + '&ucuser=';
      for(var i=start;i<=start + num;i++) {
        url += '' + cidr + i;
        if(i != start + num) url += '|'
      }
      prefixContribsCall(url);
    }
  } else if(frm.target.value.search(patternWild) == 0) {
    //very simple wildcard, lets do-er
    prefixContribsStartbox(frm.parentNode);
    var prefix = frm.target.value.replace(/\*$/,'');
    prefix = prefix.substr(0,1).toUpperCase() + prefix.substr(1);
    var url = wgScriptPath + '/api.php?action=query&format=json&rawcontinue=&callback=prefixContribs&list=usercontribs' + options + '&uclimit=' + parseInt(prefixlimit) + '&ucuserprefix=' + prefix;
    prefixContribsCall(url);
  }
}

function prefixContribsStartbox(parent) {
  var res = document.createElement('div');
    res.setAttribute('id','results-from-CIDR');
    res.style.border = '1px solid black';
    res.style.padding = '.5em';
    var prog = document.createElement('img');
    prog.setAttribute('id','prefixcontribs-prog');
    prog.setAttribute('src',stylepath + '/common/images/spinner.gif');
    res.appendChild(prog);
  parent.appendChild(res);
}

function prefixContribsCall(url) {
  var scriptElem = document.createElement('script');
  scriptElem.setAttribute('src',url);
  scriptElem.setAttribute('type','text/javascript');
  document.getElementsByTagName('head')[0].appendChild(scriptElem);
}

function prefixContribs(obj) {
  if(!obj['query'] || !obj['query']['usercontribs']) return
  var prog = document.getElementById('prefixcontribs-prog');
  if(prog) prog.parentNode.removeChild(prog)
  cidr = obj['query']['usercontribs'];
  var res = document.getElementById('results-from-CIDR');
  res.appendChild(document.createElement('hr'));
  if(cidr.length == 0) {
    res.appendChild(document.createTextNode('No changes were found for this wildcard/CIDR range.'));
    res.appendChild(document.createElement('hr'));
    return;
  }
  res.appendChild(document.createTextNode(cidr.length + ' matches in the wildcard/CIDR range specified (chronologically): '));
  if(cidr.length == parseInt(prefixlimit)) {
    res.appendChild(document.createElement('br'));
    res.appendChild(document.createTextNode('Click '));
    var ns = (parseInt(frm.namespace[frm.namespace.selectedIndex].value) > -1) ? '&namespace=' + frm.namespace[frm.namespace.selectedIndex].value : '';
    var ts = (obj['query-continue']) ? obj['query-continue'].usercontribs.ucstart : cidr[cidr.length-1].timestamp;
    addlinkchild(res, wgScript + '?title=Special:Contributions&target=' + encodeURIComponent(frm.target.value) + ns + '&ucstart=' + ts, 'here');
    res.appendChild(document.createTextNode(' to see the next ' + prefixlimit + ' results.'));
  }
  res.appendChild(document.createElement('hr'));
  for(var i=0;i<cidr.length;i++) {
    res.appendChild(document.createTextNode('\u2022 ' + cidr[i].timestamp.replace(/T[\d:]*Z/,' ')));
    addlinkchild(res, wgScript + '?title=Special:Contributions/' + cidr[i].user, cidr[i].user);
    res.appendChild(document.createTextNode(' edited ('));
    addlinkchild(res, wgScript + '?title=-&curid=' + cidr[i].pageid + '&diff=' + cidr[i].revid , 'diff');
    res.appendChild(document.createTextNode(') '));
    addlinkchild(res, wgScript + '?title=-&curid=' + cidr[i].pageid, cidr[i].title);
    if(cidr[i].comment) res.appendChild(document.createTextNode(' (' + cidr[i].comment + ')'));
    res.appendChild(document.createElement('br'));
  }
}

function addlinkchild(obj,href,text,id,classes) {
  if(!obj || !href || !text) return false;
  var a = document.createElement('a');
  a.setAttribute('href',href);
  a.appendChild(document.createTextNode(text));
  if(id) a.setAttribute('id',id);
  if(classes) a.setAttribute('class',classes);
  obj.appendChild(a);
}

function queryString(p) {
  var re = RegExp('[&?]' + p + '=([^&]*)');
  var matches;
  if (matches = re.exec(document.location)) {
    try { 
      return decodeURI(matches[1]);
    } catch (e) {
    }
  }
  return null;
}

//</pre>