User:Ale jrb/Scripts/csdhelper.js

/* ============================================== *\ \* ============================================== */
 * CSD Helper - JavaScript CSD Script
 * for FAMEPedia
 * Created by Alex Barley User:Ale_jrb
 * Tracker: User:Ale_jrb/Scripts
 * You are advised to import this script to your
 * monobook.js page - AVOID CREATING YOUR OWN
 * VERSION WHERE POSSIBLE.
 * Instructions for this script can be found at
 * User:Ale_jrb/Scripts - refer to this for
 * setting details.
 * Instructions for this script can be found at
 * User:Ale_jrb/Scripts - refer to this for
 * setting details.

// NB. this script relies on User:Ale_jrb/Scripts/waLib.js. // the following settings are used in this script: if (csdhDisplayAlways == null)		var csdhDisplayAlways	= false;		// whether to display CSDH even if the page is not tagged if (notifyByDefaultDec == null) 	var notifyByDefaultDec	= true;			// whether to check the 'notify tagger' box by default when declining a speedy deletion request if (notifyByDefaultDel == null) 	var notifyByDefaultDel	= false;		// whether to check the 'notify tagger' box by default when changing a speedy deletion rationale if (notifyByDefaultPrd == null) 	var notifyByDefaultPrd	= true;			// whether to check the 'notify tagger' box by default when converting a speedy deletion to PROD if (notifyByDefaultNew == null) 	var notifyByDefaultNew	= true;			// whether to check the 'use newbie message' box by default if (notifyLimit == null) 			var notifyLimit			= 12;			// how many revisions should be retrieved when determining who tagged the page if (notifyTemplate == null)			var notifyTemplate		= 'User:Ale_jrb/Scripts/CSDHelper'; // the template that should be substituted for notification messages

if (csdhDoRedirect == null)			var csdhDoRedirect		= true; if (redirectAfterDel == null) 		var redirectAfterDel	= mw.config.get ( 'wgScript' ) + '?title=Category:Candidates_for_speedy_deletion&action=purge#Pages_in_category'; // where to redirect after deletion if (myDeleteReasons == null)		var myDeleteReasons		= []; 	// any addition speedy deletion reasons to add to the list

if (logOnDecline == null)			var logOnDecline		= false; if (logOnDeclinePath == null)		var logOnDeclinePath	= ''; if (overwriteDeclineReasons == null)var overwriteDeclineReasons	= false; 		// whether to overwrite the in-build decline reasons with the user defined ones if (overwriteDeleteReasons == null)	var overwriteDeleteReasons	= false; 		// whether to overwrite the in-build delete reasons with the user defined ones if (myDeclineReasons == null)		var myDeclineReasons		= []; 	// any addition speedy deletion decline reasons to add to the list if (myDeclineListing == null)		var myDeclineListing		= '%CRITERION%: %REASON%' // the appearance of the option in the drop-down box if (myDeclineSummary == null)		var myDeclineSummary		= 'Speedy deletion %ACTION%. Criterion %CRITERION% does not apply: %REASON%';	// the summary to use when removing a deletion tag from a page because it has been declined or contested if (myDeclineSummarySpecial == null)var myDeclineSummarySpecial	= 'Speedy deletion %ACTION%. %REASON%';	// the summary to use when removing a deletion tag from a page IN A SEPCIAL CASE. NOTE: %CRITERION% will be blank!

// Top-level helpers function isPageTagged { return document.getElementById('delete-criterion') != null; }

function isPageContested { const contestString = 'speedy deletion of this page is contested.'; return document.body.innerHTML.indexOf(contestString) > -1; }

