function addlimenu(tabs, name, id, href, position) {
var na, mn;
var li;
if (!id) id = name;
if (!href) href = '#';
na = document.createElement("a");
na.appendChild(document.createTextNode(name));
na.href = href;
mn = document.createElement("ul");
li = document.createElement("li");
li.appendChild(na);
li.appendChild(mn);
if (id) li.id = id;
li.className = 'tabmenu';
if (position) {
tabs.insertBefore(li, position);
} else {
tabs.appendChild(li);
}
return mn; // useful because it gives us the <ul> to add <li>s to
}
var wgPreferences = wgPreferences || new Object;
var wgMessages = wgMessages || new Object;
/**
* Date Format 1.2.2
* (c) 2007-2008 Steven Levithan <stevenlevithan.com>
* MIT license
* Includes enhancements by Scott Trenda <scott.trenda.net> and Kris Kowal <cixar.com/~kris.kowal/>
* Includes modifications by D. Trebbien to remove localized day names (`ddd` and `dddd`) and to use `wgMessages.monthNames` instead of `dateFormat.i18n.monthNames`. Also `mmm` was removed and `mmmm` altered so that the 'january' message would be at `wgMessages.monthNames[0]`.
*
* Accepts a date, a mask, or a date and a mask.
* Returns a formatted version of the given date.
* The date defaults to the current date/time.
* The mask defaults to dateFormat.masks.default.
*
* @see http://blog.stevenlevithan.com/archives/date-time-format
*/
var dateFormat = function() {
var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
timezoneClip = /[^-+\dA-Z]/g,
pad = function(val, len) {
val = String(val);
len = len || 2;
while(val.length < len) val = "0" + val;
return val;
};
// regexes and supporting functions are cached through closure
return function(date, mask, utc) {
var dF = dateFormat;
// you can't provide utc if you skip other args (use the "UTC:" mask prefix)
if(arguments.length == 1 && (typeof date == "string" || date instanceof String) && !/\d/.test(date))
{
mask = date;
date = undefined;
}
// passing date through Date applies Date.parse, if necessary
date = date ? new Date(date) : new Date();
if(isNaN(date)) throw new SyntaxError("invalid date");
mask = String(dF.masks[mask] || mask || dF.masks["default"]);
// allow setting the utc argument via the mask
if(mask.slice(0, 4) == "UTC:")
{
mask = mask.slice(4);
utc = true;
}
var _ = utc ? "getUTC" : "get",
d = date[_ + "Date"](),
D = date[_ + "Day"](),
m = date[_ + "Month"](),
y = date[_ + "FullYear"](),
H = date[_ + "Hours"](),
M = date[_ + "Minutes"](),
s = date[_ + "Seconds"](),
L = date[_ + "Milliseconds"](),
o = utc ? 0 : date.getTimezoneOffset(),
flags = {
d: d,
dd: pad(d),
//ddd: dF.i18n.dayNames[D],
//dddd: dF.i18n.dayNames[D + 7],
m: m + 1,
mm: pad(m + 1),
//mmm: dF.i18n.monthNames[m],
mmmm: wgMessages.monthNames[m],
yy: String(y).slice(2),
yyyy: y,
h: H % 12 || 12,
hh: pad(H % 12 || 12),
H: H,
HH: pad(H),
M: M,
MM: pad(M),
s: s,
ss: pad(s),
l: pad(L, 3),
L: pad(L > 99 ? Math.round(L / 10) : L),
t: H < 12 ? "a" : "p",
tt: H < 12 ? "am" : "pm",
T: H < 12 ? "A" : "P",
TT: H < 12 ? "AM" : "PM",
Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
};
return mask.replace(token, function($0) {
return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
});
};
}();
// some common format strings
dateFormat.masks =
{
"default": "ddd mmm dd yyyy HH:MM:ss",
shortDate: "m/d/yy",
mediumDate: "mmm d, yyyy",
longDate: "mmmm d, yyyy",
fullDate: "dddd, mmmm d, yyyy",
shortTime: "h:MM TT",
mediumTime: "h:MM:ss TT",
longTime: "h:MM:ss TT Z",
isoDate: "yyyy-mm-dd",
isoTime: "HH:MM:ss",
isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};
// for convenience...
Date.prototype.format = function(mask, utc) {
return dateFormat(this, mask, utc);
};
/**
* Takes a given timestamp, as generated by the API, and formats it per the user's Date & Time preferences.
*
* Note that the API timestamp "2008-08-22T21:37:39Z" means "Mon, 22 Sep 2008 21:37:39 GMT".
*/
var formatTimestamp = function(timestamp) {
timestamp = timestamp.split(/-0?|:0?|T|Z/);
var date = new Date(Date.UTC(parseInt(timestamp[0]), parseInt(timestamp[1]), parseInt(timestamp[2]),
parseInt(timestamp[3]), parseInt(timestamp[4]), parseInt(timestamp[5])));
var timeCorrection = wgPreferences.timecorrection.split(/:0?/);
date.setUTCHours(date.getUTCHours() + parseInt(timeCorrection[0]));
date.setUTCMinutes(date.getUTCMinutes() + parseInt(timeCorrection[1]));
var format = "HH:MM, d mmmm yyyy";
switch(wgPreferences.date)
{
case "ISO 8601":
format = "isoDateTime";
break;
case "ymd":
format = "HH:MM, yyyy mmmm d";
break;
case "mdy":
format = "HH:MM, mmmm d, yyyy";
break;
default:
case "default":
case "dmy":
break;
}
return date.format("UTC:" + format);
};
if(!Object.prototype.join)
{
/**
* Joins together the keys of an object, separating them by `separator`.
*
* The effect should be no different than creating an array `arr` of all of the object's keys,
* and calling `join(separator)` on that.
*/
Object.prototype.join = function(separator) {
var result = "";
for(var k in this)
{
if(result != "")
result += separator;
result += k;
}
return result;
};
}
if(!window.hasAttribute)
{
if(window.HTMLElement && HTMLElement.prototype.hasAttribute && window.Element && Element.prototype.hasAttribute) // Firefox
{
window.hasAttribute = function(e, attr)
{
return e.hasAttribute(attr);
}
}
else // IE, Chrome
{
window.hasAttribute = function(e, attr)
{
return e.getAttribute(attr) != null;
}
}
}
var wRclimit = wRclimit || 50;
if(500 < wRclimit)
wRclimit = 500;
var wRcshow = wRcshow || "!bot|!redirect";
var wUpdateDelay = wUpdateDelay || 10000;
if(wUpdateDelay < 3000)
wUpdateDelay = 3000;
if(!window.wUpdatesEnabledByDefault)
window.wUpdatesEnabledByDefault = true;
// if this is updated, be sure to update the code @pared-processComment
function processComment(comment)
{
comment = comment.replace(/</g, "<"); // to help prevent XSS attacks
comment = comment.replace(/\[\[\s*(?![Ii]mage\s*:)([^|]*?)(?:\|(.*?))?\s*\]\]/g,
"<a href='" + wgServer + "/wiki/$1' title='$1'>$+</a>");
comment = comment.replace(/'''([^']*?)'''/g, "<b>$1</b>");
comment = comment.replace(/''([^']*?)''/g, "<i>$1</i>");
comment = comment.replace(/\{\{\s*([^|]*?)(\s*(\||<!|\}))/g,
"{"+"{<a href='" + wgServer + "/wiki/Template:$1' title='Template:$1' class='external text'>$1</a>$2");
return comment;
}
function finishDisablingUpdates()
{
var endiUpdates = document.getElementById("a-endiupdates");
endiUpdates.onclick = function() {
enableUpdates();
};
endiUpdates.innerHTML = "Enable updates";
}
function enableUpdates(initialRun)
{
if(!updateNewPages.updatesEnabled || initialRun)
{
updateNewPages.updatesEnabled = true;
var endiUpdates = document.getElementById("a-endiupdates");
endiUpdates.onclick = function() {
endiUpdates.innerHTML = "Disabling...";
updateNewPages.updatesEnabled = false;
};
endiUpdates.innerHTML = "Disable updates";
setTimeout("updateNewPages()", 1);
}
}
function updateNewPages()
{
if(updateNewPages.updatesEnabled)
{
var bodyContent = document.getElementById("bodyContent");
var ul = bodyContent.getElementsByTagName("ul")[0];
var list = updateNewPages.list;
var request = updateNewPages.request;
request.open("GET", wgServer + wgScriptPath + "/api.php?format=xml&action=query&list=recentchanges" +
"&rctype=new&rcnamespace=0&rcprop=user|comment|timestamp|title|ids|sizes|redirect|patrolled&rcshow=" + wRcshow + "&rclimit=" + wRclimit, // TO DO: handle the `offset` parameter of the URL
false);
request.send(null);
if(request.responseXML)
{
var titles = new Array;
var users = new Object; // this is a map between `User:...` and `User talk:...`s and arrays of <a> elements that link to the page
var rcs = request.responseXML.getElementsByTagName("rc");
for(var i = 0; i < rcs.length; i++)
{
var rc = rcs[i];
var title = rc.getAttribute("title");
titles.push(title);
var li = null;
for(var j = 0; j < list.length; j++)
{
if(list[j].title == title) // TO CHECK: whether the `title` parameter of new pages, as generated by the Special:NewPages page, is escaped in the same way as the `title` parameter of <rc>s
{
li = list[j];
li.patrolled = hasAttribute(rc, "patrolled");
}
}
if(!li)
{
if(wRclimit <= list.length)
ul.removeChild(list.shift());
li = document.createElement("li");
li.title = title;
li.appendChild(document.createTextNode(formatTimestamp(rc.getAttribute("timestamp")) + " "));
var a = document.createElement("a"); // link to the article
a.title = title;
if(hasAttribute(rc, "patrolled"))
{
a.href = wgServer + "/wiki/" + encodeURIComponent(title) + "?easydb=1";
li.patrolled = true;
}
else
a.href = wgServer + "/w/index.php?title=" + encodeURIComponent(title) + "&rcid=" + rc.getAttribute("rcid") + "&easydb=1";
a.innerHTML = title;
li.appendChild(a);
li.appendChild(document.createTextNode(" ("));
a = document.createElement("a"); // hist
a.title = title;
a.href = wgServer + "/w/index.php?title=" + encodeURIComponent(title) + "&action=history";
a.innerHTML = "hist";
li.appendChild(a);
li.appendChild(document.createTextNode(") [" + rc.getAttribute("newlen") + " bytes] ")); // TO DO: format the number
a = document.createElement("a"); // link to the user page
var user = rc.getAttribute("user");
if(hasAttribute(rc, "anon"))
{
a.title = user;
a.href = wgServer + "/wiki/Special:Contributions/" + user;
}
else
{
a.title = "User:" + user;
if(!users[a.title])
users[a.title] = new Array;
users[a.title].push(a);
a.href = wgServer + "/wiki/User:" + user;
}
a.innerHTML = user;
li.appendChild(a);
li.appendChild(document.createTextNode(" ("));
a = document.createElement("a"); // link to user talk
a.title = "User talk:" + user;
if(!users[a.title])
users[a.title] = new Array;
users[a.title].push(a);
a.href = wgServer + "/wiki/User talk:" + user;
a.innerHTML = "Talk";
li.appendChild(a);
if(!hasAttribute(rc, "anon"))
{
li.appendChild(document.createTextNode(" | "));
a = document.createElement("a"); // link to user contributions list
a.title = "Special:Contributions/" + user;
a.href = wgServer + "/wiki/Special:Contributions/" + user;
a.innerHTML = "contribs";
li.appendChild(a);
}
li.appendChild(document.createTextNode(") "));
var span = document.createElement("span");
span.className = "comment";
span.innerHTML = processComment(rc.getAttribute("comment"));
li.appendChild(span);
list.push(li);
ul.insertBefore(li, ul.firstChild);
}
}
// check if titles have been deleted, or if they are in `Category:Candidates for speedy deletion` or `Category:Possible copyright violations`, and set the class name
request.abort();
request.open("GET", wgServer + wgScriptPath + "/api.php?format=xml&action=query&prop=info|categories" +
"&cllimit=500&titles=" + encodeURIComponent(titles.join("|")),
false);
request.send(null);
if(request.responseXML)
{
var pages = request.responseXML.getElementsByTagName("page");
outer: for(var i = 0; i < pages.length; i++)
{
var page = pages[i];
var title = page.getAttribute("title");
for(var j = 0; j < list.length; j++) // find the corresponding <li>
{
if(list[j].title == title) // TO CHECK: whether the `title` parameter of new pages, as generated by the Special:NewPages page or as the attribute of an <rc>, is escaped in the same way as the `title` parameter of <page>s
{
var li = list[j];
if(hasAttribute(page, "missing"))
{
if(li.style.display != "none")
{
li.style.display = "none"; // hide it for now. It will eventually be deleted.
window.status = title + " was deleted.";
//window.alert(title + " was deleted.");
}
}
else
{
var categories = page.getElementsByTagName("cl");
for(var k = 0; k < categories.length; k++)
{
var title = categories[k].getAttribute("title");
if(title == "Category:Candidates for speedy deletion")
{
li.className = "plainlinks sdcandidate";
continue outer;
}
else if(title == "Category:Possible copyright violations")
{
li.className = "plainlinks possiblecopyvio";
continue outer;
}
}
if(li.patrolled)
{
li.className = "plainlinks";
li.getElementsByTagName("a")[0].href = wgServer + "/wiki/" + encodeURIComponent(li.title) + "?easydb=1";
}
else
{
li.className = "plainlinks not-patrolled";
li.getElementsByTagName("a")[0].href = wgServer + "/w/index.php?title=" + encodeURIComponent(li.title) + "&rcid=" + rc.getAttribute("rcid") + "&easydb=1";
}
}
continue outer;
}
}
}
}
// go through `users`, performing existence checks
request.abort();
request.open("GET", wgServer + wgScriptPath + "/api.php?format=xml&action=query&prop=info" +
"&titles=" + encodeURIComponent(users.join("|")),
false);
request.send(null);
if(request.responseXML)
{
var pages = request.responseXML.getElementsByTagName("page");
for(var i = 0; i < pages.length; i++)
{
var page = pages[i];
if(hasAttribute(page, "missing"))
{
var arr = users[page.getAttribute("title")];
for(var j = 0; j < arr.length; j++)
{
arr[j].className = "new";
}
}
}
}
} // end `if(request.responseXML)`
request.abort();
setTimeout("updateNewPages()", wUpdateDelay);
}
else
finishDisablingUpdates();
}
updateNewPages.list = new Array; // from oldest to newest
updateNewPages.request = sajax_init_object();
updateNewPages.updatesEnabled = wUpdatesEnabledByDefault;
$(function() {
var i = window.location.href.indexOf("?");
var queryString = (0 < i) ? window.location.href.substring(i+1) : "";
if(wgCanonicalNamespace == "Special" && wgCanonicalSpecialPageName == "Newpages")
{
if(!wgPreferences.timecorrect || !wgPreferences.date || !wgPreferences.language)
{
wgPreferences.language = wgUserLanguage;
var request = sajax_init_object();
request.open("GET", wgServer + wgScriptPath + "/api.php?format=xml&action=query" +
"&meta=userinfo&uiprop=options",
false);
request.send(null);
if(request.responseXML)
{
var options = request.responseXML.getElementsByTagName("options")[0];
wgPreferences.timecorrection = options.getAttribute("timecorrection");
wgPreferences.date = options.getAttribute("date");
if(window.wAlertSource && wgPreferences.toSource)
window.alert("var wgPreferences = " + wgPreferences.toSource() + ";");
}
else
{
wgPreferences.timecorrection = "0:00";
}
}
if(!wgMessages.monthNames)
{
wgMessages.monthNames = new Array;
var request = sajax_init_object();
request.open("GET", wgServer + wgScriptPath + "/api.php?format=xml&action=query" +
"&meta=allmessages&ammessages=january|february|march|april|may|june" +
"|july|august|september|october|november|december&amlang=" + wgPreferences.language,
false);
request.send(null);
if(request.responseXML)
{
var messages = request.responseXML.getElementsByTagName("message");
for(var i = 0; i < messages.length; i++)
{
var message = messages[i];
var name = message.getAttribute("name");
wgMessages[name] = message.innerText || message.textContent;
wgMessages.monthNames.push(message.innerText || message.textContent);
}
if(window.wgMessages && wgMessages.toSource)
window.alert("var wgMessages = " + wgMessages.toSource() + ";");
}
else
{
window.wgMessages = ({monthNames:["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], january:"January", february:"February", march:"March", april:"April", may:"May", june:"June", july:"July", august:"August", september:"September", october:"October", november:"November", december:"December"});
}
}
var bodyContent = document.getElementById("bodyContent");
var ul = bodyContent.getElementsByTagName("ul")[0];
var lis = ul.getElementsByTagName("li");
// TO DO: trim to `wRclimit`
for(var i = 0; i < lis.length; i++)
{
var li = lis[i];
var title = li.getElementsByTagName("a")[0].title.replace("_", " ");
li.title = title;
var span = li.getElementsByTagName("span")[0];
var comment = span.innerHTML;
// pared-processComment
comment = comment.replace(/'''([^']*?)'''/g, "<b>$1</b>");
comment = comment.replace(/''([^']*?)''/g, "<i>$1</i>");
comment = comment.replace(/\{\{\s*([^|]*?)(\s*(\||<!|\}))/g,
"{"+"{<a href='" + wgServer + "/wiki/Template:$1' title='Template:$1' class='external text'>$1</a>$2");
span.innerHTML = comment;
updateNewPages.list.unshift(li); // the <li>s go from newest to oldest, so we insert at 0 each time
}
var endiUpdates = document.createElement("a");
endiUpdates.id = "a-endiupdates";
endiUpdates.href = "#";
endiUpdates.style.paddingLeft = "12px";
ul.parentNode.insertBefore(endiUpdates, ul);
if(updateNewPages.updatesEnabled)
enableUpdates(true);
else
finishDisablingUpdates();
}
else if(0 <= queryString.search(/(?:^|&)easydb=/i))
{
// TO DO: http://matt.blissett.me.uk/web/authoring/css_menus/with_javascript/
//importScript('Wikipedia:WikiProject User scripts/Scripts/Add LI menu');
importStylesheet("Wikipedia:WikiProject User scripts/Scripts/Add LI menu/css");
var tabs = document.getElementById("p-cactions").getElementsByTagName("ul")[0];
addlimenu(tabs, "db", "ca-db", "#", document.getElementById("ca-edit"));
mw.util.addPortletLink("ca-db", "javascript:db('attack')", "attack", "ca-db-attack", "Serves no purpose but to disparage or threaten its subject or some other entity");
mw.util.addPortletLink("ca-db", "javascript:db('band')", "band", "ca-db-band", "About a band, singer, musician, or musical ensemble that does not indicate the importance or significance of the subject");
mw.util.addPortletLink("ca-db", "javascript:db('bio')", "bio", "ca-db-bio", "About a real person that does not indicate the importance or significance of the subject");
mw.util.addPortletLink("ca-db", "javascript:db('blank')", "blank", "ca-db-blank", "Empty article, or one that consists only of external links, category tags and \"see also\" sections, a rephrasing of the title, attempts to correspond with the person or group named by its title, chat-like comments, template tags and/or images");
mw.util.addPortletLink("ca-db", "javascript:db('nocontext')", "nocontext", "ca-db-nocontext", "Very short and lacking sufficient context to identify the subject");
mw.util.addPortletLink("ca-db", "javascript:db('nonsense')", "nonsense", "ca-db-nonsense", "Unsalvageably incoherent with no meaningful content or history; patent nonsense");
mw.util.addPortletLink("ca-db", "javascript:db('spam')", "spam", "ca-db-spam", "Does nothing but promote some entity and would require a fundamental rewrite in order to become encyclopedic");
mw.util.addPortletLink("ca-db", "javascript:db('test')", "test", "ca-db-test", "Test page");
mw.util.addPortletLink("ca-db", "javascript:db('vandalism')", "vandalism", "ca-db-vandalism", "Pure vandalism");
}
else if(wgAction == "edit" && /&db=([^&]*)/.test(queryString))
{
var code = RegExp.$1;
var wpTextbox1 = document.getElementById("wpTextbox1");
if(/\{\{\s*db-(\w*)\s*\}\}/.test(wpTextbox1.innerHTML))
{
window.alert("The article already has a speedy deletion template, `{"+"{db-" + RegExp.$1 + "}"+"}`, so `{"+"{db-" + code + "}"+"}` will not be added.");
}
else
{
wpTextbox1.style.display = "none";
wpTextbox1.innerHTML = "{"+"{db-" + code + "}"+"}\n" + wpTextbox1.innerHTML;
document.getElementById("wpSummary").value = "db-" + code;
document.getElementById("wpMinoredit").setAttribute("checked", "1");
document.getElementById("wpSave").click();
}
}
});
if(!window.wShowDBConfirmationDialog)
window.wShowDBConfirmationDialog = true;
function db(code)
{
if(!wShowDBConfirmationDialog)
{
window.location = wgServer + "/w/index.php?action=edit&title=" + encodeURIComponent(wgTitle) + "&db=" + code;
}
else if(!db.inUse)
{
db.inUse = true;
var request = sajax_init_object();
request.open("GET", wgServer + wgScriptPath + "/api.php?format=xml&action=parse&text={"+"{db-" + code + "}"+"}", false);
request.send(null);
if(request.responseXML)
{
var div = document.createElement("div");
div.id = "db-confirmation-dialog";
var text = request.responseXML.getElementsByTagName("text")[0];
div.innerHTML = text.innerText || text.textContent;
div.style.position = "absolute";
div.style.zIndex = "10";
div.style.top = "170px";
div.style.right = "0";
document.getElementById("bodyContent").appendChild(div);
var tbody = div.getElementsByTagName("tbody")[0];
var tr = document.createElement("tr");
var td = document.createElement("td");
td.style.border = "medium none";
td.style.padding = "0px";
td.style.width = "1px";
tr.appendChild(td);
td = document.createElement("td");
td.align = "right";
var button = document.createElement("button");
button.innerHTML = "<b>Confirm</b>";
button.onclick = function() {
window.location = wgServer + "/w/index.php?action=edit&title=" + encodeURIComponent(wgTitle) + "&db=" + code;
};
button.style.marginRight = "3px";
td.appendChild(button);
button = document.createElement("button");
button.innerHTML = "Cancel";
button.onclick = function() {
var div = document.getElementById("db-confirmation-dialog");
div.parentNode.removeChild(div);
db.inUse = false;
};
td.appendChild(button);
tr.appendChild(td);
tbody.appendChild(tr);
}
else
{
window.alert("Failed to parse `{"+"{db-" + code + "}"+"}`");
}
}
}