User:Celeste/common.js: Difference between revisions

From Celeste Wiki
Jump to navigation Jump to search
Content added Content deleted
(Loading my own JS scripts)
 
No edit summary
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
// Highlight admins
mw.loader.load('//en.uncyclopedia.co/w/index.php?title=User:Charlie/common.js&action=raw&ctype=text/javascript');
;(function($, mw){
$.getJSON(mw.config.get('wgScriptPath')+'/index.php?action=raw&ctype=application/json&title=User:Amalthea_(bot)/userhighlighter.js/sysop.js', function(data){
ADMINHIGHLIGHT_EXTLINKS = window.ADMINHIGHLIGHT_EXTLINKS || false;
ADMINHIGHLIGHT_NAMESPACES = [-1,2,3];
mw.loader.using(['mediawiki.util','mediawiki.Uri', 'mediawiki.Title'], function() {
mw.util.addCSS(".userhighlighter_sysop.userhighlighter_sysop {background-color: #00FFFF !important}");
$('#bodyContent a').each(function(index,linkraw){
try {
var link = $(linkraw);
var url = link.attr('href');
if (!url || url.charAt(0) === '#') return; // Skip <a> elements that aren't actually links; skip anchors
if (url.lastIndexOf("http://", 0) != 0 && url.lastIndexOf("https://", 0) != 0 && url.lastIndexOf("/", 0) != 0) return; //require http(s) links, avoid "javascript:..." etc. which mw.Uri does not support
var uri = new mw.Uri(url);
if (!ADMINHIGHLIGHT_EXTLINKS && !$.isEmptyObject(uri.query)) return; // Skip links with query strings if highlighting external links is disabled
if (uri.host == 'en.wikipedia.org') {
var mwtitle = new mw.Title(mw.util.getParamValue('title',url) || decodeURIComponent(uri.path.slice(6))); // Try to get the title parameter of URL; if not available, remove '/wiki/' and use that
if ($.inArray(mwtitle.getNamespaceId(), ADMINHIGHLIGHT_NAMESPACES)>=0) {
var user = mwtitle.getMain().replace(/_/g," ");
if (mwtitle.getNamespaceId() === -1) user = user.replace('Contributions/',''); // For special page "Contributions/<username>"
if (data[user] == 1) {
link.addClass('userhighlighter_sysop'); // Override the above color by using `a.userhighlighter_sysop.userhighlighter_sysop {background-color: COLOR !important}`
}
}
}
} catch (e) {
// Sometimes we will run into unparsable links, so just log these and move on
window.console && console.error('Admin highlighter recoverable error',e.message);
}
});
});
});
}(jQuery, mediaWiki));

/**
* SkinSwitcher.js
* @file Allows for easy switching between seven main skins, and Timeless
* @author Eizzen <en.wikipedia.org/wiki/User_talk:Eizzen>
* @timeless added by Zombiebaron
* @license Apache-2.0
* @external "jQuery"
* @external "mediawiki.util"
*/

/*jslint browser, this:true */
/*global mw, jQuery, window */

