MediaWiki:Gadget-twinkleconfig.js: Difference between revisions

localise
m (1 revision)
 
(localise)
 
(7 intermediate revisions by 2 users not shown)
Line 9: Line 9:
  *** twinkleconfig.js: Preferences module
  *** twinkleconfig.js: Preferences module
  ****************************************
  ****************************************
  * Mode of invocation:    Adds configuration form to Wikipedia:Twinkle/Preferences and user  
  * Mode of invocation:    Adds configuration form to Sarkarverse:Twinkle/Preferences and user
                           subpages named "/Twinkle preferences", and adds ad box to the top of user  
                           subpages named "/Twinkle preferences", and adds ad box to the top of user
                           subpages belonging to the currently logged-in user which end in '.js'
                           subpages belonging to the currently logged-in user which end in '.js'
  * Active on:              What I just said.  Yeah.
  * Active on:              What I just said.  Yeah.
Line 16: Line 16:


  I, [[User:This, that and the other]], originally wrote this.  If the code is misbehaving, or you have any
  I, [[User:This, that and the other]], originally wrote this.  If the code is misbehaving, or you have any
  questions, don't hesitate to ask me.  (This doesn't at all imply [[WP:OWN]]ership - it's just meant to
  questions, don't hesitate to ask me.  (This doesn't at all imply [[SV:OWN]]ership - it's just meant to
  point you in the right direction.)  -- TTO
  point you in the right direction.)  -- TTO
  */
  */
