User:Anoptimistix/common.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. |
![]() | The accompanying .css page for this skin is at User:Anoptimistix/common.css. |
importScript('User:Lourdes/PageCuration.js'); // Linkback: [[User:Lourdes/PageCuration.js]]
*/
$.when( mw.loader.using( ['mediawiki.util'] ), $.ready ).done( function() {
mw.util.addPortletLink(
'p-personal',
mw.util.getUrl('Special:NewPagesFeed'),
'Page Curation',
'pt-pagecuration',
'View Special:New Pages using the Page Curation tool',
null,
'#pt-preferences'
);
});
// <nowiki>
$( function($) {
var moveToDraft = function moveToDraft() {
//'Global' vars & objects are stored in the m2d object
var m2d = {};
m2d.Api = new mw.Api();
m2d.page = mw.config.get(['wgArticleId', 'wgPageName']);
m2d.rationale = "Undersourced, incubate in draftspace";
m2d.editsummary = "[[WP:AFC|AFC]] draft";
m2d.notification_heading = "[[Draft:$1|$1]] moved to draftspace";
m2d.notification = "An article you recently created, [[Draft:$1|$1]], does not have enough sources and citations as written to remain published. It needs more citations from [[WP:RS|reliable]], [[WP:IS|independent sources]]. <small>([[WP:42|?]])</small> Information that can't be referenced should be removed ([[WP:V|verifiability]] is of [[WP:5|central importance]] on Wikipedia). I've moved your draft to [[Wikipedia:Draftspace|draftspace]] (with a prefix of \"<code>Draft:</code>\" before the article title) where you can incubate the article with minimal disruption. When you feel the article meets Wikipedia's [[WP:GNG|general notability guideline]] and thus is ready for mainspace, please follow the prompts on the [[Wikipedia:AfC|Articles for Creation]] template atop the page. ~~~~";
m2d.scriptad = " ([[User:Evad37/MoveToDraft.js|via script]])";
//get user-specified default rationale & notification from window object
if ( window.m2d_rationale != null ) { m2d.rationale = window.m2d_rationale; }
if ( window.m2d_editsummary != null ) { m2d.editsummary = window.m2d_rationale; }
if ( window.m2d_notification != null ) { m2d.notification = window.m2d_notification; }
//Make error message from returned values when api fails
var makeErrorMsg = function(code, result) {
var details = "";
if ( code === "http" ) {
details = "HTTP error: " + result.textStatus; // result contains the jqXHR object
} else if ( code === "ok-but-empty" ) {
details = "Error: Got an empty response from the server";
} else {
details = "API error: " + code;
}
return details;
};
var getPageText = function(p) {
var t = mw.Title.newFromText( decodeURIComponent(p) );
if (t) {
return t.getPrefixedText();
} else {
return p.replace(/_/g, " ");
}
};
// --- Api calls ---
// Grab page data - initial author, current wikitext, whether Draft:pagename already exists
var grabPageData = function() {
var patt_isRedirect = /^\s*#redirect/i;
//function to check if all done
var checkPageData = function() {
if ( m2d.author != null && m2d.oldwikitext != null ) {
//all done - go to next screen
screen1();
}
};
//try making an api call or just the first revision - but if that is a redirect, then get 'max'
//number of revisions, and look for first non-redirect revision - use this as the initial author,
//not the creator of the redirect.
var apiCallback_getAuthor_maxRvlimit = function (result) {
var revisions = result.query.pages[m2d.page.wgArticleId].revisions;
for ( var i=1; i<revisions.length; i++ ) {
if ( !patt_isRedirect.test(revisions[i]['*']) ) {
m2d.author = revisions[i].user;
break;
}
}
//Check that we actually found an author (i.e. not all revisions were redirects
if ( m2d.author != null ) {
checkPageData();
} else {
m2d.Api.abort();
var retry = prompt("Could not retrieve page author:\n"+makeErrorMsg(c, r)+"\n\nTry again?");
if ( retry ) {
screen0();
} else {
$("#M2D-modal").remove();
}
}
};
var apiCallback_getAuthor = function (result) {
// Check if page is currently a redirect
if ( result.query.pages[m2d.page.wgArticleId].redirect ) {
m2d.Api.abort();
alert("Error: " + m2d.page.wgPageName + " is a redirect");
return;
}
// Check if first revision is a redirect
rvwikitext = result.query.pages[m2d.page.wgArticleId].revisions[0]['*'];
if ( patt_isRedirect.test(rvwikitext) ) {
//repeat query, to look for first non-redirect revision
m2d.Api.get( {
action: 'query',
pageids: m2d.page.wgArticleId,
prop: 'revisions',
rvprop: ['user', 'content'],
rvlimit: 'max',
rvdir: 'newer'
} )
.done( apiCallback_getAuthor_maxRvlimit )
.fail( function(c,r) {
m2d.Api.abort();
var retry = prompt("Could not retrieve page author:\n"+makeErrorMsg(c, r)+"\n\nTry again?");
if ( retry ) {
screen0();
} else {
$("#M2D-modal").remove();
}
} );
} else {
m2d.author = result.query.pages[m2d.page.wgArticleId].revisions[0].user;
checkPageData();
}
};
//Get author
m2d.Api.get( {
action: 'query',
pageids: m2d.page.wgArticleId,
prop: ['revisions', 'info'],
rvprop: ['user', 'content'],
rvlimit: 1,
rvdir: 'newer'
} )
.done( apiCallback_getAuthor )
.fail( function(c,r) {
m2d.Api.abort();
var retry = prompt("Could not retrieve page author:\n"+makeErrorMsg(c, r)+"\n\nTry again?");
if ( retry ) {
screen0();
} else {
$("#M2D-modal").remove();
}
} );
var apiCallback_getWikitext = function(result) {
m2d.oldwikitext = result.query.pages[m2d.page.wgArticleId].revisions[0]['*'];
checkPageData();
};
//Get current wikitext
//TODO: also get proposed Draft: page (to check if it is empty or not)
m2d.Api.get( {
action: 'query',
pageids: m2d.page.wgArticleId,
prop: 'revisions',
rvprop: 'content'
} )
.done( apiCallback_getWikitext )
.fail( function(c,r) {
m2d.Api.abort();
var retry = prompt("Could not retrieve page wikitext:\n"+ makeErrorMsg(c, r)+"\n\nTry again?");
if ( retry ) {
screen0();
} else {
$("#M2D-modal").remove();
}
} );
};
//Move page
var movePage = function() {
$("#M2D-task0").css({"color":"#00F", "font-weight":"bold"});
$("#M2D-status0").html("...");
m2d.Api.postWithToken( 'csrf', {
action: 'move',
fromid: m2d.page.wgArticleId,
to: m2d.newTitle,
movetalk: 1,
noredirect: 1,
reason: m2d.rationale + m2d.scriptad
} )
.done( function() {
$("#M2D-task0").css({"color":"#000", "font-weight":""});
$("#M2D-status0").html("Done!");
getImageInfo();
} )
.fail( function(c,r) {
var retry = prompt("Could not move page:\n"+ makeErrorMsg(c, r)+"\n\nTry again?");
if ( retry ) {
movePage();
} else {
$("#M2D-modal").remove();
}
} );
};
//Find which images are non-free
var getImageInfo = function() {
$("#M2D-task1").css({"color":"#00F", "font-weight":"bold"});
$("#M2D-status1").html("...");
apiCallback_getImageInfo = function(result) {
var nonfreefiles = [];
if ( result && result.query ) {
var pageids = result.query.pageids;
for ( var i=0; i<pageids.length; i++ ) {
if ( pageids[i]>0 && result.query.pages[pageids[i]].categories ) {
nonfreefiles.push(result.query.pages[pageids[i]].title);
}
}
}
editWikitext(nonfreefiles);
};
m2d.Api.get( {
action: 'query',
pageids: m2d.page.wgArticleId,
generator: 'images',
gimlimit: 'max',
prop: 'categories',
cllimit: 'max',
clcategories: 'Category:All non-free media',
indexpageids: 1
} )
.done( function(result){
$("#M2D-task1").css({"color":"#000", "font-weight":""});
$("#M2D-status1").html("Done!");
apiCallback_getImageInfo(result);
} )
.fail( function(c,r) {
var retry = prompt("Could not find if there are non-free files:\n"+ makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip");
if ( retry ) {
getImageInfo();
} else {
$("#M2D-task1").css({"color":"#F00", "font-weight":""});
$("#M2D-status1").html("Skipped");
editWikitext([]);
}
} );
};
//Comment out non-free files, turn categories into links, add substed afc draft template
var editWikitext = function(nonfreefiles) {
$("#M2D-task2").css({"color":"#00F", "font-weight":"bold"});
$("#M2D-status2").html("...");
// afc, categories
var wikitext = "{{subst:AFC draft|" + m2d.author + "}}\n" +
m2d.oldwikitext.replace(/\[\[\s*[Cc]ategory\s*:/g, "[[:Category:");
// non-free files
// (derived from [[WP:XFDC]] - https://en.wikipedia.org/wiki/User:Evad37/XFDcloser.js )
if ( nonfreefiles.length > 0 ) {
// Start building regex strings
normal_regex_str = "(";
gallery_regex_str = "(";
free_regex_str = "(";
for ( var i=0; i<nonfreefiles.length; i++ ) {
// Take off namespace prefix
filename = nonfreefiles[i].replace(/^.*?:/, "");
// For regex matching: first character can be either upper or lower case, special
// characters need to be escaped, spaces can be either spaces or underscores
filename_regex_str = "[" + mw.RegExp.escape(filename.slice(0, 1).toUpperCase()) +
mw.RegExp.escape(filename.slice(0, 1).toLowerCase()) + "]" +
mw.RegExp.escape(filename.slice(1)).replace(/ /g, "[ _]");
// Add to regex strings
normal_regex_str += "\\[\\[\\s*(?:[Ii]mage|[Ff]ile)\\s*:\\s*" + filename_regex_str +
"\\s*\\|?.*?(?:(?:\\[\\[.*?\\]\\]).*?)*\\]\\]";
gallery_regex_str += "^\\s*(?:[Ii]mage|[Ff]ile):\\s*" + filename_regex_str + ".*?$";
free_regex_str += "\\|\\s*(?:[\\w\\s]+\\=)?\\s*(?:(?:[Ii]mage|[Ff]ile):\\s*)?" +
filename_regex_str;
if ( i+1 === nonfreefiles.length ) {
normal_regex_str += ")(?![^<]*?-->)";
gallery_regex_str += ")(?![^<]*?-->)";
free_regex_str += ")(?![^<]*?-->)";
} else {
normal_regex_str += "|";
gallery_regex_str += "|";
free_regex_str += "|";
}
}
// Check for normal file usage, i.e. [[File:Foobar.png|...]]
var normal_regex = new RegExp( normal_regex_str, "g");
wikitext = wikitext.replace(normal_regex, "<!-- Commented out: $1 -->");
// Check for gallery usage, i.e. instances that must start on a new line, eventually
// preceded with some space, and must include File: or Image: prefix
var gallery_regex = new RegExp( gallery_regex_str, "mg" );
wikitext = wikitext.replace(gallery_regex, "<!-- Commented out: $1 -->");
// Check for free usages, for example as template argument, might have the File: or Image:
// prefix excluded, but must be preceeded by an |
var free_regex = new RegExp( free_regex_str, "mg" );
wikitext = wikitext.replace(free_regex, "<!-- Commented out: $1 -->");
}
m2d.Api.postWithToken( 'csrf', {
action: 'edit',
pageid: m2d.page.wgArticleId,
text: wikitext,
summary: m2d.editsummary + m2d.scriptad
} )
.done( function(){
$("#M2D-task2").css({"color":"#000", "font-weight":""});
$("#M2D-status2").html("Done!");
notifyAuthor();
} )
.fail( function(c,r) {
var retry = prompt("Could not edit draft artice:\n"+ makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip");
if ( retry ) {
editWikitext(nonfreefiles);
} else {
$("#M2D-task2").css({"color":"#F00", "font-weight":""});
$("#M2D-status2").html("Skipped");
notifyAuthor();
}
} );
};
var notifyAuthor = function() {
$("#M2D-task3").css({"color":"#00F", "font-weight":"bold"});
$("#M2D-status3").html("...");
//TODO
m2d.Api.postWithToken( 'csrf', {
action: 'edit',
title: 'User talk:' + m2d.authorName,
section: 'new',
sectiontitle: m2d.notifyMsgHead,
text: m2d.notifyMsg,
} )
.done( function(){
$("#M2D-task3").css({"color":"#000", "font-weight":""});
$("#M2D-status3").html("Done!");
updateTalk();
} )
.fail( function(c,r) {
var retry = prompt("Could not edit author talk page:\n"+ makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip");
if ( retry ) {
notifyAuthor();
} else {
$("#M2D-task3").css({"color":"#F00", "font-weight":""});
$("#M2D-status3").html("Skipped");
updateTalk();
}
} );
};
var updateTalk = function() {
$("#M2D-task4").css({"color":"#00F", "font-weight":"bold"});
$("#M2D-status4").html("...");
//if page exists, do a regex search/repace for class/importances parameters
var apiCallback_getTalkWikitext = function(result) {
var talk_id = result.query.pageids[0];
if ( talk_id < 0 ) {
$("#M2D-task4").css({"color":"#000", "font-weight":""});
$("#M2D-status4").html("Done (talk page does not exist)");
$("#M2D-finished, #M2D-abort").toggle();
return;
}
var old_talk_wikitext = result.query.pages[talk_id].revisions[0]['*'];
var new_talk_wikitext = old_talk_wikitext.replace(/(\|\s*(?:class|importance)\s*=\s*)[^\|}]*(?=[^}]*}})/g, "$1");
if ( new_talk_wikitext === old_talk_wikitext ) {
$("#M2D-task4").css({"color":"#000", "font-weight":""});
$("#M2D-status4").html("Done (no changes needed)");
$("#M2D-finished, #M2D-abort").toggle();
return;
}
m2d.Api.postWithToken( 'csrf', {
action: 'edit',
pageid: talk_id,
section: '0',
text: new_talk_wikitext,
summary: 'Remove class/importance from project banners' + m2d.scriptad
} )
.done( function(){
$("#M2D-task4").css({"color":"#000", "font-weight":""});
$("#M2D-status4").html("Done!");
$("#M2D-finished, #M2D-abort").toggle();
} )
.fail( function(c,r) {
var retry = prompt("Could not edit draft's talk page:\n"+ makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip");
if ( retry ) {
updateTalk();
} else {
$("#M2D-task4").css({"color":"#F00", "font-weight":""});
$("#M2D-status4").html("Skipped");
$("#M2D-finished, #M2D-abort").toggle();
}
} );
};
//get talk page wikitext (section 0)
m2d.Api.get( {
action: 'query',
titles: m2d.newTitle.replace("Draft:", "Draft talk:"),
prop: 'revisions',
rvprop: 'content',
rvsection: '0',
indexpageids: 1
} )
.done( apiCallback_getTalkWikitext )
.fail( function(c,r) {
var retry = prompt("Could not find draft's talk page:\n"+ makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip");
if ( retry ) {
updateTalk();
} else {
$("#M2D-task4").css({"color":"#F00", "font-weight":""});
$("#M2D-status4").html("Skipped");
$("#M2D-finished, #M2D-abort").toggle();
}
} );
};
// --- Interface screens ---
//0) Initial screen
var screen0 = function() {
$("#M2D-interface-header").html("Move To Draft...");
$("#M2D-interface-content").html("Loading...");
grabPageData();
};
//1) User inputs
var screen1 = function() {
$("#M2D-interface-header").html("Move To Draft: options");
$("#M2D-interface-content").html(
'<label for="M2D-option-newtitle">Move to <b>Draft:</b></label>'+
'<input type="text" name="M2D-option-newtitle" id="M2D-option-newtitle" /><br/><br/>'+
'<label for="M2D-option-author" id="M2D-option-author-label">Author:</label>'+
'<input type="text" name="M2D-option-author" id="M2D-option-author" /><br/><br/>'+
'<label for="M2D-option-message-head" id="M2D-option-message-head-label">Notification heading:</label><br/>'+
'<textarea id="M2D-option-message-head" rows=1 style="width:99%;" /><br/>'+
'<label for="M2D-option-message" id="M2D-option-message-label">Notification message:</label><br/>'+
'<textarea id="M2D-option-message" rows=6 style="width:99%;" />'
//TODO(?): Move rationale and edit summary text inputs
);
$('#M2D-option-newtitle').val(getPageText(m2d.page.wgPageName));
$('#M2D-option-author').val(m2d.author);
$('#M2D-option-message-head').val(m2d.notification_heading.replace(/\$1/g, getPageText(m2d.page.wgPageName)));
$('#M2D-option-message').val(m2d.notification.replace(/\$1/g, getPageText(m2d.page.wgPageName)));
$("#M2D-interface-footer").html(
'<button id="M2D-next">Continue</button><button id="M2D-cancel" style="margin-left:3em;">Cancel</button>'
);
$("#M2D-cancel").click(function(){
$("#M2D-modal").remove();
});
$("#M2D-next").click(function(){
//Gather inputs
m2d.newTitle = "Draft:" + $('#M2D-option-newtitle').val().trim();
m2d.authorName = $('#M2D-option-author').val().trim();
m2d.notifyMsgHead = $('#M2D-option-message-head').val().trim();
m2d.notifyMsg = $('#M2D-option-message').val().trim();
//Verify inputs
var errors=[];
if ( m2d.newTitle.length === 0 ) {
errors.push("Invalid draft title");
}
if ( m2d.authorName.length === 0 ) {
errors.push("Invalid user name");
}
if ( m2d.notifyMsgHead.length === 0 ) {
errors.push("Notification heading is empty");
}
if ( m2d.notifyMsg.length === 0 ) {
errors.push("Notification message is empty");
}
if ( errors.length >= 1 ) {
alert("Error:\n\n" + errors.join(";\n"));
return;
}
//start process off
screen2();
});
};
//2) Progress indicators
var screen2 = function() {
$("#M2D-interface-header").html("Move To Draft: In progress...");
$("#M2D-interface-content").html(
'<ul id="M2D-tasks">'+
'<li id="M2D-task0">Moving page... <span id="M2D-status0">(waiting)</span></li>'+
'<li id="M2D-task1">Checking images... <span id="M2D-status1">(waiting)</span></li>'+
'<li id="M2D-task2">Editing page wikitext... <span id="M2D-status2">(waiting)</span></li>'+
'<li id="M2D-task3">Notifying author... <span id="M2D-status3">(waiting)</span></li>'+
'<li id="M2D-task4">Updating talk page banners... <span id="M2D-status4">(waiting)</span></li>'+
'</ul>'
);
$("#M2D-tasks").css("color", "#888");
$("#M2D-interface-footer").html(
'<button id="M2D-abort">Abort uncompleted tasks</button>'+
'<span id="M2D-finished">Finished! <button id="M2D-close">Close</button></span>'
);
$("#M2D-finished").hide();
$("#M2D-close").click( function(){
$("#M2D-modal").remove();
window.location.reload();
} );
$("M2D-abort").click( function(){
m2d.Api.abort();
$("#M2D-modal").remove();
window.location.reload();
} );
//Start task 0. The rest are done sequentially as each task is completed (or skipped).
movePage();
};
// --- Add link to 'More' menu which starts everything ---
mw.util.addPortletLink( 'p-cactions', '#', 'Move to draft', 'ca-m2d', null, null, "#ca-move");
$('#ca-m2d').on('click', function(e) {
e.preventDefault();
// Add interface shell
$('body').prepend('<div id="M2D-modal">'+
'<div id="M2D-interface">'+
'<h4 id="M2D-interface-header"></h4>'+
'<hr>'+
'<div id="M2D-interface-content"></div>'+
'<hr>'+
'<div id="M2D-interface-footer"></div>'+
'</div>'+
'</div>');
// Interface styling
$("#M2D-modal").css({
"position": "fixed",
"z-index": "1",
"left": "0",
"top": "0",
"width": "100%",
"height": "100%",
"overflow": "auto",
"background-color": "rgba(0,0,0,0.4)"
});
$("#M2D-interface").css({
"background-color": "#f0f0f0",
"margin": "15% auto",
"padding": "2px 20px",
"border": "1px solid #888",
"width": "80%",
"max-width": "60em",
"font-size": "90%"
});
$("#M2D-interface-content").css("min-height", "7em");
$("#M2D-interface-footor").css("min-height", "3em");
// Initial interface content
screen0();
});
// End of function moveToDraft
};
// Only operate in article and user namespaces
if( mw.config.get('wgNamespaceNumber') === 0 ) {
mw.loader.using( ['mediawiki.util', 'mediawiki.api', 'mediawiki.Title', 'mediawiki.RegExp'], moveToDraft() );
} else {
//console.log("[M2D] not namespace 0");
}
});
// </nowiki>