User:MPGuy2824/MoveToDraft-sandbox.js

/*************************************************************************************************** MoveToDraft - Version 2.5.4 - A script to move unsourced articles to draft space, including cleanup and author notification. - Moves page to draftspace - Checks if any files used are non-free - Checks if any redirects pointed to the page - Comments out non-free files, turn categories into links, add afc draft template, add redirects - Adds notification message on author talk page - Updates talk page banners - Logs draftification in user subpage

derived from https://en.wikipedia.org/wiki/User:Evad37/MoveToDraft.js /* jshint laxbreak: true, undef: true, maxerr:999 */ /* globals console, window, document, $, mw, OO, extraJs */ // $.when(	// Resource loader modules	mw.loader.using(['mediawiki.util', 'mediawiki.api', 'mediawiki.Title', 'ext.gadget.libExtraUtil']),	// Page ready	$.ready ).then(function { /* ========== Config ============================================================================ */ var config = {	// Script info	script: {		location: 'User:MPGuy2824/MoveToDraft.js',		advert: ' (via script)', // For edit summaries		version: '2.5.4'	},	// MediaWiki configuration values	mw: mw.config.get( [ 'wgArticleId', 'wgCurRevisionId', 'wgPageName', 'wgUserGroups', 'wgUserName', 'wgMonthNames', 'wgNamespaceNumber', 'wgTitle' ] ) };

/* ========== API =============================================================================== */ var API = new mw.Api( {	ajax: {		headers: { 			'Api-User-Agent': 'MoveToDraft/' + config.script.version + 				' ( https://en.wikipedia.org/wiki/User:MPGuy2824/MoveToDraft )'		}	} } );