Line 31: Line 31:
csdCriteria: {
csdCriteria: {
db: "Custom rationale ({{db}})",
db: "Custom rationale ({{db}})",
g1: "G1", g2: "G2", g3: "G3", g4: "G4", g5: "G5", g6: "G6", g7: "G7", g8: "G8", g10: "G10", g11: "G11", g12: "G12", g13: "G13",
g1: "G1", g2: "G2", g3: "G3", g4: "G4", g5: "G5", g6: "G6", g7: "G7", g8: "G8", g10: "G10", g11: "G11", g12: "G12", g13: "G13", g14: "G14",
a1: "A1", a2: "A2", a3: "A3", a5: "A5", a7: "A7", a9: "A9", a10: "A10", a11: "A11",
a1: "A1", a2: "A2", a3: "A3", a5: "A5", a7: "A7", a9: "A9", a10: "A10", a11: "A11",
u1: "U1", u2: "U2", u3: "U3",
u1: "U1", u2: "U2", u3: "U3", u5: "U5",
f1: "F1", f2: "F2", f3: "F3", f7: "F7", f8: "F8", f9: "F9", f10: "F10",
f1: "F1", f2: "F2", f3: "F3", f7: "F7", f8: "F8", f9: "F9", f10: "F10",
c1: "C1",
c1: "C1",
t2: "T2", t3: "T3",
t2: "T2", t3: "T3",
r2: "R2", r3: "R3",
r2: "R2", r3: "R3", r4: "R4",
p1: "P1", p2: "P2"
p1: "P1", p2: "P2"
},
},
csdCriteriaDisplayOrder: [
csdCriteriaDisplayOrder: [
"db",
"db",
"g1", "g2", "g3", "g4", "g5", "g6", "g7", "g8", "g10", "g11", "g12", "g13",
"g1", "g2", "g3", "g4", "g5", "g6", "g7", "g8", "g10", "g11", "g12", "g13", "g14",
"a1", "a2", "a3", "a5", "a7", "a9", "a10", "a11",
"a1", "a2", "a3", "a5", "a7", "a9", "a10", "a11",
"u1", "u2", "u3",
"u1", "u2", "u3", "u5",
"f1", "f2", "f3", "f7", "f8", "f9", "f10",
"f1", "f2", "f3", "f7", "f8", "f9", "f10",
"c1",
"c1",
"t2", "t3",
"t2", "t3",
"r2", "r3",
"r2", "r3", "r4",
"p1", "p2"
"p1", "p2"
],
],
Line 54: Line 54:
db: "Custom rationale ({{db}})",
db: "Custom rationale ({{db}})",
g1: "G1", g2: "G2", g3: "G3", g4: "G4", g6: 'G6 ("unnecessary disambig." and "copy-paste move" only)',
g1: "G1", g2: "G2", g3: "G3", g4: "G4", g6: 'G6 ("unnecessary disambig." and "copy-paste move" only)',
g10: "G10", g11: "G11", g12: "G12", g13: "G13",
g10: "G10", g11: "G11", g12: "G12", g13: "G13", g14: "G14",
a1: "A1", a2: "A2", a3: "A3", a5: "A5", a7: "A7", a9: "A9", a10: "A10", a11: "A11",
a1: "A1", a2: "A2", a3: "A3", a5: "A5", a7: "A7", a9: "A9", a10: "A10", a11: "A11",
u3: "U3",
u3: "U3", u5: "U5",
f1: "F1", f2: "F2", f3: "F3", f7: "F7", f8: "F8", f9: "F9", f10: "F10",
f1: "F1", f2: "F2", f3: "F3", f7: "F7", f8: "F8", f9: "F9", f10: "F10",
c1: "C1",
c1: "C1",
t2: "T2", t3: "T3",
t2: "T2", t3: "T3",
r2: "R2", r3: "R3",
r2: "R2", r3: "R3", r4: "R4",
p1: "P1", p2: "P2"
p1: "P1", p2: "P2"
},
},
csdCriteriaNotificationDisplayOrder: [
csdCriteriaNotificationDisplayOrder: [
"db",
"db",
"g1", "g2", "g3", "g4", "g6", "g10", "g11", "g12", "g13",
"g1", "g2", "g3", "g4", "g6", "g10", "g11", "g12", "g13", "g14",
"a1", "a2", "a3", "a5", "a7", "a9", "a10", "a11",
"a1", "a2", "a3", "a5", "a7", "a9", "a10", "a11",
"u3",
"u3", "u5",
"f1", "f2", "f3", "f7", "f9", "f10",
"f1", "f2", "f3", "f7", "f9", "f10",
"c1",
"c1",
"t2", "t3",
"t2", "t3",
"r2", "r3",
"r2", "r3", "r4",
"p1", "p2"
"p1", "p2"
],
],
csdAndDICriteria: {
csdAndDICriteria: {
db: "Custom rationale ({{db}})",
db: "Custom rationale ({{db}})",
g1: "G1", g2: "G2", g3: "G3", g4: "G4", g5: "G5", g6: "G6", g7: "G7", g8: "G8", g10: "G10", g11: "G11", g12: "G12", g13: "G13",
g1: "G1", g2: "G2", g3: "G3", g4: "G4", g5: "G5", g6: "G6", g7: "G7", g8: "G8", g10: "G10", g11: "G11", g12: "G12", g13: "G13", g14: "G14",
a1: "A1", a2: "A2", a3: "A3", a5: "A5", a7: "A7", a9: "A9", a10: "A10", a11: "A11",
a1: "A1", a2: "A2", a3: "A3", a5: "A5", a7: "A7", a9: "A9", a10: "A10", a11: "A11",
u1: "U1", u2: "U2", u3: "U3",
u1: "U1", u2: "U2", u3: "U3", u5: "U5",
f1: "F1", f2: "F2", f3: "F3", f4: "F4", f5: "F5", f6: "F6", f7: "F7", f8: "F8", f9: "F9", f10: "F10", f11: "F11",
f1: "F1", f2: "F2", f3: "F3", f4: "F4", f5: "F5", f6: "F6", f7: "F7", f8: "F8", f9: "F9", f10: "F10", f11: "F11",
c1: "C1",
c1: "C1",
t2: "T2", t3: "T3",
t2: "T2", t3: "T3",
r2: "R2", r3: "R3",
r2: "R2", r3: "R3", r4: "R4",
p1: "P1", p2: "P2"
p1: "P1", p2: "P2"
},
},
csdAndDICriteriaDisplayOrder: [
csdAndDICriteriaDisplayOrder: [
"db",
"db",
"g1", "g2", "g3", "g4", "g5", "g6", "g7", "g8", "g10", "g11", "g12", "g13",
"g1", "g2", "g3", "g4", "g5", "g6", "g7", "g8", "g10", "g11", "g12", "g13", "g14",
"a1", "a2", "a3", "a5", "a7", "a9", "a10", "a11",
"a1", "a2", "a3", "a5", "a7", "a9", "a10", "a11",
"u1", "u2", "u3",
"u1", "u2", "u3", "u5",
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11",
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11",
"c1",
"c1",
"t2", "t3",
"t2", "t3",
"r2", "r3",
"r2", "r3", "r4",
"p1", "p2"
"p1", "p2"
],
],
Line 117: Line 117:
"108": "Book",
"108": "Book",
"109": "Book talk",
"109": "Book talk",
"118": "Draft",
"119": "Draft talk",
"710": "TimedText",
"710": "TimedText",
"711": "TimedText talk",
"711": "TimedText talk",
Line 200: Line 202:
name: "dialogLargeFont",
name: "dialogLargeFont",
label: "Use larger text in Twinkle dialogs",
label: "Use larger text in Twinkle dialogs",
type: "boolean"
}
]
},
{
title: "ARV",
preferences: [
{
name: "spiWatchReport",
label: "Add sockpuppet report pages to watchlist",
type: "enum",
enumValues: Twinkle.config.commonEnums.watchlist
}
]
},
{
title: "Block user",
adminOnly: true,
preferences: [
// TwinkleConfig.blankTalkpageOnIndefBlock (boolean)
// if true, blank the talk page when issuing an indef block notice (per [[SV:UWUL#Indefinitely blocked users]])
{
name: "blankTalkpageOnIndefBlock",
label: "Blank the talk page when indefinitely blocking users",
helptip: "See <a href=\"" + mw.util.getUrl("Sarkarverse:WikiProject_User_warnings/Usage_and_layout#Indefinitely_blocked_users") + "\">SV:UWUL</a> for more information.",
type: "boolean"
type: "boolean"
}
}
Line 374: Line 403:
name: "markSpeedyPagesAsPatrolled",
name: "markSpeedyPagesAsPatrolled",
label: "Mark page as patrolled when tagging (if possible)",
label: "Mark page as patrolled when tagging (if possible)",
helptip: "Due to technical limitations, pages are only marked as patrolled when they are reached via Special:NewPages.",
type: "boolean"
type: "boolean"
},
},
Line 597: Line 625:
"6": "Single-issue notices",
"6": "Single-issue notices",
"7": "Single-issue warnings",
"7": "Single-issue warnings",
"9": "Custom warnings",
"9": "Custom warnings"
"8": "Block (admin only)"
}
}
},
},
Line 608: Line 635:
name: "showSharedIPNotice",
name: "showSharedIPNotice",
label: "Add extra notice on shared IP talk pages",
label: "Add extra notice on shared IP talk pages",
helptip: "Notice used is {{SharedIPAdvice}}",
helptip: "Notice used is {{Shared IP advice}}",
type: "boolean"
type: "boolean"
},
},
Line 620: Line 647:
},
},


