User:Terasail/Edit Request Tool.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. |
![]() | This user script seems to have a documentation page at User:Terasail/Edit Request Tool. |
//<nowiki>
var rOS = 9; //Reply options start
var replyERT = {
semi: ["Semi", "semi", "1/1b/", "ESp|"],
extended: ["Extended", "extended", "8/8c/", "EEp|"],
template: ["Template", "template", "5/53/", "ETp|"],
full: ["Full", "fully", "4/44/", "EP|"],
"interface": ["Interface", "interface", "2/28/", "EIp|"],
"Close": ["", "Close", "Closed edit request"],
"Change": ["", "Close", "Changed level of protected edit request"],
"ChangeTarget": ["", "Close", "Changed target of protected edit request"],
"Remove": ["", "Remove", "Removed edit request"],
"Comment (No template)": ["", "speechBubbleAdd", "Comment"],
"Done": ["d", "checkAll", "Done"],
"Partly done:": ["pd", "check", "Partly done"],
"Already Done": ["a", "clock", "Already Done"],
"In progress: An editor is implementing the requested edit.": ["prog", "clock", "In progress"],
"Note:": ["note", "ellipsis", "Note"],
"Question:": ["q", "helpNotice", "Question"],
"Not done:": ["n", "notice", "Not done"],
"Not done for now:": ["nfn", "notice", "Not done for now"],
"Not done: it's not clear what changes you want to be made. Please mention the specific changes in a 'change X to Y' format and provide a reliable source if appropriate.": ["xy", "helpNotice", "Not done - Unclear request"],
"Not done: please provide reliable sources that support the change you want to be made.": ["rs", "link", "Not done - Needs reliable sources"],
"Not done for now: please establish a consensus for this alteration before using the edit protected template.": ["c", "userGroup", "Not done - Needs consensus"],
"Not done: please make your requested changes to the template's sandbox first; see WP:TESTCASES.": ["sb", "linkExternal", "Not done - Use sandbox first"],
"Not done: this is the talk page for the page. Please make your request at the talk page for the article concerned.": ["mis", "ongoingConversation", "Not done - Misplaced"],
"Not done: this is the talk page for discussing improvements to the page. If possible, please make your request at the talk page for the article concerned.": ["tp", "ongoingConversation", "Not done - Misplaced"],
"Not done: According to the page's protection level you should be able to edit the page yourself. If you seem to be unable to, please reopen the request with further details.": ["hr", "unLock", "Not done - User can edit page"],
"Not done: The page's protection level has changed since this request was placed. You should now be able to edit the page yourself...": ["nlp", "unLock", "Not done - Page protection has changed"],
"Not done: {{Edit protected}} is usually not required for edits to the documentation or categories of templates using a documentation subpage.": ["doc", "code", "Not done"],
"Not done: requests for increases to the page protection level should be made at Wikipedia:Requests for page protection.": ["r", "editLock", "Not done - Use [[WP:RPP]]"],
"Not done: requests for decreases to the page protection level should be directed to the protecting admin or to Wikipedia:Requests for page protection.": ["ru", "editLock", "Not done - Use [[WP:RPP]]"],
"Not done: requests for recreating deleted pages protected against creation should be made at Wikipedia:Deletion review.": ["drv", "articleAdd", "Not done - Use [[WP:DRV]]"],
"Not done: page move requests should be made at Wikipedia:Requested moves.": ["m", "tableMoveColumnAfter", "Not done - Use [[WP:RM]]"],
"Not done: Please make your request for a new image to be uploaded to Files For Upload. Once the file has been properly uploaded, feel free to reactivate this request.": ["ffu", "imageLayoutFrameless", "Not done - Use [[WP:FFU]]"],
"Not done: this is not the right page to request additional user rights. You may reopen this request with the specific changes to be made and someone will add them for you.": ["p", "userAdd", "Not done - Use [[WP:RFPERM]]"],
"Partially undone: This request has been partially undone.": ["pud","undo", "Partly undone"],
"Undone: This request has been undone.": ["ud", "undo", "Undone"]
};
function postEdit(wikitext, editSummary, pageName, secIdx) {
let api = new mw.Api();
api.postWithEditToken({
action: 'edit',
title: pageName,
text: wikitext,
section: secIdx,
summary: editSummary
}).done(function(result) {
window.location = "/w/index.php?title=" + pageName + "&type=revision&diff=cur&oldid=prev";
});
}
function execute(currentBox, replyOption, inputText, answered, boxType, targets) {
OO.ui.confirm("Confirm in order to reply to this edit request.").done(function(confirmed) {
if (confirmed) {
//Change buttons to label box + loading bar
let leftOOUI = currentBox.getElementsByClassName('mbox-image')[0].getElementsByClassName('oo-ui-widget');
if (leftOOUI.length > 1) {
leftOOUI[0].remove();
}
leftOOUI[0].remove();
currentBox.children[2].remove();
let infoBox = new OO.ui.MessageWidget( {
icon: 'pageSettings',
type: 'notice',
label: 'Processing request — Edit request starting, getting section data to edit.'
});
let firstRow = currentBox.getElementsByTagName('tr')[1].children[0];
firstRow.style = "padding-bottom:10px";
firstRow.innerHTML = "";
let progressBar = new OO.ui.ProgressBarWidget( {
progress: false
});
$(firstRow).append(progressBar.$element);
$(firstRow).append(infoBox.$element);
progressBar.$element[0].style = "margin:auto";
infoBox.$element[0].style = "margin:10px auto 0px; max-width:50em";
//Find header
let header = "";
let curElement = currentBox.parentNode;
do {
curElement = curElement.previousElementSibling;
if (curElement.getElementsByClassName("mw-headline").length == 1) {
header = curElement.getElementsByClassName("mw-headline")[0].id;
}
}
while (header == "");
let pageName = mw.config.values.wgPageName;
let api = new mw.Api();
api.get( {
action: "parse",
page: pageName,
prop: "sections|wikitext|revid"
}).done(function(data) {
infoBox.setLabel("Processing request — Making changes to the edit request");
boxType = replyERT[boxType];
let editTemplate = "{{Edit " + boxType[1] + "-protected";
if (answered) { answered = "yes"; } else { answered = "no"; }
for (let c3 = 0; c3 < targets.length; c3++) {
editTemplate += "|" + targets[c3];
}
editTemplate += "|answered=" + answered;
let sections = data.parse.sections;
let wikitext = data.parse.wikitext["*"];
let newRev = data.parse.revid;
let secIndx = sections[0], endIndx = -1;
for (let j = 0; j < sections.length; j++) {
let tempSec = sections[j];
if (tempSec.anchor == header && !isNaN(Number(tempSec.index))) {
secIndx = tempSec;
endIndx = j + 1;
} else if (tempSec.number.slice(0, secIndx.number.length) == (secIndx.number)) { //Get any subsections
endIndx = j + 1;
}
}
secIndx = secIndx.index;
let headings = [...wikitext.matchAll(/==[^\n]+==/g)];
headings[headings.length] = wikitext.length;
wikitext = wikitext.slice(headings[secIndx - 1].index, headings[endIndx].index);
wikitext = wikitext.replace(/{{ *([SETFI]PER|Edit[ -]?[A-Z]+[ -]?Protected)\s*[^}}]*/i, editTemplate);
let editSummary = "/* " + header.replaceAll("_", " ") + " */ " + replyOption[2] + " ([[User:Terasail/Edit_Request_Tool|Edit Request Tool]])";
if (replyOption[1] != "Close") {
let lastMsg = wikitext.lastIndexOf("\n", wikitext.lastIndexOf("(UTC)")) + 1;
wikitext = wikitext.trim() + "\n:";
while(lastMsg == wikitext.indexOf(":", lastMsg)) {
lastMsg++;
wikitext += ":";
}
if (replyOption[0] != "") { wikitext += "{{subst:" + boxType[3] + replyOption[0] + "}} "; }
if (inputText != "") { wikitext += inputText.replaceAll(/\s*~~~~\s*/g, "") + " "; }
wikitext += "~~~~";
if (replyOption[1] == "Remove") {
wikitext = "";
editSummary = editSummary.replace(/[^]+\*\/ /, "");
}
}
infoBox.setType("success");
infoBox.setLabel("Processing '" + replyOption[2] + "' request — Saving changes to the talk page.");
if (newRev == mw.config.values.wgRevisionId) {
postEdit(wikitext, editSummary, pageName, secIndx);
} else {
OO.ui.confirm("There has been a new revision to the page, do you wish to continue?").done(function(revCon) {
if (revCon) { postEdit(wikitext, editSummary, pageName, secIndx); }
});
}
});
}
});
}
function addButtons(currentBox) {
let boxType = currentBox.parentElement.dataset.origlevel;
let replyList = Object.entries(replyERT);
let mainResponse = [[replyList[rOS + 9][1], "Unclear: X-Y", "Unclear request"], [replyList[rOS + 10][1], "WP:Reliable", "Needs reliable sources"], [replyList[rOS + 11][1], "WP:Consensus", "Change needs consensus"]];
$(currentBox).append('<tr><td colspan="2"><div style="display: flex; justify-content: center;"></div></td></tr><tr style="display:none;"><td colspan=2 style="padding-bottom:10px; text-align:center"><div style="display: flex; justify-content: center;"></div></td></tr>');
let firstRow = currentBox.children[1].children[0].children[0];
//Create type change dropdown
let typeChange = new OO.ui.DropdownInputWidget( {
value: boxType,
options: [
{data:"semi", label:"Semi protected edit request"},
{data:"extended", label:"Extended confirmed protected edit request"},
{data:"template", label:"Template protected edit request"},
{data:"full", label:"Fully protected edit request"},
{data:"interface", label:"Interface protected edit request"}
]
});
typeChange.$element[0].style = "text-align:left; margin:auto";
$(currentBox.children[2].children[0]).append(typeChange.$element);
//Create target page list
let boxLinks = currentBox.getElementsByClassName("mbox-text")[0].getElementsByClassName("external text");
let pageLinks = [];
if (boxLinks.length > 0) {//Open request
for(let c1 = 0; c1 < boxLinks.length; c1++) {
if (boxLinks[c1].parentElement.tagName == "LI" || boxLinks[c1].parentElement.tagName == "B") {
pageLinks[pageLinks.length] = boxLinks[c1].innerHTML;
}
}
} else {//Closed request
boxLinks = currentBox.getElementsByClassName("mbox-text")[0].getElementsByTagName("A");
for(let c2 = 1; c2 < boxLinks.length; c2++) {
pageLinks[pageLinks.length] = boxLinks[c2].title;
}
if (pageLinks.length == 0) {
pageLinks = mw.config.values.wgPageName.replace(/(_talk|Talk:)/, "").replaceAll("_", " ");
}
}
let targetPages = new OO.ui.TagMultiselectWidget( {
placeholder: 'Target Pages',
allowArbitrary: true,
selected: pageLinks
});
targetPages.$element[0].style = "text-align:left; margin:5px auto 5px auto";
$(currentBox.children[2].children[0]).append(targetPages.$element);
//Create dropdown menu
let dropMenu = new OO.ui.DropdownWidget( {
label: "Select reply option - Add additional text below",
menu: {items: []}
});
for (let count = 9; count < replyList.length; count++) {
let newOption = new OO.ui.MenuOptionWidget({
label: replyList[count][0],
icon: replyList[count][1][1]
});
dropMenu.menu.addItems([newOption]);
}
dropMenu.$element[0].style = "text-align:left; margin:0px";
$(currentBox.children[2].children[0]).append(dropMenu.$element);
//Create input box
let inputText = new OO.ui.MultilineTextInputWidget({autosize: true, label: "Automatically signed"});
inputText.$element[0].style = "margin:auto";
$(currentBox.children[2].children[0]).append(inputText.$element);
//Create top horizontal layout
let hzLayoutT = new OO.ui.HorizontalLayout();
//Done
let doneB = new OO.ui.ButtonWidget( {
icon: "checkAll",
label: "Done",
flags: ["primary", "progressive"],
title: "Mark as done"
});
doneB.on("click", function() {
if (doneB.getLabel() == "Submit") {
if (typeof(replyERT[dropMenu.getLabel()]) != "undefined") {
execute(currentBox, replyERT[dropMenu.getLabel()], inputText.value, toggleAns.selected, typeChange.value, targetPages.getValue());
} else if (typeChange.value != typeChange.defaultValue) {
execute(currentBox, replyERT.Change, "", false, typeChange.value, targetPages.getValue());
}
let newTargets = false;
let targets = targetPages.items;
if (targets.length == pageLinks.length) {
for(let item = 0; item < targets.length; item++) {
if (targets[item].data != pageLinks[item]) { newTargets = true; }
}
} else {
newTargets = true;
}
if (newTargets) {
execute(currentBox, replyERT.ChangeTarget, "", false, typeChange.value, targetPages.getValue());
}
} else {
execute(currentBox, replyERT.Done, "", toggleAns.selected, typeChange.defaultValue, targetPages.getValue());
}
});
hzLayoutT.addItems([doneB]);
mainResponse.forEach(function(item) {
item[3] = new OO.ui.ButtonWidget({
label: item[1],
title: item[2]
});
item[3].on("click", function() {
execute(currentBox, item[0], "", toggleAns.selected, typeChange.defaultValue, targetPages.getValue());
});
hzLayoutT.addItems([item[3]]);
});
//Respond
let respondB = new OO.ui.ButtonWidget( {
icon: "add",
label: "More",
title: "Extra response options"
});
respondB.on("click", function() {
if (respondB.getIcon() == "add") {
currentBox.children[2].style = "";
doneB.setLabel("Submit");
doneB.setTitle("Submit response");
respondB.setIcon("subtract");
respondB.setLabel("Less");
} else {
currentBox.children[2].style = "display:none";
inputText = "";
doneB.setLabel("Done");
doneB.setTitle("Mark as done");
respondB.setIcon("add");
respondB.setLabel("More");
}
});
hzLayoutT.addItems([respondB]);
//Toggle answer button
let toggleAns = new OO.ui.CheckboxInputWidget({selected: true});
hzLayoutT.addItems([toggleAns, new OO.ui.LabelWidget({label: "Answered"})]);
//Create firstrow fieldset
let fieldsetT = new OO.ui.FieldsetLayout();
// Add an horizontal field layout
fieldsetT.addItems( [
new OO.ui.FieldLayout(
new OO.ui.Widget( {
content: [hzLayoutT]
} )
)
] );
$(firstRow).append(fieldsetT.$element);
//Close request
let closeB = new OO.ui.ButtonWidget( {
icon: "unFlag",
invisibleLabel: true,
title: "Mark as closed"
});
closeB.$element[0].style = "margin:10px 10px 0px";
closeB.on("click", function() {
execute(currentBox, replyERT.Close, "", true, typeChange.defaultValue, targetPages.getValue());
});
if (currentBox.parentElement.attributes[2].localName != "data-origlevel") {
$(currentBox.children[0].children[0]).append(closeB.$element);
}
//Remove request
let remove = new OO.ui.ButtonWidget( {
icon: "trash",
flags: ["primary", "destructive"],
invisibleLabel: true,
title: "Delete entire section!"
});
remove.$element[0].style = "margin:10px";
remove.on("click", function() {
execute(currentBox, replyERT.Remove, "", null, typeChange.defaultValue, targetPages.getValue());
});
$(currentBox.children[0].children[0]).append(remove.$element);
}
function addRButton(currentBox) {
let boxType = replyERT[currentBox.parentElement.dataset.origlevel];
let openB = new OO.ui.ButtonWidget( {
icon: "edit",
flags: "progressive",
invisibleLabel: true,
title: "Add response / reopen"
});
openB.$element[0].style = "margin-top:2px";
openB.on("click", function() {
openB.$element.remove();
currentBox.parentElement.className = "plainlinks tmbox tmbox-notice editrequest";
let imgSrc = boxType[0] + "-protection-shackle.svg";
let origImg = currentBox.getElementsByTagName("img")[0];
let img = origImg.outerHTML.slice(0, origImg.outerHTML.match(/\d\//).index);
img += boxType[2] + imgSrc + "/60px-" + imgSrc + '.png" height="60" width="60" style="margin-top:5px">';
origImg.outerHTML = img;
let mboxText = currentBox.children[0].children[1];
mboxText.style = "font-size:120%; text-align:center;";
mboxText.innerHTML = mboxText.innerHTML.replace(/ Set.*\/b>/i, '<br/>Uncheck the "answered" checkbox and use a reply option');
addButtons(currentBox);
});
$(currentBox.children[0].children[0]).append(openB.$element);
}
var editRequestBoxes = document.getElementsByClassName("plainlinks tmbox tmbox-notice editrequest");
if (editRequestBoxes.length != 0) {
mw.loader.using(["oojs-ui-core", "oojs-ui-widgets", "oojs-ui-windows"]).done(function() {
mw.loader.load(["oojs-ui.styles.icons-alerts", "oojs-ui.styles.icons-interactions", "oojs-ui.styles.icons-moderation", "oojs-ui.styles.icons-user", "oojs-ui.styles.icons-content", "oojs-ui.styles.icons-editing-core", "oojs-ui.styles.icons-editing-advanced"]);
for (let i = 0; i < editRequestBoxes.length; i++) {
let currentBox = editRequestBoxes[i].children[0]; //The tbody tag for the box
if (editRequestBoxes[i].id != "") {
addButtons(currentBox);
} else if (currentBox.getElementsByTagName("code").length == 2) { //Check that it is a closed protected edit request
addRButton(currentBox);
}
}
});
}
//</nowiki>[[Category:Wikipedia scripts]]