User:Dtrebbien/Sandbox/newPagesTool.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
Documentation for this user script can be added at User:Dtrebbien/Sandbox/newPagesTool. |
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 + "}"+"}`");
}
}
}