// TwinkleConfig.blankTalkpageOnIndefBlock (boolean)
// if true, blank the talk page when issuing an indef block notice (per [[WP:UW#Indefinitely blocked users]])
{
name: "blankTalkpageOnIndefBlock",
label: "Blank the talk page when indefinitely blocking users",
helptip: "See <a href=\"" + mw.util.wikiGetlink("WP:UW#Indefinitely blocked users") + "\">WP:UW</a> for more information.",
adminOnly: true,
type: "boolean"
},
{
{
name: "customWarningList",
name: "customWarningList",
Line 636: Line 654:
customListValueTitle: "Template name (no curly brackets)",
customListValueTitle: "Template name (no curly brackets)",
customListLabelTitle: "Text to show in warning list (also used as edit summary)"
customListLabelTitle: "Text to show in warning list (also used as edit summary)"
},
{
name: "markXfdPagesAsPatrolled",
label: "Mark page as patrolled when nominating for AFD (if possible)",
type: "boolean"
}
}
]
]
Line 803: Line 827:
{
{
name: "batchUndeleteMinCutOff",
name: "batchUndeleteMinCutOff",
type: "integer"
},
// twinkledelimages.js: How many files should be processed at a time
{
name: "deliChunks",
type: "integer"
},
// twinkledelimages.js: How many files should be processed maximum
{
name: "deliMax",
type: "integer"
type: "integer"
},
},
Line 837: Line 851:
(mw.config.get("wgNamespaceNumber") === mw.config.get("wgNamespaceIds").user && mw.config.get("wgTitle").lastIndexOf("/Twinkle preferences") === (mw.config.get("wgTitle").length - 20))) &&
(mw.config.get("wgNamespaceNumber") === mw.config.get("wgNamespaceIds").user && mw.config.get("wgTitle").lastIndexOf("/Twinkle preferences") === (mw.config.get("wgTitle").length - 20))) &&
mw.config.get("wgAction") === "view") {
mw.config.get("wgAction") === "view") {
// create the config page at Wikipedia:Twinkle/Preferences, and at user subpages (for testing purposes)
// create the config page at Sarkarverse:Twinkle/Preferences, and at user subpages (for testing purposes)


if (!document.getElementById("twinkle-config")) {
if (!document.getElementById("twinkle-config")) {
Line 853: Line 867:
var contentnotice = document.createElement("p");
var contentnotice = document.createElement("p");
// I hate innerHTML, but this is one thing it *is* good for...
// I hate innerHTML, but this is one thing it *is* good for...
contentnotice.innerHTML = "<b>Before modifying your preferences here,</b> make sure you have removed any old <code>TwinkleConfig</code> and <code>FriendlyConfig</code> settings from your <a href=\"" + mw.util.wikiGetlink("Special:MyPage/skin.js") + "\" title=\"Special:MyPage/skin.js\">user JavaScript file</a>.";
contentnotice.innerHTML = "<b>Before modifying your preferences here,</b> make sure you have removed any old <code>TwinkleConfig</code> and <code>FriendlyConfig</code> settings from your <a href=\"" + mw.util.getUrl("Special:MyPage/skin.js") + "\" title=\"Special:MyPage/skin.js\">user JavaScript file</a>.";
contentdiv.appendChild(contentnotice);
contentdiv.appendChild(contentnotice);


Line 1,118: Line 1,132:
// convert mentions of templates in the helptip to clickable links
// convert mentions of templates in the helptip to clickable links
cell.innerHTML = pref.helptip.replace(/{{(.+?)}}/g,
cell.innerHTML = pref.helptip.replace(/{{(.+?)}}/g,
'{{<a href="' + mw.util.wikiGetlink("Template:") + '$1" target="_blank">$1</a>}}');
'{{<a href="' + mw.util.getUrl("Template:") + '$1" target="_blank">$1</a>}}');
}
}
// add reset link (custom lists don't need this, as their config value isn't displayed on the form)
// add reset link (custom lists don't need this, as their config value isn't displayed on the form)
Line 1,167: Line 1,181:
// since all the section headers exist now, we can try going to the requested anchor
// since all the section headers exist now, we can try going to the requested anchor
if (location.hash) {
if (location.hash) {
location.hash = location.hash;
window.location.hash = location.hash;
}
}


Line 1,198: Line 1,212:
}
}
link = document.createElement("a");
link = document.createElement("a");
link.setAttribute("href", mw.util.wikiGetlink(mw.config.get("wgFormattedNamespaces")[mw.config.get("wgNamespaceIds").project] + ":Twinkle/Preferences") );
link.setAttribute("href", mw.util.getUrl(mw.config.get("wgFormattedNamespaces")[mw.config.get("wgNamespaceIds").project] + ":Twinkle/Preferences") );
link.appendChild(document.createTextNode("Twinkle preferences panel"));
link.appendChild(document.createTextNode("Twinkle preferences panel"));
box.appendChild(link);
box.appendChild(link);
Line 1,210: Line 1,224:
box.appendChild(document.createTextNode("If you want to set Twinkle preferences, you can use the "));
box.appendChild(document.createTextNode("If you want to set Twinkle preferences, you can use the "));
link = document.createElement("a");
link = document.createElement("a");
link.setAttribute("href", mw.util.wikiGetlink(mw.config.get("wgFormattedNamespaces")[mw.config.get("wgNamespaceIds").project] + ":Twinkle/Preferences") );
link.setAttribute("href", mw.util.getUrl(mw.config.get("wgFormattedNamespaces")[mw.config.get("wgNamespaceIds").project] + ":Twinkle/Preferences") );
link.appendChild(document.createTextNode("Twinkle preferences panel"));
link.appendChild(document.createTextNode("Twinkle preferences panel"));
box.appendChild(link);
box.appendChild(link);
Line 1,330: Line 1,344:
addButton.style.minWidth = "8em";
addButton.style.minWidth = "8em";
addButton.setAttribute("type", "button");
addButton.setAttribute("type", "button");
addButton.addEventListener("click", function(e) {
addButton.addEventListener("click", function() {
Twinkle.config.listDialog.addRow(dlgtbody);
Twinkle.config.listDialog.addRow(dlgtbody);
}, false);
}, false);
Line 1,345: Line 1,359:
var button = document.createElement("button");
var button = document.createElement("button");
button.setAttribute("type", "submit");  // so Morebits.simpleWindow puts the button in the button pane
button.setAttribute("type", "submit");  // so Morebits.simpleWindow puts the button in the button pane
button.addEventListener("click", function(e) {
button.addEventListener("click", function() {
Twinkle.config.listDialog.save($prefbutton, dlgtbody);
Twinkle.config.listDialog.save($prefbutton, dlgtbody);
dialog.close();
dialog.close();
Line 1,353: Line 1,367:
button = document.createElement("button");
button = document.createElement("button");
button.setAttribute("type", "submit");  // so Morebits.simpleWindow puts the button in the button pane
button.setAttribute("type", "submit");  // so Morebits.simpleWindow puts the button in the button pane
button.addEventListener("click", function(e) {
button.addEventListener("click", function() {
Twinkle.config.listDialog.reset($prefbutton, dlgtbody);
Twinkle.config.listDialog.reset($prefbutton, dlgtbody);
}, false);
}, false);
Line 1,360: Line 1,374:
button = document.createElement("button");
button = document.createElement("button");
button.setAttribute("type", "submit");  // so Morebits.simpleWindow puts the button in the button pane
button.setAttribute("type", "submit");  // so Morebits.simpleWindow puts the button in the button pane
button.addEventListener("click", function(e) {
button.addEventListener("click", function() {
dialog.close();  // the event parameter on this function seems to be broken
dialog.close();  // the event parameter on this function seems to be broken
}, false);
}, false);
Line 1,454: Line 1,468:


case "set":
case "set":
$.each(pref.setValues, function(itemkey, itemvalue) {
$.each(pref.setValues, function(itemkey) {
if (document.getElementById(pref.name + "_" + itemkey)) {
if (document.getElementById(pref.name + "_" + itemkey)) {
document.getElementById(pref.name + "_" + itemkey).checked = ((inFriendlyConfig ?
document.getElementById(pref.name + "_" + itemkey).checked = ((inFriendlyConfig ?
Line 1,501: Line 1,515:
return false;
return false;
};
};
// The JSON stringify method in the following code was excerpted from
// http://www.JSON.org/json2.js
// version of 2011-02-23
// Douglas Crockford, the code's author, has released it into the Public Domain.
// See http://www.JSON.org/js.html
var JSON;
if (!JSON) {
JSON = {};
}
(function() {
var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent = '  ',  // hardcoded indent
meta = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' };
function quote(string) {
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
var i, k, v, length, mind = gap, partial, value = holder[key];
if (value && typeof value === 'object' && $.isFunction(value.toJSON)) {
value = value.toJSON(key);
}
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
return String(value);
case 'object':
if (!value) {
return 'null';
}
gap += indent;
partial = [];
if ($.isArray(value)) {
length = value.length;
for (i = 0; i < length; ++i) {
partial[i] = str(i, value) || 'null';
}
v = partial.length === 0 ? '[]' : gap ?
'[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
'[' + partial.join(',') + ']';
gap = mind;
return v;
}
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
v = partial.length === 0 ? '{}' : gap ?
'{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
'{' + partial.join(',') + '}';
gap = mind;
return v;
default:
throw new Error( "JSON.stringify: unknown data type" );
}
}
if (!$.isFunction(JSON.stringify)) {
JSON.stringify = function (value, ignoredParam1, ignoredParam2) {
ignoredParam1 = ignoredParam2;  // boredom
gap = '';
return str('', {'': value});
};
}
}());


Twinkle.config.writePrefs = function twinkleconfigWritePrefs(pageobj) {
Twinkle.config.writePrefs = function twinkleconfigWritePrefs(pageobj) {
var form = pageobj.getCallbackParameters();
var form = pageobj.getCallbackParameters();
var statelem = pageobj.getStatusElement();


// this is the object which gets serialized into JSON
// this is the object which gets serialized into JSON
Line 1,609: Line 1,537:
// compare({}, {}) === false, but it's good enough for our purposes here
// compare({}, {}) === false, but it's good enough for our purposes here
var compare = function(a, b) {
var compare = function(a, b) {
if ($.isArray(a)) {
if (Array.isArray(a)) {
if (a.length !== b.length) {
if (a.length !== b.length) {
return false;
return false;
Line 1,670: Line 1,598:
} else {
} else {
// read all the keys in the list of values
// read all the keys in the list of values
$.each(pref.setValues, function(itemkey, itemvalue) {
$.each(pref.setValues, function(itemkey) {
if (form[pref.name + "_" + itemkey].checked) {
if (form[pref.name + "_" + itemkey].checked) {
userValue.push(itemkey);
userValue.push(itemkey);
Line 1,735: Line 1,663:


pageobj.setPageText(text);
pageobj.setPageText(text);
pageobj.setEditSummary("Saving Twinkle preferences: automatic edit from [[" + Morebits.pageNameNorm + "]] ([[WP:TW|TW]])");
pageobj.setEditSummary("Saving Twinkle preferences: automatic edit from [[:" + Morebits.pageNameNorm + "]] ([[SV:TW|TW]])");
pageobj.setCreateOption("recreate");
pageobj.setCreateOption("recreate");
pageobj.save(Twinkle.config.saveSuccess);
pageobj.save(Twinkle.config.saveSuccess);
Line 1,747: Line 1,675:
noticebox.style.fontSize = "100%";
noticebox.style.fontSize = "100%";
noticebox.style.marginTop = "2em";
noticebox.style.marginTop = "2em";
noticebox.innerHTML = "<p><b>Your Twinkle preferences have been saved.</b></p><p>To see the changes, you will need to <b>clear your browser cache entirely</b> (see <a href=\"" + mw.util.wikiGetlink("WP:BYPASS") + "\" title=\"WP:BYPASS\">WP:BYPASS</a> for instructions).</p>";
noticebox.innerHTML = "<p><b>Your Twinkle preferences have been saved.</b></p><p>To see the changes, you will need to <b>clear your browser cache entirely</b> (see <a href=\"" + mw.util.getUrl("SV:BYPASS") + "\" title=\"SV:BYPASS\">SV:BYPASS</a> for instructions).</p>";
Morebits.status.root.appendChild(noticebox);
Morebits.status.root.appendChild(noticebox);
var noticeclear = document.createElement("br");
var noticeclear = document.createElement("br");
14,061

edits