MediaWiki:Gadget-VisualFileChange.js/exec.js

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
// Main script is at [[MediaWiki:VisualFileChange.js]]
// These are the delayed loaded edit components in order to speed up loading of the first UI
// <nowiki>

// Invoke jsHint-validation

/*global jQuery:false, mediaWiki:false, alert:false, console:false */
/*jshint curly:false, maxerr:200, smarttabs:true, loopfunc:true*/
(function ($, mw) {
'use strict';

// Return if Main Script is not loaded
if (!window.VisualFileChange) return;
// Return if this script is already loaded
if (window.VisualFileChange.editComponents) return;

var vfc = window.VisualFileChange,
	$doc = $(document),
	$win = $(window);

$.extend(window.VisualFileChange,
{
	editComponents: true,
	/**  
	**  Reads user's input to the thumbnail-dialog; Called when user clicked next
	**/
	mdExecute: function () {
		vfc.mdTaskToPerform = vfc.$ctrs.ajaxMdType.val();
		var cmdConfig = vfc.mdCommandsExec[vfc.mdTaskToPerform];
		
		vfc.startDate = new Date();
		vfc.api.eFirst = vfc.mdSettings.firstTest-1;
		vfc.api.total = 0;
		vfc.api.done = 0;
		
		if (0 !== vfc.mdNumberOfExecs || 0 !== vfc.mdListUploadsPending) return; // refuse futher exec request
		if (0 !== vfc.mdPendingBatchQueries) { // call me later
			setTimeout(function () { 
				vfc.mdExecute();
			}, 1000);
			return;
		}
		vfc.mdNumberOfExecs++;

		$doc.triggerHandler('vFC', ['processing user\'s input', vfc]);
		vfc.pb.addTask('inputcheck');
		vfc.pb.setTaskState('inputcheck', 'md-doing');
		vfc.pb.setHelp(vfc.i18n.mdPleaseWait);
		vfc.pb.setHelp2('');
		vfc.pb.setHelp3('');

		var filesToTag = 0;
 
		$('input[name="mdCheckDelete"]').each(function(index) {
			if (this.checked) {
				vfc.iUploads[this.value].iId = -2; // Indicate the action will be performed on this file
				filesToTag++;
				var $gb = vfc.gbs[this.value];
				if ($gb) {
					$gb.$thumb.addClass('progress-doing');
				}
			}
		});
 
		if (0 === filesToTag) {
			if ( ('other' !== vfc.mdTaskToPerform ) && ('otrs' !== vfc.mdTaskToPerform) && (0 < vfc.ioUploads) ) {
				vfc.addTask('mdRvGenOGallery');
			}
			vfc.addTask('mdExecuteReady');
			vfc.dlg.dialog('close');
			vfc.nextTask();
			return;
		} else {
			vfc.mdInsertedTag = true;
		}
 
		vfc.mdDeleteHeading = vfc.cleanReason(vfc.$ctrs.deleteHeading.val());
 
		if (vfc.$ctrs.deleteReason.val()) {
			vfc.reason = cmdConfig.cleanReason ? vfc.cleanReason(vfc.$ctrs.deleteReason.val()) : vfc.$ctrs.deleteReason.val();
		} else {
			vfc.reason = '';
		}
		vfc.mdReplacePermission = vfc.$ctrs.replacePermission[0].checked;
		vfc.mdTalkNote = vfc.$ctrs.talkNote.val();
		vfc.mdAddEditSummary = vfc.$ctrs.editSummary.val() || '';

		// Processing for custom replace
		$.each(vfc.mdReplacementMatrix, function(i, rObj) {
			rObj.match = rObj.match.val();
			rObj.replace = rObj.replace.val();
			rObj.regex = rObj.regex[0].checked;
			rObj.vars = rObj.vars[0].checked;
			if (rObj.regex && rObj.match) {
				rObj.match = vfc.mdRegExpFromString(rObj.match);
				if (!rObj.match) vfc.pb.setError('INVALIDINPUT: -' + rObj.match + '- is not a valid RegExp!');
			}
			if ( /russavia/i.test( rObj.match || '' ) && $.inArray( 'autoconfirmed', mw.config.get( 'wgUserGroups' ) ) === -1 ) {
				vfc.pb.setError( 'VisualFileChange refuses to execute this request. Too much fuss around this topic currently. '
					+ 'Of course you can host your own copy of VFC. In this case, please amend the edit summary. Thanks!' );
				throw new Error( 'Induced guru meditation.' );
			}
		});
		
		// Try to save the current input state into the automatically generated client profile
		try {
			vfc.mdSaveProfileToClient('last executed (auto-saved)');
		} catch (e) {
			vfc.pb.setHelp2(vfc.i18n.mdProfileCantSave);
		}
		vfc.addTask('mdExecuteContinue');
		vfc.nextTask();
	},
	
	formatDate: function (fmt, date) {
		return mw.libs.commons.formatDate(fmt, date, this.startDate);
	},

	/**  
	**  Preparing to perform our edits
	**/
	mdExecuteContinue: function () {
		$doc.triggerHandler('vFC', ['generating page messages and summaries', vfc]);
 
		// set up some page names we'll need later
		var qp = vfc.queryParams,
			si = vfc.startInput,
			mdRequestPage;
			
		if (si.modeCat) mdRequestPage = 'Files in ';
		if (si.modeUser) mdRequestPage = 'Files uploaded by ';
		if (si.modePage) mdRequestPage = 'Files on ';
		if (si.modeSearch) mdRequestPage = 'Files found with ';
		
		mdRequestPage += qp.target;
		vfc.requestPage =  vfc.mdRequestPagePrefix + mdRequestPage;
		vfc.dailyLogPage = vfc.mdRequestPagePrefix + vfc.formatDate("YYYY/MM/DD");

		var uploadCt = 0,
		
			action = vfc.mdTaskToPerform,
			opt = vfc.mdOpt[action],
			cmdConfig = vfc.mdCommandsExec[action],
			cmdConfigPostExec = vfc.mdCommandsPostExec[action],
			fTag = vfc.mdFileTags[action],
			uTag = vfc.mdUserTags[action];
			
			
		vfc.tag = fTag.tag && fTag.tag.replace('%REASON%', vfc.reason).replace('%SUBPAGE%', mdRequestPage).replace('%D%', vfc.formatDate('year=YYYY|month=MON|day=DAY'));
		
		vfc.file_summary = vfc.mdAddEditSummary +
			(vfc.mdAddEditSummary && fTag.summary && ' - ') + 
			(fTag.summary && fTag.summary.replace('%pattern%', vfc.reason).replace('%replacementcount%', vfc.mdReplacementMatrix.length-1).replace('%REASON%', vfc.reason));
		var r = vfc.file_summary.match(/\%(.{1,9})\%/);
		if (r && r[1]) vfc.file_summary = vfc.file_summary.replace('%' + r[1] + '%', vfc.mdOptText[r[1]]);
		
		vfc.uploaders = {};
		
		// Reverse-mapping: files-uploader --- > uploader-files
		$.each(vfc.iUploads, function(upload, uItem) {
			if ( -2 === uItem.iId )  {
				if (vfc.startInput.modeUser) {
					if (!vfc.uploaders[qp.target]) {
						vfc.uploaders[qp.target] = { uploads: {} };
					}
					vfc.uploaders[qp.target].uploads[upload] = true;
				} else {
					// Remember: u is just an index of an array
					$.each(uItem.uploader, function(u, ul) {
						ul = mw.libs.commons.getUploadBotUser(ul, uItem.content, uItem.comments[u]);
						if (!vfc.uploaders[ul]) {
							vfc.uploaders[ul] = { uploads: {} };
						}
						vfc.uploaders[ul].uploads[upload] = true;
					});
				}
			}
		});
		
		$.each(vfc.uploaders, function(uploader, uploaderItem) {
			uploadCt = 0;
			
			uploaderItem.tag = (uTag.tag && uTag.tag.replace('%REQUESTPAGE%', mdRequestPage)) || '';
			uploaderItem.summary = (uTag.summary && uTag.summary.replace('%FULLREQUESTPAGE%', vfc.requestPage)) || '';
			if (/\%FILE\%/.test(uploaderItem.tag)) {
				$.each(uploaderItem.uploads, function(userUpload, unused) {
					if ( 0 === uploadCt ) {
						uploaderItem.tag = uploaderItem.tag.replace('%FILE%', userUpload);
						uploaderItem.summary = uploaderItem.summary.replace('%FILE%', userUpload);
					} else if ( 1 === uploadCt ) {
						uploaderItem.tag += "\nAnd also: \n* [[:" + userUpload + "]] "; 
					} else {
						uploaderItem.tag += '\n* [[:' + userUpload + ']] '; 
					}
					uploadCt++;
				});
			}
			if (uTag.summary) {
				if (vfc.mdTalkNote) uploaderItem.tag += '\n\n' + vfc.mdTalkNote;
			}
		});
		
		// Prepare for createRequestSubpage
		vfc.requestPageContents = vfc.reason;
		$.each(vfc.iUploads, function(upload, upli) {
			if ( vfc.iUploads.hasOwnProperty(upload) && (-2 === upli.iId) )  { 
				vfc.requestPageContents += '\n* [[:' + upload + ']]'; 
			}
		});
				
		// Task sheduling
		$.each(cmdConfig.tasks, function(id, task) {
			vfc.addTask(task);
			if (task in vfc.i18n.task) vfc.pb.addTask(task);
		});
		$.each(cmdConfigPostExec.tasks, function(id, task) {
			vfc.addTask(task);
			if (task in vfc.i18n.task) vfc.pb.addTask(task);
		});
		vfc.addTask('mdExecuteReady');
		vfc.nextTask();
	},
	
	mdPrependText: function () {
		this.pb.setCurrentTaskDone();
		this.pb.setTaskState('mdPrependText', 'md-doing');
		this.tag = this.reason;
		this.nextTask();
	},
	
	mdAppendText: function () {
		this.pb.setCurrentTaskDone();
		this.pb.setTaskState('mdAppendText', 'md-doing');
		this.tag = this.reason;
		this.nextTask();
	},
 
	mdPrependTemplate: function () {
		this.pb.setCurrentTaskDone();
		this.pb.setTaskState('mdPrependTemplate', 'md-doing');
		this.secureCall('mdAddTemplate', 'prependtext');
	},
	
	mdAppendTemplate: function () {
		this.pb.setCurrentTaskDone();
		this.pb.setTaskState('mdAppendTemplate', 'md-doing');
		this.secureCall('mdAddTemplate', 'appendtext');
	},
	
	mdAddTemplate: function (edittype) {
		$doc.triggerHandler('vFC', ['adding templates to filepages', this]);
		this.mdUploadCt = 0;
 
		for (var upload in this.iUploads) {
			if (this.iUploads.hasOwnProperty(upload) && (-2 === this.iUploads[upload].iId)) {
				var page = {
					title: upload,
					text: this.tag,
					editType: edittype,
					watchlist: this.mdSettings.watchlistFiles
				};
				
				this.mdUploadCt++;
				this.mdEdit(page, this.file_summary, 'mdTemplateAdded', 'mdTemplateAdded');
			}
		}
		if (0 === this.mdUploadCt) this.nextTask();
	},
	
	mdRefreshCache: function () {
		$doc.triggerHandler('vFC', ['refreshing cache of file-wikitext', vfc]);
		vfc.pb.setCurrentTaskDone();
		vfc.pb.setTaskState('mdRefreshCache', 'md-doing');
		
		// Test how old the data are
		if ((new Date().getTime() - vfc.mdDateOldestDataFetched.getTime() < 60000) && vfc.startInput.loadWikitext) {
			vfc.nextTask();
			return;
		}
		vfc.refreshRequests = 0;
		var i = 0, 
			titles = [],
			query = {
				action: 'query',
				prop: 'revisions',
				rvprop: 'content'
			};
		var makeRequest = function() {
			i = -1;
			query.titles = titles.join('|');
			titles = [];
			vfc.refreshRequests++;
			vfc.queryAPI(query, 'mdRefreshCacheCB');
		};
		$.each(vfc.iUploads, function(upload, upli) {
			if (!vfc.iUploads.hasOwnProperty(upload) || -2 !== upli.iId) return;
			titles.push(upload);
			if (10 === i) makeRequest();
			i++;
		});
		if (titles.length) makeRequest();
		if (0 === vfc.refreshRequests) vfc.nextTask();
	},
	
	mdRefreshCacheCB: function (result) {
		$doc.triggerHandler('vFC', ['got fresh page contents', vfc, result]);
		
		vfc.refreshRequests--;
		$.each(result.query.pages, function(id, pg) {
			vfc.iUploads[pg.title].content = pg.revisions[0]['*'];
		});
		if (0 === vfc.refreshRequests) vfc.nextTask();
	},

	mdInsertPermission: function () {
		$doc.triggerHandler('vFC', ['inserting permission OR custom replace', vfc]);
		vfc.pb.setCurrentTaskDone();
		vfc.pb.setTaskState('mdInsertPermission', 'md-doing');
		vfc.mdUploadCt = 0;

		var replaceSecurityLevel = vfc.$selPreserve.val(),
			replaceContainer = mw.libs.wikiDOM.nowikiEscaper();

			if ('c_replace' === vfc.mdTaskToPerform) replaceContainer.alsoPreserve(vfc.$alsoPreserve.val());

		$.each(vfc.iUploads, function(upload, upli) {
			if (!vfc.iUploads.hasOwnProperty(upload) || -2 !== upli.iId) return;
 
			var page = {};
			
			replaceContainer.setText(upli.content);

			page.title = upload;
			page.watchlist = vfc.mdSettings.watchlistOTRS;
			page.basetimestamp = upli.basetimestamp;
			page.editType = 'text';
 
			if ('otrs' === vfc.mdTaskToPerform) { // drop out other permission templates
				var iCt = 0;
				$.each(vfc.mdTagRemoval, function(id, tri) {
					iCt++;
					if (1 === iCt) return; // Skip first pattern
					replaceContainer.secureReplace(tri[0], '');
				});
			}
			if ('c_replace' !== vfc.mdTaskToPerform) {
				replaceContainer.setText( vfc.secureCall( 'mdInsertOTRS', replaceContainer.getText(), vfc.reason ) );
			} else {
				switch (replaceSecurityLevel) {
				 case 'secure':
					$.each(vfc.mdReplacementMatrix, function(i, rObj) {
						if ('' === rObj.match) return;
						replaceContainer.secureReplace(rObj.match, (rObj.vars ? vfc.mdVarReplacements(rObj.replace, upload, upli) : rObj.replace));
					});
					break;
				 case 'placeholder':
					$.each(vfc.mdReplacementMatrix, function(i, rObj) {
						if ('' === rObj.match) return;
						replaceContainer.replace(rObj.match, (rObj.vars ? vfc.mdVarReplacements(rObj.replace, upload, upli) : rObj.replace));
					});
					break;
				 case 'none':
					$.each(vfc.mdReplacementMatrix, function(i, rObj) {
						if ('' === rObj.match) return;
						replaceContainer.ordinaryReplace(rObj.match, (rObj.vars ? vfc.mdVarReplacements(rObj.replace, upload, upli) : rObj.replace));
					});
					break;
				}
				page.watchlist = vfc.mdSettings.watchlistReplace;
			}
 
			if (upli.content === replaceContainer.getText()) {
				var $gb = vfc.gbs[upload];
				if ($gb) $gb.$thumb.removeClass('progress-doing').addClass('progress-nochange');
			} else {
				page.text = replaceContainer.doCleanUp();
				vfc.mdUploadCt++;
				vfc.mdEdit(page, vfc.file_summary, 'mdTemplateAdded', 'mdTemplateAdded');
			}
		});
		
		if (0 === vfc.mdUploadCt) vfc.nextTask();
	},
 
	mdInsertOTRS: function (sitetext, insert) {
		if (this.mdPermissionPattern.test(sitetext)) {
			if (this.mdReplacePermission) {
				var texparts = sitetext.match(this.mdPermissionPattern);
				// in rare cases [3] is undefined in other cases [3] contains the next param of {{information}}
				if (texparts[3] && this.mdNextParamPattern.test(texparts[3])) {
					sitetext = texparts[1] + texparts[2] + insert + texparts[3] + texparts[4];
				} else {
					sitetext = texparts[1] + texparts[2] + insert + texparts[4];
				}
			} else {
				sitetext = sitetext.replace(this.mdSimplePermissionPattern, '$1' + insert);
			}
		} else { // if no information template is available, prepend
			sitetext = insert + '\n' + sitetext;
		}
		return sitetext;
	},
 
	mdCreateRequestSubpage: function () {
		$doc.triggerHandler('vFC', ['creating request subpage', this]);
		this.pb.setCurrentTaskDone();
		this.pb.setTaskState('mdCreateRequestSubpage', 'md-doing');
		
		var page = {
			title: this.requestPage,
			text: '\n=== ' + this.mdDeleteHeading + ' ===\n\n' + this.requestPageContents + '\n~~' + '~~\n',
			watchlist: 'watch',
			editType: 'appendtext',
			create: true
		};
		
		$doc.triggerHandler('vFC', ['request subpage', this, page]);
		this.mdEdit(page, 'Starting mass deletion request', 'mdCreateRequestSubpageCB', 'mdCreateRequestSubpageCB');
	},
	
	mdCreateRequestSubpageCB: function (result, query, err) {
		if (err) {
			this.pb.setCurrentTaskState('md-attention');
			this.pb.setError(err);
		} else {
			this.pb.setCurrentTaskDone();
		}
		this.nextTask();
	},
	
	
	
	/**
	** Transclude the nomination page onto today's DR log page, creating it if necessary.
	** The log page will never be watchlisted (unless the user is already watching it).
	**/
	mdListRequestSubpage: function () {
		$doc.triggerHandler('vFC', ['creating request subpage', this]);
		this.pb.setCurrentTaskDone();
		this.pb.setTaskState('mdListRequestSubpage', 'md-doing');
		var page = {
			title: this.dailyLogPage,
			text: '\n{{' + this.requestPage + '}}\n',
			watchlist: 'nochange',
			editType: 'appendtext'
		};

		this.mdEdit(page, "Listing [[" + this.requestPage + "]]", 'mdListRequestSubpageCB', 'mdListRequestSubpageCB');
	},
	
	mdListRequestSubpageCB: function (result, query, err) {
		if (err) {
			this.pb.setCurrentTaskState('md-attention');
			this.pb.setError(err);
		} else {
			this.pb.setCurrentTaskDone();
		}
		this.nextTask();
	},
	
	isMobile: function (cats) {
		var isMobile = false;

		for (var i = 0, len = cats.length; i < len; i++) {
			isMobile = isMobile || /^Category:Uploaded with Mobile/.test(cats[i].title);
		}
		return isMobile;
	},

	listMobileUpload: function () {
		var isMobile = false;
		vfc.pb.setCurrentTaskDone();
		vfc.pb.setTaskState('listMobileUpload', 'md-doing');
		
		$.each(vfc.iUploads, function(title, upli) {
			if (!vfc.iUploads.hasOwnProperty(title) || -2 !== upli.iId) return;
			isMobile = isMobile || vfc.isMobile(upli.categories);
		});
		if (!isMobile) {
			vfc.pb.setCurrentTaskDone();
			return vfc.nextTask();
		}
		
		var page = {
			title: 'Commons:Deletion requests/mobile tracking',
			text: '\n{{' + vfc.requestPage + '}}\n',
			watchlist: 'nochange',
			editType: 'appendtext'
		};

		vfc.mdEdit(page, "Listing [[" + vfc.requestPage + "]]", 'listMobileUploadCB', 'listMobileUploadCB');
	},
	
	listMobileUploadCB: function (result, query, err) {
		if (err) {
			this.pb.setCurrentTaskState('md-attention');
			this.pb.setError(err);
		} else {
			this.pb.setCurrentTaskDone();
		}
		this.nextTask();
	},

	listMobileUploadSpeedy: function () {
		var mobileUploads = [];
		vfc.pb.setCurrentTaskDone();
		vfc.pb.setTaskState('listMobileUploadSpeedy', 'md-doing');
		
		$.each(vfc.iUploads, function(title, upli) {
			if (!vfc.iUploads.hasOwnProperty(title) || -2 !== upli.iId) return;
			if (vfc.isMobile(upli.categories)) mobileUploads.push(title);
		});
		if (!mobileUploads.length) {
			vfc.pb.setCurrentTaskDone();
			return vfc.nextTask();
		}
	
		var page = {
			title: 'Commons:Mobile app/deletion request tracking',
			text: '\n# [[:' + mobileUploads.join(']]\n# [[:') + ']]',
			watchlist: 'nochange',
			editType: 'appendtext'
		};

		vfc.mdEdit(page, "Listing uploads", 'listMobileUploadCB', 'listMobileUploadCB');
	},
	
	mdTemplateAdded: function (result, query, err) {
		vfc.mdUploadCt--;

		var pgTitle = (result.requestid || query.title),
			$gb = vfc.gbs[pgTitle];

		if ($gb) {
			$gb.$thumb.removeClass('progress-doing').addClass(err ? 'progress-failed' : 'progress-done');
			if (err) $gb.find('.gallerytext').prepend($('<span>', { 'class': 'error' }).text(err), '<br/>');
			if (0 === $gb.inView().length) {
				if (vfc.gbScrollTimeout) clearTimeout(vfc.gbScrollTimeout);
				vfc.gbScrollTimeout = setTimeout(function() {
					// Scroll to the recently edited 
					if(vfc.dlg) {
						vfc.dlg.clearQueue().animate({ scrollTop: $gb.position().top }, 800);
					}
				}, 150);
			}
		}
		if (result.error) {
			vfc.pb.setCurrentTaskState('md-attention');
		}
		if (0 === vfc.mdUploadCt) vfc.nextTask();
	},
	
	mdNotifyUploaders: function () {
		$doc.triggerHandler('vFC', ['notifying uploaders', vfc, vfc.uploaders]);
		vfc.pb.setCurrentTaskDone();
		vfc.pb.setTaskState('mdNotifyUploaders', 'md-doing');
		vfc.api.total = 0;
		vfc.api.done = 0;
		
		vfc.uploadersToNotify = 0;
		$.each(vfc.uploaders, function(user, upli) {
			if (mw.libs.commons.isSmallChangesBot(user)) return;
			var page = {};
			page.title = vfc.mdUserTalkPrefix + user;
			page.text = "\n" + upli.tag + " ~~" + "~~\n";
			page.editType = 'appendtext';
			page.redirect = true;
			page.create = true;
			page.watchlist = vfc.mdSettings.watchlistUserTalk;
			page.minor = false;
			vfc.mdEdit(page, upli.summary, 'mdUploaderNotified');

			vfc.uploadersToNotify++;
		});
		if (vfc.uploadersToNotify === 0) vfc.nextTask();
	},

	mdUploaderNotified: function (result, query, err) {
		this.uploadersToNotify--;
		if (this.uploadersToNotify === 0) this.nextTask();
	},
	
	/**
	** Submit an edited page.
	**/
	mdEdit: function (page, summary, callback, errCallBack) {
		var edit = {
			action: 'edit',
			summary: summary,
			watchlist: (page.watchlist || 'preferences'),
			title: page.title,
			requestid: page.title,
			editType: page.editType,
			text: page.text,
			tags: vfc.mdChangeTag
		};
		if (!page.create) edit.nocreate = true;
		if (page.redirect) edit.redirect = true;
		if (page.basetimestamp) edit.basetimestamp = page.basetimestamp;
		if ('minor' in page) edit.minor = page.minor;
		// Token last - will be set by libAPI
		
		// submit edit and showProgress
		vfc.editAPI(edit, callback, errCallBack, true);

	},
	
	/**
	** Execute the delete-task.
	**/
	mdDelete: function() {
		vfc.pb.setCurrentTaskDone();
		vfc.pb.setTaskState('mdDelete', 'md-doing');
		
		$doc.triggerHandler('vFC', ['deleting files', vfc]);
		vfc.mdUploadCt = 0;
 
		for (var upload in vfc.iUploads) {
			if (vfc.iUploads.hasOwnProperty(upload) && (-2 === vfc.iUploads[upload].iId)) {
				vfc.secureCall('mdDeletePage', upload, vfc.file_summary);
			}
		}
		if (0 === vfc.mdUploadCt) vfc.nextTask();
	},
	mdDeletePage: function(page, summary) {
		vfc.mdUploadCt++;
		vfc.api.total++;
		
		var _always = function() {
			vfc.api.done++;
			vfc.pb.showProgress(vfc.api.total, vfc.api.done, 'deletions');
		};
		var _deleted = function() {
			vfc.mdTemplateAdded({ requestid: page }, '');
			_always();
		};
		var _problem = function(text) {
			vfc.mdTemplateAdded({ requestid: page }, '', text);
			_always();
		};
		var _err = function(text) {
			vfc.mdTemplateAdded({ requestid: page }, '', text);
			_always();
		};
		// Delete as many pages the same time as specified (max. 5)
		mw.libs.commons.api.config.maxSimultaneousReq = Math.min(vfc.mdSettings.maxSimultaneousReq, 5);
		mw.libs.commons.api.deletePage({
			cb: function() {
				_deleted();
			},
			// r-result, query, text
			errCb: function(t, r, q) {
				if (r && r.error && r.error.code === 'missingtitle') {
					_problem('File not found');
				} else {
					_err(t);
					vfc.api.wasError = true;
				}
			},
			title: page,
			reason: summary,
			tags: vfc.mdChangeTag
		});
	}
});

mw.loader.using([
	'ext.gadget.libWikiDOM'
	], function() {
	$doc.triggerHandler('scriptLoaded', ['VisualFileChange', 'editComponents']);
});

}(jQuery, mediaWiki));
// </nowiki>