mw.loader.using("mediawiki.util", function () {
"use strict";

/**
* @class SkinSwitcher
* @classdesc The central SkinSwitcher class
*/
var SkinSwitcher = {
lang: {
script: "Skin Switcher",
viewIn: "View this page in $1 skin"
},
skins: {
"vector": "Vector",
"monobook": "MonoBook",
"modern": "Modern",
"minerva": "Minerva",
"minervaneue": "MinervaNeue",
"cologneblue": "CologneBlue",
"apioutput": "ApiOutput",
"timeless": "Timeless"
},
/**
* @method constructElement
* @param {string} $selectedSkin
* @param {string} $itemText
* @returns {html}
*/
constructElement: function ($selectedSkin, $itemText) {
var $href = window.location.href;
var $param = (window.location.search)
? "&"
: "?";

return mw.html.element("li", {
"id": "skinSwitcher-li-" + $selectedSkin,
"class": "skinSwitcher-li"
}, new mw.html.Raw(
mw.html.element("a", {
"href": $href.replace(/#.*/, "") +
$param + jQuery.param({useskin: $selectedSkin}),
"title": this.lang.viewIn.replace("$1", $itemText),
"id": "skinSwitcher-a-" + $selectedSkin,
"class": "skinSwitcher-a"
}, $itemText)
));
},
/**
* @method assembleElements
* @returns {string[] } $elementsArray
*/
assembleElements: function () {
var $elementsArray = [];

Object.keys(this.skins).forEach(function ($property) {
$elementsArray.push(
this.constructElement($property, this.skins[$property])
);
}, this);

return $elementsArray;
},
/**
* @method cloneMenu
* @param {string} $template
* @returns {void}
*/
cloneMenu: function ($template) {
jQuery($template)
.clone()
.attr("id", "skinSwitcher")
.insertAfter($template);
jQuery("#skinSwitcher h3")
.html("<span>" + this.lang.script + "</span>");
jQuery("#skinSwitcher ul").empty();
},
/**
* @method experimentalPlacement
* @returns {void}
*/
experimentalPlacement: function () {
// Experimental CSS to center links horizontally in header
mw.util.addCSS(
"#skinSwitcher {" +
"display: flex;" +
"justify-content: center;" +
"flex-direction: row;" +
"align-items: center;" +
"}" +
".skinSwitcher-li {" +
"display:inline-block;" +
"margin:5px 25px 0 25px;" +
"}"
);

jQuery("<ul>", {
id: "skinSwitcher"
}).prependTo(".mw-body");
},
/**
* @method determinePlacement
* @param {string[] } $assembledElements
* @returns {void}
*/
determinePlacement: function ($assembledElements) {
var $appendLocation;

switch (this.currentSkin) {
case "vector":
case "monobook":
case "modern":
case "cologneblue":
this.cloneMenu("#p-tb");
$appendLocation = jQuery("#skinSwitcher ul");
break;
case "minerva":
case "minervaneue":
case "apioutput":
this.experimentalPlacement();
$appendLocation = jQuery("#skinSwitcher");
break;
case "timeless":
}

$assembledElements.forEach(function ($element) {
jQuery($element).appendTo($appendLocation);
});
},
/**
* @method init
* @returns {void}
*/
init: function () {
if (
window.isSkinSwitcherLoaded ||
jQuery("#skinSwitcher").length
) {
return;
}

window.isSkinSwitcherLoaded = true;
this.currentSkin = mw.config.get("skin");

if (this.skins.hasOwnProperty(this.currentSkin)) {
delete this.skins[this.currentSkin];
this.determinePlacement(this.assembleElements());
}
}
};

jQuery(document).ready(function () {
SkinSwitcher.init();
});
});

// Creates a link and an html class to invert the screen
// Documentation at [[w:User:BrandonXLF/Invert]]

mw.loader.load('//en.uncyclopedia.co/w/index.php?title=User:Zombiebaron/Invert.css&action=raw&ctype=text/css', 'text/css'); // Import stylesheet

$(function() {
function update(){ // Function to update filter
if(mw.storage.get('InvertPage') == 'true'){
$(document.body).addClass('inverted-colors'); // Add CSS
}else{
$(document.body).removeClass('inverted-colors'); // Remove CSS
}
}
function set(e){ // Function to set web storage and update filter
e.preventDefault(); // Pervent default action
if(mw.storage.get('InvertPage') == 'true'){
mw.storage.set('InvertPage','false');
}else{
mw.storage.set('InvertPage','true');
}
update(); // Update fiter
}
var node = mw.util.addPortletLink( // Add link
'p-personal',
"https://en.wikipedia.org/wiki/User:BrandonXLF/Invert/select", // Backup link to URL
'🌛',
'night mode',
'enter night mode',
'n',
'#pt-mytalk'
);
update();
$(node).on('click',function(e){ // Make the dark mode link work
set(e);
});
$('#ToggleWikiInvert').click(function(e){ // Allow for id to toggle dark mode
set(e);
});
$('.ToggleWikiInvert').click(function(e){ // Allow to CSS class to toggle dark mode
set(e);
});
});

mw.loader.using(['mediawiki.api', 'mediawiki.Title'], function () {
"use strict";

var config = mw.config.get(['wgNamespaceNumber', 'wgTitle', 'wgUserGroups', 'skin']);

function removeBlanks(arr) {
var ret = [];
var i, len;
for (i = 0, len = arr.length; i < len; i++) {
var s = arr[i];
s = s.trim();
if (s) {
ret.push(s);
}
}
return ret;
}

function doMassDelete() {
document.getElementById("wpMassDeleteSubmit").disabled = true;
var articles = document.getElementById("wpMassDeletePages").value.split("\n");
articles = removeBlanks(articles);
if (!articles.length) {
return;
}
var
api = new mw.Api(),
wpMassDeleteReasons = document.getElementById("wpMassDeleteReasons").value,
wpMassDeleteReason = document.getElementById("wpMassDeleteReason").value,
deleted = 0,
failed = [],
error = [],
deferreds = [],
reason = wpMassDeleteReasons == "other" ?
wpMassDeleteReason :
wpMassDeleteReasons + (wpMassDeleteReason ? " (" + wpMassDeleteReason + ")" : ""),
onSuccess = function () {
deleted++;
document.getElementById("wpMassDeleteSubmit").value = "(" + deleted + ")";
};

function makeDeleteFunc(article) {
return function () {
return $.Deferred(function (deferred) {
var promise = api.postWithToken('delete', {
format: 'json',
action: 'delete',
title: article,
reason: reason
});
promise.done(onSuccess);
promise.fail(function (code, obj) {
failed.push(article);
error.push(obj.error.info);
});
promise.always(function () {
deferred.resolve();
});
});
};
}

// Make a chain of deferred objects. We chain them rather than execute them in
// parallel so that we don't make 1000 simultaneous delete requests and bring the
// site down. We use deferred objects rather than the promise objects returned
// from the API request so that the chain continues even if some articles gave
// errors.
var deferred = makeDeleteFunc(articles[0])();
for (var i = 1, len = articles.length; i < len; i++) {
deferred = deferred.then(makeDeleteFunc(articles[i]));
}

// Show the output and do cleanup once all the requests are done.
$.when(deferred).then(function () {
document.getElementById("wpMassDeleteSubmit").value = "Done (" + deleted + ")";
if (failed.length) {
var $failedList = $('<ul>');
for(var x = 0; x < failed.length; x++) {
// Link the titles in the "failed" array
var failedTitle = mw.Title.newFromText(failed[x]);
var $failedItem = $('<li>');
if (failedTitle) {
$failedItem.append( $('<a>')
.attr('href', failedTitle.getUrl())
.text(failed[x])
);
} else {
$failedItem.text(failed[x]);
}
$failedItem.append(document.createTextNode(': ' + error[x]));
$failedList.append($failedItem);
}
$('#wpMassDeleteFailedContainer')
.append($('<br />'))
.append($('<b>')
.text('Failed deletions:')
)
.append($failedList);
}
});
}
function massdeleteform() {
var bodyContent = (config.skin == "cologneblue" ? "article" : "bodyContent");
document.getElementsByTagName("h1")[0].textContent = "Animum's mass-deletion tool";
document.title = "Animum's mass-deletion tool - Wikipedia, the free encyclopedia";
document.getElementById(bodyContent).innerHTML = '<h3 id="siteSub">From Wikipedia, the free encyclopedia</h3><br /><br />' +
'<form id="wpMassDelete" name="wpMassDelete">' +
'<b>If you abuse this tool, it\'s <i>your</i> fault, not mine.</b>' +
'<div id="wpMassDeleteFailedContainer"></div>' +
'<br /><br />' +
'Pages to delete (one on each line, please):<br />' +
'<textarea tabindex="1" accesskey="," name="wpMassDeletePages" id="wpMassDeletePages" rows="10" cols="80"></textarea>' +
'<br /><br /><table style="background-color:transparent">' +
'<tr><td>Common reasons:</td>' +
'<td><select id="wpMassDeleteReasons">' +
'<optgroup label="Other reason">' +
'<option value="other">Other reason</option>' +
'</optgroup>' +
'<optgroup label="Criteria for speedy deletion">' +
'<optgroup label="General criteria">' +
'<option value="[[WP:CSD#G1|G1]]: [[WP:PN|Patent nonsense]], meaningless, or incomprehensible">G1: Patent nonsense</option>' +
'<option value="[[WP:CSD#G2|G2]]: Test page">G2: Test page</option>' +
'<option value="[[WP:CSD#G3|G3]]: [[WP:Vandalism|Vandalism]]">G3: Vandalism</option>' +
'<option value="[[WP:CSD#G3|G3]]: Blatant [[WP:Do not create hoaxes|hoax]]">G3: Hoax</option>' +
'<option value="[[WP:CSD#G4|G4]]: Recreation of a page that was [[WP:DEL|deleted]] per a [[WP:XFD|deletion discussion]]">G4: Repost</option>' +
'<option value="[[WP:CSD#G5|G5]]: Creation by a [[WP:BLOCK|blocked]] or [[WP:BAN|banned]] user in violation of block or ban">G5: Banned</option>' +
'<option value="[[WP:CSD#G6|G6]]: Housekeeping and routine (non-controversial) cleanup">G6: Maintenance</option>' +
'<option value="[[WP:CSD#G7|G7]]: One author who has requested deletion or blanked the page">G7: Author</option>' +
'<option value="[[WP:CSD#G8|G8]]: Page dependent on a deleted or nonexistent page">G8: Orphaned talk page</option>' +
'<option value="[[WP:CSD#G10|G10]]: [[WP:ATP|Attack page]] or negative unsourced [[WP:BLP|BLP]]">G10: Attack page</option>' +
'<option value="[[WP:CSD#G11|G11]]: Unambiguous [[WP:NOTADVERTISING|advertising]] or promotion">G11: Advertising</option>' +
'<option value="[[WP:CSD#G12|G12]]: Unambiguous [[WP:CV|copyright infringement]]">G12: Copyvio</option>' +
'<option value="[[WP:CSD#G13|G13]]: Abandoned draft or [[WP:AFC|Articles for Creation]] submission – to retrieve it, see [[WP:REFUND/G13]]">G13: Abandoned draft</option>' +
'</optgroup>' +
'<optgroup label="Articles">' +
'<option value="[[WP:CSD#A1|A1]]: Short article without enough context to identify the subject">A1: No context</option>' +
'<option value="[[WP:CSD#A2|A2]]: Article in a foreign language that exists on another project">A2: Foreign</option>' +
'<option value="[[WP:CSD#A3|A3]]: Article that has no meaningful, substantive content">A3: No content</option>' +
'<option value="[[WP:CSD#A5|A5]]: Article that has been transwikied to another project">A5: Transwiki</option>' +
'<option value="[[WP:CSD#A7|A7]]: No credible indication of importance (individuals, animals, organizations, web content, events)">A7: Non-notable individual, animal, organization, web content, or event</option>' +
'<option value="[[WP:CSD#A9|A9]]: Music recording by redlinked artist and no indication of importance or significance">A9: Non-notable recording by redlinked artist</option>' +
'<option value="[[WP:CSD#A10|A10]]: Recently created article that duplicates an existing topic">A10: Recently created article that duplicates an existing topic</option>' +
'<option value="[[WP:CSD#A11|A11]]: [[Wikipedia:Wikipedia is not for things made up one day|Made up]] by article creator or an associate, and no indication of importance/significance">A11: Made up</option>' +
'</optgroup>' +
'<optgroup label="Redirects">' +
'<option value="[[WP:CSD#R2|R2]]: Cross-[[WP:NS|namespace]] [[WP:R|redirect]] from mainspace">R2: Cross-namespace</option>' +
'<option value="[[WP:CSD#R3|R3]]: Recently created, implausible [[WP:R|redirect]]">R3: Implausible redirect</option>' +
'</optgroup>' +
'<optgroup label="Images and other media">' +
'<option value="[[WP:CSD#F1|F1]]: File redundant to another on Wikipedia">F1: Redundant</option>' +
'<option value="[[WP:CSD#F2|F2]]: Corrupt or empty file, or a file description page for a file on Commons">F2: Corrupt, empty. or Commons</option>' +
'<option value="[[WP:CSD#F3|F3]]: File with improper license">F3: File with improper license</option>' +
'<option value="[[WP:CSD#F4|F4]]: Lack of licensing information">F4: Lack of licensing information</option>' +
'<option value="[[WP:CSD#F5|F5]]: Unused non-free media">F5: Unfree and unused</option>' +
'<option value="[[WP:CSD#F6|F6]]: Non-free file without [[WP:RAT|fair-use rationale]]">F6: No rationale</option>' +
'<option value="[[WP:CSD#F7|F7]]: [[WP:NFCC|Invalid]] fair-use claim">F7: Bad fair use rationale</option>' +
'<option value="[[WP:CSD#F8|F8]]: Media file available on Commons">F8: On Commons</option>' +
'<option value="[[WP:CSD#F9|F9]]: File [[WP:COPYVIO|copyright violation]]">F9: File copyvio</option>' +
'<option value="[[WP:CSD#F10|F10]]: Useless media file">F10: Useless media file</option>' +
'<option value="[[WP:CSD#F11|F11]]: No evidence of permission">F11: No permission</option>' +
'</optgroup>' +
'<optgroup label="Categories">' +
'<option value="[[WP:CSD#C1|C1]]: Empty category">C1: Empty</option>' +
'<option value="[[WP:CSD#C2|C2]]: Speedy renaming">C2: Speedy rename</option>' +
'<option value="[[WP:CSD#G8|G8]]: Populated by deleted or retargeted template">G8: Populated by deleted or retargeted template</option>' +
'</optgroup>' +
'<optgroup label="User namespace">' +
'<option value="[[WP:CSD#U1|U1]]: User request to delete page in own userspace">U1: User requests deletion</option>' +
'<option value="[[WP:CSD#U2|U2]]: Userpage or subpage of a nonexistent user">U2: Non-existent user</option>' +
'<option value="[[WP:CSD#U3|U3]]: [[WP:NFC|Non-free]] [[Help:Gallery|gallery]]">U3: Fair use gallery</option>' +
'<option value="[[WP:CSD#U5|U5]]: [[WP:NOTWEBHOST|Misuse of Wikipedia as a web host]]">U5: Misuse as webhost</option>' +
'</optgroup>' +
'<optgroup label="Templates">' +
'<option value="[[WP:CSD#T3|T3]]: Unused, redundant template">T3: Redundant and unused</option>' +
'<option value="[[WP:CSD#G8|G8]]: Component or documentation of a deleted template">G8: component of deleted template</option>' +
'</optgroup>' +
'<optgroup label="Portals">' +
'<option value="[[WP:CSD#P1|P1]]: [[WP:P|Portal]] page that would be subject to speedy deletion as an article">P1: Deletion as article</option>' +
'<option value="[[WP:CSD#P2|P2]]: [[WP:P|Portal]] without a substantial topic base">P2: Underpopulated</option>' +
'</optgroup>' +
'<optgroup label="Other">' +
'<option value="[[WP:PROD]]: Nominated for seven days with no objection">PRODded for more than 7 days without objection</option>' +
'<option value="[[WP:BLPPROD]]: Nominated for seven days with no reliable sources present in the article">BLPPRODded for more than seven days without a source</option>' +
'<option value="Listed at [[Wikipedia:Copyright problems]] for over seven days">Listed at Copyright problems for over seven days</option>' +
'</optgroup>' +
'</optgroup>' +
'</select></td></tr>' +
'<tr><td>Other/additional reason:</td>' +
'<td><input type="text" id="wpMassDeleteReason" name="wpMassDeleteReason" maxlength="255" /></td></tr>' +
'<tr><td><input type="button" id="wpMassDeleteSubmit" name="wpMassDeleteSubmit" value="Delete" /></td>' +
'</form>';
document.getElementById("wpMassDeleteReasons").onchange = function() {
var maxlength = (document.getElementById("wpMassDeleteReasons").value == "other" ? 255 : 252-document.getElementById("wpMassDeleteReasons").value.length); //It's 252 because of the three characters (" ()") in addition to the selected summary.
document.getElementById("wpMassDeleteReason").setAttribute("maxlength", maxlength);
};
document.getElementById("wpMassDeleteSubmit").addEventListener("click", function (e) {
doMassDelete();
});
}
if (config.wgNamespaceNumber == -1 &&
config.wgTitle.toLowerCase() == "massdelete" &&
/sysop/.test(config.wgUserGroups)
) {
massdeleteform();
}

});

/** This script contains the code required for loading [[User:Joeytje50/JWB.js]].
* All other code is located at that page.
*/

//Idea by [[User:Epicgenius]]
$.when(mw.loader.using(['mediawiki.util'], $.ready)).done( function() {
mw.util.addPortletLink("p-tb", mw.config.get('wgArticlePath').replace('$1', "Project:AutoWikiBrowser/Script"), "JS Wiki Browser", "tb-awbscript", "Run Javascript Wiki Browser");
});

if (mw.config.get('wgCanonicalNamespace')+':'+mw.config.get('wgTitle') === 'Project:AutoWikiBrowser/Script' && mw.config.get('wgAction') == 'view')
mw.loader.load('//en.wikipedia.org/w/index.php?title=User:Joeytje50/JWB.js&action=raw&ctype=text/javascript');
function DateSub(Date1,Date2) {
var timeDifference = Date2 - Date1;
var minutesAgo = Math.round(timeDifference / 1000 / 60);
var hoursAgo = 0
var daysAgo = 0
var hoursText = 'hour'
var daysText = 'day'

while (minutesAgo >= 60) {
minutesAgo = minutesAgo-60;
hoursAgo++;
}

while (hoursAgo >= 24) {
hoursAgo = hoursAgo-24;
daysAgo++;
}

if (hoursAgo!=1)
hoursText = hoursText + 's';

if (daysAgo!=1)
daysText = daysText + 's';

if (daysAgo > 0) {
if (hoursAgo > 0) {
if (minutesAgo <=1 ) {
minutesAgo = daysAgo + ' ' + daysText + ', ' + hoursAgo + ' ' + hoursText;
}
else {
minutesAgo = daysAgo + ' ' + daysText + ', ' + hoursAgo + ' ' + hoursText + ', ' + minutesAgo + ' minutes';
}
}
else {
if (minutesAgo <=1 ) {
minutesAgo = daysAgo + ' ' + daysText;
}
else {
minutesAgo = daysAgo + ' ' + daysText + ', ' + minutesAgo + ' minutes';
}
}
}
else {
if (hoursAgo > 0) {
if (minutesAgo <=1 ) {
minutesAgo = hoursAgo + ' ' + hoursText;
}
else {
minutesAgo = hoursAgo + ' ' + hoursText + ', ' + minutesAgo + ' minutes';
}
}
else {
if (minutesAgo <=1 ) {
minutesAgo = 'Less than a minute';
}
else {
minutesAgo = minutesAgo + ' minutes';
}
}
}
return minutesAgo;
}

if (document.getElementById('mw-diff-otitle1') || document.getElementById('mw-diff-ntitle1')) {

function convertTimestampStringToDate(id) {
var timestamp = document.getElementById(id).firstChild.firstChild.firstChild.nodeValue;
var str = /evision as of /g
str.lastIndex = 0;
str.test(timestamp)
var date = timestamp.substring(str.lastIndex)
/*

All this following bogus crap is because Safari
doesn't recognize Wikipedia's date format.
Every other browser can just use the date string
object above, but Safari is retarded

*/
var str1 = /[A-z]+/
var str2 = /\d+/g
var monthtext = date.match(str1);
var testdate = date.match(str2);
var hours = testdate[0];
var minutes = testdate[1];
var day = testdate[2];
var year = testdate[3];
var months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
for (i in months) {
if (monthtext==months[i]) {
var month = i;
break;
}
i++
}
/*

End Safari madness

*/
date = new Date(year,month,day,hours,minutes);
return date;
}

var leftNode = document.getElementById('mw-diff-otitle1');
var rightNode = document.getElementById('mw-diff-ntitle1');
var firstDate = convertTimestampStringToDate('mw-diff-otitle1');
var secondDate = convertTimestampStringToDate('mw-diff-ntitle1');

function TimeBetweenDiffs() {

var minutesAgo = DateSub(firstDate,secondDate);

var newNode = document.createElement('span');
newNode.setAttribute('style', 'font-weight:bold; color:red;')
newNode.appendChild(document.createTextNode('(' + minutesAgo + ' later)'));
newNode.appendChild(document.createElement('br'));

rightNode.insertBefore(newNode, rightNode.firstChild);
}

function TimeSinceDiff() {
var DateNow = new Date();

var minutesAgo1 = DateSub(firstDate,DateNow);
var minutesAgo2 = DateSub(secondDate,DateNow);

document.getElementById('mw-diff-otitle1').title=minutesAgo1 + ' ago';
document.getElementById('mw-diff-ntitle1').title=minutesAgo2 + ' ago';

var t = setTimeout("TimeSinceDiff()",60000);
}

$(window).load(TimeSinceDiff); // Adds time since displayed diffs as tooltip
$(window).load(TimeBetweenDiffs); // Adds time between diffs

}

// Modified from [[User:Gary King/link intermediate revisions.js]]

if (typeof(unsafeWindow) != 'undefined')
{
var console = unsafeWindow.console;
importScriptURI = unsafeWindow.importScriptURI;
mw = unsafeWindow.mw;
}

mw.loader.using( ['mediawiki.util'], function () {
$(createDiffMultiLink);
});

function createDiffMultiLink()
{
if (!mw.util.getParamValue('diff') || !mw.util.getParamValue('oldid')) return false;
$.get(mw.config.get('wgScriptPath') + '/api.php', {
action: 'query',
prop: 'revisions',
titles: mw.config.get('wgPageName'),
rvprop: 'timestamp',
rvstartid: mw.util.getParamValue('diff'),
rvendid: mw.util.getParamValue('oldid'),
rvlimit: '5000',
format: 'json',
indexpageids: 1
}, diffMultiCallback);
}
function twoDigitPadding(integer)
{
var string = integer.toString();
if (string.length == 1) return '0' + integer;
else return integer;
}
function diffMultiCallback(response)
{
if (!response['query'] || !response['query']['pages'] || response['query']['pageids'][0] == -1) return false;
var diffMultis = $('#bodyContent .diff-multi');
if (!diffMultis.length) return false;
var pageId = response['query']['pageids'][0];
var page = response['query']['pages'][pageId];
var revisions = page['revisions'];
if (!revisions) return false;
var oldid = new Date(revisions[revisions.length - 1]['timestamp']);
oldid = oldid.getUTCFullYear().toString() + twoDigitPadding(oldid.getUTCMonth() + 1).toString() + oldid.getUTCDate().toString() + twoDigitPadding(oldid.getUTCHours() + 1).toString() + twoDigitPadding(oldid.getUTCMinutes() + 1).toString() + twoDigitPadding(oldid.getUTCSeconds() + 1).toString();
var diff = new Date(revisions[0]['timestamp']);
diff = diff.getUTCFullYear().toString() + twoDigitPadding(diff.getUTCMonth() + 1).toString() + diff.getUTCDate().toString() + twoDigitPadding(diff.getUTCHours() + 1).toString() + twoDigitPadding(diff.getUTCMinutes() + 1).toString() + twoDigitPadding(diff.getUTCSeconds() + 1).toString();
var diffMulti = diffMultis.eq(0);
var a = $('<a href="' + mw.config.get('wgScript') + '?title=' + mw.config.get('wgPageName') + '&action=history&offset=' + diff + '&limit=' + revisions.length + '"></a>').append(diffMulti.contents().eq(0));
diffMulti.append(a);
}

if (typeof inspectText == "undefined")
{
inspectText = "inspect&nbsp;diff";
}
if (typeof showText == "undefined")
{
showText = "show&nbsp;diff";
}
if (typeof hideText == "undefined")
{
hideText = "hide&nbsp;diff";
}
var specialPageName = mw.config.get("wgCanonicalSpecialPageName");
if (specialPageName == "Watchlist" ||
specialPageName == "Recentchanges" ||
specialPageName == "Contributions" ||
mw.config.get("wgAction") == "history" ||
specialPageName == "Recentchangeslinked" ||
(specialPageName == "Blankpage" && mw.config.get("wgTitle").indexOf("section-watchlist") > 0))
{
function inspectionEachHelper(index, element)
{
var findString;
if (mw.config.get("wgAction") == "history" || $(element).hasClass("mw-enhanced-rc-nested"))
{
findString = 'a:contains("prev")';
}
else
{
findString = 'a:contains("diff")';
}

var regex;

if (specialPageName == "Contributions")
{
regex = /&oldid=(\d+)$/;

}
else
{
regex = /(?:&diff=(\d+)&oldid=|&diff=prev&oldid=(\d+))/;
}
var diffLink = $(element).find(findString);
if (diffLink.length > 0)
{
var regexResult = regex.exec(diffLink[0].href);
if (regexResult != null && regexResult.length >= 2)
{
var diffID = regexResult[1] || regexResult[2];
//don't re-add if it already exists
if ($("#" + diffID).length > 0)
{
return;
}
var inlineDiffButton;
if (typeof inlineDiffBigUI === "undefined")
{
inlineDiffButton = document.createElement("a");
inlineDiffButton.href = "#";
inlineDiffButton.innerHTML = '<b><span style="color:black;"> [</span><span style="color:#008A00;">' + inspectText + '</span><span style="color:black;">] </span></b>';
}
else
{
inlineDiffButton = document.createElement("input");
inlineDiffButton.type = "button";
inlineDiffButton.value = "Inspect edit";
}
inlineDiffButton.id = diffID;
$(inlineDiffButton).addClass("inspectDiffButton");
$(inlineDiffButton).click(function ()
{
return inspectWatchlistDiff(this);
}
);
if ($(element).find("tr:first").length == 0)
{
$(element).find(".mw-changeslist-separator:first").css("padding-right", 0);
$(inlineDiffButton).insertAfter($(element).find(".mw-changeslist-separator:first"));
}
else
{
$(inlineDiffButton).insertBefore($(element).find(".mw-title"));
$(inlineDiffButton).addClass("mw-enhanced-rc-diff");
/*
$(element).find("tr:first").append("<td></td>");
$(element).find("tr:first>td:last").append(inlineDiffButton);
*/
}
}
}
}
function addWatchlistInspectionBoxes()
{
mw.loader.using("mediawiki.diff.styles").done(function()
{
var entries = $("#mw-content-text table.mw-enhanced-rc");
if (entries.length == 0)
{
$("#mw-content-text ul").each(function (ind, el)
{
$(el).children("li").each(inspectionEachHelper);
});
}
else
{
entries.each(inspectionEachHelper);
$("td.mw-enhanced-rc-nested").each(inspectionEachHelper);
}
});
}

function inspectWatchlistDiff(button)
{
mw.loader.using(['mediawiki.api']).done(function ()
{
var mwApi = new mw.Api();
mwApi.get(
{
action: "query",
prop: "revisions",
format: "json",
rvprop: "timestamp",
rvdiffto: "prev",
revids: button.id
}
).done(function (response)
{
if (response == null)
{
alert("Request failed!");
return false;
}

var diffString = response.query.pages[Object.keys(response.query.pages)[0]].revisions[0].diff["*"];

if (diffString == null)
{
alert("Request failed!");
return false;
}

var newTable = document.createElement("table");
newTable.className = "diff";
$(newTable).html('<colgroup><col class="diff-marker"><col class="diff-content"><col class="diff-marker"><col class="diff-content"></colgroup>');

$(newTable).append(diffString);
diffParent = null;
if ($("#" + button.id).hasClass("mw-enhanced-rc-diff"))
{
$("#" + button.id).parents("table").after(newTable);
}
else
{
diffParent = $("#" + button.id).parent();
diffParent.append(newTable);
}
newTable.id = button.id + "display";

mw.hook('new-diff-table').fire(newTable);

$(button).unbind("click");
if (typeof inlineDiffBigUI === "undefined")
{
$(button).html('<b><span style="color:black;"> [</span><span style="color:#008A00;">' + hideText + '</span><span style="color:black;">] </span></b>');
$(button).click(function ()
{
return hideSmallEditInspection(this);
}
);
}
else
{
$(button).attr("value", "Hide edit");
$(button).click(function ()
{
return hideEditInspection(this);
}
);
}
if (typeof markAsViewed != "undefined" && markAsViewed)
{
mwApi.postWithToken('csrf',
{
action: "setnotificationtimestamp",
revids: button.id
}
).done(function (data)
{
if (diffParent != null)
{
diffParent.removeClass("mw-changeslist-line-watched");
diffParent.addClass("mw-changeslist-line-not-watched");
}
}
);
}
}
);
}
);
return false;
}

function showEditInspection(button)
{
$("#" + button.id + "display").css("display", "");
$(button).attr("value", "Hide edit");
$(button).unbind("click");
$(button).click(function ()
{
return hideEditInspection(this);
}
);
return false;
}

function hideEditInspection(button)
{
$("#" + button.id + "display").css("display", "none");
$(button).attr("value", "Show edit");
$(button).unbind("click");
$(button).click(function ()
{
return showEditInspection(this);
}
);
return false;
}

function showSmallEditInspection(button)
{
$("#" + button.id + "display").css("display", "");
$(button).html('<b><span style="color:black;"> [</span><span style="color:#008A00;">' + hideText + '</span><span style="color:black;">] </span></b>');
$(button).unbind("click");
$(button).click(function ()
{
return hideSmallEditInspection(this);
}
);
return false;
}

function hideSmallEditInspection(button)
{
$("#" + button.id + "display").css("display", "none");
$(button).html('<b><span style="color:black;"> [</span><span style="color:#008A00;">' + showText + '</span><span style="color:black;">] </span></b>');
$(button).unbind("click");
$(button).click(function ()
{
return showSmallEditInspection(this);
}
);
return false;
}

mw.hook('wikipage.content').add(addWatchlistInspectionBoxes);
}

/*
* Pages Created -- finds all the pages created by a user
* see [[User:Jfmantis/pagesCreated]]
*/

(function() {

/*
* create <li> list item for one article
* right now, just a link to the page & the date
*/
function makeCreatedPageItem(contrib) {
var item = document.createElement("li");

var link = document.createElement("a");
link.href = mw.util.getUrl(contrib.title);
link.innerHTML = contrib.title;

item.appendChild(link);

item.innerHTML += " . . " + new Date(contrib.timestamp).toDateString();

return item;
}

/*
* looks through all of a user's non-minor namespace 0 edits,
* looking for edits tagged as "new"
*
* the arguments all in one object so that it can be expanded
* in the future without having to add a bunch more parameters
*/
function findPagesCreated(bundle) {
bundle.api.get({
action: "query",
rawcontinue: '',
list: "usercontribs",
ucuser: bundle.user,
ucstart: bundle.start,
ucprop: "flags|title|timestamp",
ucshow: "!minor",
uclimit: 500,
ucnamespace: 0
}).done( function(data) {
$.each(data.query.usercontribs, function(index, contrib) {
if (contrib.new != undefined) {
bundle.list.appendChild(makeCreatedPageItem(contrib));
bundle.count++;
}
});

if (data["query-continue"]) { // more contributions
bundle.start = data["query-continue"].usercontribs.ucstart
setTimeout(function() { findPagesCreated(bundle); }, 3000);
} else { // done
$("#pc-status")[0].innerHTML = "<br />" + bundle.user + " has created " + bundle.count + " articles";
}
}).fail( function(error) {
alert(error);
});
}

/*
* change title, clear content area, etc.
*/
function setupPagesCreated(user) {
// set new title
mw.util.$content.find("#firstHeading")[0].innerHTML = "Pages created by " + user;

// status bar (text + waiting gif)
var status = document.createElement("span");
status.id = "pc-status";
status.innerHTML = "<br />Fetching user data...";

// heading for results
var heading = document.createElement("h3");
heading.innerHTML = "Articles";

// list of results
var articles = document.createElement("ul");
articles.id = "pc-articles";

var body = mw.util.$content.find("#bodyContent")[0];
body.innerHTML = "";
body.appendChild(status);
body.appendChild(heading);
body.appendChild(articles);

var api = new mw.Api();
api.get({
action: "query",
list: "users",
ususers: user,
usprop: "editcount"
}).done(function(data) {
// 500 results per request, 1 request every 3 seconds
var count = data.query.users[0].editcount;
status.innerHTML = "<br />User has " + count + " edits, this should take less than ";
status.innerHTML += (3 * Math.round(count / 500)) + " seconds &nbsp;&nbsp;&nbsp;";

var waitgif = document.createElement("img");
waitgif.src = "https://upload.wikimedia.org/wikipedia/commons/4/42/Loading.gif";
status.appendChild(waitgif);

findPagesCreated(
{"api": api,
"user": user,
"list": articles,
"start": "",
"count": 0}
);
}).fail(function(error) {
alert(error);
});

return false;
}

mw.loader.using("mediawiki.util", function() {
// add portlet when page is User or User_talk, but not on subpages
if ((wgNamespaceNumber == 2 || wgNamespaceNumber == 3) && (wgTitle.indexOf("/") == -1)) {
if (mw.util.getParamValue("pagesCreated")) {
setupPagesCreated(wgTitle);
} else {
mw.util.addPortletLink("p-tb",
document.location.toString() + "?pagesCreated=true",
"Pages created", "pc-pages",
"Get a list of all pages created by this user"
);
}
}
});

})();

if ( mw.config.get( "wgAction" ) === "history" ) {
$( document ).ready( function() {
"use strict";
const HC = document.getElementById( "mw-history-compare" );
if ( HC ) {
const PH = document.getElementById( "pagehistory" ),
BTNS = HC.querySelectorAll( 'input[value="Compare selected revisions"]' ),
TOP = BTNS[ 0 ],
BTM = BTNS[ 1 ],
encapsulate = function() {
const LSB = PH.querySelector( 'li.selected.before' ),
LSA = PH.querySelector( 'li.selected.after' );
if ( TOP && LSB ) {
PH.insertBefore( TOP, LSB );
}
if ( BTM && LSA ) {
const NES = LSA.nextElementSibling;
if ( NES ) {
PH.insertBefore( BTM, NES );
} else {
PH.appendChild( BTM );
}
}
/* move buttons added by User:Enterprisey/cv-revdel.js along with the "Compare selected revisions" buttons */
HC.querySelectorAll( "button.cv-rd-add-range" ).forEach( function( b, i ) { PH.insertBefore( b, BTNS[ i ] ) } );
};
encapsulate();
HC.addEventListener( "change", encapsulate );
}
} );
}

/* Rollback all */
$( function() {
if ( $('span.mw-rollback-link')[0] && mw.config.get( 'wgCanonicalSpecialPageName' ) == 'Contributions' )
mw.util.addPortletLink( 'p-cactions', 'javascript:rollbackEverything()', "rollback all", "ca-rollbackeverything", "Rollback all top edits displayed here" );
} );
function rollbackEverything() {
for ( var i in document.links ) {
if ( document.links[i].href.indexOf( 'action=rollback' ) != -1 )
window.open( document.links[i].href+'&bot=1' );
}
}

/* Interface modifications */

$( function(){

// These add action tabs at the top of a page

if( mw.config.get( 'wgNamespaceNumber' ) > -1 ) {
mw.util.addPortletLink( 'p-cactions', '/wiki/Special:PrefixIndex/' + wgPageName, 'Subpages', 'd-subpages', 'List subpages and other pages starting with this title' );
mw.util.addPortletLink( 'p-cactions', '/w/index.php?title=Special:Log&page=' + wgPageName, 'Logs', 'd-logs', 'Show any relevant logs for this title' );
mw.util.addPortletLink( 'p-cactions', '/wiki/' + wgPageName + '?action=purge', 'Purge', 'd-purge', 'Purge the current page' );
// mw.util.addPortletLink( 'p-cactions', '/wiki/' + wgPageName + '?useskin=vector', 'Vector', 'd-vector', 'View page in the Vector skin' );
}

// These add personal links at the top right of every page

mw.util.addPortletLink( 'p-personal', '/wiki/Special:ListFiles/' + wgUserName, 'Uploads', 'pt-uploads' );
mw.util.addPortletLink( 'p-personal', '/wiki/Special:Log/' + wgUserName, 'Logs', 'pt-logs' );
mw.util.addPortletLink( 'p-personal', '/wiki/Special:PrefixIndex/User:'+ wgUserName, 'Subpages', 'pt-subpages' );

$("#pt-logout").hide();

// These add toolbox links to the sidebar of every page

mw.util.addPortletLink( 'p-tb', 'https://en.uncyclopedia.co/wiki/User:Zombiebaron/2019.js', '2019.js Project', 't-2019' );
mw.util.addPortletLink( 'p-tb', 'https://en.uncyclopedia.co/wiki/User:Zombiebaron/Images', 'Images', 't-images' );
mw.util.addPortletLink( 'p-tb', 'https://en.uncyclopedia.co/wiki/Special:MassDelete', 'mass delete', 't-massdelete' );



$('#n-currentevents').after($('#n-recentchanges'));
$('#n-recentchanges').css({ 'font-weight': 'bold' });

} );

/* Edit counter in top bar - by Wikipedia:User:Mvolz */

$(document).ready( function () {
mw.loader.using( 'mediawiki.user', function() {
( new mw.Api() ).get( {
action: 'query',
meta: 'userinfo',
uiprop: 'editcount'
} ).done( function( result ) {
document.getElementById( 'pt-mycontris' ).append( ' (' + result.query.userinfo.editcount + ')' );
} );
} );
} );

// Stolen from https://en.wikipedia.org/w/index.php?title=User:PleaseStand/userinfo.js&oldid=803890891 to tweak some options
// See also [[User:Equazcion/sysopdetector.js]] and [[User:Anomie/useridentifier.js]]
// based on [[User:Fran Rogers/dimorphism.js]] and [[User:Splarka/sysopdectector.js]]

// Display on all user (sub)pages and contribs, logs, etc.
// Edit counter link for current project
// Show a symbol if no gender pronoun selected
// Don't show the "From Wikipedia" if showing userinfo
// Add option to disable for self



// userinfoHideSelf defaults to off
if (window.userinfoHideSelf === undefined || typeof window.userinfoHideSelf !== 'boolean') {
window.userinfoHideSelf = false;
}


function UserinfoJsFormatQty(qty, singular, plural) {
return String(qty).replace(/\d{1,3}(?=(\d{3})+(?!\d))/g, "$&,") + "\u00a0" + (qty == 1 ? singular : plural);
}

function UserinfoJsFormatDateRel(old) {
// The code below requires the computer's clock to be set correctly.
var age = new Date().getTime() - old.getTime();
var ageNumber, ageRemainder, ageWords;
if(age < 60000) {
// less than one minute old
ageNumber = Math.floor(age / 1000);
ageWords = UserinfoJsFormatQty(ageNumber, "second", "seconds");
} else if(age < 3600000) {
// less than one hour old
ageNumber = Math.floor(age / 60000);
ageWords = UserinfoJsFormatQty(ageNumber, "minute", "minutes");
} else if(age < 86400000) {
// less than one day old
ageNumber = Math.floor(age / 3600000);
ageWords = UserinfoJsFormatQty(ageNumber, "hour", "hours");
ageRemainder = Math.floor((age - ageNumber * 3600000) / 60000);
} else if(age < 604800000) {
// less than one week old
ageNumber = Math.floor(age / 86400000);
ageWords = UserinfoJsFormatQty(ageNumber, "day", "days");
} else if(age < 2592000000) {
// less than one month old
ageNumber = Math.floor(age / 604800000);
ageWords = UserinfoJsFormatQty(ageNumber, "week", "weeks");
} else if(age < 31536000000) {
// less than one year old
ageNumber = Math.floor(age / 2592000000);
ageWords = UserinfoJsFormatQty(ageNumber, "month", "months");
} else {
// one year or older
ageNumber = Math.floor(age / 31536000000);
ageWords = UserinfoJsFormatQty(ageNumber, "year", "years");
ageRemainder =
Math.floor((age - ageNumber * 31536000000) / 2592000000);
if(ageRemainder) {
ageWords += " " +
UserinfoJsFormatQty(ageRemainder, "month", "months");
}
}
return ageWords;
}

// If on a user or user talk page
if (mw.config.exists('wgRelevantUserName') && !(window.userinfoHideSelf && mw.config.get('wgRelevantUserName') === mw.config.get('wgUserName'))) {
// add a hook to...
mw.loader.using( ['mediawiki.util'], function() { $(function(){
// Request the user's information from the API.
// Note that this is allowed to be up to 5 minutes old.
var et = encodeURIComponent(mw.config.get("wgRelevantUserName"));

$.getJSON(mw.config.get("wgScriptPath") + "/api.php?format=json&action=query&list=users|usercontribs&usprop=blockinfo|editcount|gender|registration|groups&uclimit=1&ucprop=timestamp&ususers=" + et + "&ucuser=" + et + "&meta=allmessages&amprefix=grouppage-&amincludelocal=1")
.done(function(query) {
// When response arrives extract the information we need.
if(!query.query) { return; } // Suggested by Gary King to avoid JS errors --PS 2010-08-25
query = query.query;
var user, invalid, missing, groups, groupPages={}, editcount, registration, blocked, partial, gender, lastEdited;
try {
user = query.users[0];
invalid = typeof user.invalid != "undefined";
missing = typeof user.missing != "undefined";
groups = (typeof user.groups == "object") ? user.groups : [];
editcount = (typeof user.editcount == "number") ? user.editcount : null;
registration = (typeof user.registration == "string") ?
new Date(user.registration) : null;
blocked = typeof user.blockedby != "undefined";
partial = typeof user.blockpartial != "undefined";
gender = (typeof user.gender == "string") ? user.gender : null;
lastEdited = (typeof query.usercontribs[0] == "object") &&
(typeof query.usercontribs[0].timestamp == "string") ?
new Date(query.usercontribs[0].timestamp) : null;
for (var am=0; am<query.allmessages.length; am++) {
groupPages[query.allmessages[am]["name"].replace("grouppage-","")] = query.allmessages[am]["*"].replace("{{ns:project}}:","Project:");
}
} catch(e) {
return; // Not much to do if the server is returning an error (e.g. if the username is malformed).
}

// Format the information for on-screen display

var statusText = "";
var ipUser = false;
var ipv4User = false;
var ipv6User = false;

// User status
if(blocked) {
statusText += "<a href=\"" + mw.config.get("wgScript") +
"?title=Special:Log&amp;page=" +
encodeURIComponent(mw.config.get("wgFormattedNamespaces")[2] + ":" + user.name) +
"&amp;type=block\">" + (partial ? 'partially ' : '') + "blocked</a> ";
}
if (missing) {
statusText += "username not registered";
} else if (invalid) {
ipv4User = mw.util.isIPv4Address(user.name);
ipv6User = mw.util.isIPv6Address(user.name);
ipUser = ipv4User || ipv6User;
if (ipv4User) {
statusText += "anonymous IPv4 user";
} else if (ipv6User) {
statusText += "anonymous IPv6 user";
} else {
statusText += "invalid username";
}
} else {
// User is registered and may be in a privileged group. Below we have a list of user groups.
// Only need the ones different from the software's name (or ones to exclude), though.
var friendlyGroupNames = {
// Exclude implicit user group information provided by MW 1.17 --PS 2010-02-17
'*': false,
'user': false,
'autoconfirmed': false,
abusefilter: "edit filter manager",
'abusefilter-helper': "abuse filter helper",
autopatrolled: "autopatrolled user",
bureaucrat: "bureaucrat",
extendedconfirmed: "extended confirmed user",
'interface-admin': "interface op",
'empress': "empress",
'ipblock-exempt': "IP block exemption",
rollback: "rollbacker",
sysop: "administrator",
'sysadmin': "sysadmin",
};

var friendlyGroups = [];
for(var i = 0; i < groups.length; ++i) {
var s = groups[i];
var t = friendlyGroupNames.hasOwnProperty(s) ? friendlyGroupNames[s] : s;
if (t) {
if (groupPages.hasOwnProperty(s)) {
friendlyGroups.push("<a href=\"" + mw.config.get("wgArticlePath").replace("$1", encodeURIComponent( groupPages[s] )) + "\">" + t + "</a>");
} else {
friendlyGroups.push(t);
}
}
}
switch(friendlyGroups.length) {
case 0:
// User not in a privileged group
// Changed to "registered user" by request of [[User:Svanslyck]]
// --PS 2010-05-16

// statusText += "user";
if(blocked) {
statusText += "user";
} else {
statusText += "registered user";
}
break;
case 1:
statusText += friendlyGroups[0];
break;
case 2:
statusText += friendlyGroups[0] + " and " + friendlyGroups[1];
break;
default:
statusText += friendlyGroups.slice(0, -1).join(", ") +
", and " + friendlyGroups[friendlyGroups.length - 1];
break;
}
}

// Registration date
if(registration) {
var firstLoggedUser = new Date("09 07, 2005 22:16Z"); // When the [[Special:Log/newusers]] was first activated
if(registration >= firstLoggedUser) {
statusText += ", <a href='" + mw.config.get("wgScript") +
"?title=Special:Log&amp;type=newusers&amp;dir=prev&amp;limit=1&amp;user=" +
et + "'>" + UserinfoJsFormatDateRel(registration) + "</a> old";
} else {
statusText += ", <a href='" + mw.config.get("wgScript") +
"?title=Special:ListUsers&amp;limit=1&amp;username=" +
et + "'>" + UserinfoJsFormatDateRel(registration) + "</a> old";
}
}

// Edit count
if(editcount !== null) {
statusText += ", with " +
"<a href=\"//celeste.ink/wiki/Special:Editcount" +
"/" + encodeURIComponent(user.name) + "\">" +
UserinfoJsFormatQty(editcount, "edit", "edits") + "</a>";
}

// Prefix status text with correct article
if("AEIOaeio".indexOf(statusText.charAt(statusText.indexOf('>')+1)) >= 0) {
statusText = "An " + statusText;
} else {
statusText = "A " + statusText;
}

// Add full stop to status text
statusText += ".";

// Last edited --PS 2010-06-27
// Added link to contributions page --PS 2010-07-03
if(lastEdited) {
statusText += " Last edited <a href=\"" + mw.config.get("wgArticlePath").replace("$1", "Special:Contributions/" + encodeURIComponent(user.name)) + "\">" + UserinfoJsFormatDateRel(lastEdited) + " ago</a>.";
}

// Show the correct gender symbol
var fh = document.getElementById("firstHeading") ||
document.getElementById("section-0");
// Add classes for blocked, registered, and anonymous users
var newClasses = [];
if(blocked) {
newClasses.push("ps-blocked");
}
if(ipUser) {
newClasses.push("ps-anonymous");
} else if(invalid) {
newClasses.push("ps-invalid");
} else {
newClasses.push("ps-registered");
}
fh.className += (fh.className.length ? " " : "") + groups.map(function(s) {
return "ps-group-" + s;
}).concat(newClasses).join(" ");
var genderSpan = document.createElement("span");
genderSpan.id = "ps-gender-" + (gender || "unknown");
genderSpan.style.paddingLeft = "0.25em";
genderSpan.style.fontFamily = '"Lucida Grande", "Lucida Sans Unicode", "sans-serif"';
genderSpan.style.fontSize = "75%";
var genderSymbol;
switch(gender) {
case "male": genderSymbol = "\u2642"; break;
case "female": genderSymbol = "\u2640"; break;
default: genderSymbol = "\u2609"; break;
//See https://en.wikipedia.org/wiki/Miscellaneous_Symbols
}
genderSpan.appendChild(document.createTextNode(genderSymbol));
fh.appendChild(genderSpan);

// Now show the other information. Non-standard? Yes, but it gets the job done.
// Add a period after the tagline when doing so. --PS 2010-07-03

var ss = document.getElementById("siteSub");
if(!ss) {
ss = document.createElement("div");
ss.id = "siteSub";
ss.innerHTML = "";
var bc = document.getElementById("bodyContent");
bc.insertBefore(ss, bc.firstChild);
}
// ss.innerHTML = '<span id="ps-userinfo">' + statusText + '</span> ' + ss.innerHTML + '.';
ss.innerHTML = '<span id="ps-userinfo">' + statusText + '</span>';
ss.style.display = "block";
});
}); });
}

Latest revision as of 01:00, 17 May 2021

// Highlight admins
;(function($, mw){
	$.getJSON(mw.config.get('wgScriptPath')+'/index.php?action=raw&ctype=application/json&title=User:Amalthea_(bot)/userhighlighter.js/sysop.js', function(data){
		ADMINHIGHLIGHT_EXTLINKS = window.ADMINHIGHLIGHT_EXTLINKS || false;
		ADMINHIGHLIGHT_NAMESPACES = [-1,2,3];
		mw.loader.using(['mediawiki.util','mediawiki.Uri', 'mediawiki.Title'], function() {
			mw.util.addCSS(".userhighlighter_sysop.userhighlighter_sysop {background-color: #00FFFF !important}");
			$('#bodyContent a').each(function(index,linkraw){
				try {
					var link = $(linkraw);
					var url = link.attr('href');
					if (!url || url.charAt(0) === '#') return; // Skip <a> elements that aren't actually links; skip anchors
					if (url.lastIndexOf("http://", 0) != 0 && url.lastIndexOf("https://", 0) != 0 && url.lastIndexOf("/", 0) != 0) return; //require http(s) links, avoid "javascript:..." etc. which mw.Uri does not support
					var uri = new mw.Uri(url);
					if (!ADMINHIGHLIGHT_EXTLINKS && !$.isEmptyObject(uri.query)) return; // Skip links with query strings if highlighting external links is disabled
					if (uri.host == 'en.wikipedia.org') {
						var mwtitle = new mw.Title(mw.util.getParamValue('title',url) || decodeURIComponent(uri.path.slice(6))); // Try to get the title parameter of URL; if not available, remove '/wiki/' and use that
						if ($.inArray(mwtitle.getNamespaceId(), ADMINHIGHLIGHT_NAMESPACES)>=0) {
							var user = mwtitle.getMain().replace(/_/g," ");
							if (mwtitle.getNamespaceId() === -1) user = user.replace('Contributions/',''); // For special page "Contributions/<username>"
							if (data[user] == 1) {
								link.addClass('userhighlighter_sysop'); // Override the above color by using `a.userhighlighter_sysop.userhighlighter_sysop {background-color: COLOR !important}`
							}
						}
					}
				} catch (e) {
					// Sometimes we will run into unparsable links, so just log these and move on
					window.console && console.error('Admin highlighter recoverable error',e.message);
				}
			});
		});
	});
}(jQuery, mediaWiki));

/**
 * SkinSwitcher.js
 * @file Allows for easy switching between seven main skins, and Timeless
 * @author Eizzen <en.wikipedia.org/wiki/User_talk:Eizzen>
 * @timeless added by Zombiebaron
 * @license Apache-2.0
 * @external "jQuery"
 * @external "mediawiki.util"
 */

/*jslint browser, this:true */
/*global mw, jQuery, window */

mw.loader.using("mediawiki.util", function () {
    "use strict";

    /**
     * @class SkinSwitcher
     * @classdesc The central SkinSwitcher class
     */
    var SkinSwitcher = {
        lang: {
            script: "Skin Switcher",
            viewIn: "View this page in $1 skin"
        },
        skins: {
            "vector": "Vector",
            "monobook": "MonoBook",
            "modern": "Modern",
            "minerva": "Minerva",
            "minervaneue": "MinervaNeue",
            "cologneblue": "CologneBlue",
            "apioutput": "ApiOutput",
            "timeless": "Timeless"
        },
        /**
         * @method constructElement
         * @param {string} $selectedSkin
         * @param {string} $itemText
         * @returns {html}
         */
        constructElement: function ($selectedSkin, $itemText) {
            var $href = window.location.href;
            var $param = (window.location.search)
                ? "&"
                : "?";

            return mw.html.element("li", {
                "id": "skinSwitcher-li-" + $selectedSkin,
                "class": "skinSwitcher-li"
            }, new mw.html.Raw(
                mw.html.element("a", {
                    "href": $href.replace(/#.*/, "") +
                            $param + jQuery.param({useskin: $selectedSkin}),
                    "title": this.lang.viewIn.replace("$1", $itemText),
                    "id": "skinSwitcher-a-" + $selectedSkin,
                    "class": "skinSwitcher-a"
                }, $itemText)
            ));
        },
        /**
         * @method assembleElements
         * @returns {string[] } $elementsArray
         */
        assembleElements: function () {
            var $elementsArray = [];

            Object.keys(this.skins).forEach(function ($property) {
                $elementsArray.push(
                    this.constructElement($property, this.skins[$property])
                );
            }, this);

            return $elementsArray;
        },
        /**
         * @method cloneMenu
         * @param {string} $template
         * @returns {void}
         */
        cloneMenu: function ($template) {
            jQuery($template)
                .clone()
                .attr("id", "skinSwitcher")
                .insertAfter($template);
            jQuery("#skinSwitcher h3")
                .html("<span>" + this.lang.script + "</span>");
            jQuery("#skinSwitcher ul").empty();
        },
        /**
         * @method experimentalPlacement
         * @returns {void}
         */
        experimentalPlacement: function () {
            // Experimental CSS to center links horizontally in header
            mw.util.addCSS(
                "#skinSwitcher {" +
                    "display: flex;" +
                    "justify-content: center;" +
                    "flex-direction: row;" +
                    "align-items: center;" +
                "}" +
                ".skinSwitcher-li {" +
                    "display:inline-block;" +
                    "margin:5px 25px 0 25px;" +
                "}"
            );

            jQuery("<ul>", {
                id: "skinSwitcher"
            }).prependTo(".mw-body");
        },
        /**
         * @method determinePlacement
         * @param {string[] } $assembledElements
         * @returns {void}
         */
        determinePlacement: function ($assembledElements) {
            var $appendLocation;

            switch (this.currentSkin) {
            case "vector":
            case "monobook":
            case "modern":
            case "cologneblue":
                this.cloneMenu("#p-tb");
                $appendLocation = jQuery("#skinSwitcher ul");
                break;
            case "minerva":
            case "minervaneue":
            case "apioutput":
                this.experimentalPlacement();
                $appendLocation = jQuery("#skinSwitcher");
                break;
            case "timeless":
            }

            $assembledElements.forEach(function ($element) {
                jQuery($element).appendTo($appendLocation);
            });
        },
        /**
         * @method init
         * @returns {void}
         */
        init: function () {
            if (
                window.isSkinSwitcherLoaded ||
                jQuery("#skinSwitcher").length
            ) {
                return;
            }

            window.isSkinSwitcherLoaded = true;
            this.currentSkin = mw.config.get("skin");

            if (this.skins.hasOwnProperty(this.currentSkin)) {
                delete this.skins[this.currentSkin];
                this.determinePlacement(this.assembleElements());
            }
        }
    };

    jQuery(document).ready(function () {
        SkinSwitcher.init();
    });
});

// Creates a link and an html class to invert the screen
// Documentation at [[w:User:BrandonXLF/Invert]]

mw.loader.load('//en.uncyclopedia.co/w/index.php?title=User:Zombiebaron/Invert.css&action=raw&ctype=text/css', 'text/css'); // Import stylesheet

$(function() {
	function update(){                                                          // Function to update filter 
		if(mw.storage.get('InvertPage') == 'true'){  
			$(document.body).addClass('inverted-colors'); // Add CSS
		}else{
			$(document.body).removeClass('inverted-colors'); // Remove CSS
		} 
	}
	
	function set(e){                                                            // Function to set web storage and update filter
		e.preventDefault();                                                     // Pervent default action
		if(mw.storage.get('InvertPage') == 'true'){                        
			mw.storage.set('InvertPage','false');
		}else{
			mw.storage.set('InvertPage','true');
		} 
		update();                                                               // Update fiter
	}
	
	var node = mw.util.addPortletLink(                                          // Add link
	    'p-personal',
	    "https://en.wikipedia.org/wiki/User:BrandonXLF/Invert/select",          // Backup link to URL
	    '🌛',
	    'night mode',
	    'enter night mode',
	    'n',
	    '#pt-mytalk'
	);
	
	update();  
	
	$(node).on('click',function(e){                                         	// Make the dark mode link work
		set(e);
	});
	
	$('#ToggleWikiInvert').click(function(e){               					// Allow for id to toggle dark mode
		set(e);
	}); 
	
	$('.ToggleWikiInvert').click(function(e){                             		// Allow to CSS class to toggle dark mode
		set(e);
	}); 
});

mw.loader.using(['mediawiki.api', 'mediawiki.Title'], function () {
	"use strict";

	var config = mw.config.get(['wgNamespaceNumber', 'wgTitle', 'wgUserGroups', 'skin']);

	function removeBlanks(arr) {
		var ret = [];
		var i, len;
		for (i = 0, len = arr.length; i < len; i++) {
			var s = arr[i];
			s = s.trim();
			if (s) {
				ret.push(s);
			}
		}
		return ret;
	}

	function doMassDelete() {
		document.getElementById("wpMassDeleteSubmit").disabled = true;
		var articles = document.getElementById("wpMassDeletePages").value.split("\n");
		articles = removeBlanks(articles);
		if (!articles.length) {
			return;
		}
		var
			api = new mw.Api(),
			wpMassDeleteReasons = document.getElementById("wpMassDeleteReasons").value,
			wpMassDeleteReason = document.getElementById("wpMassDeleteReason").value,
			deleted = 0,
			failed = [],
			error = [],
			deferreds = [],
			reason = wpMassDeleteReasons == "other" ?
				wpMassDeleteReason :
				wpMassDeleteReasons + (wpMassDeleteReason ? " (" + wpMassDeleteReason + ")" : ""),
			onSuccess = function () {
				deleted++;
				document.getElementById("wpMassDeleteSubmit").value = "(" + deleted + ")";
			};

		function makeDeleteFunc(article) {
			return function () {
				return $.Deferred(function (deferred) {
					var promise = api.postWithToken('delete', {
						format: 'json',
						action: 'delete',
						title: article,
						reason: reason
					});
					promise.done(onSuccess);
					promise.fail(function (code, obj) {
						failed.push(article);
						error.push(obj.error.info);
					});
					promise.always(function () {
						deferred.resolve();
					});
				});
			};
		}

		// Make a chain of deferred objects. We chain them rather than execute them in
		// parallel so that we don't make 1000 simultaneous delete requests and bring the
		// site down. We use deferred objects rather than the promise objects returned
		// from the API request so that the chain continues even if some articles gave
		// errors.
		var deferred = makeDeleteFunc(articles[0])();
		for (var i = 1, len = articles.length; i < len; i++) {
			deferred = deferred.then(makeDeleteFunc(articles[i]));
		}

		// Show the output and do cleanup once all the requests are done.
		$.when(deferred).then(function () {
			document.getElementById("wpMassDeleteSubmit").value = "Done (" + deleted + ")";
			if (failed.length) {
				var $failedList = $('<ul>');
				for(var x = 0; x < failed.length; x++) {
					// Link the titles in the "failed" array
					var failedTitle = mw.Title.newFromText(failed[x]);
					var $failedItem = $('<li>');
					if (failedTitle) {
						$failedItem.append( $('<a>')
							.attr('href', failedTitle.getUrl())
							.text(failed[x])
						);
					} else {
						$failedItem.text(failed[x]);
					}
					$failedItem.append(document.createTextNode(': ' + error[x]));
					$failedList.append($failedItem);
				}
				$('#wpMassDeleteFailedContainer')
					.append($('<br />'))
					.append($('<b>')
						.text('Failed deletions:')
					)
					.append($failedList);
			}
		});
	}
	 
	function massdeleteform() {
		var bodyContent = (config.skin == "cologneblue" ? "article" : "bodyContent");
		document.getElementsByTagName("h1")[0].textContent = "Animum's mass-deletion tool";
		document.title = "Animum's mass-deletion tool - Wikipedia, the free encyclopedia";
		document.getElementById(bodyContent).innerHTML = '<h3 id="siteSub">From Wikipedia, the free encyclopedia</h3><br /><br />' +
			'<form id="wpMassDelete" name="wpMassDelete">' +
			'<b>If you abuse this tool, it\'s <i>your</i> fault, not mine.</b>' +
			'<div id="wpMassDeleteFailedContainer"></div>' +
			'<br /><br />' +
				'Pages to delete (one on each line, please):<br />' +
					'<textarea tabindex="1" accesskey="," name="wpMassDeletePages" id="wpMassDeletePages" rows="10" cols="80"></textarea>' +
				'<br /><br /><table style="background-color:transparent">' +
					'<tr><td>Common reasons:</td>' +
						'<td><select id="wpMassDeleteReasons">' +
							'<optgroup label="Other reason">' +
								'<option value="other">Other reason</option>' +
							'</optgroup>' +
							'<optgroup label="Criteria for speedy deletion">' +
								'<optgroup label="General criteria">' +
									'<option value="[[WP:CSD#G1|G1]]: [[WP:PN|Patent nonsense]], meaningless, or incomprehensible">G1: Patent nonsense</option>' +
									'<option value="[[WP:CSD#G2|G2]]: Test page">G2: Test page</option>' +
									'<option value="[[WP:CSD#G3|G3]]: [[WP:Vandalism|Vandalism]]">G3: Vandalism</option>' +
									'<option value="[[WP:CSD#G3|G3]]: Blatant [[WP:Do not create hoaxes|hoax]]">G3: Hoax</option>' +
									'<option value="[[WP:CSD#G4|G4]]: Recreation of a page that was [[WP:DEL|deleted]] per a [[WP:XFD|deletion discussion]]">G4: Repost</option>' +
									'<option value="[[WP:CSD#G5|G5]]: Creation by a [[WP:BLOCK|blocked]] or [[WP:BAN|banned]] user in violation of block or ban">G5: Banned</option>' +
									'<option value="[[WP:CSD#G6|G6]]: Housekeeping and routine (non-controversial) cleanup">G6: Maintenance</option>' +
									'<option value="[[WP:CSD#G7|G7]]: One author who has requested deletion or blanked the page">G7: Author</option>' +
									'<option value="[[WP:CSD#G8|G8]]: Page dependent on a deleted or nonexistent page">G8: Orphaned talk page</option>' +
									'<option value="[[WP:CSD#G10|G10]]: [[WP:ATP|Attack page]] or negative unsourced [[WP:BLP|BLP]]">G10: Attack page</option>' +
									'<option value="[[WP:CSD#G11|G11]]: Unambiguous [[WP:NOTADVERTISING|advertising]] or promotion">G11: Advertising</option>' +
									'<option value="[[WP:CSD#G12|G12]]: Unambiguous [[WP:CV|copyright infringement]]">G12: Copyvio</option>' +
									'<option value="[[WP:CSD#G13|G13]]: Abandoned draft or [[WP:AFC|Articles for Creation]] submission – to retrieve it, see [[WP:REFUND/G13]]">G13: Abandoned draft</option>' +
								'</optgroup>' +
								'<optgroup label="Articles">' +
									'<option value="[[WP:CSD#A1|A1]]: Short article without enough context to identify the subject">A1: No context</option>' +
									'<option value="[[WP:CSD#A2|A2]]: Article in a foreign language that exists on another project">A2: Foreign</option>' +
									'<option value="[[WP:CSD#A3|A3]]: Article that has no meaningful, substantive content">A3: No content</option>' +
									'<option value="[[WP:CSD#A5|A5]]: Article that has been transwikied to another project">A5: Transwiki</option>' +
									'<option value="[[WP:CSD#A7|A7]]: No credible indication of importance (individuals, animals, organizations, web content, events)">A7: Non-notable individual, animal, organization, web content, or event</option>' +
									'<option value="[[WP:CSD#A9|A9]]: Music recording by redlinked artist and no indication of importance or significance">A9: Non-notable recording by redlinked artist</option>' +
									'<option value="[[WP:CSD#A10|A10]]: Recently created article that duplicates an existing topic">A10: Recently created article that duplicates an existing topic</option>' +
									'<option value="[[WP:CSD#A11|A11]]: [[Wikipedia:Wikipedia is not for things made up one day|Made up]] by article creator or an associate, and no indication of importance/significance">A11: Made up</option>' +
								'</optgroup>' +
								'<optgroup label="Redirects">' +
									'<option value="[[WP:CSD#R2|R2]]: Cross-[[WP:NS|namespace]] [[WP:R|redirect]] from mainspace">R2: Cross-namespace</option>' +
									'<option value="[[WP:CSD#R3|R3]]: Recently created, implausible [[WP:R|redirect]]">R3: Implausible redirect</option>' +
								'</optgroup>' +
								'<optgroup label="Images and other media">' +
									'<option value="[[WP:CSD#F1|F1]]: File redundant to another on Wikipedia">F1: Redundant</option>' +
									'<option value="[[WP:CSD#F2|F2]]: Corrupt or empty file, or a file description page for a file on Commons">F2: Corrupt, empty. or Commons</option>' +
									'<option value="[[WP:CSD#F3|F3]]: File with improper license">F3: File with improper license</option>' +
									'<option value="[[WP:CSD#F4|F4]]: Lack of licensing information">F4: Lack of licensing information</option>' +
									'<option value="[[WP:CSD#F5|F5]]: Unused non-free media">F5: Unfree and unused</option>' +
									'<option value="[[WP:CSD#F6|F6]]: Non-free file without [[WP:RAT|fair-use rationale]]">F6: No rationale</option>' +
									'<option value="[[WP:CSD#F7|F7]]: [[WP:NFCC|Invalid]] fair-use claim">F7: Bad fair use rationale</option>' +
									'<option value="[[WP:CSD#F8|F8]]: Media file available on Commons">F8: On Commons</option>' +
									'<option value="[[WP:CSD#F9|F9]]: File [[WP:COPYVIO|copyright violation]]">F9: File copyvio</option>' +
									'<option value="[[WP:CSD#F10|F10]]: Useless media file">F10: Useless media file</option>' +
									'<option value="[[WP:CSD#F11|F11]]: No evidence of permission">F11: No permission</option>' +
								'</optgroup>' +
								'<optgroup label="Categories">' +
									'<option value="[[WP:CSD#C1|C1]]: Empty category">C1: Empty</option>' +
									'<option value="[[WP:CSD#C2|C2]]: Speedy renaming">C2: Speedy rename</option>' +
									'<option value="[[WP:CSD#G8|G8]]: Populated by deleted or retargeted template">G8: Populated by deleted or retargeted template</option>' +
								'</optgroup>' +
								'<optgroup label="User namespace">' +
									'<option value="[[WP:CSD#U1|U1]]: User request to delete page in own userspace">U1: User requests deletion</option>' +
									'<option value="[[WP:CSD#U2|U2]]: Userpage or subpage of a nonexistent user">U2: Non-existent user</option>' +
									'<option value="[[WP:CSD#U3|U3]]: [[WP:NFC|Non-free]] [[Help:Gallery|gallery]]">U3: Fair use gallery</option>' +
									'<option value="[[WP:CSD#U5|U5]]: [[WP:NOTWEBHOST|Misuse of Wikipedia as a web host]]">U5: Misuse as webhost</option>' +
								'</optgroup>' +
								'<optgroup label="Templates">' +
									'<option value="[[WP:CSD#T3|T3]]: Unused, redundant template">T3: Redundant and unused</option>' +
									'<option value="[[WP:CSD#G8|G8]]: Component or documentation of a deleted template">G8: component of deleted template</option>' +
								'</optgroup>' +
								'<optgroup label="Portals">' +
									'<option value="[[WP:CSD#P1|P1]]: [[WP:P|Portal]] page that would be subject to speedy deletion as an article">P1: Deletion as article</option>' +
									'<option value="[[WP:CSD#P2|P2]]: [[WP:P|Portal]] without a substantial topic base">P2: Underpopulated</option>' +
								'</optgroup>' +
								'<optgroup label="Other">' +
									'<option value="[[WP:PROD]]: Nominated for seven days with no objection">PRODded for more than 7 days without objection</option>' +
									'<option value="[[WP:BLPPROD]]: Nominated for seven days with no reliable sources present in the article">BLPPRODded for more than seven days without a source</option>' +
									'<option value="Listed at [[Wikipedia:Copyright problems]] for over seven days">Listed at Copyright problems for over seven days</option>' +
								'</optgroup>' +
							'</optgroup>' +
						'</select></td></tr>' +
				'<tr><td>Other/additional reason:</td>' +
					'<td><input type="text" id="wpMassDeleteReason" name="wpMassDeleteReason" maxlength="255" /></td></tr>' +
					'<tr><td><input type="button" id="wpMassDeleteSubmit" name="wpMassDeleteSubmit" value="Delete" /></td>' +
			'</form>';
		document.getElementById("wpMassDeleteReasons").onchange = function() {
			var maxlength = (document.getElementById("wpMassDeleteReasons").value == "other" ? 255 : 252-document.getElementById("wpMassDeleteReasons").value.length); //It's 252 because of the three characters (" ()") in addition to the selected summary.
			document.getElementById("wpMassDeleteReason").setAttribute("maxlength", maxlength);
		};
		document.getElementById("wpMassDeleteSubmit").addEventListener("click", function (e) {
			doMassDelete();
		});
	}
	 
	if (config.wgNamespaceNumber == -1 &&
		config.wgTitle.toLowerCase() == "massdelete" &&
		/sysop/.test(config.wgUserGroups)
	) {
		massdeleteform();
	}

});

/** This script contains the code required for loading [[User:Joeytje50/JWB.js]].
 *  All other code is located at that page.
 */

//Idea by [[User:Epicgenius]]
$.when(mw.loader.using(['mediawiki.util'], $.ready)).done( function() {
	mw.util.addPortletLink("p-tb", mw.config.get('wgArticlePath').replace('$1', "Project:AutoWikiBrowser/Script"), "JS Wiki Browser", "tb-awbscript", "Run Javascript Wiki Browser");
});

if (mw.config.get('wgCanonicalNamespace')+':'+mw.config.get('wgTitle') === 'Project:AutoWikiBrowser/Script' && mw.config.get('wgAction') == 'view')
	mw.loader.load('//en.wikipedia.org/w/index.php?title=User:Joeytje50/JWB.js&action=raw&ctype=text/javascript');
	
function DateSub(Date1,Date2) {
    var timeDifference = Date2 - Date1;
    var minutesAgo = Math.round(timeDifference / 1000 / 60);
    var hoursAgo = 0
    var daysAgo = 0
    var hoursText = 'hour'
    var daysText = 'day'

    while (minutesAgo >= 60) {
        minutesAgo = minutesAgo-60;
        hoursAgo++;
    }

    while (hoursAgo >= 24) {
        hoursAgo = hoursAgo-24;
        daysAgo++;
    }

    if (hoursAgo!=1)
        hoursText = hoursText + 's';

    if (daysAgo!=1)
        daysText = daysText + 's';

    if (daysAgo > 0) {
        if (hoursAgo > 0) {
            if (minutesAgo <=1 ) {
                minutesAgo = daysAgo + ' ' + daysText + ', ' + hoursAgo + ' ' + hoursText;
            }
            else {
                minutesAgo = daysAgo + ' ' + daysText + ', ' + hoursAgo + ' ' + hoursText + ', ' + minutesAgo + ' minutes';
            }
        }
        else {
            if (minutesAgo <=1 ) {
                minutesAgo = daysAgo + ' ' + daysText;
            }
            else {
                minutesAgo = daysAgo + ' ' + daysText + ', ' + minutesAgo + ' minutes';
            }
        }
    }
    else {
        if (hoursAgo > 0) {
            if (minutesAgo <=1 ) {
                minutesAgo = hoursAgo + ' ' + hoursText;
            }
            else {
                minutesAgo = hoursAgo + ' ' + hoursText + ', ' + minutesAgo + ' minutes';
            }
        }
        else {
            if (minutesAgo <=1 ) {
                minutesAgo = 'Less than a minute';
            }
            else {
                minutesAgo = minutesAgo + ' minutes';
            }
        }
    }
    return minutesAgo;
}

if (document.getElementById('mw-diff-otitle1') || document.getElementById('mw-diff-ntitle1')) {

function convertTimestampStringToDate(id) {
    var timestamp = document.getElementById(id).firstChild.firstChild.firstChild.nodeValue;
    var str = /evision as of /g
    str.lastIndex = 0;
    str.test(timestamp)
    var date = timestamp.substring(str.lastIndex)
/*

All this following bogus crap is because Safari
doesn't recognize Wikipedia's date format.
Every other browser can just use the date string
object above, but Safari is retarded

*/
    var str1 = /[A-z]+/
    var str2 = /\d+/g
    var monthtext = date.match(str1);
    var testdate = date.match(str2);
    var hours = testdate[0];
    var minutes = testdate[1];
    var day = testdate[2];
    var year = testdate[3];
    var months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
    for (i in months) {
        if (monthtext==months[i]) {
            var month = i;
            break;
        }
        i++
    }
/*

End Safari madness

*/
    date = new Date(year,month,day,hours,minutes);
    return date;
}

var leftNode = document.getElementById('mw-diff-otitle1');
var rightNode = document.getElementById('mw-diff-ntitle1');
var firstDate = convertTimestampStringToDate('mw-diff-otitle1');
var secondDate = convertTimestampStringToDate('mw-diff-ntitle1');

function TimeBetweenDiffs() {

    var minutesAgo = DateSub(firstDate,secondDate);

    var newNode = document.createElement('span');
    newNode.setAttribute('style', 'font-weight:bold; color:red;')
    newNode.appendChild(document.createTextNode('(' + minutesAgo + ' later)'));
    newNode.appendChild(document.createElement('br'));

    rightNode.insertBefore(newNode, rightNode.firstChild);
}

function TimeSinceDiff() {
    var DateNow = new Date();

    var minutesAgo1 = DateSub(firstDate,DateNow);
    var minutesAgo2 = DateSub(secondDate,DateNow);

    document.getElementById('mw-diff-otitle1').title=minutesAgo1 + ' ago';
    document.getElementById('mw-diff-ntitle1').title=minutesAgo2 + ' ago';

    var t = setTimeout("TimeSinceDiff()",60000);
}

$(window).load(TimeSinceDiff);                                  // Adds time since displayed diffs as tooltip
$(window).load(TimeBetweenDiffs);                               // Adds time between diffs

}

// Modified from [[User:Gary King/link intermediate revisions.js]]

if (typeof(unsafeWindow) != 'undefined')
{
	var console = unsafeWindow.console;
	importScriptURI = unsafeWindow.importScriptURI;
	mw = unsafeWindow.mw;
}

mw.loader.using( ['mediawiki.util'], function () {
	$(createDiffMultiLink);
});

function createDiffMultiLink()
{
	if (!mw.util.getParamValue('diff') || !mw.util.getParamValue('oldid')) return false;
	$.get(mw.config.get('wgScriptPath') + '/api.php', { 
             action: 'query', 
             prop: 'revisions', 
             titles: mw.config.get('wgPageName'), 
             rvprop: 'timestamp', 
             rvstartid: mw.util.getParamValue('diff'), 
             rvendid: mw.util.getParamValue('oldid'), 
             rvlimit: '5000',
             format: 'json', 
             indexpageids: 1 
        }, diffMultiCallback);
}
 
function twoDigitPadding(integer)
{
	var string = integer.toString();
	if (string.length == 1) return '0' + integer;
	else return integer;
}
 
function diffMultiCallback(response)
{
	if (!response['query'] || !response['query']['pages'] || response['query']['pageids'][0] == -1) return false;
 
	var diffMultis = $('#bodyContent .diff-multi');
	if (!diffMultis.length) return false;
	var pageId = response['query']['pageids'][0];
	var page = response['query']['pages'][pageId];
	var revisions = page['revisions'];
	if (!revisions) return false;
 
	var oldid = new Date(revisions[revisions.length - 1]['timestamp']);
	oldid = oldid.getUTCFullYear().toString() + twoDigitPadding(oldid.getUTCMonth() + 1).toString() + oldid.getUTCDate().toString() + twoDigitPadding(oldid.getUTCHours() + 1).toString() + twoDigitPadding(oldid.getUTCMinutes() + 1).toString() + twoDigitPadding(oldid.getUTCSeconds() + 1).toString();
	var diff = new Date(revisions[0]['timestamp']);
	diff = diff.getUTCFullYear().toString() + twoDigitPadding(diff.getUTCMonth() + 1).toString() + diff.getUTCDate().toString() + twoDigitPadding(diff.getUTCHours() + 1).toString() + twoDigitPadding(diff.getUTCMinutes() + 1).toString() + twoDigitPadding(diff.getUTCSeconds() + 1).toString();
 
	var diffMulti = diffMultis.eq(0);
	var a = $('<a href="' + mw.config.get('wgScript') + '?title=' + mw.config.get('wgPageName') + '&action=history&offset=' + diff + '&limit=' + revisions.length + '"></a>').append(diffMulti.contents().eq(0));
	diffMulti.append(a);
}

if (typeof inspectText == "undefined")
{
	inspectText = "inspect&nbsp;diff";
}
if (typeof showText == "undefined")
{
	showText = "show&nbsp;diff";
}
if (typeof hideText == "undefined")
{
	hideText = "hide&nbsp;diff";
}
var specialPageName = mw.config.get("wgCanonicalSpecialPageName");
if (specialPageName  == "Watchlist" ||
	specialPageName  == "Recentchanges" ||
	specialPageName  == "Contributions" ||
	mw.config.get("wgAction") == "history" || 
	specialPageName == "Recentchangeslinked" ||
	(specialPageName == "Blankpage" && mw.config.get("wgTitle").indexOf("section-watchlist") > 0))
{
	function inspectionEachHelper(index, element)
	{
		var findString;
		if (mw.config.get("wgAction") == "history" || $(element).hasClass("mw-enhanced-rc-nested"))
		{
			findString = 'a:contains("prev")';
		}
		else
		{
			findString = 'a:contains("diff")';
		}

		var regex;

		if (specialPageName == "Contributions")
		{
			regex = /&oldid=(\d+)$/;

		}
		else
		{
			regex = /(?:&diff=(\d+)&oldid=|&diff=prev&oldid=(\d+))/;
		}
		var diffLink = $(element).find(findString);
		if (diffLink.length > 0)
		{
			var regexResult = regex.exec(diffLink[0].href);
			if (regexResult != null && regexResult.length >= 2)
			{
				var diffID = regexResult[1] || regexResult[2];
				//don't re-add if it already exists
				if ($("#" + diffID).length > 0)
				{
					return;
				}
				var inlineDiffButton;
				if (typeof inlineDiffBigUI === "undefined")
				{
					inlineDiffButton = document.createElement("a");
					inlineDiffButton.href = "#";
					inlineDiffButton.innerHTML = '<b><span style="color:black;"> [</span><span style="color:#008A00;">' + inspectText + '</span><span style="color:black;">] </span></b>';
				}
				else
				{
					inlineDiffButton = document.createElement("input");
					inlineDiffButton.type = "button";
					inlineDiffButton.value = "Inspect edit";
				}
				inlineDiffButton.id = diffID;
				$(inlineDiffButton).addClass("inspectDiffButton");
				$(inlineDiffButton).click(function ()
				{
					return inspectWatchlistDiff(this);
				}
				);
				if ($(element).find("tr:first").length == 0)
				{
					$(element).find(".mw-changeslist-separator:first").css("padding-right", 0);
					$(inlineDiffButton).insertAfter($(element).find(".mw-changeslist-separator:first"));
				}
				else
				{
					$(inlineDiffButton).insertBefore($(element).find(".mw-title"));
					$(inlineDiffButton).addClass("mw-enhanced-rc-diff");
					/*
					$(element).find("tr:first").append("<td></td>");
					$(element).find("tr:first>td:last").append(inlineDiffButton);
					*/
				}
			}
		}
	}
	function addWatchlistInspectionBoxes()
	{
		mw.loader.using("mediawiki.diff.styles").done(function()
		{
			var entries = $("#mw-content-text table.mw-enhanced-rc");
			if (entries.length == 0)
			{
				$("#mw-content-text ul").each(function (ind, el)
				{
					$(el).children("li").each(inspectionEachHelper);
				});
			}
			else
			{
				entries.each(inspectionEachHelper);
				$("td.mw-enhanced-rc-nested").each(inspectionEachHelper);
			}
		});
	}

	function inspectWatchlistDiff(button)
	{
		mw.loader.using(['mediawiki.api']).done(function ()
		{
			var mwApi = new mw.Api();
			mwApi.get(
			{
				action: "query",
				prop: "revisions",
				format: "json",
				rvprop: "timestamp",
				rvdiffto: "prev",
				revids: button.id
			}
			).done(function (response)
			{
				if (response == null)
				{
					alert("Request failed!");
					return false;
				}

				var diffString = response.query.pages[Object.keys(response.query.pages)[0]].revisions[0].diff["*"];

				if (diffString == null)
				{
					alert("Request failed!");
					return false;
				}

				var newTable = document.createElement("table");
				newTable.className = "diff";
				$(newTable).html('<colgroup><col class="diff-marker"><col class="diff-content"><col class="diff-marker"><col class="diff-content"></colgroup>');

				$(newTable).append(diffString);
				diffParent = null;
				if ($("#" + button.id).hasClass("mw-enhanced-rc-diff"))
				{
					$("#" + button.id).parents("table").after(newTable);
				}
				else
				{
					diffParent = $("#" + button.id).parent();
					diffParent.append(newTable);
				}
				newTable.id = button.id + "display";

				mw.hook('new-diff-table').fire(newTable);

				$(button).unbind("click");
				if (typeof inlineDiffBigUI === "undefined")
				{
					$(button).html('<b><span style="color:black;"> [</span><span style="color:#008A00;">' + hideText + '</span><span style="color:black;">] </span></b>');
					$(button).click(function ()
					{
						return hideSmallEditInspection(this);
					}
					);
				}
				else
				{
					$(button).attr("value", "Hide edit");
					$(button).click(function ()
					{
						return hideEditInspection(this);
					}
					);
				}
				if (typeof markAsViewed != "undefined" && markAsViewed)
				{
					mwApi.postWithToken('csrf',
					{
						action: "setnotificationtimestamp",
						revids: button.id
					}
					).done(function (data)
					{
						if (diffParent != null)
						{
							diffParent.removeClass("mw-changeslist-line-watched");
							diffParent.addClass("mw-changeslist-line-not-watched");
						}
					}
					);
				}
			}
			);
		}
		);
		return false;
	}

	function showEditInspection(button)
	{
		$("#" + button.id + "display").css("display", "");
		$(button).attr("value", "Hide edit");
		$(button).unbind("click");
		$(button).click(function ()
		{
			return hideEditInspection(this);
		}
		);
		return false;
	}

	function hideEditInspection(button)
	{
		$("#" + button.id + "display").css("display", "none");
		$(button).attr("value", "Show edit");
		$(button).unbind("click");
		$(button).click(function ()
		{
			return showEditInspection(this);
		}
		);
		return false;
	}

	function showSmallEditInspection(button)
	{
		$("#" + button.id + "display").css("display", "");
		$(button).html('<b><span style="color:black;"> [</span><span style="color:#008A00;">' + hideText + '</span><span style="color:black;">] </span></b>');
		$(button).unbind("click");
		$(button).click(function ()
		{
			return hideSmallEditInspection(this);
		}
		);
		return false;
	}

	function hideSmallEditInspection(button)
	{
		$("#" + button.id + "display").css("display", "none");
		$(button).html('<b><span style="color:black;"> [</span><span style="color:#008A00;">' + showText + '</span><span style="color:black;">] </span></b>');
		$(button).unbind("click");
		$(button).click(function ()
		{
			return showSmallEditInspection(this);
		}
		);
		return false;
	}

	mw.hook('wikipage.content').add(addWatchlistInspectionBoxes);
}

/*
*	Pages Created -- finds all the pages created by a user
*	see [[User:Jfmantis/pagesCreated]]
*/

(function() {

/*
*	create <li> list item for one article
*	right now, just a link to the page & the date
*/
function makeCreatedPageItem(contrib) {
	var item = document.createElement("li");

	var link = document.createElement("a");
	link.href = mw.util.getUrl(contrib.title);
	link.innerHTML = contrib.title;

	item.appendChild(link);

	item.innerHTML += " . . " + new Date(contrib.timestamp).toDateString();

	return item;
}

/*
*	looks through all of a user's non-minor namespace 0 edits,
*	looking for edits tagged as "new"
*
*	the arguments all in one object so that it can be expanded
*	in the future without having to add a bunch more parameters
*/
function findPagesCreated(bundle) {
	bundle.api.get({
		action: "query",
		rawcontinue: '',
		list: "usercontribs",
		ucuser: bundle.user,
		ucstart: bundle.start,
		ucprop: "flags|title|timestamp",
		ucshow: "!minor",
		uclimit: 500,
		ucnamespace: 0
	}).done( function(data) {
		$.each(data.query.usercontribs, function(index, contrib) {
			if (contrib.new != undefined) {
				bundle.list.appendChild(makeCreatedPageItem(contrib));
				bundle.count++;
			}
		});

		if (data["query-continue"]) {	// more contributions
			bundle.start = data["query-continue"].usercontribs.ucstart
			setTimeout(function() { findPagesCreated(bundle); }, 3000);
		} else {	// done
			$("#pc-status")[0].innerHTML = "<br />" + bundle.user + " has created " + bundle.count + " articles";
		}
	}).fail( function(error) {
		alert(error);
	});
}

/*
*	change title, clear content area, etc.
*/
function setupPagesCreated(user) {
	// set new title
	mw.util.$content.find("#firstHeading")[0].innerHTML = "Pages created by " + user;

	// status bar (text + waiting gif)
	var status = document.createElement("span");
	status.id = "pc-status";
	status.innerHTML = "<br />Fetching user data...";

	// heading for results
	var heading = document.createElement("h3");
	heading.innerHTML = "Articles";

	// list of results
	var articles = document.createElement("ul");
	articles.id = "pc-articles";

	var body = mw.util.$content.find("#bodyContent")[0];
	body.innerHTML = "";
	body.appendChild(status);
	body.appendChild(heading);
	body.appendChild(articles);

	var api = new mw.Api();
	api.get({
		action: "query",
		list: "users",
		ususers: user,
		usprop: "editcount"
	}).done(function(data) {
		// 500 results per request, 1 request every 3 seconds
		var count = data.query.users[0].editcount;
		status.innerHTML = "<br />User has " + count + " edits, this should take less than ";
		status.innerHTML += (3 * Math.round(count / 500)) + " seconds &nbsp;&nbsp;&nbsp;";

		var waitgif = document.createElement("img");
		waitgif.src = "https://upload.wikimedia.org/wikipedia/commons/4/42/Loading.gif";
		status.appendChild(waitgif);

		findPagesCreated(
			{"api": api,
			"user": user,
			"list": articles,
			"start": "",
			"count": 0}
		);
	}).fail(function(error) {
		alert(error);
	});

	return false;
}

mw.loader.using("mediawiki.util", function() {
	// add portlet when page is User or User_talk, but not on subpages
	if ((wgNamespaceNumber == 2 || wgNamespaceNumber == 3) && (wgTitle.indexOf("/") == -1)) {
		if (mw.util.getParamValue("pagesCreated")) {
			setupPagesCreated(wgTitle);
		} else {
			mw.util.addPortletLink("p-tb",
				document.location.toString() + "?pagesCreated=true",
				"Pages created", "pc-pages",
				"Get a list of all pages created by this user"
			);
		}
	}
});

})();

if ( mw.config.get( "wgAction" ) === "history" ) {
	$( document ).ready( function() {
		"use strict";
		const HC = document.getElementById( "mw-history-compare" );
		if ( HC ) {
			const PH = document.getElementById( "pagehistory" ),
				BTNS = HC.querySelectorAll( 'input[value="Compare selected revisions"]' ),
				TOP = BTNS[ 0 ],
				BTM = BTNS[ 1 ],
				encapsulate = function() {
					const LSB = PH.querySelector( 'li.selected.before' ),
						LSA = PH.querySelector( 'li.selected.after' );
					if ( TOP && LSB ) {
						PH.insertBefore( TOP, LSB );
					}
					if ( BTM && LSA ) {
						const NES = LSA.nextElementSibling;
						if ( NES ) {
							PH.insertBefore( BTM, NES );
						} else {
							PH.appendChild( BTM );
						}
					}
					/* move buttons added by User:Enterprisey/cv-revdel.js along with the "Compare selected revisions" buttons */
					HC.querySelectorAll( "button.cv-rd-add-range" ).forEach( function( b, i ) { PH.insertBefore( b, BTNS[ i ] ) } );
				};
			encapsulate();
			HC.addEventListener( "change", encapsulate );
		}
	} );
}

/* Rollback all */
$( function() {
	if ( $('span.mw-rollback-link')[0] && mw.config.get( 'wgCanonicalSpecialPageName' ) == 'Contributions' )
		mw.util.addPortletLink( 'p-cactions', 'javascript:rollbackEverything()', "rollback all", "ca-rollbackeverything", "Rollback all top edits displayed here" );
} );
function rollbackEverything() {
	for ( var i in document.links ) {
		if ( document.links[i].href.indexOf( 'action=rollback' ) != -1 )
			window.open( document.links[i].href+'&bot=1' );
	}
}

/* Interface modifications */

$( function(){ 

// These add action tabs at the top of a page

	if( mw.config.get( 'wgNamespaceNumber' ) > -1 ) {  
 		mw.util.addPortletLink( 'p-cactions', '/wiki/Special:PrefixIndex/' + wgPageName, 'Subpages', 'd-subpages', 'List subpages and other pages starting with this title' ); 
 		mw.util.addPortletLink( 'p-cactions', '/w/index.php?title=Special:Log&page=' + wgPageName, 'Logs', 'd-logs', 'Show any relevant logs for this title' );
 		mw.util.addPortletLink( 'p-cactions', '/wiki/' + wgPageName + '?action=purge', 'Purge', 'd-purge', 'Purge the current page' ); 
// 		mw.util.addPortletLink( 'p-cactions', '/wiki/' + wgPageName + '?useskin=vector', 'Vector', 'd-vector', 'View page in the Vector skin' ); 
	}

// These add personal links at the top right of every page

	mw.util.addPortletLink( 'p-personal', '/wiki/Special:ListFiles/' + wgUserName, 'Uploads', 'pt-uploads' );
	mw.util.addPortletLink( 'p-personal', '/wiki/Special:Log/' + wgUserName, 'Logs', 'pt-logs' ); 
	mw.util.addPortletLink( 'p-personal', '/wiki/Special:PrefixIndex/User:'+ wgUserName, 'Subpages', 'pt-subpages' );

	$("#pt-logout").hide();

// These add toolbox links to the sidebar of every page

	mw.util.addPortletLink( 'p-tb', 'https://en.uncyclopedia.co/wiki/User:Zombiebaron/2019.js', '2019.js Project', 't-2019' );
	mw.util.addPortletLink( 'p-tb', 'https://en.uncyclopedia.co/wiki/User:Zombiebaron/Images', 'Images', 't-images' );
	mw.util.addPortletLink( 'p-tb', 'https://en.uncyclopedia.co/wiki/Special:MassDelete', 'mass delete', 't-massdelete' );



	$('#n-currentevents').after($('#n-recentchanges'));
	$('#n-recentchanges').css({ 'font-weight': 'bold' });

} );

/* Edit counter in top bar - by Wikipedia:User:Mvolz */

$(document).ready( function () { 
	mw.loader.using( 'mediawiki.user', function() {
	    ( new mw.Api() ).get( {
	        action: 'query',
	        meta: 'userinfo',
	        uiprop: 'editcount'
	    } ).done( function( result ) {
	    	document.getElementById( 'pt-mycontris' ).append( ' (' + result.query.userinfo.editcount + ')' );
	    } );
	} );
} );

// Stolen from https://en.wikipedia.org/w/index.php?title=User:PleaseStand/userinfo.js&oldid=803890891 to tweak some options
// See also [[User:Equazcion/sysopdetector.js]] and [[User:Anomie/useridentifier.js]]
// based on [[User:Fran Rogers/dimorphism.js]] and [[User:Splarka/sysopdectector.js]]

// Display on all user (sub)pages and contribs, logs, etc.
// Edit counter link for current project
// Show a symbol if no gender pronoun selected
// Don't show the "From Wikipedia" if showing userinfo
// Add option to disable for self



// userinfoHideSelf defaults to off
if (window.userinfoHideSelf === undefined || typeof window.userinfoHideSelf !== 'boolean') {
	window.userinfoHideSelf = false;
}


function UserinfoJsFormatQty(qty, singular, plural) {
    return String(qty).replace(/\d{1,3}(?=(\d{3})+(?!\d))/g, "$&,") + "\u00a0" + (qty == 1 ? singular : plural);
}

function UserinfoJsFormatDateRel(old) {
    // The code below requires the computer's clock to be set correctly.
    var age = new Date().getTime() - old.getTime();
    var ageNumber, ageRemainder, ageWords;
    if(age < 60000) {
	// less than one minute old
	ageNumber = Math.floor(age / 1000);
	ageWords = UserinfoJsFormatQty(ageNumber, "second", "seconds");
    } else if(age < 3600000) {
	// less than one hour old
	ageNumber = Math.floor(age / 60000);
	ageWords = UserinfoJsFormatQty(ageNumber, "minute", "minutes");
    } else if(age < 86400000) {
	// less than one day old
	ageNumber = Math.floor(age / 3600000);
	ageWords = UserinfoJsFormatQty(ageNumber, "hour", "hours");
	ageRemainder = Math.floor((age - ageNumber * 3600000) / 60000);
    } else if(age < 604800000) {
	// less than one week old
	ageNumber = Math.floor(age / 86400000);
	ageWords = UserinfoJsFormatQty(ageNumber, "day", "days");
    } else if(age < 2592000000) {
	// less than one month old
	ageNumber = Math.floor(age / 604800000);
	ageWords = UserinfoJsFormatQty(ageNumber, "week", "weeks");
    } else if(age < 31536000000) {
	// less than one year old
	ageNumber = Math.floor(age / 2592000000);
	ageWords = UserinfoJsFormatQty(ageNumber, "month", "months");
    } else {
	// one year or older
	ageNumber = Math.floor(age / 31536000000);
	ageWords = UserinfoJsFormatQty(ageNumber, "year", "years");
	ageRemainder =
	    Math.floor((age - ageNumber * 31536000000) / 2592000000);
	if(ageRemainder) {
	    ageWords += " " +
		UserinfoJsFormatQty(ageRemainder, "month", "months");
	}
    }
    return ageWords;
}

// If on a user or user talk page
if (mw.config.exists('wgRelevantUserName') && !(window.userinfoHideSelf && mw.config.get('wgRelevantUserName') === mw.config.get('wgUserName'))) {
    // add a hook to...
    mw.loader.using( ['mediawiki.util'], function() { $(function(){
	// Request the user's information from the API.
	// Note that this is allowed to be up to 5 minutes old.
	var et = encodeURIComponent(mw.config.get("wgRelevantUserName"));

	$.getJSON(mw.config.get("wgScriptPath") + "/api.php?format=json&action=query&list=users|usercontribs&usprop=blockinfo|editcount|gender|registration|groups&uclimit=1&ucprop=timestamp&ususers=" + et + "&ucuser=" + et + "&meta=allmessages&amprefix=grouppage-&amincludelocal=1")
	    .done(function(query) {
		// When response arrives extract the information we need.
		if(!query.query) { return; } // Suggested by Gary King to avoid JS errors --PS 2010-08-25
		query = query.query;
		var user, invalid, missing, groups, groupPages={}, editcount, registration, blocked, partial, gender, lastEdited;
		try {
		    user = query.users[0];
		    invalid = typeof user.invalid != "undefined";
		    missing = typeof user.missing != "undefined";
		    groups = (typeof user.groups == "object") ? user.groups : [];
		    editcount = (typeof user.editcount == "number") ? user.editcount : null;
		    registration = (typeof user.registration == "string") ?
			new Date(user.registration) : null;
		    blocked = typeof user.blockedby != "undefined";
		    partial = typeof user.blockpartial != "undefined";
		    gender = (typeof user.gender == "string") ? user.gender : null;
		    lastEdited = (typeof query.usercontribs[0] == "object") &&
			(typeof query.usercontribs[0].timestamp == "string") ?
			new Date(query.usercontribs[0].timestamp) : null;
		    for (var am=0; am<query.allmessages.length; am++) {
			groupPages[query.allmessages[am]["name"].replace("grouppage-","")] = query.allmessages[am]["*"].replace("{{ns:project}}:","Project:");
		    }
		} catch(e) {
		    return; // Not much to do if the server is returning an error (e.g. if the username is malformed).
		}

		// Format the information for on-screen display

		var statusText = "";
		var ipUser = false;
		var ipv4User = false;
		var ipv6User = false;

		// User status
		if(blocked) {
		    statusText += "<a href=\"" + mw.config.get("wgScript") +
			"?title=Special:Log&amp;page=" +
			encodeURIComponent(mw.config.get("wgFormattedNamespaces")[2] + ":" + user.name) +
			"&amp;type=block\">" + (partial ? 'partially ' : '') + "blocked</a> ";
		}
		if (missing) {
		    statusText += "username not registered";
		} else if (invalid) {
		    ipv4User = mw.util.isIPv4Address(user.name);
		    ipv6User = mw.util.isIPv6Address(user.name);
		    ipUser = ipv4User || ipv6User;
		    if (ipv4User) {
			statusText += "anonymous IPv4 user";
		    } else if (ipv6User) {
			statusText += "anonymous IPv6 user";
		    } else {
			statusText += "invalid username";
		    }
		} else {
		    // User is registered and may be in a privileged group. Below we have a list of user groups.
		    // Only need the ones different from the software's name (or ones to exclude), though.
		    var friendlyGroupNames = {
			// Exclude implicit user group information provided by MW 1.17 --PS 2010-02-17
			'*': false,
			'user': false,
			'autoconfirmed': false,
			abusefilter: "edit filter manager",
			'abusefilter-helper': "abuse filter helper",
			autopatrolled: "autopatrolled user",
			bureaucrat: "bureaucrat",
			extendedconfirmed: "extended confirmed user",
			'interface-admin': "interface op",
			'empress': "empress",
			'ipblock-exempt': "IP block exemption",
			rollback: "rollbacker",
			sysop: "administrator",
			'sysadmin': "sysadmin",
		    };

		    var friendlyGroups = [];
		    for(var i = 0; i < groups.length; ++i) {
			var s = groups[i];
			var t = friendlyGroupNames.hasOwnProperty(s) ? friendlyGroupNames[s] : s;
			if (t) {
			    if (groupPages.hasOwnProperty(s)) {
				friendlyGroups.push("<a href=\"" +  mw.config.get("wgArticlePath").replace("$1", encodeURIComponent( groupPages[s] )) + "\">" + t + "</a>");
			    } else {
				friendlyGroups.push(t);
			    }
			}
		    }
		    switch(friendlyGroups.length) {
		    case 0:
			// User not in a privileged group
			// Changed to "registered user" by request of [[User:Svanslyck]]
			// --PS 2010-05-16

			// statusText += "user";
			if(blocked) {
			    statusText += "user";
			} else {
			    statusText += "registered user";
			}
			break;
		    case 1:
			statusText += friendlyGroups[0];
			break;
		    case 2:
			statusText += friendlyGroups[0] + " and " + friendlyGroups[1];
			break;
		    default:
			statusText += friendlyGroups.slice(0, -1).join(", ") +
			    ", and " + friendlyGroups[friendlyGroups.length - 1];
			break;
		    }
		}

		// Registration date
		if(registration) {
		    var firstLoggedUser = new Date("09 07, 2005 22:16Z"); // When the [[Special:Log/newusers]] was first activated
		    if(registration >= firstLoggedUser) {
			statusText += ", <a href='" + mw.config.get("wgScript") +
			    "?title=Special:Log&amp;type=newusers&amp;dir=prev&amp;limit=1&amp;user=" +
			    et + "'>" + UserinfoJsFormatDateRel(registration) + "</a> old";
		    } else {
			statusText += ", <a href='" + mw.config.get("wgScript") +
			    "?title=Special:ListUsers&amp;limit=1&amp;username=" +
			    et + "'>" + UserinfoJsFormatDateRel(registration) + "</a> old";
		    }
		}

		// Edit count
		if(editcount !== null) {
		    statusText += ", with " +
			"<a href=\"//celeste.ink/wiki/Special:Editcount" +
			"/" + encodeURIComponent(user.name) + "\">" +
			UserinfoJsFormatQty(editcount, "edit", "edits") + "</a>";
		}

		// Prefix status text with correct article
		if("AEIOaeio".indexOf(statusText.charAt(statusText.indexOf('>')+1)) >= 0) {
		    statusText = "An " + statusText;
		} else {
		    statusText = "A " + statusText;
		}

		// Add full stop to status text
		statusText += ".";

		// Last edited --PS 2010-06-27
		// Added link to contributions page --PS 2010-07-03
		if(lastEdited) {
		    statusText += "  Last edited <a href=\"" + mw.config.get("wgArticlePath").replace("$1", "Special:Contributions/" + encodeURIComponent(user.name)) + "\">" + UserinfoJsFormatDateRel(lastEdited) + " ago</a>.";
		}

		// Show the correct gender symbol
		var fh = document.getElementById("firstHeading") ||
		    document.getElementById("section-0");
		// Add classes for blocked, registered, and anonymous users
		var newClasses = [];
		if(blocked) {
		    newClasses.push("ps-blocked");
		}
		if(ipUser) {
		    newClasses.push("ps-anonymous");
		} else if(invalid) {
		    newClasses.push("ps-invalid");
		} else {
		    newClasses.push("ps-registered");
		}
		fh.className += (fh.className.length ? " " : "") + groups.map(function(s) {
		    return "ps-group-" + s;
		}).concat(newClasses).join(" ");
		var genderSpan = document.createElement("span");
		genderSpan.id = "ps-gender-" + (gender || "unknown");
		genderSpan.style.paddingLeft = "0.25em";
		genderSpan.style.fontFamily = '"Lucida Grande", "Lucida Sans Unicode", "sans-serif"';
		genderSpan.style.fontSize = "75%";
		var genderSymbol;
		switch(gender) {
		case "male": genderSymbol = "\u2642"; break;
		case "female": genderSymbol = "\u2640"; break;
		default: genderSymbol = "\u2609"; break;
		    //See https://en.wikipedia.org/wiki/Miscellaneous_Symbols
		}
		genderSpan.appendChild(document.createTextNode(genderSymbol));
		fh.appendChild(genderSpan);

		// Now show the other information. Non-standard? Yes, but it gets the job done.
		// Add a period after the tagline when doing so. --PS 2010-07-03

		var ss = document.getElementById("siteSub");
		if(!ss) {
		    ss = document.createElement("div");
		    ss.id = "siteSub";
		    ss.innerHTML = "";
		    var bc = document.getElementById("bodyContent");
		    bc.insertBefore(ss, bc.firstChild);
		}
		//            ss.innerHTML = '<span id="ps-userinfo">' + statusText + '</span> ' + ss.innerHTML + '.';
		ss.innerHTML = '<span id="ps-userinfo">' + statusText + '</span>';
		ss.style.display = "block";
	    });
    }); });
}