var moveToDraft = function moveToDraft {

/* ========== Additional config ================================================================= */ // Wikitext strings config.wikitext = { 'rationale':	window.m2d_rationale || 'Not ready for mainspace, incubate in draftspace', 'editsummary':	window.m2d_editsummary || window.m2d_rationale || 'AFC draft', 'notification_heading': '$1 moved to draftspace', 'notification':	window.m2d_notification || "Thanks for creating $1. Unfortunately, it is not ready for publishing$3.\nYour article is now a draft where you can improve it undisturbed for a while.\n\nPlease see more information at Help:Unreviewed new page.\nWhen the article is ready for publication, please click on the \"Submit your draft for review!\" button at the top of the page. ~", 'logMsg':		'#$1 moved to $2 at ' }; config.draftReasons = { 'no-sources':'it has no sources', 'more-sources':'it needs more sources to establish notability', 'grammar':'it has too many problems of language or grammar', 'bad-translation':'it is a poor translation', 'ad':'it is promotional and reads like an advertisement', 'coi':'you may have a possible Conflict of Interest' }; config.minimumAgeInMinutes = 15; config.maximumAgeInDays = 90;

config.doNotLog = window.m2d_doNotLog ? true : false; // Page data -- to be retreived later from api config.pagedata = {}; config.pagedata.previousDraftification = false;

// Helper functions // - prettify an encoded page title (or at least replace underscores with spaces) var getPageText = function(p) { var t = mw.Title.newFromText( decodeURIComponent(p) ); if (t) { return t.getPrefixedText; } else { return p.replace(/_/g, " "); } };

/* ========== Tasks ============================================================================= */

// Grab page data - initial author, current wikitext, any redirects, if Draft: page already exists var grabPageData = function {

var patt_isRedirect = /^\s*#redirect/i;

var checkedPageTriageStatus = false;

// Function to check if all done var checkPageData = function { if (			config.pagedata.author != null &&			config.pagedata.oldwikitext != null &&			config.pagedata.redirects != null &&			checkedPageTriageStatus		) { //all done - go to next screen screen1; }	};

/* -- Initial author */

/* Try making an api call for 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 processMaxRvAuthorQuery = function (result) { var revisions = result.query.pages[config.mw.wgArticleId].revisions; for ( var i=0; i<revisions.length; i++ ) { if ( !patt_isRedirect.test(revisions[i]['*']) ) { if (config.pagedata.author == undefined) { config.pagedata.author = revisions[i].user; config.pagedata.creationTimestamp = revisions[i].timestamp; }

console.log(i+":"+revisions[i].comment.search(/moved page \[\[.*\]\] to \[\[Draft:/)); if( revisions[i].comment.search(/moved page \[\[.*\]\] to \[\[Draft:/) !== -1) { config.pagedata.previousDraftification = true; }			}		}		//Check that we actually found an author (i.e. not all revisions were redirects		if ( config.pagedata.author == null ) {			API.abort;			var retry = confirm("Could not retrieve page author:\n"+extraJs.makeErrorMsg(c, r)+"\n\nTry again?");			if ( retry ) {				screen0;			} else {				$("#M2D-modal").remove;			}		}

checkPageData; };

var processAuthorQuery = function (result) { // Check if page is currently a redirect if ( result.query.pages[config.mw.wgArticleId].redirect ) { API.abort; alert("Error: " + config.mw.wgPageName + " is a redirect"); return; }

// query to look for first non-redirect revision API.get( {			action: 'query',			pageids: config.mw.wgArticleId,			prop: 'revisions',			rvprop: ['user', 'content', 'timestamp', 'comment'],			rvlimit: 'max',			rvdir: 'newer'		} ) .done( processMaxRvAuthorQuery ) .fail( function(c,r) {			if ( r.textStatus === 'abort' ) { return; }

API.abort; var retry = confirm("Could not retrieve page author:\n"+extraJs.makeErrorMsg(c, r)+"\n\nTry again?"); if ( retry ) { screen0; } else { $("#M2D-modal").remove; }		} );		return;

checkPageData; };

//Get author API.get( {		action: 'query',		pageids: config.mw.wgArticleId,		prop: ['revisions', 'info'],		rvprop: 'content',		rvlimit: 1,		rvdir: 'newer'	} ) .done( processAuthorQuery ) .fail( function(c,r) {		if ( r.textStatus === 'abort' ) { return; }

API.abort; var retry = confirm("Could not retrieve page author:\n"+extraJs.makeErrorMsg(c, r)+"\n\nTry again?"); if ( retry ) { screen0; } else { $("#M2D-modal").remove; }	} );

/* -- Current wikitext -- */

API.get( {		action: 'query',		pageids: config.mw.wgArticleId,		prop: 'revisions',		rvprop: 'content'	} ) .done( function(result) {		config.pagedata.oldwikitext = result.query.pages[config.mw.wgArticleId].revisions[0]['*'];		checkPageData;	} ) .fail( function(c,r) {		if ( r.textStatus === 'abort' ) { return; }

API.abort; var retry = confirm("Could not retrieve page wikitext:\n"+ extraJs.makeErrorMsg(c, r)+"\n\nTry again?"); if ( retry ) { screen0; } else { $("#M2D-modal").remove; }	} );

//TODO(?): also get proposed Draft: page (to check if it is empty or not)

/* -- Redirects - */ var redirectTitles = [];

var processRedirectsQuery = function(result) { if ( !result.query || !result.query.pages ) { // No results config.pagedata.redirects = false; checkPageData; return; }		// Gather redirect titles into array $.each(result.query.pages, function(_id, info) {			redirectTitles.push(info.title);		}); // Continue query if needed if ( result.continue ) { doRedirectsQuery($.extend(redirectsQuery, result.continue)); return; }

// Check if redirects were found if ( redirectTitles.length === 0 ) { config.pagedata.redirects = false; checkPageData; return; }

// Set redirects config.pagedata.redirects = ( redirectTitles.length === 0 ) ? false : redirectTitles; checkPageData; };

var redirectsQuery = { action: 'query', pageids: config.mw.wgArticleId, generator: 'redirects', grdlimit: 500 };	var doRedirectsQuery = function(q) { API.get( q ) .done( processRedirectsQuery ) .fail( function(c,r) {			if ( r.textStatus === 'abort' ) { return; }

API.abort; var retry = confirm("Could not retrieve redirects:\n" + extraJs.makeErrorMsg(c, r) +				"\n\nTry again? (or Cancel to skip)"); if ( retry ) { screen0; } else { config.pagedata.redirects = false; checkPageData; }		} );	};	doRedirectsQuery(redirectsQuery);

/* -- Review (Page Triage) status - */

API.get( {		action: 'pagetriagelist',		page_id: config.mw.wgArticleId	} ) .done( function(result) {		if ( !result.pagetriagelist.pages.length ) {			var keepGoing = confirm('WARNING: Page has already been reviewed by a New Page Patroller. Are you sure you want to draftify this page?');			if ( !keepGoing ) {				API.abort;				$("#M2D-modal").remove;				return;			}		}		checkedPageTriageStatus = true;		checkPageData;	} ) .fail( function(c,r) {		if ( r.textStatus === 'abort' ) { return; }

API.abort; var retry = confirm("Could not retrieve page triage status:\n"+ extraJs.makeErrorMsg(c, r)+"\n\nTry again?"); if ( retry ) { screen0; } else { $("#M2D-modal").remove; }	} );

};

//Sets the status of tasks in the progress screen var setTaskStatus = function(taskNumber, status, extraText) { if(taskNumber < 0 || taskNumber > 5 ) { //Invalid tasknumber return; }

switch ( status ) { case "started": $("#M2D-task" + taskNumber).css({'color':'#00F', 'font-weight':'bold'}); $("#M2D-status" + taskNumber).text('In process'); break; case "done": $("#M2D-task" + taskNumber).css({'color':'#000', 'font-weight':''}); $("#M2D-status" + taskNumber).html('&check;'); $("#M2D-status" + taskNumber).css('color', 'green'); break; case "skipped": $("#M2D-task" + taskNumber).css({'color':'#F00', 'font-weight':''}); $("#M2D-status" + taskNumber).text('Skipped!'); break; }	$("#M2D-status" + taskNumber) .css('margin', '0.75em');

if (extraText !== undefined) { $("#M2D-status" + taskNumber).append(" (" + extraText + ")"); } };

//Move page var movePage = function { setTaskStatus(0, "started");

// First check the page hasn't been draftified in the meantime API.get({		action: "query",		pageids: config.mw.wgArticleId,		format: "json",		formatversion: "2"	}).then(function(response) {		var page = response && response.query && response.query.pages && response.query.pages[0];		if (!page) {			return $.Deferred.reject;		} else if (page.missing) {			return $.Deferred.reject("moveToDraft-pagemissing");		} else if (page.ns === 118 /* Draft NS */) {			return $.Deferred.reject("moveToDraft-alreadydraft");		} else if (page.ns !== config.mw.wgNamespaceNumber) {			return $.Deferred.reject("moveToDraft-movednamespace");		}

return API.postWithToken( 'csrf', {			action: 'move',			fromid: config.mw.wgArticleId,			to: config.inputdata.newTitle,			movetalk: 1,			noredirect: 1,			reason: config.inputdata.rationale + config.script.advert		} ); })	.done( function { if (			-1 === $.inArray('sysop', config.mw.wgUserGroups) &&			-1 === $.inArray('extendedmover', config.mw.wgUserGroups)		) { // Newly created redirect to be tagged for speedy deletion tagRedirect; return; }		setTaskStatus(0, "done"); getImageInfo; } )	.fail( function(c,r) { if ( r && r.textStatus === 'abort' ) { return; } else if (c === "moveToDraft-pagemissing") { alert("The page no longer appears to exists. It may have been deleted."); $("#M2D-modal").remove; window.location.reload; return; } else if (c === "moveToDraft-alreadydraft") { alert("Aborted: The page has already been moved to draftspace."); $("#M2D-modal").remove; window.location.reload; return; } else if (c === "moveToDraft-alreadydraft") { alert("Aborted: The page has already been moved out of mainspace."); $("#M2D-modal").remove; window.location.reload; return; }

var retry = confirm("Could not move page:\n"+ extraJs.makeErrorMsg(c, r)+"\n\nTry again?"); if ( retry ) { movePage; } else { screen1(true); }	} ); };