function shouldDisplayCsdh { // Always exclude certain pages if (mw.config.get('wgNamespaceNumber') == 10 ||		document.getElementById('noarticletext') ||		document.getElementById('newarticletext')) {		return false; }

// Otherwise perform display checks return csdhDisplayAlways || isPageTagged || isPageContested; }

function launchCsdh { if (shouldDisplayCsdh) { // Launch controller. this.control = new csdH_controller; this.control.attachLinks; return true; } }

// Core function csdH_controller { csdHController 		= this; this.notifyExempt	= new Array('SDPatrolBot','Ale jrb 2'); // these editors are exempt from being notified (if they added the tag, notification will fail) csdHController.deleteRegex = /[\s]*\{\{(?:db|speedy ?delet(?:e|ion)|speedy|d|rm|del(?:ete)? ?(?:because)?|csd|nn|[GARFCUTPX][0-9]{1,2})(?:-(?:.+?))?(?:\|(?:.+?))?\}\}[\s]*/gi; csdHController.hangonRegex = /[\s]*\{\{(?:hang|hold)(?: |-)?oo?n(?:\|.+?)?\}\}[\s]*/gi; csdHController.doNotifyDec = ''; csdHController.doNotifyDel = ''; csdHController.doNotifyPrd = '';

if (notifyByDefaultDec == true) csdHController.doNotifyDec = ' checked'; if (notifyByDefaultDel == true) csdHController.doNotifyDel = ' checked'; if (notifyByDefaultPrd == true) csdHController.doNotifyPrd = ' checked'; if (notifyByDefaultNew == true) csdHController.doNotifyNew = ' checked'; if (waUser.isSysop == true) { csdHController.isSysop = 'yes'; csdHController.decAction = 'declined'; } else { csdHController.isSysop = 'no'; csdHController.decAction = 'contested'; }	// default arrays - it's fine to edit these, but if you simply wish to add additional decline reasons, use the // setting for additional options described above. this.declineReasons = new Array(										['G1', 		'Not nonsense - there is meaningful content'],										['G2', 		'Not a test page'],										['G3', 		'Not blatantly vandalism or a hoax'],										['G4', 		'Not previously been deleted via a deletion discussion'],										['G5', 		'Not created by a banned user, or the page does not violate the user\'s ban'],										['G6', 		'Deletion of this page may be controversial or is under discussion'],										['G7', 		'Author has not requested deletion, or other users have added substantial content'],										['G8', 		'Does not rely on a page that does not exist'],										['G9', 		'G9 can only be used at the request of, or by, the Wikimedia Foundation'],										['G10', 	'Not blatantly an attack page or negative, unsourced BLP'],										['G11', 	'Not unambiguously promotional'],										['G12', 	'Not an unambiguous copyright infringement, or there is other content to save'], ['G13',		'Page is not a draft, or has been edited in the last six months'], ['G14',		'Page is not a disambiguation page, or disambiguates two or more extant pages'],

['A1', 		'There is sufficient context to identify the subject of the article'], ['A2', 		'The article is in English, or does not exist at a foreign project'], ['A3', 		'Contains sufficient content to be a stub'], ['A5', 		'The article has not been transwikied to another project'], ['A7', 		'The article makes a credible assertion of importance or significance, sufficient to pass A7'], ['A7', 		'A7 does not apply to schools'], ['A7', 		'A7 does not apply to software'], ['A9', 		'The article makes a credible assertion of importance or significance, or is not a musical recording'], ['A10', 	'Page title is a plausible redirect, or it does not substantially duplicate the other topic'], ['A11',		'Subject is not obviously invented by the page creator'], ['R2', 		'Does not redirect to a different or incorrect namespace'], ['R3', 		'Is a plausible, useful redirect or is not a redirect at all'], ['R3',		'Not a recently created redirect - consider FP:RfD'], ['R4', 		'Not the same name as a Commons file or redirect'], ['R4', 		'Has incoming file links - consider FP:RfD'], ['F1',		'File is used, or it is not a lower-quality version of an existing image'], ['F2',		'File is neither corrupt, missing, or empty'], ['F3',		'File has a suitable license'], ['F4',		'File has the necessary licensing information'], ['F5',		'File is used, or it has a free license'], ['F6',		'File has a use rationale'], ['F7',		'File has a valid fair-use claim'], ['F8',		'File is not identical to the Commons version, or has been marked as "Keep local"'], ['F9',		'Not an unambiguous copyright infringement'], ['F10',		'File is not a useless non-media file'], ['F11',		'Evidence of permission has been given'], ['C1',		'Category is populated or is otherwise allowed to be empty'], ['U1', 		'Not a user page'], ['U1', 		'Does not apply to user talk pages'], ['U2', 		'User does exist, or this is not a user page'], ['U3',		'Gallery does not contain "fair use" and non-free images'], ['U5',		'Not a blatant misuse of FAMEPedia as a webhost'] );	this.deleteReasons = new Array( ['N/A', 	'You must select a rationale...'], ['G1', 		'Patent nonsense, meaningless, or incomprehensible'], ['G2', 		'Test page'], ['G3', 		'Vandalism'], ['G3', 		'Vandalism - blatant hoax or misinformation'], ['G4', 		'Recreation of a page that was deleted per a deletion discussion'], ['G5', 		'Creation by a banned user in violation of ban'], ['G6', 		'Housekeeping and routine (non-controversial) cleanup'], ['G7', 		'One author who has requested deletion or blanked the page'], ['G8', 		'Page dependent on a deleted or nonexistent page'], ['G8',		'Talk page of a deleted page'], ['G10', 	'Attack page or negative unsourced BLP that serves no purpose but to threaten or disparage its subject'], ['G11', 	'Unambiguous advertising or promotion'], ['G12', 	'Unambiguous copyright infringement'], ['G13', 	'Abandoned Draft or Article for creation — to retrieve it, see FP:REFUND/G13'], ['G14', 	'Disambiguation page that disambiguates only one page and whose title ends in (disambiguation) or disambiguates zero extant pages'], ['A1', 		'Not enough context to identify article\'s subject'], ['A2', 		'Article in a foreign language that exists on another project'], ['A3', 		'Article that has no meaningful, substantive content'], ['A5', 		'Article that has been transwikied to another project'], ['A7', 		'No indication that the article may meet the guidelines for inclusion'], ['A7',		'Article about a real person, which does not credibly indicate the importance or significance of the subject'], ['A7',		'Article about a band, singer, musician, or musical ensemble that does not credibly indicate the importance or significance of the subject'], ['A7',		'Article about a web site, blog, web forum, webcomic, podcast, browser game, or similar web content, which does not credibly indicate the importance or significance of the subject'], ['A7',		'Article about a company, corporation, organization, or group which does not credibly indicate the importance or significance of the subject'], ['A7',		'Article about a group or club, which does not credibly indicate the importance or significance of the subject'], ['A7',		'Article about an organized event, which does not credibly indicate the importance or significance of the subject'], ['A7',		'Article about an individual animal, which does not credibly indicate the importance or significance of the subject'], ['A9', 		'Article about a musical recording, which does not credibly indicate the importance or significance of the subject and where the artist has no article'], ['A10', 	'Article where the only content is already existing in another article and where a redirect to the existing article would be implausible'], ['A11',    'Article about a subject that was obviously invented by the creator or someone they know and which does not credibly indicate the importance or significance of the subject'], ['R2', 		'Cross-namespace redirect from mainspace'], ['R3', 		'Recently-created, implausible redirect'], ['R4', 		'File redirect with no incoming file links and the same name as a file or redirect at Wikimedia Commons'], ['F1',		'Redundant file (also on FAMEPedia)'], ['F2',		'Corrupt or empty file, or a file description page for a file on Commons'], ['F3',		'File licensed as "for non-commercial use only", "no derivative use", "for FAMEPedia use only", "used with permission", or GFDL 1.2 only.'], ['F4',		'Lack of licensing information'], ['F5',		'Unused non-free media file for more than 7 days'], ['F6',		'Non-free media file with no non-free use rationale'], ['F7',		'Invalid fair-use rationale'], ['F8',		'Media file available on Commons'], ['F9',		'Media file copyright violation without credible claim of fair use or permission'], ['F10',		'Unusable non-media file'], ['F11',		'No evidence of permission for more than 7 days'], ['C1',		'Empty category'], ['U1', 		'User request to delete pages in own userspace'], ['U2', 		'Userpage or subpage of a nonexistent user'], ['U3', 		'Non-free gallery'], ['U5',     'Blatant use of FAMEPedia as a web host by user with no or very few edits'] );

// Handle user defined content... // declining if (overwriteDeclineReasons == true) { this.declineReasons.length = 0; this.declineReasons = myDeclineReasons; } else { this.declineReasons = this.declineReasons.concat(myDeclineReasons); }

// deleting if (overwriteDeleteReasons == true) { this.deleteReasons.length = 0; this.deleteReasons = myDeleteReasons; } else { this.deleteReasons = this.deleteReasons.concat(myDeleteReasons); }

// append necessary options to decline reasons var declineReasonsEnd = new Array(									 	['INVALID', 		'The reason given is not a valid speedy deletion criterion'],	// don't touch this										['DONTPROVIDE', 	'No reason given.'], 						// don't touch this										['OTHER', 			'Other - provide your own reason below']	// don't touch this									); this.declineReasons = this.declineReasons.concat(declineReasonsEnd); // GUI function getStandardElements { if (!(isPageTagged || isPageContested)) { return ''; }

let result = 'Decline Speedy ' + 'Change to PROD ' + '';		return result; }

function getSysopElements { if (!waUser.isSysop) { return ''; }

let result = 'Delete Page ' + '';

return result; }

function getCoreElements { let result = ' ' +				' Handle Speedy Deletion ' + ' What do you want to do to this page? ' +				' ' +					getSysopElements + getStandardElements + ' ' +			' ';

return result; }

this.showcsdHWindow = function { // grab position of button var offsetL = 0; var offsetT = 0; var thisObject = document.getElementById('ca-speedy'); if (thisObject.offsetParent) { do { offsetL += thisObject.offsetLeft; offsetT += thisObject.offsetTop; } while (thisObject = thisObject.offsetParent); }		// build window to show user if (this.interface == null) { this.interface = new wa_window(document.getElementById('content')); this.visible = true; this.csdHelperLink.ele_obj.setAttribute('class', 'selected');

this.interface.win_content = getCoreElements; } else { this.interface.win_content = getCoreElements; if (this.visible == true) { this.csdHelperLink.ele_obj.setAttribute('class', ''); this.interface.win_disp = 'none'; this.interface.applyAll; this.visible = false; return true; } else { this.csdHelperLink.ele_obj.setAttribute('class', 'selected'); this.interface.win_disp = 'block'; this.interface.win_height = 170; this.interface.applyAll; this.visible = true; return true; }		}		if ( mw.config.get ( 'skin' ) == 'vector' ) { this.interface.win_left = offsetL - 17; this.interface.win_top = offsetT + 39; } else { this.interface.win_left = document.getElementById('ca-speedy').offsetLeft - 17; this.interface.win_top = -1; }		this.interface.win_width = 600; this.interface.win_height = 170; this.interface.win_bg = '#fff'; this.interface.win_bd = '#aaaaaa'; this.interface.win_bd_wd = 1; this.interface.applyAll; }	this.declinePage = function { // build the selection options var declineOptions = ''; var optionSelected = false; for (var i = 0; i < this.declineReasons.length; i++) { var selected = ''; // determine whether this option should be selected if (optionSelected == false) { if (document.getElementById('delete-criterion') != null) { // if this matches the criterion provided, select it. if (document.getElementById('delete-criterion').innerHTML == this.declineReasons[i][0]) { selected = ' selected '; optionSelected = true; } if ( (this.declineReasons[i][0] == 'INVALID') && (optionSelected == false) ) { selected = ' selected '; optionSelected = true; } } else { // if no criterion was selected, wait until 'other' is selected. if (this.declineReasons[i][0] == 'OTHER') { selected = ' selected '; optionSelected = true; } }			}			// build the visible message for use in the drop-down. var tempVisible = myDeclineListing.replace(/%CRITERION%/gi, this.declineReasons[i][0]); tempVisible = tempVisible.replace(/%REASON%/gi, this.declineReasons[i][1]); declineOptions += ''+tempVisible+' '; }		if ( mw.config.get ( 'skin' ) == 'vector' ) { var skinPos = '3'; } else { var skinPos = '10'; } this.interface.win_content = ''+ ' Decline Speedy Deletion '+ ' Select the reason for declining the deletion from the list. This text will be used as the edit summary. '+								''+declineOptions+' '+ ' Or provide your own reason and summary below. '+								''+ ' -- decline speedy deletion -- '+ 'notify tagger  '+ 'use newbie message  '+ ' '+								'';		this.interface.applyAll; }	this.declineDo = function(callback) { // get page content if (!callback) var callback = 0; switch (callback) { default: // main vars csdHController.declineText = 	document.getElementById('declineText').value; csdHController.declineSel = 	document.getElementById('declineReason').selectedIndex; csdHController.declineNotify = 	document.getElementById('notifyTagger').checked; csdHController.notifyNewbie = 	document.getElementById('notifyNewbie').checked; if ((csdHController.declineText == '') && (csdHController.declineSel == csdHController.declineReasons.length-1)) { // if no reason is typed, byt 'Other' is selected, use the 'No reason provided' option. csdHController.declineSel = csdHController.declineReasons.length - 2; }				csdHController.declineCategory 	= 	csdHController.declineReasons[csdHController.declineSel][0]; csdHController.declineReason 	=	csdHController.declineReasons[csdHController.declineSel][1]; // build all messages if ( (csdHController.declineCategory == 'INVALID') || (csdHController.declineCategory == 'DONTPROVIDE') ) { // if it's a 'special' case, use the 'special' summary var tempSummary = myDeclineSummarySpecial; tempSummary = tempSummary.replace(/%ACTION%/gi, csdHController.decAction); tempSummary = tempSummary.replace(/%REASON%/gi, csdHController.declineReason); csdHController.editSummary = tempSummary; } else if (csdHController.declineCategory == 'OTHER') { // if they've typed a reason, use that var tempSummary = myDeclineSummarySpecial; tempSummary = tempSummary.replace(/%ACTION%/gi, csdHController.decAction); tempSummary = tempSummary.replace(/%REASON%/gi, csdHController.declineText); csdHController.editSummary = tempSummary; } else { // otherwise, use the 'normal' summary var tempSummary = myDeclineSummary; tempSummary = tempSummary.replace(/%ACTION%/gi, csdHController.decAction); tempSummary = tempSummary.replace(/%CRITERION%/gi, csdHController.declineCategory); tempSummary = tempSummary.replace(/%REASON%/gi, csdHController.declineReason); csdHController.editSummary = tempSummary; }				csdHController.editSummary += ' (CSDH)'; // start this.interface.win_content = ''+ ' Working... '+								' Please wait while CSDHelper performs the requested operations. This can take several seconds. '+								' - Retrieving existing content... '+								' '+								'';				this.interface.applyAll; csdHController.pageReq = new wa_mediawikiApi; csdHController.pageReq.onCompleteAction = function { csdHController.declineDo('1'); }; csdHController.pageReq.getPage(mw.config.get('wgPageName'), notifyLimit, 'user|content'); break; case '1': document.getElementById('workingStatus').innerHTML += '- Removing tags... ';				csdHController.pageContent = csdHController.pageReq.data['page']['revisions'][0]['content']; var regReplace = csdHController.deleteRegex; csdHController.pageContent = csdHController.pageContent.replace(regReplace, ''); var regReplace = csdHController.hangonRegex; csdHController.pageContent = csdHController.pageContent.replace(regReplace, ''); csdHController.newContent = csdHController.pageContent; // grab a record of that document.getElementById('workingStatus').innerHTML += '- Updating page... ';				csdHController.editReq = new wa_mediawikiApi; csdHController.editReq.onCompleteAction = function { csdHController.declineDo('2'); }; csdHController.editReq.editPage(mw.config.get('wgPageName'), csdHController.newContent, csdHController.editSummary, false, 'text'); break; case '2': // check for notify if ( (csdHController.declineNotify == true) || (logOnDecline == true) ) { document.getElementById('workingStatus').innerHTML += '- Determining user who tagged page... ';					var tags = 0; csdHController.tagger = ''; var revisionCount = csdHController.pageReq.data['page']['revisions'].length; var limit = Math.min(notifyLimit, revisionCount); for (var i = 0; i < limit; i++) { var thisPage = csdHController.pageReq.data['page']['revisions'][i]['content']; // count tags var regTest = csdHController.deleteRegex; var k = 1; var count = 0; while (k != null) { k = regTest.exec(thisPage); if (k != null) count++; }						regTest.lastIndex = 0; // check if we have fewer than last time (1 was added on that rev) if (count < tags) { csdHController.tagger = csdHController.pageReq.data['page']['revisions'][i - 1]['user']; break; } else { tags = count; }					}					if (csdHController.tagger == '') { document.getElementById('workingStatus').innerHTML += '- Could not determine tagger: will not log or notify. Finished. '; break; } for (var i = 0; i < csdHController.notifyExempt.length; i++) { if (csdHController.tagger == csdHController.notifyExempt[i]) { document.getElementById('workingStatus').innerHTML += '- Tagger ('+csdHController.tagger+') is on the tagger exempt list, and will not be notified. Finished. ';							if (logOnDecline == true) { csdHController.declineNotify = false; csdHController.declineDo('3'); } else { return true; } }					}					if ( (logOnDecline == true) && (logOnDeclinePath != '') ) { csdHController.declineDo('3'); } else { csdHController.declineDo('5'); } } else { window.location.reload(true); csdHController.showcsdHWindow; } break; case '3': // log decline action where relevant document.getElementById('workingStatus').innerHTML += '- Logging decline action to \''+logOnDeclinePath+'\' - retrieving page... ';				csdHController.pageReq = new wa_mediawikiApi; csdHController.pageReq.onCompleteAction = function { csdHController.declineDo('4'); }; csdHController.pageReq.getPage(logOnDeclinePath, 1, 'content'); break; case '4': // we have retrieved the data regarding the log page; move to edit it document.getElementById('workingStatus').innerHTML += 'modifying page... ';				//var logOnDeclinePath = logOnDeclinePath.replace(/ /g,'_'); // check whether there is existing content var pageData = csdHController.pageReq.data['page']; if (pageData['status'] == 'OK') { var oldContent = pageData['revisions'][0]['content']; if ( oldContent === '' ) oldContent = "{| class=\"sortable wikitable\" style=\"font-size: 80%;\" border=\"2\" cellpadding=\"1\" background:#f9f9f9;\"|\n|-\n! style=\"text-align: left\" | Article\n! Tagger\n! Criterion\n! Decline reason\n! Date\n|}";				} else {					var oldContent = "{| class=\"sortable wikitable\" style=\"font-size: 80%;\" border=\"2\" cellpadding=\"1\" background:#f9f9f9;\"|\n|-\n! style=\"text-align: left\" | Article\n! Tagger\n! Criterion\n! Decline reason\n! Date\n|}"; }				// message var pageName = mw.config.get('wgPageName').replace(/_/g, ' '); var reason = (csdHController.declineCategory == 'OTHER') ? csdHController.declineText : csdHController.declineReason; var crit = document.getElementById('delete-criterion').innerHTML; var message = "|-\n| " + pageName + " || " + csdHController.tagger + " || CSD " + crit + " || " +reason + " || " + "" + "" + "~\n"; // add the new row to the table var newContent = oldContent.replace('|}', message + '|}'); // build vars var editSummary = 'Adding ' + pageName + ' to speedy decline log (CSDH)'; // perform the edit csdHController.editReq = new wa_mediawikiApi; csdHController.editReq.onCompleteAction = function { csdHController.declineDo('5'); }; csdHController.editReq.editPage(logOnDeclinePath, newContent, editSummary, true, 'text'); break; case '5': // check notify if (csdHController.declineNotify != true) { window.location.reload(true); csdHController.showcsdHWindow; break; } // output document.getElementById('workingStatus').innerHTML += '- Tagged by \''+csdHController.tagger+'\' - notifying user... ';				// edit summary csdHController.editSummary = 'Notifying about '+csdHController.decAction+' speedy deletion (CSDH)'; // decide whether to use newbie message if (csdHController.notifyNewbie) { var useNewbie = 'yes'; } else { var useNewbie = 'no'; } // fix message - handle other special case if (csdHController.declineCategory == 'OTHER') csdHController.declineReason = csdHController.declineText; // fix message - handle punctuation at the end of the message (it must be added if absent). var p = csdHController.declineReason.substr(csdHController.declineReason.length - 1); if ( (p != '.') && (p != '!') && (p != '?') ) csdHController.declineReason += '.'; // message var message = '== Speedy deletion '+csdHController.decAction+': '+mw.config.get('wgPageName').replace(/_/g, ' ')+' =='+"\n"+' '+''; csdHController.saveReq = new wa_mediawikiApi; csdHController.saveReq.onCompleteAction = function { window.location.reload(true); csdHController.showcsdHWindow; }; csdHController.saveReq.editPage('User_talk:'+csdHController.tagger, message, csdHController.editSummary, false, 'appendtext'); break; }	}	this.prodPage = function { var prodOptions = ''; var content = document.getElementById('bodyContent'); var regTest = /criteria for speedy deletion<\/a><\/i> because (.*?)\.<\/b> For valid criteria,/i var rationale = regTest.exec(content); if (rationale != null) { rationale = rationale[1]; } else { rationale = ''; } this.interface.win_content = ''+ ' Convert to PROD '+ ' You are asserting that the page cannot be speedy deleted, but can be deleted by proposed deletion. '+								'Enter the reason for deletion below - if the tagger provided one, it will be filled automatically. '+								''+ 'notify tagger of conversion  '+								'use newbie message <input id="notifyNewbie"'+csdHController.doNotifyNew+' style="position: relative; top: 3px; " type="checkbox" /> '+ ' -- convert to PROD</a> -- '+ ' '+								'';		this.interface.applyAll; }	this.prodDo = function(callback) { if (!callback) var callback = 0; switch (callback) { default: csdHController.prodReason = document.getElementById('prodReason').value; csdHController.prodNotify = document.getElementById('notifyTagger').checked; csdHController.notifyNewbie = document.getElementById('notifyNewbie').checked; this.interface.win_content = ''+ ' Working... '+								' Please wait while CSDHelper performs the requested operations. This can take several seconds. '+								' '+								' '+								'';				this.interface.applyAll; if (csdHController.prodNotify == true) { document.getElementById('workingStatus').innerHTML += '- Searching for tagger... ';					if (notifyLimit > 15) notifyLimit = 15; csdHController.pageReq = new wa_mediawikiApi; csdHController.pageReq.onCompleteAction = function { csdHController.prodDo('1'); }; csdHController.pageReq.getPage(mw.config.get('wgPageName'), notifyLimit + 1, 'content|user'); } else { csdHController.pageReq = new wa_mediawikiApi; csdHController.pageReq.onCompleteAction = function { csdHController.prodDo('3'); }; csdHController.pageReq.getPage(mw.config.get('wgPageName'), 1, 'content|user'); }				break; case '1': var tags = 0; csdHController.tagger = ''; var revisionCount = csdHController.pageReq.data['page']['revisions'].length; var limit = Math.min(notifyLimit, revisionCount); for (var i = 0; i < limit; i++) { var thisPage = csdHController.pageReq.data['page']['revisions'][i]['content']; // count tags var regTest = csdHController.deleteRegex; var k = 1; var count = 0; while (k != null) { k = regTest.exec(thisPage); if (k != null) count ++; }					regTest.lastIndex = 0; // check if we have fewer than last time (1 was added on that rev) if (count < tags) { csdHController.tagger = csdHController.pageReq.data['page']['revisions'][i - 1]['user']; break; } else { tags = count; }				}				if (csdHController.tagger == '') { document.getElementById('workingStatus').innerHTML += '- Could not determine tagger. Moving to tag page... '; csdHController.prodDo('3'); break; } for (var i = 0; i < csdHController.notifyExempt.length; i ++) { if (csdHController.tagger == csdHController.notifyExempt[i]) { document.getElementById('workingStatus').innerHTML += '- Tagger ('+csdHController.tagger+') is on the tagger exempt list, and will not be notified. Moving to tag page... ';						csdHController.prodDo('3'); return true; }				}				csdHController.prodDo('2'); break; case '2': // notify tagger document.getElementById('workingStatus').innerHTML += '- Tagged by \''+csdHController.tagger+'\' - notifying user... ';				// edit summary csdHController.editSummary = 'Notifying about speedy deletion converted to PROD (CSDH)'; // decide whether to use newbie message if (csdHController.notifyNewbie) { var useNewbie = 'yes'; } else { var useNewbie = 'no'; } // message var message = '== Speedy deletion converted to PROD: '+mw.config.get('wgPageName').replace(/_/g, ' ')+' =='+"\n"+' '+''; csdHController.notifyReq = new wa_mediawikiApi; csdHController.notifyReq.onCompleteAction = function { csdHController.prodDo('3'); }; csdHController.notifyReq.editPage('User_talk:'+csdHController.tagger, message, csdHController.editSummary, false, 'appendtext'); break; case '3': document.getElementById('workingStatus').innerHTML += '- Converting tags... ';				csdHController.pageContent = csdHController.pageReq.data['page']['revisions'][0]['content']; var regReplace = csdHController.deleteRegex; csdHController.pageContent = csdHController.pageContent.replace(regReplace, ''); var regReplace = csdHController.hangonRegex; csdHController.pageContent = csdHController.pageContent.replace(regReplace, ''); if (csdHController.prodReason != 'nn') { csdHController.pageContent = '{'+'{subst:prod|'+csdHController.prodReason+'}'+'}\n' + csdHController.pageContent; } else { csdHController.pageContent = '{'+'{subst:prod-nn}'+'}\n' + csdHController.pageContent; } csdHController.newContent = csdHController.pageContent; // grab a record of that csdHController.editSummary = 'Speedy deletion converted to PROD (CSDH)'; document.getElementById('workingStatus').innerHTML += '- Updating page... ';				csdHController.editReq = new wa_mediawikiApi; csdHController.editReq.onCompleteAction = function { window.location.reload(true); csdHController.showcsdHWindow; }; csdHController.editReq.editPage(mw.config.get('wgPageName'), csdHController.newContent, csdHController.editSummary, false, 'text'); break; }	}	this.deletePage = function { // build the selection options var deleteOptions = ''; var optionSelected = false; for (var i = 0; i < this.deleteReasons.length; i++) { var selected = ''; if ( (document.getElementById('delete-criterion') != null) && (optionSelected == false) ) { if (document.getElementById('delete-criterion').innerHTML == this.deleteReasons[i][0]) { csdHController.initialRationale = this.deleteReasons[i][0]; selected = ' selected'; optionSelected = true; } } else { if (this.deleteReasons[i][0] == 'N/A') { selected = ' selected '; optionSelected = true; } }			// general var visibleReasoning = this.deleteReasons[i][1].replace(/\[\[(?:.*?\|)(.+?)\]\]/g, '$1'); deleteOptions += '<option value="'+i+'"'+selected+'>'+this.deleteReasons[i][0]+': '+visibleReasoning+' '; }		if (document.getElementById('delete-criterion') == null) { var displayTagCommand = 'display: none;'; } else { var displayTagCommand = 'display: block;'; } this.interface.win_content = ''+ ' Perform Speedy Deletion '+ ' Select the reason for deletion from the list. The rationale specified by the tagger is automatically selected. If you select a reason that does not '+ 'match the tag, will be given the option of notifying the tagger. '+								'<select id="deleteReason" style="font-size: 11px; margin-left: 9px; width: 576px;" onchange="'+									'if (document.getElementById(\'delete-criterion\') != null) {'+										'if (csdHController.deleteReasons[document.getElementById(\'deleteReason\').selectedIndex][0] != document.getElementById(\'delete-criterion\').innerHTML) { '+											'if (csdHController.deleteReasons[document.getElementById(\'deleteReason\').selectedIndex][0] == \'N/A\') { document.getElementById(\'notifyTaggerDiv\').style.display = \'none\'; } else { document.getElementById(\'notifyTaggerDiv\').style.display = \'block\'; }'+										'} else {'+											'document.getElementById(\'notifyTaggerDiv\').style.display = \'none\'; '+										'}'+									'} else { document.getElementById(\'notifyTaggerDiv\').style.display = \'none\'; }'+									'if (csdHController.deleteReasons[document.getElementById(\'deleteReason\').selectedIndex][0] == \'N/A\') {'+ 'document.getElementById(\'performDeletionDiv\').style.display = \'none\'; '+ '} else {'+ 'document.getElementById(\'performDeletionDiv\').style.display = \'block\'; '+ '}'+								'">'+deleteOptions+' '+								'<div id="notifyTaggerDiv" style="display: none; margin-top: 10px; font-size: 11px; margin-left: 20px; float: left; vertical-align: middle;">notify tagger of rationale change <input id="notifyTagger"'+csdHController.doNotifyDel+' style="position: relative; top: 3px; " type="checkbox" /> '+								'use newbie message <input id="notifyNewbie"'+csdHController.doNotifyNew+' style="position: relative; top: 3px; " type="checkbox" /> '+								'<div id="performDeletionDiv" style="margin: auto; margin-top: 13px; font-size: 11px; width: 200px; text-align: center; '+displayTagCommand+'">-- perform speedy deletion</a> -- '+								' '+								'';		this.interface.applyAll;	}	this.deleteDo = function(callback) {		if (!callback) var callback = 0;		switch (callback) {			default:				csdHController.deleteSel 		= document.getElementById('deleteReason').selectedIndex; csdHController.deleteNotify 	= document.getElementById('notifyTagger').checked; csdHController.notifyNewbie		= document.getElementById('notifyNewbie').checked; if (document.getElementById('delete-criterion') == null) { csdHController.allowDelNotify = false; } else { csdHController.allowDelNotify = (csdHController.deleteReasons[csdHController.deleteSel][0] != document.getElementById('delete-criterion').innerHTML); } this.interface.win_content = ''+ ' Working... '+								' Please wait while CSDHelper performs the requested operations. This can take several seconds. '+								' '+								' '+								'';				this.interface.applyAll; if ((csdHController.deleteNotify == true) && (csdHController.allowDelNotify == true)) { document.getElementById('workingStatus').innerHTML += '- Searching for tagger... ';					if (notifyLimit > 15) notifyLimit = 15; csdHController.pageReq = new wa_mediawikiApi; csdHController.pageReq.onCompleteAction = function { csdHController.deleteDo('1'); }; csdHController.pageReq.getPage(mw.config.get('wgPageName'), notifyLimit + 1, 'content|user'); } else { csdHController.deleteDo('3'); } break; case '1': var tags = 0; csdHController.tagger = ''; var revisionCount = csdHController.pageReq.data['page']['revisions'].length; var limit = Math.min(notifyLimit, revisionCount); for (var i = 0; i < limit; i++) { var thisPage = csdHController.pageReq.data['page']['revisions'][i]['content']; // count tags var regTest = csdHController.deleteRegex; var k = 1; var count = 0; while (k != null) { k = regTest.exec(thisPage); if (k != null) count ++; }					regTest.lastIndex = 0; // check if we have fewer than last time (1 was added on that rev) if (count < tags) { csdHController.tagger = csdHController.pageReq.data['page']['revisions'][i - 1]['user']; break; } else { tags = count; }				}				if (csdHController.tagger == '') { document.getElementById('workingStatus').innerHTML += '- Could not determine tagger. Moving to deletion... '; csdHController.deleteDo('3'); break; } for (var i = 0; i < csdHController.notifyExempt.length; i ++) { if (csdHController.tagger == csdHController.notifyExempt[i]) { document.getElementById('workingStatus').innerHTML += '- Tagger ('+csdHController.tagger+') is on the tagger exempt list, and will not be notified. Moving to deletion... ';						csdHController.deleteDo('3'); return true; }				}				csdHController.deleteDo('2'); break; case '2': // notify tagger document.getElementById('workingStatus').innerHTML += '- Tagged by \''+csdHController.tagger+'\' - notifying user... ';				// edit summary csdHController.editSummary = 'Notifying about altered speedy deletion rationale (CSDH)'; // decide whether to use newbie message if (csdHController.notifyNewbie) { var useNewbie = 'yes'; } else { var useNewbie = 'no'; } // message var message = '== Altered speedy deletion rationale: '+mw.config.get('wgPageName').replace(/_/g, ' ')+' =='+"\n"+' '+''; csdHController.notifyReq = new wa_mediawikiApi; csdHController.notifyReq.onCompleteAction = function { csdHController.deleteDo('3'); }; csdHController.notifyReq.editPage('User_talk:'+csdHController.tagger, message, csdHController.editSummary, false, 'appendtext'); break; case '3': // perform the edit document.getElementById('workingStatus').innerHTML += '- Deleting page... ';				var deleteReason = ''+csdHController.deleteReasons[csdHController.deleteSel][0]+': ' + csdHController.deleteReasons[csdHController.deleteSel][1] + ' (CSDH)'; csdHController.deleteReq = new wa_mediawikiApi; csdHController.deleteReq.onCompleteAction = function(callback) { if ((callback == null) || (callback == false) || (mw.config.get('wgNamespaceNumber') != 0)) { // No talk page if (csdhDoRedirect) { window.location = redirectAfterDel; } else { window.location.reload(true); }						csdHController.showcsdHWindow; } else { // Talk page exists csdHController.talkpageId = callback; document.getElementById('workingStatus').innerHTML = ''+ ' Warning: this page now has an orphaned talk page. Do you wish to delete it under G8?

'+							' Delete</a> | Ignore</a> '+ '';					}				};				csdHController.deleteReq.performAction('delete', mw.config.get('wgPageName'), deleteReason); break; case '4': // delete the talk page - get the title var talkPage = 'Talk:' + mw.config.get('wgPageName'); csdHController.deleteReq = new wa_mediawikiApi; csdHController.deleteReq.onCompleteAction = function { window.location = redirectAfterDel; csdHController.showcsdHWindow; }; csdHController.deleteReq.performAction('delete', talkPage, 'G8: Talk page of deleted page. (CSDH)'); break; }	}	this.displayError = function { this.interface.win_content = ''+ ' An error occurred... '+								' '+								'';		this.interface.applyAll; }	this.attachLinks = function { this.csdHelperLink 						= new wa_element('li'); this.csdHelperLink.ele_obj.id			= 'ca-speedy'; this.csdHelperLink.addScriptEvent('click', function { csdHController.showcsdHWindow; }); if ( mw.config.get ( 'skin' ) == 'vector' ) { this.csdHelperLink.ele_obj.innerHTML	= ' Speedy</a> '; this.csdHelperLink.attach(document.getElementById('ca-talk'), 'after'); } else { this.csdHelperLink.ele_obj.innerHTML	= 'speedy</a>'; this.csdHelperLink.attach(document.getElementById('ca-move'), 'before'); }	}; }

// -- run program function launchCsdHelper { // lib proto wa_window.prototype = new wa_document; wa_element.prototype = new wa_document; // run launchCsdh; }

$.getScript("https://en.FAMEPedia.org/w/index.php?title=User:Ale_jrb/Scripts/waLib.js&type=text/javascript&action=raw", function {	$(document).ready(launchCsdHelper); });