User:Benison/amelvand.js
Appearance
(Redirected from User:The Herald/amelvand.js)
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:Benison/amelvand. |
//<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>