MediaWiki:Gadget-autodel.js

/** * Replacement for the old MediaWiki:Gadget-autodel.js that is now on User:Mike.lifeguard/Gadget-autodel.js * Eases deletion of pages * Documentation at Help:Gadget-autodel.js * * @rev 1 (2012-07-02) * @author Rillke, 2012 */ // List the global variables for jsHint-Validation. Please make sure that it passes http://jshint.com/ // Scheme: globalVariable:allowOverwriting[, globalVariable:allowOverwriting][, globalVariable:allowOverwriting] /*global jQuery:false, mediaWiki:false*/ // Set jsHint-options. You should not set forin or undef to false if your script does not validate. /*jshint forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, strict:true, undef:true, curly:false, browser:true*/ ( function ( $, mw ) { "use strict"; var autoDel = null,	server = mw.config.get('wgServer'),	articlePath = mw.config.get('wgArticlePath');

if ( (-1 === $.inArray(mw.config.get('wgCanonicalSpecialPageName'), ['Contributions', 'Whatlinkshere', 'Log', 'Prefixindex', 'Newpages'])) &&	(!mw.config.get('wgArticleId') || -1 === $.inArray(mw.config.get('wgAction'), ['submit', 'view', 'edit', 'delete'])) ) return; mw.util.addCSS('.autodel-dellink { background-color:#CEEDB4; font-size:.8em; position:relative; top:-0.5em; }'); autoDel = { aDelInstall: function { var p = mw.util.addPortletLink('p-cactions', '#', 'Add DeleteLinks', 'ca-dellink', 'generate deletion links'); if (p) { p = $(p); } else { return; }		p.click(function(e) {			e.preventDefault;			autoDel.tasks = ['aDelQueryDefaultReason', 'aDelAddDelLinks'];			autoDel.nextTask;		}); if ('delete' === mw.config.get('wgAction') && mw.util.getParamValue('submitdelete')) { $('#mw-content-text').prepend($(' ').addClass('error').text( "Either you are using an old version of autoDel or you opened a link in a new tab. " + "Deletion via URL is evil and therefore not done. " + "If you are using the latest version of autoDel, simply click the delete link. " + "An in-page-dialog will be opened. You can submit deletion immediately pressing the enter-key. " + "While it makes your account vulnerable, you can skip this dialog adding " ), $(' ', { text: 'window.skipAutodelConfirm = true;' }),			$('', { text: " to your common.js", href: 'Special:MyPage/common.js' }),			$(' ').addClass('error').text( "If you decided to add it to your js, be careful where you are clicking and double-check the tool tips." ));		}		// Providing functionality for // Additional safeguard: only run on the delinker-command-page or those the user wants it		window.autodelPages = $.extend({'User:CommonsDelinker/commands': true}, window.autodelPages); if (!window.autodelPages[mw.config.get('wgPageName')]) return; var $ins = $('.instant-nuke').css('display', 'inline-block').attr('title', 'Invoke immediate deletion'); $ins.each(function(i, el) {			try {				var $el = $(el),					h = $el.find('a:first').attr('href'),					pg_ = mw.util.getParamValue('title', h),					pg = pg_.replace(/_/g, ' '),					r = mw.util.getParamValue('wpReason', h),					bt = $el.find('.selToBlock').text,					$b = $el.parents(bt),					// WikiUrlencode does too much, same for encodeURIComponent					$ol = $b.find('a[href$="' + encodeURI(pg_).replace(/\'/g, '%27').replace(/\"/g, '%22') + '"]');				$el.data('autoDel', { page: pg, $parent: $b, $oLink: $ol, reason: r });				if (!autoDel.aDelPages[pg]) autoDel.aDelPages[pg] = [];				autoDel.aDelPages[pg].push($el);				$(el).find('a').attr('title', 'Delete ' + pg);				$el.click(autoDel.__aDelConfirmDelete);			} catch (ex) {}		});	},	aDelQueryDefaultReason: function {		var c = mw.cookie.get('com-autodel-reason');		this.reason = c || 'per COM:SPEEDY';		this.prompt([{			message: 'default reason', prefill: this.reason, returnvalue: 'reason', cleanUp: true, noEmpty: true, byteLimit: 250, parseReason: true }], "Adding links: Set the default reason.");	},	aDelAddDelLinks: function {		if (this.delLinksAdded) return;		var tryDecode = function(title) {			try {				// MediaWiki also encodes "=" even if not required (not a query string)				if (title) title = decodeURIComponent(title);				return title;			} catch(ex2) {				try {					if (title) title = decodeURI(title);				} catch (ex) {}				return title;			}		};		var tryDecodeComponent = function(title) {			try {				if (title) title = decodeURIComponent(title);			} catch (ex) {}			return title;		};		var addLink = function(pg, $el) {			if (!pg) return;			if (0 === pg.indexOf(mw.config.get('wgFormattedNamespaces')[-1])) return;			pg = pg.replace(/_/g, ' ');			var $dLink = $('', { 'class': 'autodel-dellink', href: '#', text: 'Delete!', title: 'Delete ' + pg });			$el.wrap(' ').after($dLink);			$dLink.data('autoDel', { page: pg, $parent: $el.parent, $oLink: $el }); $dLink.click(autoDel.__aDelConfirmDelete); if (!autoDel.aDelPages[pg]) autoDel.aDelPages[pg] = []; autoDel.aDelPages[pg].push($dLink); return true; };		$('#mw-content-text').find('a').each(function(i, el) {			var $el = $(el),				h = $el.attr('href'),				pg, REArticle, m;			if ($el.hasClass('new')) return;

pg = mw.util.getParamValue('title', h); if (addLink(tryDecodeComponent(pg), $el)) return; REArticle = new RegExp('^' + mw.RegExp.escape(articlePath.replace('$1', '')) + '(.+?)(?:#.*)?$'); m = h.match(REArticle); if (m) if (addLink(tryDecode(m[1]), $el)) return; REArticle = new RegExp(mw.RegExp.escape(server + articlePath.replace('$1', '')) + '(.+?)(?:#.*)?$'); m = h.match(REArticle); if (m) if (addLink(tryDecode(m[1]), $el)) return; });		this.delLinksAdded = true;		// Finally save the reason into a cookie		mw.cookie.set('com-autodel-reason', this.reason, { expires: 14, // expires in 14 days path: '/' // domain-wide, entire wiki });	},	__aDelConfirmDelete: function(e) {		e.preventDefault;		e.stopPropagation;		var $dLink = $(this),			d = $dLink.data('autoDel'),			$toRemove = $dLink,			$toBlock = d.$parent, 			$toSetNew = d.$oLink;		// Add all links with the same target page		$.each(autoDel.aDelPages[d.page], function(i, el) { var $el = $(el), di = $el.data('autoDel'); if (!di) return; $toRemove = $toRemove.add($el); $toBlock = $toBlock.add(di.$parent); $toSetNew = $toSetNew.add(di.$oLink); });		var wasValidLink = !!$dLink.inView.length && (/[Dd]elete/.test($dLink.text) || /\/16px-Gr%C3%BCnerm%C3%BClleimer\.svg\.png$/.test($dLink.find('img').attr('src')) && $dLink.find('img').inView.length );		// The last param is the check whether the delete-link was probably faked		autoDel.secureCall('aDelConfirmDelete', d.page, $toRemove, $toBlock, $toSetNew, d.reason, wasValidLink);	},	aDelFillInfoNode: function(page, $node) {		var query, isFile = (0 === page.indexOf(mw.config.get('wgFormattedNamespaces')[6]));		if (isFile) {			query = {				action: 'query',				prop: 'imageinfo|info',				intoken: 'delete',				iiprop: 'user|timestamp|url',				iiurlwidth: 250,				iiurlheight: 250,				iilimit: 1,				titles: page			};		} else {			query = {				action: 'query',				prop: 'info|revisions',				rvprop: 'user|timestamp',				rvlimit: 1,				rvdir: 'newer',				intoken: 'delete',				titles: page };		}		this.queryAPI(query, function(r) {			var pgs = r.query.pages,				rv,				type = "page",				pg;			$.each(pgs, function(i, pgObj) { pg = pgObj; });

