// <nowiki>
//Ameliorating vandalism. Naught to do with the Belgian municipality.
//TODO: combine addRollback and addRestore into one function
// use WikiTitle throughout the script
// add history visualization to get around IE prompt "security" issue
AmelPrefs = {
data: {},
set: function(name, value) {
return this.data[name] = value;
},
get: function(name, alternate) {
return this.contains(name) ? this.data[name] : alternate;
},
contains: function(name) {
return (typeof this.data[name] != "undefined");
}
};
if(typeof(AmelPrefs.data["summarySuffix"]) == "undefined") AmelPrefs.set("summarySuffix", "");
if(typeof(AmelPrefs.data["watchReversion"]) == "undefined") AmelPrefs.set("watchReversion", false);
//combine these into one function.
function addRollback() {
if(document.getElementById("mw-diff-ntitle1").getElementsByTagName("a")[0].firstChild.nodeValue.indexOf("Current revision") == -1) return;
var roll = document.createElement("input");
roll.type = "button";
roll.onclick = AmelUtil.diffRollback(document);
roll.value = "Rollback";
getElementsByClassName(document, "td", "diff-otitle")[0].appendChild(roll);
}
function addRestore() {
var rest = document.createElement("input")
rest.type = "button";
rest.onclick = AmelUtil.diffRestore(document);
rest.value = "Restore revision";
getElementsByClassName(document, "td", "diff-otitle")[0].appendChild(rest);
}
function AdminRollback(url) {
if (!url || this == window)
return; //no title given, or "new" keyword not used
this.url = url;
try {
this.userFrom = decodeURIComponent(url.match(/[&?]from=([^&]*)/)[1]).replace(/_/g, " ");
this.title = url.match(/[&?]title=([^&]*)/)[1];
} catch (e) {
return; //error in parsing link; not correct
}
this.init();
}
AdminRollback.prototype.init = function() {
var me = this;
AmelUtil.colorStatus("#EFE");
var req = new XMLHttpRequest();
req.open("HEAD", this.url, true);
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
AmelUtil.colorStatus("#EEF");
new WikiEdit(me.title).getHistory(function(obj){showHistory(me.title, obj)});
}
};
req.send(null);
new Warning(this.title, this.userFrom);
}
function Rollback(title, revFrom, userFrom) {
if (!title || this == window)
return; //no title given, or "new" keyword not used
this.title = title; //in encoded form
this.from = { "revid" : revFrom || undefined, "user" : userFrom || undefined };
this.revTo = undefined;
this.revnum = 0;
this.editor = new WikiEdit(title, this);
this.init();
}
Rollback.prototype.init = function () {
AmelUtil.colorStatus("#FEE");
this.editor.downloadEditFormData();
this.editor.getHistory(this.parseHistory);
}
Rollback.prototype.parseHistory = function(history) {
AmelUtil.colorStatus("#FFE");
if (!history || !history[0]) {
alert("Error retriving page history"); //go modal boxes!
return;
}
this.editor.setTimes(AmelUtil.isoToNumerical(history[0]["timestamp"]));
//some situations the reverter should check out
var cautionMode = undefined;
if (this.from.revid) {
if (history[0]["revid"] == this.from.revid)
this.from.user = history[0]["user"]; //just in case it's not defined
else
cautionMode = "The revision amelvand was told to revert from is not the most recent one.";
}
else if (this.from.user && this.from.user != history[0]["user"])
cautionMode = "The user amelvand was told to revert from is not the most recent editor of the article.";
else
cautionMode = "Neither a revision nor a user was received, so just making sure that we really want to revert.";
i = 0;
if (cautionMode) {
j = [];
var min = Math.min(history.length, 8);
for (i = 0; i < min; i++) //add summary?
j[i] = i + ". " + history[i]["user"] + (history[i]["revid"] == this.from.revid ? " (original)" : "");
i = prompt(j.join("\n") + "\n\nCaution mode enabled. Reason: " + cautionMode + "\n\nFrom which revision do you wish to revert?", "0"); //moar options!
if (isNaN(parseInt(i))) return;
this.revid = history[i][0];
this.user = history[i][1];
}
//cautionModeBox(cautionMode, history); } else {
this.revnum = i;
while (this.revnum < history.length && history[this.revnum]["user"] == this.from.user) {
this.revnum++;
}
if (this.revnum - i != 1) {
if(!confirm("Rollback " + (this.revnum - i) + " edits by " + this.from.user + "?")) {
j = prompt("Then rollback how many edits?", "1")
if (isNaN(parseInt(j)))
return;
else
this.revnum = j;
}
}
if (this.revnum < history.length) {
this.revTo = history[this.revnum]["revid"];
this.commit();
}
else
alert("Last revision not by user not found.");
}
Rollback.prototype.commit = function() {
new Warning(this.title, this.from.user);
var editSum = "Reverted " + AmelUtil.plural(this.revnum, "edit", "edits") + " by [[Special:Contributions/$2|$2]] ([[User talk:$2|talk]])".replace(/\$2/g, this.from.user) + " to last revision by $1"; //$1 is assigned by RestoreRevision
new RestoreRevision(this.title, this.revTo, this.editor, editSum)
};
function RestoreRevision(title, revTo, editor, editSum) {
if (!title || !revTo || this == window)
return;
AmelUtil.colorStatus("#EFE");
this.title = title;
this.revTo = revTo;
this.editSum = editSum || "Restored revision " + this.revTo + " by [[Special:Contributions/$1|$1]]"; //$1 is assigned by commit(obj)
if (!editor) {
editor = new WikiEdit(title);
editor.downloadEditFormData();
editor.getHistory(function(obj) {
editor.setTimes(AmelUtil.isoToNumerical(obj["timestamp"]));
}, 1);
}
editor.setParent(this);
this.editor = editor;
this.init();
}
RestoreRevision.prototype.init = function() {
this.editor.getText(this.commit, this.revTo);
}
RestoreRevision.prototype.commit = function(obj) {
if (!obj) return;
var text = obj["*"];
if (!text && text != "") return;
this.editSum = this.editSum.replace(/\$1/g, obj["user"]) + AmelPrefs.get("summarySuffix", "");
var editor = this.editor; //short-hand reference
var title = this.title;
editor.setMinor(false);
editor.setWatch(AmelPrefs.get("watchReversion", false));
editor.setCallback(function() {
AmelUtil.colorStatus("#EEF");
editor.getHistory(function(obj){showHistory(title, obj)});
});
editor.setText(text);
editor.setSummary(this.editSum);
editor.submit();
}
//---------------------------------
//@Private
function WikiTitle(displayTitle, urlTitle) {
this.displayTitle = displayTitle;
this.urlTitle = urlTitle;
}
WikiTitle.fromURL = function(url, param) {
var urlmatch = (!param && /\/wiki\/(.*)/.exec(url)) ||
new RegExp("[?&]" + (param || "title") + "=([^&]*)").exec(url);
if (urlmatch)
return WikiEdit.fromEncoded(urlmatch[1]);
}
WikiTitle.fromEncoded = function(encoded) {
return new WikiTitle(decodeURIComponent(encoded).replace(/_/g, " "),
encoded);
}
WikiTitle.fromDisplay = function(display) {
return new WikiTitle(display,
encodeURIComponent(display.replace(/ /g, "_")));
}
//accessors
WikiTitle.prototype = {
toEncoded : function() {
return this.urlTitle;
},
toIndexUrl : function() {
return mw.config.get('wgServer') + mw.config.get('wgScript') + "?title=" + this.urlTitle;
},
toApiUrl : function() {
return mw.config.get('wgServer') + mw.config.get('wgScriptPath') + "/api.php?titles=" + this.urlTitle;
},
toString : function() {
return this.displayTitle;
}
};
function Warning(title, user) {
if (!title || !user || this == window)
return;
var me = this;
this.user = user;
title = WikiTitle.fromEncoded(title);
this.title = title;
var warnTitle = WikiTitle.fromDisplay("User talk:" + user),
aivTitle = WikiTitle.fromDisplay("Wikipedia:Administrator intervention against vandalism");
this.data = new Object();
this.data[Warning.WARN] = {
"title": warnTitle,
"editor": new WikiEdit(warnTitle, me),
"summary": "Note: edits on [[" + title + "]]",
"savedtext": undefined,
"addtext": undefined,
"infotext": "",
"button": "Report to AIV",
"init": Warning.warnInit,
"editpage": title
};
this.data[Warning.AIV] = {
"title": aivTitle,
"editor": new WikiEdit(aivTitle, me),
"summary": "Reporting [[Special:Contributions/$1|$1]]".replace(/\$1/g, user),
"savedtext": undefined,
"addtext": "*{{" + (AmelUtil.isIP(user) ? "IPvandal" : "Userlinks") + "|" + user + "}} vandalism past last warning ~~" + "~~",
"infotext": "Reporting " + user + ". ",
"button": "Warn User",
"init": Warning.aivInit,
"regex": new RegExp(user + "\\}\\}") //basic sensing mechanism
};
this.mode = Warning.NONE;
//initialize GUI. no "live" elements have innerHTML changed.
var warnDiv = document.createElement("div");
warnDiv.innerHTML = '<strong id="warnPage"></strong> <span id="warnInfo"></span><br /><textarea rows="10" name="warnBox" id="warnBox"> </textarea><br /><input type="text" value="" id="warnSum" size="30" onkeypress="if (event.which == 13) warning.submit();" /> <input type="button" value="Submit" id="warnSubmit" /> <input type="button" value="" id="warnSwitch" />';
var jumpToNav = document.getElementById("jump-to-nav");
if (!jumpToNav) return false;
jumpToNav.parentNode.insertBefore(warnDiv, jumpToNav);
this.gui = {
"warnBox": document.getElementById("warnBox"),
"warnPage": document.getElementById("warnPage"),
"warnInfo": document.getElementById("warnInfo"),
"warnSwitch": document.getElementById("warnSwitch"),
"warnSubmit": document.getElementById("warnSubmit"),
"warnSum": document.getElementById("warnSum")
}
this.gui["warnBox"].value = "";
this.gui["warnPage"].appendChild(document.createTextNode(""));
this.gui["warnInfo"].appendChild(document.createTextNode(""));
this.gui["warnSwitch"].onclick = function() {me.setNextMode();};
this.gui["warnSubmit"].onclick = function() {me.submit();};
this.setNextMode();
}
Warning.NONE = ["NONE"];
Warning.WARN = ["WARN"];
Warning.AIV = ["AIV"];
Warning.warnInit = function(text) {
this.savedtext = text;
var parser = new WarningsParser(text);
if (parser.report())
this.infotext += "NOTE! User is past last warning. ";
var now = new Date();
var warnDate = parser.previousDate();
var secElapsed = Math.ceil((now.getTime() - warnDate.getTime()) / 1000);
if (secElapsed < 0) secElapsed += 3600; //an hour. voodoo programming!
if (secElapsed < 600) { //ten minutes
var minElapsed = Math.floor(secElapsed / 60);
this.infotext += "Latest warning was left " + (minElapsed == 0 ? "" : AmelUtil.plural(minElapsed, "minute", "minutes") + " and ") + AmelUtil.plural(secElapsed % 60, "second", "seconds") + " ago. ";
}//12
var headers = parser.getHeaders(), prefixHeader = "";
if (!headers.warning || (headers.warning && headers.page) || (headers.warning && (now.getMonth() != warnDate.getMonth() || now.getFullYear() != warnDate.getFullYear())))
prefixHeader = "== " + AmelUtil.monthNames[now.getUTCMonth()] + " " + now.getUTCFullYear() + " ==\n";
this.savedtext += (/^\s*$/.test(this.savedtext) ? "" : "\n\n") +
(this.addtext = prefixHeader + "{{subst:uw-v" + parser.nextWarning() + "|" + this.editpage + "|Thank you.|subst=subst:}} ~~" + "~~");
}
Warning.aivInit = function(text) {
if (this.regex.test(text))
this.infotext += "NOTE! \"" + this.user + "\" found on page. ";
this.savedtext = text + "\n" + this.addtext;
}
Warning.nextMode = function(mode) {
switch (mode) {
case Warning.NONE: return Warning.WARN;
case Warning.WARN: return Warning.AIV;
case Warning.AIV: return Warning.WARN;
default: return Warning.NONE;
}
}
Warning.prototype.getDownloadCallback = function(mode) {
var me = this;
return function(obj) {
me.set(obj, mode);
}
}
Warning.prototype.setNextMode = function() {
this.set(null, Warning.nextMode(this.mode));
}
Warning.prototype.set = function(obj, newMode) {
var mData = this.data[newMode];
var text = obj && obj["*"];
if (!mData) return;
if (!mData.savedtext || mData.savedtext == "") {
if (text || text == "") {
mData.init(text);
mData.editor.setTimes(AmelUtil.isoToNumerical(obj["timestamp"]));
this.gui["warnSwitch"].value += "...";
this.showMode(newMode);
} else {
var func = this.getDownloadCallback(newMode);
mData.editor.getText(func);
mData.editor.downloadEditFormData();
}
} else {
if (text) {
if (confirm("The page \"" + mData.title + "\" is already initialized. Overwrite displayed text?"))
mData.init(text);
else
return;
}
this.showMode(newMode);
}
}
Warning.prototype.showMode = function(newMode) {
var thisData = this.data[this.mode];
var newData = this.data[newMode];
var gui = this.gui;
if (thisData) {
thisData.savedtext = gui["warnBox"].value;
thisData.summary = gui["warnSum"].value;
}
gui["warnBox"].value = newData.savedtext;
gui["warnSum"].value = newData.summary;
gui["warnPage"].firstChild.nodeValue = newData.title;
gui["warnInfo"].firstChild.nodeValue = newData.infotext;
gui["warnSwitch"].value = newData.button;
this.mode = newMode;
}
Warning.prototype.submit = function() {
var summary = this.gui["warnSum"].value;
var text = this.gui["warnBox"].value;
if (this.mode == Warning.WARN) {
var re = /\{\{subst:uw-(.*?)(?:\|.*?)?\}\}/gi;
if (summary.charAt(summary.length - 1) == "*") //shorthand for "no template plz"
summary = summary.substring(0, summary.length - 1);
else {
var templateMatch, templateName;
while (templateMatch = re.exec(text))
templateName = templateMatch[1];
if (templateName)
summary += " (" + templateName + ")";
}
} else if (this.mode != Warning.AIV) {
return; //only Warning.WARN and Warning.AIV allowed at the moment
}
var button = this.gui["warnSubmit"];
button.disabled = true;
var editor = this.data[this.mode].editor;
editor.setText(text);
editor.setSummary(summary);
editor.setMinor(false);
editor.setWatch(false);
editor.setCallback(function() { button.disabled = false; });
editor.submit();
}
//---------------------------------
//construct object: get in, get out. No need for state.
function showHistory(title, historyObj, showButtons, limit) {
limit = Math.min(historyObj.length, limit || 5);
if (!limit) return;
var pageURL = WikiTitle.fromEncoded(title).toIndexUrl();
var currentId = historyObj[0]["revid"];
var newLink = function(url, title) {
var link = document.createElement("a");
link.href = url;
link.title = title;
link.appendChild(document.createTextNode(title));
return link;
}
var historyItem = function(item, nextItem) {
//more pretty list under construction
var liItem = document.createElement("li");
if (nextItem) {
liItem.appendChild(document.createTextNode("("));
liItem.appendChild(newLink(pageURL + "&diff=" + currentId + "&oldid=" + item["revid"], "cur"));
liItem.appendChild(document.createTextNode(") ("));
} else {
liItem.appendChild(document.createTextNode("(cur) ("));
}
liItem.appendChild(newLink(pageURL + "&diff=" + item["revid"] + "&dir=prev", "last"));
liItem.appendChild(document.createTextNode(") "));
liItem.appendChild(newLink(pageURL + "&oldid=" + item["revid"], AmelUtil.isoToStandard(item.timestamp)));
liItem.appendChild(document.createTextNode(" "));
liItem.appendChild(newLink(WikiTitle.fromDisplay("Special:Contributions/" + item.user).toIndexUrl(), item.user));
if (item["comment"]) {
var summary = item["comment"].replace(/\[\[([^\|\]]+)\|?(.*?)\]\]/g, function (ignore, link, display) { return "<a href=\"" + WikiTitle.fromDisplay(link).toIndexUrl() + "\">" + (display || link) + "</a>"});
summary = summary.replace(/\/\*\s+(.+?)\s+\*\//g, function(ignore, anchor) { return "<a href=\"#" + WikiTitle.fromDisplay(anchor).toEncoded() + "\">→</a><span class=\"autocomment\">" + anchor + "</span> - "});
var summaryElem = document.createElement("span");
summaryElem.innerHTML = " | " + summary;
liItem.appendChild(summaryElem);
}
return liItem;
}
var historyDiv = document.getElementById("historyDiv");
if (historyDiv && historyDiv.firstChild) {
historyDiv.removeChild(historyDiv.firstChild);
} else {
historyDiv = document.createElement("div");
historyDiv.id = "historyDiv";
var jumpToNav = document.getElementById("jump-to-nav");
if (!jumpToNav) return false;
jumpToNav.parentNode.insertBefore(historyDiv, jumpToNav);
historyDiv = document.getElementById("historyDiv");
}
var historyList = document.createElement("ol");
var currentItem, nextItem;
for (var i = 0; i < limit; i++) {
currentItem = historyObj[i];
historyList.appendChild(historyItem(currentItem, nextItem));
nextItem = currentItem;
}
historyDiv.appendChild(historyList);
}
//---------------------------------
function WarningsParser(text) {
var state = { header: false, hasWarnings: false };
//if the latest header contains the most recent warning, if warnings can be found
var recent = { header: undefined, text: undefined, date: new Date(0), level: 0 };
//the header under which the latest warning appears, the warning's text,
//the date of the warning, its level.
var warningMatch = 0, warning;
var dayAgo = new Date();
dayAgo.setTime(dayAgo.getTime() - (24*60*60*1000));
var re = /<!-- Template:(.*?) -->.*?(\d{2}:\d{2}, \d+ \w+ \d{4}) \(UTC\)/gi;
var warning;
while (warning = re.exec(text)) {
if (!warning)
break;
recent.date = new Date(warning[2] + " UTC"); //UTC can't be in parentheses :|
if (recent.date > dayAgo)
recent.text = warning[1];
state.hasWarnings = true;
warningMatch = re.lastIndex;
}
//find the header the warning is under
var headerRe = /^(={2,6}).+?\1\s*?$/mg;
var warningH = text.substring(0, warningMatch).match(headerRe);
var pageH = text.substring(warningMatch).match(headerRe);
recent.header = warningH && warningH.pop();
state.header = !!pageH;
if (recent.text) {
var levels = recent.text.match(/^.*?(\d)(im)?$/);
if (levels && levels[1])
recent.level = parseInt(levels[1]);
else if (/first/i.test(recent.text)) recent.level = 1;
else if (/second/i.test(recent.text)) recent.level = 2;
else if (/third/i.test(recent.text)) recent.level = 3;
else if (/fourth/i.test(recent.text)) recent.level = 4;
} else if (state.hasWarnings) {
recent.level = 1; //if there are warnings there, use a level 2. put this in prefs?
}
this.pageData = state;
this.warningData = recent;
}
//encapsulate state
WarningsParser.prototype = {
report : function() {
return this.warningData.level == 4;
},
hasWarnings: function() {
return this.pageData.hasWarnings;
},
nextWarning: function() {
var recent = this.warningData;
if (recent.level < 4)
return recent.level + 1;
else if (recent.level == 4)
return 4;
else //not sure what we have; stick with level 1.
return 1;
},
previousDate: function() {
return this.warningData.date;
},
getHeaders: function() {
return { page: this.pageData.header, warning: this.warningData.header };
}
}
AmelUtil = new Object();
AmelUtil.plural = function(num, singular, plural) {
return num + " " + (num == 1 ? singular : plural);
}
//previously named AmelUtil.yetAnotherJsMonthNameArray. too long, though :P
AmelUtil.monthNames = ["January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"];
AmelUtil.isIP = function(str) {
var rangeCheck = function(num) {
return (!/\D/.test(num) && parseInt(num) >> 8 == 0);
}
var nums = str.split("."), index = nums.length;
if (index != 4 && index != 6) return false;
while (--index >= 0)
if (!rangeCheck(nums[index])) return false;
return true;
}
AmelUtil.numericalTsNow = function() {
var now = new Date();
var padDD = function(num) { //double-digit pad
return ("0" + num).slice(-2);
}
return now.getUTCFullYear() + padDD(now.getUTCMonth() + 1) + padDD(now.getUTCDate()) +
padDD(now.getUTCHours()) + padDD(now.getUTCMinutes()) + padDD(now.getUTCSeconds());
}
AmelUtil.isoToNumerical = function(timestamp) {
return timestamp && timestamp.replace( /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z/, "$1$2$3$4$5$6")
}
AmelUtil.isoToStandard = function(timestamp) {
return timestamp && timestamp.replace( /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z/, function(ignore, year, month, date, hour, minute) { return hour + ":" + minute + ", " + date + " " + AmelUtil.monthNames[month - 1] + " " + year});
}
AmelUtil.getPageObj = function(jsonObj) {
try {
jsonObj = jsonObj.query.pages;
for (var pageObj in jsonObj)
return jsonObj[pageObj];
} catch (e) {
}
}
AmelUtil.colorStatus = function(color) {
document.getElementById("content").style.background = color;
}
AmelUtil.rollbackPerm = function() {
if (wgUserGroups.indexOf)
return wgUserGroups.indexOf("sysop") != -1 || wgUserGroups.indexOf("rollbacker") != -1;
for (var i = 0, length = wgUserGroups.length; i < length; i++)
if (wgUserGroups[i] == "sysop" || wgUserGroups[i] == "rollbacker") return true;
return false;
}
AmelUtil.diffRollback = function() {
var checkExist = document.getElementById("mw-diff-ntitle1");
if (!checkExist) return null;
if (AmelUtil.rollbackPerm()) {
var rb = document.getElementById("mw-diff-ntitle2").getElementsByTagName("span");
if (rb.length > 1) {
var rbUrl = rb[1].getElementsByTagName("a")[0].href
return function() {
new AdminRollback(rbUrl);
};
} //else, continue along with normal revert
}
var link = checkExist.getElementsByTagName("a");
link = link[link.length - 1].href;
var revFrom = link.match(/[&?]undo=([^&]*)/);
var pageName = link.match(/[&?]title=([^&]*)/);
var userFrom = document.getElementById("mw-diff-ntitle2")
.getElementsByTagName("a")[0].title.match(/(?:User:|Special:Contributions\/)(.*$)/);
if (pageName)
return function() {
new Rollback(pageName[1], (revFrom ? revFrom[1] : undefined), (userFrom ? userFrom[1] : undefined));
}
};
AmelUtil.diffRestore = function(container) {
var checkExist = container.getElementById("mw-diff-otitle1");
if (!checkExist) return null;
var link = checkExist.getElementsByTagName("a")[0].href;
var pageName = link.match(/[&?]title=([^&]*)/);
var revTo = link.match(/[&?]oldid=([^&]*)/);
var userTo = container.getElementById("mw-diff-otitle2")
.getElementsByTagName('a')[0].title.match(/(?:User:|Special:Contributions\/)(.*$)/);
if (pageName && revTo)
return function() {
latest = new RestoreRevision(pageName[1], revTo[1]);
}
};
//-------------------------------------
//Mode: press spacebar to revert
AmelKeyFuncs = {};
AmelKeyFuncs.enabled = document.cookie.indexOf("amelKeys=true") != -1;
AmelKeyFuncs.formatOnLoad = function() {
mw.util.addPortletLink("p-tb", "javascript:AmelKeyFuncs.toggleUse()", (AmelKeyFuncs.enabled ? "Don't use" : "Use") + " spacebar reversion", "t-amelkeys", "Enable reversion on diffs using the spacebar");
window.onkeypress = AmelKeyFuncs.checkToRevert;
window.focus();
}
AmelKeyFuncs.pageEnabled = true;
AmelKeyFuncs.checkToRevert = function(e) {
if (!AmelKeyFuncs.enabled || !AmelKeyFuncs.pageEnabled)
return true;
e = e || window.event;
if (e.charCode == 32) {
var func = AmelUtil.diffRollback();
AmelKeyFuncs.pageEnabled = false;
if (func) {
func.call(this);
return false;
}
}
return true;
}
AmelKeyFuncs.toggleUse = function() {
var now = new Date();
if (!AmelKeyFuncs.enabled)
now.setTime(now.getTime() + 365*24*60*60*1000);
AmelKeyFuncs.enabled = !AmelKeyFuncs.enabled;
document.cookie = "amelKeys=" + AmelKeyFuncs.enabled + "; expires=" + now.toGMTString() + "; path=/"
document.getElementById("t-amelkeys").firstChild.firstChild.nodeValue = (AmelKeyFuncs.enabled ? "Don't use" : "Use") + " spacebar reversion";
}
//-------------------------------------
var WikiEdit = function(title, parent, autosubmit) {
if (!title)
throw new Error("title needed for WikiEdit");
this.title = title;
this.autosubmit = autosubmit;
this.submitCallback = function(){};
this.closed = false;
this.editMonitor = false;
this.submitData = {}; //the form fields
this.onSubmitHooks = []; //to be processed immediately before submitting
this.submitXHR = null;
this.parent = parent;
}
WikiEdit.needToSubmit = ["wpTextbox1", "wpSummary", "wpEditToken", "wpStarttime", "wpEdittime"];
WikiEdit.prototype.setCallback = function(callback) {
this.submitCallback = callback;
}
WikiEdit.prototype.cancel = function() {
this.closed = true;
if (this.submitXHR)
this.submitXHR.abort();
}
WikiEdit.prototype.addSubmitHook = function(func) {
if (this.closed)
return false;
this.onSubmitHooks.push(func);
return true;
}
WikiEdit.prototype.doPreSubmitHook = function(func) {
if (this.closed)
return false;
this.editMonitor = true;
func.call(this);
this.editMonitor = false;
this.addSubmitData({});
return true;
}
WikiEdit.prototype.downloadEditFormData = function() {
if (this.closed)
return;
var me = this;
var req = new XMLHttpRequest();
req.open("GET", mw.config.get('wgServer') + mw.config.get('wgScriptPath') + "/api.php?action=query&prop=info&intoken=edit&format=json&titles=" + this.title, true);
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
var pageObj = AmelUtil.getPageObj(eval("(" + req.responseText + ")"));
if (pageObj) {
me.addSubmitData({"wpEditToken" : pageObj["edittoken"]});
}
else
alert("Could not retrieve edit form data");
}
}
req.send(null);
}
WikiEdit.prototype.setParent = function(parent) {
this.parent = parent;
}
WikiEdit.prototype.setText = function(wikitext) {
this.addSubmitData({"wpTextbox1" : wikitext});
}
WikiEdit.prototype.setTimes = function(edittime) {
var tsNow = AmelUtil.numericalTsNow();
this.addSubmitData({"wpEdittime" : edittime || tsNow,
"wpStarttime" : tsNow});
}
WikiEdit.prototype.setSummary = function(text) {
this.addSubmitData({"wpSummary" : text});
}
WikiEdit.prototype.setMinor = function(boole) {
if (boole) this.addSubmitData({"wpMinoredit" : "1"});
}
WikiEdit.prototype.setWatch = function(boole) {
if (boole) this.addSubmitData({"wpWatchthis" : "1"});
}
WikiEdit.prototype.getHistory = function(callback, limit) {
this.getRevInformation(callback, ["user", "ids", "comment", "timestamp"], limit || 20, undefined);
}
WikiEdit.prototype.getText = function(callback, oldid) {
this.getRevInformation(callback, ["content", "user", "timestamp"], 1, oldid);
}
//Private. precondition: props are properly encoded
WikiEdit.prototype.getRevInformation = function(callback, props, limit, revid) {
if (!callback)
return;
var me = this;
var req = new XMLHttpRequest();
req.open("GET", wgServer + wgScriptPath +
"/api.php?action=query&prop=revisions&format=json&rvprop=" + props.join("|") +
(revid ? "&rvstartid=" + revid : "") + (limit ? "&rvlimit=" + limit : "") +
"&titles=" + this.title, true);
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
var pageObj = AmelUtil.getPageObj(eval("(" + req.responseText + ")"));
if (!pageObj) return;
if (pageObj.revisions) {
var returnObj = pageObj["revisions"];
if (limit == 1) returnObj = returnObj[0];
returnObj.title = pageObj.title;
callback.call(me.parent, returnObj);
} else if (pageObj.missing == "") {
callback.call(me.parent, {"user":"", "*":""});
}
}
}
req.send(null);
}
WikiEdit.prototype.submit = function() {
this.autosubmit = true;
if (this.closed || this.editMonitor)
return false;
var submitData = this.submitData, onSubmitHooks = this.onSubmitHooks;
for (var i = 0, nts = WikiEdit.needToSubmit; i < nts.length; i++)
if (!(nts[i] in submitData)) return false;
this.closed = true;
while (onSubmitHooks.length > 0)
onSubmitHooks.shift().call(this);
var parameters = [];
for (var property in submitData)
parameters.push(encodeURIComponent(property) + "=" + encodeURIComponent(submitData[property]));
var me = this;
var req = this.submitXHR = new XMLHttpRequest();
req.open("POST", mw.config.get('wgServer') + mw.config.get('wgScript') + "?title=" + this.title + "&action=submit", true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
me.submitCallback.call(me.parent);
}
};
req.send(parameters.join("&"));
return true;
}
//@Private. Adds data; submits to index.php if has all information
WikiEdit.prototype.addSubmitData = function(obj) {
var submitData = this.submitData;
if (this.closed)
return;
for (var property in obj) //merge into submitData
submitData[property] = obj[property];
if (this.autosubmit)
this.submit();
}
//-------------------------------------
var isDiff = /[?&]diff=/.test(document.location.href);
if (isDiff) {
addOnloadHook(addRollback);
addOnloadHook(addRestore);
if (AmelKeyFuncs.enabled)
addOnloadHook(AmelKeyFuncs.formatOnLoad);
}
// </nowiki>