var tagRedirect = function { $("#M2D-status0").html("Done, Tagging redirect for speedy deletion..."); API.postWithToken( 'csrf', {		action: 'edit',		title: config.mw.wgPageName,		prependtext: '\n',		summary: 'R2 speedy deletion request (article moved to draftspace)' + config.script.advert	} ) .done( function {		setTaskStatus(0, "done");		getImageInfo;	} ) .fail( function(c,r) {		if ( r.textStatus === 'abort' ) { return; }

var retry = confirm("Could not tag redirect for speedy deletion:\n"+			extraJs.makeErrorMsg(c, r) + "\n\nTry again?"); if ( retry ) { tagRedirect; } else { setTaskStatus(0, "skipped"); getImageInfo; }	} ); };

//Find which images are non-free var getImageInfo = function { setTaskStatus(1, "started");

processImageInfo = function(result) { var nonfreefiles = []; if ( result && result.query ) { $.each(result.query.pages, function(id, page) {				if ( id > 0 && page.categories ) {					nonfreefiles.push(page.title);				}			}); }		editWikitext(nonfreefiles); };

API.get( {		action: 'query',		pageids: config.mw.wgArticleId,		generator: 'images',		gimlimit: 'max',		prop: 'categories',		cllimit: 'max',		clcategories: 'Category:All non-free media',	} ) .done( function(result){		setTaskStatus(1, "done");		processImageInfo(result);	} ) .fail( function(c,r) {		if ( r.textStatus === 'abort' ) { return; }

var retry = confirm("Could not find if there are non-free files:\n"+ extraJs.makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip"); if ( retry ) { getImageInfo; } else { setTaskStatus(1, "skipped"); editWikitext([]); }	} );

};

//Comment out non-free files, turn categories into links, add afc draft template, list any redirects var editWikitext = function(nonfreefiles) { setTaskStatus(2, "started");

var redirectsList = ( !config.pagedata.redirects ) ? '' : '\n'+ '\n';

var wikitext = "" + config.inputdata.authorName + "\n" + redirectsList + config.pagedata.oldwikitext.replace(/\[\[\s*[Cc]ategory\s*:/g, "[[:Category:") +		"\n";

// 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.util.escapeRegExp(filename.slice(0, 1).toUpperCase) +			mw.util.escapeRegExp(filename.slice(0, 1).toLowerCase) + "]" +			mw.util.escapeRegExp(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. 		var normal_regex = new RegExp( normal_regex_str, "g"); wikitext = wikitext.replace(normal_regex, "");

// 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, "");

// 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, ""); }

API.postWithToken( 'csrf', {		action: 'edit',		pageid: config.mw.wgArticleId,		text: wikitext,		summary: config.wikitext.editsummary + config.script.advert	} ) .done( function{		setTaskStatus(2, "done");		notifyAuthor;	} ) .fail( function(c,r) {		if ( r.textStatus === 'abort' ) { return; }

var retry = confirm("Could not edit draft artice:\n"+ extraJs.makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip"); if ( retry ) { editWikitext(nonfreefiles); } else { setTaskStatus(2, "skipped"); notifyAuthor; }	} );

};

var notifyAuthor = function { if ( !config.inputdata.notifyEnable ) { updateTalk; return; }	setTaskStatus(3, "started");

API.postWithToken( 'csrf', {		action: 'edit',		title: 'User talk:' + config.inputdata.authorName,		section: 'new',		sectiontitle: config.inputdata.notifyMsgHead,		text: config.inputdata.notifyMsg,	} ) .done( function{		setTaskStatus(3, "done");		updateTalk;	} ) .fail( function(c,r) {		if ( r.textStatus === 'abort' ) { return; }

var retry = confirm("Could not edit author talk page:\n"+ extraJs.makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip"); if ( retry ) { notifyAuthor; } else { setTaskStatus(3, "skipped"); updateTalk; }	} ); };

var updateTalk = function { setTaskStatus(4, "started");

//if page exists, do a regex search/repace for class/importances parameters var processTalkWikitext = function(result) { var talk_id = result.query.pageids[0]; if ( talk_id < 0 ) { setTaskStatus(4, "done", "talk page does not exist"); draftifyLog; 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 ) { setTaskStatus(4, "done", "no changes needed"); draftifyLog; return; }

API.postWithToken( 'csrf', {			action: 'edit',			pageid: talk_id,			section: '0',			text: new_talk_wikitext,			summary: 'Remove class/importance from project banners' + config.script.advert		} ) .done( function{			setTaskStatus(4, "done");			draftifyLog;		} ) .fail( function(c,r) {			if ( r.textStatus === 'abort' ) { return; }

var retry = confirm("Could not edit draft's talk page:\n"+ extraJs.makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip"); if ( retry ) { updateTalk; } else { setTaskStatus(4, "skipped"); draftifyLog; }		} );	};

//get talk page wikitext (section 0) API.get( {		action: 'query',		titles: config.inputdata.newTitle.replace("Draft:", "Draft talk:"),		prop: 'revisions',		rvprop: 'content',		rvsection: '0',		indexpageids: 1	} ) .done( processTalkWikitext ) .fail( function(c,r) {		if ( r.textStatus === 'abort' ) { return; }

var retry = confirm("Could not find draft's talk page:\n"+ extraJs.makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip"); if ( retry ) { updateTalk; } else { setTaskStatus(4, "skipped"); draftifyLog; }	} );

};

var draftifyLog = function { if (config.doNotLog) { $("#M2D-finished, #M2D-abort").toggle; return; }

setTaskStatus(5, "started");

var logpage = 'User:' + config.mw.wgUserName + '/Draftify_log'; var monthNames = config.mw.wgMonthNames.slice(1); var now = new Date; var heading = '== ' + monthNames[now.getUTCMonth] + ' ' + now.getUTCFullYear + ' =='; var headingPatt = RegExp(heading);

var processLogWikitext = function(result) { var logpage_wikitext = '';

var id = result.query.pageids[0]; if ( id < 0 ) { var createlog = confirm('Log draftification (at ' + logpage + ') ?'); if ( !createlog ) { setTaskStatus(5, "skipped"); $("#M2D-finished, #M2D-abort").toggle; return; }			logpage_wikitext = 'This is a log of pages moved to draftspace using the MoveToDraft script.'; } else { logpage_wikitext = result.query.pages[id].revisions[0]['*'].trim; }

if ( !headingPatt.test(logpage_wikitext) ) { logpage_wikitext += '\n\n' + heading; }		logpage_wikitext += '\n' + config.inputdata.logMsg;

API.postWithToken( 'csrf', {			action: 'edit',			title: logpage,			text: logpage_wikitext,			summary: 'Logging '+config.inputdata.newTitle+'' + config.script.advert		} ) .done( function{			setTaskStatus(5, "done");			$("#M2D-finished, #M2D-abort").toggle;		} ) .fail( function(c,r) {			if ( r.textStatus === 'abort' ) { return; }

var retry = confirm("Could not edit log page:\n"+ extraJs.makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip"); if ( retry ) { draftifyLog; } else { setTaskStatus(5, "skipped"); $("#M2D-finished, #M2D-abort").toggle; }		} );	};

//get log page wikitext API.get( {		action: 'query',		titles: logpage,		prop: 'revisions',		rvprop: 'content',		indexpageids: 1	} ) .done( processLogWikitext ) .fail( function(c,r) {		if ( r.textStatus === 'abort' ) { return; }

var retry = confirm("Could not find log page:\n"+ extraJs.makeErrorMsg(c, r)+"\n\n[Okay] to try again, or [Cancel] to skip"); if ( retry ) { draftifyLog; } else { setTaskStatus(5, "skipped"); $("#M2D-finished, #M2D-abort").toggle; }	} ); };

var setupHeader = function(subText) { $("#M2D-interface-header").append(		$(' ').text('X')			.attr('title', 'Close')			.css('float', 'right')			.click(function{ $("#M2D-modal").remove; }),		$(' ')			.append( extraJs.makeLink(config.script.location, 'Move To Draft'), ' (v' + config.script.version + ') ', subText )			.css({"font-weight": "bold", "font-size": "large", "margin": "0.25em", "text-align": "center"})	); };

// --- Interface screens --- //0) Initial screen var screen0 = function {	$("#M2D-interface-header, #M2D-interface-content, #M2D-interface-footer").empty;	setupHeader("...");

$("#M2D-interface-content").text("Loading..."); grabPageData; };

//1) User inputs

/** * * @param {boolean} restoreValues Restore previously set values */ var screen1 = function(restoreValues) { $("#M2D-interface-header, #M2D-interface-content, #M2D-interface-footer").empty; setupHeader(": options");

$("#M2D-interface-content").append(		$(' ').css('margin-bottom','0.5em').append( $(' ')			.attr({'id': 'M2D-warning'}) .css({				display: 'block',				color: 'darkred',				'font-weight': 'bold',			}).append(				'Please ensure draftifying is appropriate per ',				extraJs.makeLink("WP:DRAFTIFY")			), $(' ')					.css({ display: 'block', color: 'red', 'font-style': 'italic', margin: '0.5em auto'}) .append(						'Add maintenance tags first if you wish, then check any or all boxes that match the issues with this article, then submit the message.'					), $(' ').attr('for','M2D-option-newtitle').append(				'Move to ',				$('').text('Draft:')			), $(' ').attr({'type':'text', 'name':'M2D-option-newtitle', 'id':'M2D-option-newtitle'}) .css('margin-left', '0.25em') ),

$(' ').css('margin-bottom','0.5em').append(			$(' ').attr({'for':'M2D-option-movelog', 'id':'M2D-option-movelog-label'})				.css('display','block').text('Reason for move (log summary):'),			$(' ').attr({'rows':'1', 'name':'M2D-option-movelog', 'id':'M2D-option-movelog'})				.css('width','99%')		),

$(' ').css('margin-bottom','0.5em').append(			$(' ').attr({'for':'M2D-option-author', 'id':'M2D-option-author-label'}).text('Author:'),			$(' ').attr({'type':'text', 'name':'M2D-option-author', 'id':'M2D-option-author'})				.css('margin-left', '0.25em')		),

$(' ').attr({'for':'M2D-option-message-enable'}).append(			$(' ').attr({'type':'checkbox', 'id':'M2D-option-message-enable'})				.css('margin-right', '0.25em')				.prop('checked', true),			'Notify author'		),

$(' ').attr({'for':'M2D-option-message-head', 'id':'M2D-option-message-head-label'}) .css({'display':'block', 'margin-top':'0.5em'}).text('Notification heading'), $(' ').attr({'id':'M2D-option-message-head', 'rows':'1'}) .css({'width':'99%', 'margin-bottom':'0.5em'}),

$(' ').attr({'id':'M2D-option-reasons-label'}) .css({'display':'block', 'margin-top':'0.5em'}).text('Reason/s:'), $(' ').attr({'id':'M2D-option-reasons'}) .css({'width':'99%', 'columns': '2'}),

$(' ').attr({'id':'M2D-option-reasons-other'}) .css({'width':'99%', 'margin-bottom':'0.5em'}),

$(' ').attr({'for':'M2D-option-message', 'id':'M2D-option-message-label'}) .css('display','block').text('Notification message:'), $(' ').attr({'id':'M2D-option-message', 'rows':'7'}) .css('width','99%') .prop("readonly", true) );

for (var key in config.draftReasons) { $("#M2D-option-reasons").append(			$(' ').append( $(' ').attr({'id':'M2D-option-reasons-checkbox-'+key, 'type':'checkbox', 'value':key}) .change( reasonChange ), $(' ').attr({'id':'M2D-option-reasons-label-'+key, 'for':'M2D-option-reasons-checkbox-'+key}) .text(config.draftReasons[key].charAt(0).toUpperCase + config.draftReasons[key].slice(1)) .css({'margin-left':'0.5em'}), $(' ')			)		);	}

//text box and label $("#M2D-option-reasons-other").append(		$(' ').attr({'id':'M2D-option-reasons-checkbox-other', 'type':'checkbox', 'value':'other'})			.css({'float':'left'}),		$(' ').attr({'for':'M2D-reason-other', 'id':'M2D-reason-other-label'})			.css({'float':'left', 'margin':'auto 0.5em'}).text('Other/additional reasons:'),		$(' ').attr({'id':'M2D-reason-other', 'rows':'1'})			.css({'width':'75%'})			.on("input keyup paste", reasonChange )	);

//Adding a warning, if needed setDraftifyWarning("#M2D-warning");

//Setting one of the checkboxes as checked by default $('#M2D-option-reasons-checkbox-no-sources').prop('checked', true); reasonChange;

$('#M2D-option-movelog').val(config.wikitext.rationale); $('#M2D-option-newtitle').val(getPageText(config.mw.wgPageName)).change(function {		$('#M2D-option-message-head').val( $('#M2D-option-message-head').val.trim .replace(/\[\[Draft\:.*?\|/, "[[Draft:" + $('#M2D-option-newtitle').val.trim + "|")		);		$('#M2D-option-message').val(			$('#M2D-option-message').val.trim			.replace(/\[\[Draft\:.*?\|/, "[[Draft:" + $('#M2D-option-newtitle').val.trim + "|")		);	});	$('#M2D-option-author').val(config.pagedata.author);	$('#M2D-option-message-enable').change(function {		$('#M2D-option-message-head').prop('disabled', !this.checked);		$('#M2D-option-message').prop('disabled', !this.checked);	});	$('#M2D-option-message-head').val(config.wikitext.notification_heading.replace(/\$1/g, getPageText(config.mw.wgPageName)));

$("#M2D-interface-footer").append(		$(' ').attr('id', 'M2D-next').text('Continue'),		$(' ').attr('id', 'M2D-cancel').css('margin-left','3em').text('Cancel')	);

$("#M2D-cancel").click(function{		$("#M2D-modal").remove;	});

if (restoreValues) { $('#M2D-option-movelog').val(config.inputdata.rationale); $('#M2D-option-newtitle').val(config.inputdata.newTitle); $('#M2D-option-author').val(config.inputdata.authorName); $('#M2D-option-message-enable').prop('checked', config.inputdata.notifyEnable); $('#M2D-option-message-head').val(config.inputdata.notifyMsgHead); $('#M2D-option-message').val(config.inputdata.notifyMsg); }

$("#M2D-next").click(function{		//Gather inputs		config.inputdata = {			rationale:		$('#M2D-option-movelog').val.trim,			newTitle: 		"Draft:" + $('#M2D-option-newtitle').val.trim,			authorName: 	$('#M2D-option-author').val.trim,			notifyEnable:		$('#M2D-option-message-enable').prop('checked'),			notifyMsgHead:	$('#M2D-option-message-head').val.trim,			notifyMsg:		$('#M2D-option-message').val.trim		};		config.inputdata.logMsg = config.wikitext.logMsg			.replace(/\$1/g, getPageText(config.mw.wgPageName))			.replace(/\$2/g, config.inputdata.newTitle);

//Verify inputs var errors=[]; if ( config.inputdata.newTitle.length === 0 ) { errors.push("Invalid draft title"); }		if ( config.inputdata.authorName.length === 0 ) { errors.push("Invalid user name"); }		if ( config.inputdata.rationale.length === 0 ) { errors.push("Move log reason is empty"); }		if ( config.inputdata.notifyEnable ) { if ( config.inputdata.notifyMsgHead.length === 0 ) { errors.push("Notification heading is empty"); }			if ( config.inputdata.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; }); };

//Checks if draftification is appropriate and warns the user accordingly var setDraftifyWarning = function( divId ) { var now = new Date; var begin = moment.utc( config.pagedata.creationTimestamp, 'YYYY-MM-DD-HH:mm:ss' ); var diff = Math.round( ( now - begin ) / ( 1000 * 60 ) );

if ( diff < config.minimumAgeInMinutes ) { $(divId).text(''); $(divId).append(			"Draftifying may not be appropriate per ",			extraJs.makeLink("WP:DRAFTIFY"),			", since this article is less than ",			config.minimumAgeInMinutes,			" minutes old."		); } else if ( diff > ( config.maximumAgeInDays * 24 * 60 ) ) { $(divId).text(''); $(divId).append(			"Draftifying may not be appropriate per ",			extraJs.makeLink("WP:DRAFTIFY"),			", since this article is more than ",			config.maximumAgeInDays,			" days old."		); } else if ( config.pagedata.previousDraftification ) { $(divId).text(''); $(divId).append(			"Draftifying may not be appropriate per ",			extraJs.makeLink("WP:DRAFTIFY"),			", since this article has been previously draftified."		); } };

//Called when the state of any of the reason checkboxes changes var reasonChange = function { var reasons = []; for (var key in config.draftReasons) { if ( $("#M2D-option-reasons-checkbox-"+key).prop("checked") == true ) { reasons.push(key); }	}

//Cloning the array var draftifyReasons = JSON.parse(JSON.stringify(config.draftReasons));

//Other reasons text box var otherText = $("#M2D-reason-other").val; if ( otherText !== '' ) { draftifyReasons.other = otherText; reasons.push('other'); $('#M2D-option-reasons-checkbox-other').prop("checked", true); } else { $('#M2D-option-reasons-checkbox-other').prop("checked", false); }

var reasonText = ""; if (reasons.length === 0) { $('#M2D-next').prop('disabled', true); } else { $('#M2D-next').prop('disabled', false); reasonText = " because " + draftifyReasons[reasons[0]] + ""; if (reasons.length > 1) { for (var i = 1; i < (reasons.length - 1); i++) { reasonText += ", " + draftifyReasons[reasons[i]] + ""; }			reasonText += " and " + draftifyReasons[reasons[reasons.length-1]] + ""; }	}

$('#M2D-option-message').val(config.wikitext.notification			.replace(/\$1/g, getPageText(config.mw.wgPageName))			.replace(/\$3/g, reasonText)	); };

//2) Progress indicators var screen2 = function {	$("#M2D-interface-header, #M2D-interface-content, #M2D-interface-footer").empty;	setupHeader(": In progress...");

$("#M2D-interface-content").append(		$('').attr('id', 'M2D-tasks').css("color", "#888").append( $('').attr('id', 'M2D-task0').append(				'Moving page',				$(' ').attr('id','M2D-status0')			), $('').attr('id', 'M2D-task1').append(				'Checking images',				$(' ').attr('id','M2D-status1')			), $('').attr('id', 'M2D-task2').append(				'Editing page wikitext',				$(' ').attr('id','M2D-status2')			), config.inputdata.notifyEnable ? $('').attr('id', 'M2D-task3').append(					'Notifying author',					$(' ').attr('id','M2D-status3')				) : '',			$('').attr('id', 'M2D-task4').append(				'Updating talk page banners',				$(' ').attr('id','M2D-status4')			),

$('').attr('id', 'M2D-task5').append(				'Logging',				config.doNotLog					? $(' ').attr('font-size', '90%' ).text('disabled')					: $(' ').attr('id','M2D-status5')			) )	);

$("#M2D-interface-footer").append(		$(' ').attr('id', 'M2D-abort').text('Abort uncompleted tasks'),		$(' ').attr('id', 'M2D-finished').hide.append( 'Finished!', $(' ').attr('id', 'M2D-close').text('Close') .css('margin-left', '0.5em') )	);

$("#M2D-close").click( function{		$("#M2D-modal").remove;		window.location.reload;	} ); $("M2D-abort").click( function{		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 (or user-specified portlet) which starts everything --- mw.util.addPortletLink( (window.m2d_portlet||'p-cactions'), '#', 'Move to draft (s)', 'ca-m2ds', null, null, "#ca-move"); $('#ca-m2ds').on('click', function(e) {	e.preventDefault;	// Add interface shell	$('body').prepend(' '+ ' '+			' '+			' '+			' '+			' '+			' '+		' '+	' ');

// 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": "7% 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 };

/* ========== Log draftifications for a user ==================================================== */ function logDraftifications(username, fromDate) { var targetUser = username; if (!targetUser && targetUser!=="") { var pageNameParts = config.mw.wgPageName.split('/'); targetUser = (pageNameParts.length > 1) ? pageNameParts[1] : ''; }	$('#mw-content-text').empty; // TODO: Form for setting user var today = new Date.toISOString.slice(0,10); var MoveToDraftEpoch = "2017-05-29"; $('#mw-content-text').append(		$(` User:  From date (and earlier)   `)	);	$('#draftifyUsername').val(targetUser); $('#draftifyLogForm').on('submit', function(e) {		e.preventDefault;		$('#draftifyLog, #draftifyLogWikitext').show;		logDraftifications($('#draftifyUsername').val, $('#draftifyFromDate').val);	});

$('#mw-content-text').append(		$(`  `)	);

$('#draftifyLogWikitext').val(`{|class="wikitable" !scope='col'|From !scope='col'|To !scope='col'|Time !scope='col'|User !scope='col'|Reason
 * }`);

var query = { action: "query", format: "json", list: "logevents", leprop: "title|timestamp|comment|details|user", letype: "move", lenamespace: "0", lelimit: "500", lestart: (fromDate || today) + "T23:59:59Z" };	if (targetUser) { query.leuser = targetUser; }

var continueInfo = {};

function onLoadMoreClick(e) { e.preventDefault; $('#draftifyStatus').empty.text("Loading..."); searchAndShowResults; }

function parseLogTable(wikitext) { API.post({			"action": "parse",			"format": "json",			"text": wikitext,			"prop": "text",			"contentmodel": "wikitext"		}).then(function(response) {			$parsedLogTable = $(response.parse.text['*']);			$('#draftifyLog tbody').empty.append( $parsedLogTable.find('tr').slice(1) );		});	}

function searchAndShowResults { API.get( $.extend({}, query, continueInfo) ) .then(function(response) {				// Store continuing info, if any				continueInfo = response.continue || {};				// Reset status, add a "Load more" if there are more results				$('#draftifyStatus').empty.append( response.continue ? $('').css("cursor", "pointer").text('Load more').click(onLoadMoreClick) : null );				// Filter to only MoveToDraft script moves				var draftifyEvents = response.query && response.query.logevents && response.query.logevents.filter(function(logevent) { return logevent.params.target_ns === 118; // Moved to Draft namespace });				var noDraftifyEvents = !draftifyEvents || !draftifyEvents.length;

switch(true) { case noDraftifyEvents && !response.continue: $('#draftifyStatus').empty.text(							$('#draftifyLog tbody tr').length == 0 ? "No results" : "No further results"						); break; case noDraftifyEvents: // Continue with next batch of results, otherwise table will initially have no results but a load more link, // or clicking "Load more" will appear to show "Loading..." but not actually add any results searchAndShowResults; break; case !response.continue: $('#draftifyStatus').empty.text("No further results"); /* falls through */ default: draftifyEvents.forEach(function(logevent) {							var fromTitle = logevent.title;							var toTitle = logevent.params.target_title;							var timeOfMove = new Date(logevent.timestamp).toUTCString.replace("GMT", "(UTC)");							var user = logevent.user;							var comment = logevent.comment;							var wikitext = $('#draftifyLogWikitext').val.replace("|}", `|- $('#draftifyLogWikitext').val(wikitext); parseLogTable(wikitext); });				}			});	}
 * ${fromTitle}
 * ${toTitle}
 * ${timeOfMove}
 * ${user}
 * ${comment}
 * }`);

// Run by default, unless page loaded without a /username suffix if (username || username==="") { searchAndShowResults; } else { $('#draftifyLog, #draftifyLogWikitext').hide; }

// End of function logDraftifications }

/* ========== Setup ============================================================================= */ // Access draftifications using Special:Draftify_log/USER_NAME var isDraftifyLogPage = config.mw.wgPageName.indexOf("Special:Draftify_log") === 0; var isUserPage = config.mw.wgNamespaceNumber === 2 || config.mw.wgNamespaceNumber === 3; if (isDraftifyLogPage) { document.title = "Draftify log - Wikipedia"; $('h1').text("Draftify log"); $('#mw-content-text').empty .text("Loading...") .before(		$(' ').append( 'Note: This page only works with the ', $('<a>').attr('href','/wiki/User:MPGuy2824/MoveToDraft').text('MoveToDraft'), ' userscript installed.' ),		$(' ')	);	logDraftifications; } else if (isUserPage) { var user = config.mw.wgTitle.split('/')[0]; var url = mw.util.getUrl("Special:Draftify_log/" + user); mw.util.addPortletLink( (window.m2d_portlet||'p-cactions'), url, 'Draftify log', 'ca-m2dlog', null, null, "#ca-move"); }

// Only operate in article namespace if( config.mw.wgNamespaceNumber !== 0 ) { return; }

// Only operate for existing pages if ( config.mw.wgCurRevisionId === 0 ) { return; }

moveToDraft;

}); //