autoDel.deletetoken = pg.deletetoken; $node.append($(' ').append( $(' ').text("You are going to delete "), $('', { href: mw.util.getUrl(pg.title), text: pg.title }), $(' ').text(" (" + pg.length + " Bytes, PageID: " + pg.pageid + ", Changed: " + pg.touched + ").") ));			if ('undefined' !== typeof pg.missing) return $('.ui-dialog').find('.ui-button-green').button('option', 'disabled', true); if (isFile) { if (!pg.imageinfo) return; rv = pg.imageinfo[0]; type = "file"; $node.append($(' ', { src: rv.thumburl, height: rv.height, width: rv.width })); } else { if (!pg.revisions) return; rv = pg.revisions[0]; }			$node.append($(' ').text("This " + type + " was created by " + rv.user + " on " + rv.timestamp )); });	},	aDelConfirmDelete: function(page, $dLink, $toBlock, $toSetNew, reason, wasValidLink) {		var $infoNode = $(' ', { css: { 'min-height': '300px' } });		this.tasks = ['aDelExecDelete'];		this.pageToDelete = page;		this.$toRemove = $dLink;		this.$toBlock = $toBlock;		this.$toSetNew = $toSetNew;		// WARNING: SETTING THIS IN YOUR common.js WILL IMMEDIATELY DELETE ON CLICK		// Always watch the tooltip to prevent accidental wrong deletions		// You are responsible if you delete the world!		if (window.skipAutodelConfirm && wasValidLink) {			if (reason) this.reason = reason;			return this.nextTask;		}		this.secureCall('aDelFillInfoNode', page, $infoNode);		this.prompt([{ message: 'Delete reason (used in the deletion log)', prefill: reason || this.reason, returnvalue: 'reason', cleanUp: true, appendNode: $infoNode, noEmpty: true, byteLimit: 250, parseReason: true }], "WARNING: You are going to DELETE " + page);	},	aDelExecDelete: function {		var $toRemove = this.$toRemove,			$toBlock = this.$toBlock,			$toSetNew = this.$toSetNew,			pg = autoDel.pageToDelete;		$toBlock.block({ message: 'Deleting', css: { color: '#A0C828', fontWeight: 'bold', background:'none', border:'none', width: '8em' } });		if (autoDel.deletetoken) mw.user.tokens.set('deleteToken', autoDel.deletetoken);		mw.loader.using(['ext.gadget.libAPI'], function { mw.libs.commons.api.deletePage({				cb: function {					autoDel.secureCall('aDelExecDeleteCB', $toBlock, $toSetNew, $toRemove, pg);				},				// r-result, query, text				errCb: function(t, r, q) {					if (r && r.error && r.error.code === 'missingtitle') {						$toBlock.block({ message: 'Not found!', css: { color: '#C8A028', fontWeight: 'bold', background:'none', border:'none', width: '10em' } });						$toBlock.unblock( { fadeOut: 5000 } );					} else {						$toBlock.unblock;						autoDel.fail(t);					}				},				title: pg,				reason: autoDel.reason			}); //console.log(pg); autoDel.aDelExecDeleteCB });	},	aDelExecDeleteCB: function($toBlock, $toSetNew, $toRemove, pg) {		$toBlock.unblock;		$toSetNew.addClass('new');		if ($toSetNew.hasClass('image')) $toSetNew.find('img').fadeTo(500, 0.5);		$toRemove.remove;		delete this.aDelPages[pg];	},	aDelPages: {} };

mw.loader.using([	'ext.gadget.jquery.blockUI', 	'ext.gadget.AjaxQuickDelete', 	'ext.gadget.jquery.in-view', 	'mediawiki.util', 	'mediawiki.user', 	'mediawiki.cookie',	'user' ], function {	// Merge into AjaxQuickDelete	autoDel = $.extend(window.AjaxQuickDelete, autoDel);

// Fire off the rest as soon as the dom is ready $( document ).ready( function { autoDel.secureCall('aDelInstall'); } ); });

}( jQuery, mediaWiki ));