Jump to content
Wikimedia Commons

MediaWiki:Gadget-AjaxQuickDelete.js

From Wikimedia Commons, the free media repository
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.
This user script seems to have a documentation page at MediaWiki:Gadget-AjaxQuickDelete and an accompanying .css page at MediaWiki:Gadget-AjaxQuickDelete.css.
 /**
  * AjaxQuickDelete from <https://commons.wikimedia.org/wiki/MediaWiki:Gadget-AjaxQuickDelete.js>
  *
  * Changelog:
  * - 2010: Created in 2010 by [[User:Ilmari Karonen]] as Ajax-based replacement for [[MediaWiki:Quick-delete-code.js]].
  * - Rewritten by [[User:DieBuche]].
  * - Botdetection and encoding fixer by [[User:Lupo]].
  * - 2011-2012: Validation and further development [[User:Rillke]], 2011-2012.
  * - 2018: dropped IE8 support.
  *
  * TODO:
  * - Fix problems with moves of videos.
  * - Support move of timed text for videos.
  *
  * This pages has automated validation on save. Interested? See [[:commons:Commons:User scripts/reports]].
  */
 // <nowiki>

 /* eslint indent:[error,tab,{outerIIFEBody:0}] */
 /* eslint-disable one-var, vars-on-top, camelcase, no-underscore-dangle, valid-jsdoc */
 /* global $:false, mw:false, importScript:false */

 (function(){
 'use strict';

 // Guard against multiple inclusions
 if(window.AjaxQuickDelete){
 return;
 }

 varAQD,
 conf=mw.config.get([
 'wgArticleId',
 'wgCanonicalNamespace',
 'wgCanonicalSpecialPageName',
 'wgCategories',
 'wgFormattedNamespaces',
 'wgNamespaceNumber',
 'wgPageName',
 'wgRestrictionEdit',
 'wgUserGroups',
 'wgUserLanguage',
 'wgUserName',
 'wgIsRedirect'
 ]),
 nsNr=conf.wgNamespaceNumber,
 pageName=conf.wgPageName;

 // A bunch of helper functions
 function_firstItem(o){
 for(variino){
 if(Object.prototype.hasOwnProperty.call(o,i)){
 returno[i];
 }
 }
 }

 $.ucFirst=function(s){
 returns[0].toUpperCase()+s.slice(1);
 };

 // Create the AjaxQuickDelete-singleton (object literal)
 AQD=window.AjaxQuickDelete={
 // When maintaining this script always bump this number!
 version:'1.1.3',
 /**
 	* Runs before document ready and before translation is available
 	* (important event-binders should be attached as fast as possible)
 	*/
 preinstall:function(){
 // Promote our gadget when user opened old move page
 if(conf.wgCanonicalSpecialPageName==='Movepage'&&Number($('select[name="wpNewTitleNs"]').val())===6){
 $('#mw-movepage-table').before(
 '<div class="mw-message-box mw-message-box-warning">Consider using <i>Move & Replace</i> from the menu on file pages (open with a single click) when moving files to care for global usage and redirects.</div>'
 );
 }

 this.doNothing=(!conf.wgArticleId||nsNr<0||/^Commons:Deletion/.test(pageName)||/^Commons:Categories/.test(pageName));

 if(this.doNothing){
 return;
 }

 // Check user group
 if(conf.wgUserGroups.indexOf('sysop')!==-1){
 this.userRights='sysop';
 }elseif(conf.wgUserGroups.indexOf('filemover')!==-1){
 this.userRights='filemover';
 }else{
 this.userRights=['autopatrolled','patroller','image-reviewer'].filter(function(g){
 returnconf.wgUserGroups.indexOf(g)!==-1;
 })[0];
 }

 if(['filemover','sysop'].indexOf(this.userRights)!==-1&&nsNr===6){
 // Change "Move" to "Move & Replace"
 var$moveLink=$('#ca-move'),
 $moveLanchor=$moveLink.find('a');
 this.$moveLink=$moveLink=$moveLanchor.length?$moveLanchor:$moveLink;

 $moveLink.text($moveLink.text()+' & Replace')
 .attr('title','Click in order to '+$moveLink.attr('title')+' and replace usage. Default form though new tab.')
 .on('click',function(e){
 e.preventDefault();
 AQD.moveFile();
 });
 }
 },
 /**
 	* Set up the AjaxQuickDelete object and add the toolbox link. Called via document.ready during page loading.
 	*/
 install:function(){
 // Disallow performing operations on empty or special pages
 if(this.doNothing){
 return;
 }

 // Check edit restrictions and do not install anything if protected
 if(conf.wgRestrictionEdit&&conf.wgRestrictionEdit.length&&
 conf.wgUserGroups.indexOf(conf.wgRestrictionEdit[0])===-1){
 return;
 }

 // Trigger a jQuery event for other scripts that like to know
 // when this script has loaded all translations and is ready to install
 $(document).triggerHandler('scriptLoaded',['AjaxQuickDelete']);

 varlink;
 // Set up toolbox link
 if(nsNr===14){
 // In categories the discuss-category link
 link=mw.util.addPortletLink('p-tb','#',this.i18n.toolboxLinkDiscuss,'t-ajaxquickdiscusscat');
 if(link){
 link.addEventListener('click',function(e){
 e.preventDefault();
 mw.loader.using('jquery.ui').then(function(){
 AQD.discussCategory();
 });
 });
 }
 }else{
 // On other pages, the nominate-for-deletion link
 link=mw.util.addPortletLink('p-tb','#',this.i18n.toolboxLinkDelete,'t-ajaxquickdelete');
 if(link){
 link.addEventListener('click',function(e){
 e.preventDefault();
 AQD.nominateForDeletion();
 });
 }
 }

 // Install AjaxMoveButton for filemovers and administrators
 if(this.$moveLink){
 // Change Move & Replace link to fully localized text
 this.$moveLink.html($('<span>').text(this.i18n.dropdownMove));
 // Add quicklinks to template
 $('#AjaxRenameLink').append('<a href="javascript:AjaxQuickDelete.moveFile();">'+this.i18n.moveAndReplace+'</a>')
 .append('<a href="javascript:AjaxQuickDelete.loadAndDeclineRequest(\'move\');" class="ajaxDeleteDeclineMove"><sup> '+this.i18n.anyDecline+'</sup></a>');
 // Install x-To-DR. See [[Template:X-To-DR]]
 $('#mw-imagepage-content .convert-to-dr')
 .find('.ctdr-btn-convert').on('click',this._convertToDR).show().end()
 // Currently filemover rights required
 .find('.ctdr-btn-remove').on('click',this._removeAnyTag).show();
 }elseif(this.userRights){
 $('#mw-imagepage-content .convert-to-dr .ctdr-btn-convert').on('click',this._convertToDR).show();
 }

 // Install "Process Duplicates"-Link (either in template
 // or if no template was detected and MediaWiki found dupes, behind the link in the dupe-section)
 if(this.userRights==='sysop'&&nsNr===6){
 vardupeSection=$('#AjaxDupeProcess');
 if(dupeSection.length){
 dupeSection.append($('<a>',{
 href:'#',
 text:this.i18n.processDupes,
 style:'font-weight:bold',
 click:function(e){
 e.preventDefault();
 AQD.processDupes();
 }
 })).show();
 }else{
 dupeSection=$('#mw-imagepage-section-duplicates .mw-imagepage-duplicates');
 if(dupeSection.length){
 dupeSection.find('li:first')
 .append($('<span>',{
 style:'display:none',
 id:'AjaxDupeDestination',
 text:dupeSection.find('a').attr('title')
 }))
 .append(' ',$('<sup>').append($('<a>',{
 href:'#',
 text:'['+this.i18n.processDupes+']',
 style:'background:#CEB',
 click:function(e){
 e.preventDefault();
 AQD.processDupes();
 }
 })));
 }
 }
 }
 // Extra buttons
 // Wait until the user's js was loaded and executed
 mw.loader.using('user',function(){
 if(mw.user.options.get('gadget-QuickDelete')){
 mw.loader.using('ext.gadget.QuickDelete').always(function(){
 AQD.doInsertTagButtons();
 });
 }
 });
 },

 /**
 	* Ensure that all variables are in a good state
 	* You must call this method before doing anything!
 	* TODO: Never override pageName, always clean task queue
 	*/
 initialize:function(){
 pageName=conf.wgPageName;
 this.tasks=[];
 this.destination=undefined;
 this.details=undefined;
 this.declineReason=undefined;
 this.notifyUser=true;
 this.watchlist='preferences';
 },

 /**
 	* If a file exists, exchange the messages (very hackish)
 	* so the user is prompted to choose another destination
 	* TODO: Develop an improved solution
 	*/
 fileExists:function(){
 this.i18n.moveDestination=this.i18n.moveOtherDestination;
 this.moveFile();
 },

 /**
 	* For moving files
 	*/
 moveFile:function(){
 varo=this;

 o.initialize();

 mw.loader.using(['jquery.ui']).then(function(){
 o.showProgress();

 if($('#AjaxRenameLink').length){
 o.possibleDestination=$('#AjaxRenameDestination').text();
 o.possibleReason=o.cleanReason($('#AjaxRenameReason').text());
 }

 // Let's be sure we have a fresh token and the latest MIME-Info
 o.addTask('getMoveToken');

 varlinkstoimage=$('#mw-imagepage-section-linkstoimage');
 if($('#globalusage').length||(
 linkstoimage.length&&
 linkstoimage.find('a').not('.mw-redirect').length-
 linkstoimage.find('.mw-imagepage-linkstoimage-ns2 a[href^="/wiki/User:OgreBot/Uploads"]').length
 )){
 o.inUse=true;
 o.addTask('chkPreMoveDecline');
 }

 o.addTask('promptForMoveTarget');

 o.addTask('doesFileExist');
 o.fileNameExistsCB='fileExists';
 o.addTask('movePage');
 o.addTask('removeTemplate');
 o.addTask('queryRedirects');
 o.addTask('replaceUsage');

 // finally reload the page to show changed page
 o.addTask('reloadPage');

 o.nextTask();
 });
 },

 promptForMoveTargetCB:function(AQD){
 if(AQD.inUse){
 $('#AjaxQuestion2').prop('disabled',true);
 }
 },

 promptForMoveTarget:function(){
 vartoAppend;
 this.showProgress();

 if(mw.user.options.get('gadget-RenameLink')){
 toAppend=[$('<a>')
 .text(this.i18n.moreInformation)
 .on('click',function(){
 if(!AQD.rGetPolicy){
 importScript('MediaWiki:RenameRequest.js');
 mw.hook('aqd.renamerequest.i18n').fire();
 }
 mw.hook('aqd.renamerequest.run').fire({exec:this});
 }).button({
 icons:{primary:'ui-icon-script'},
 showLabel:true,
 text:false
 }).css({
 fontSize:'.6em',
 margin:'0',
 width:'2.5em',
 'float':'right'
 }),'<br>'];
 }
 mw.hook('aqd.prompt').remove(this.promptForMoveTargetCB).add(this.promptForMoveTargetCB);

 this.prompt([{
 message:this.i18n.moveDestination,
 prefill:this.cleanFileName(this.possibleDestination||pageName),
 returnvalue:'destination',
 appendNode:toAppend,
 cleanUp:true,
 noEmpty:true
 },{
 message:this.i18n.reasonForMove,
 prefill:((this.reason||this.possibleReason||'').trim().replace(/'{2,}/g,'').replace(/\s{2,}/g,' ')),
 returnvalue:'reason',
 cleanUp:true,
 noEmpty:false
 },{
 message:this.i18n.leaveRedirect,
 prefill:true,
 returnvalue:'wpLeaveRedirect',
 // cleanUp: false,
 noEmpty:false,
 type:'checkbox'
 },{
 message:this.i18n.useCORSForReplace,
 prefill:!window.aqdCORSOptOut,
 returnvalue:'replaceUsingCORS',
 // cleanUp: false,
 noEmpty:false,
 type:'checkbox'
 }
 ],this.i18n.movingFile);
 },

 /* Warn other filemovers */
 chkPreMoveDecline:function(){
 $('#mw-imagepage-section-linkstoimage').find('a').each(function(){
 if($(this).text()==='Commons:File renaming/Recently declined rename requests'){
 // eslint-disable-next-line no-alert
 alert(AQD.i18n.warnRename);
 returnfalse;
 }
 });
 this.nextTask();
 },

 /**
 	* For loading jquery UI to decline a request
 	*/
 loadAndDeclineRequest:function(reason){
 varthat=this;
 mw.loader.using('jquery.ui').then(function(){
 that.declineRequest.call(that,reason);
 });
 },

 /**
 	* For declining a request
 	*/
 declineRequest:function(reason){
 reason=reason||this.declineReason;
 // No valid reason stated, see the rename guidelines or not an exact duplicate
 this.initialize();

 this.addTask('getMoveToken');
 this.addTask('removeTemplate');

 // finally reload the page to show the template was removed
 this.addTask('reloadPage');

 // TODO extend the reason (for summary)
 switch(reason){
 case'move':
 reason='rename request declined: does not comply with [[COM:FR|renaming guidelines]]';
 if(window.AjaxDeclineMoveWatchFile){
 this.watchlist='watch';
 }
 break;
 }

 this.prompt([{
 message:'',
 prefill:reason||'',
 returnvalue:'declineReason',
 cleanUp:false,
 noEmpty:true,
 byteLimit:250
 }],this.i18n.declineRequest);

 },

 // This method is generlaly used directly by user scripts without going
 // through other methods or setup functions. Needs to be standalone,
 // and ensures loading of its own dependencies.
 insertTagOnPage:function(tag,img_summary,talk_tag,talk_summary,prompt_text,page,optin_notify){
 varo=this;
 this.initialize();

 mw.loader.using(['jquery.ui'],function(){
 o.pageName=(page||pageName).replace(/_/g,' ');
 o.tag=tag.replace('%USER%',conf.wgUserName)+'\n';
 o.img_summary=img_summary;

 // first schedule some API queries to fetch the info we need...
 // get token
 o.addTask('findCreator');
 o.addTask('prependTemplate');

 if(o.isMobile()&&/(?:copyvio|nsd|npd|nld)/.test(tag)){
 o.addTask('listMobileUploadSpeedy');
 }

 varprompt=[];

 // Cave: insertTagOnPage is inserted as javascript link and therefore talk_tag can be "undefined"/string
 if(talk_tag&&talk_tag!=='undefined'){
 o.talk_tag=talk_tag.replace('%FILE%',o.pageName);
 o.talk_summary=talk_summary.replace('%FILE%','[[:'+o.pageName+']]');

 o.usersNeeded=true;

 prompt.push({
 message:o.i18n.notifyUser,
 prefill:true,
 returnvalue:'notifyUser',
 type:'checkbox'
 });
 o.addTask('notifyUploaders');
 }
 o.addTask('reloadPage');

 if(tag.indexOf('%PARAMETER%')!==-1){
 prompt.push({
 message:'',
 prefill:'',
 returnvalue:'reason',
 cleanUp:true,
 noEmpty:true,
 minLength:1
 });

 o.prompt(prompt,prompt_text||o.i18n.reasonForDeletion);
 }elseif(optin_notify&&prompt.length&&o.talk_summary){
 o.prompt(prompt,o.talk_summary);
 }else{
 o.nextTask();
 }
 });
 },

 discussCategory:function(){
 // reset task list in case an earlier error left it non-empty
 this.initialize();

 this.pageName=pageName.replace(/_/g,' ');
 this.startDate=newDate();
 // eslint-disable-next-line no-useless-escape
 this.tag='{{subst:cfd}}\n';
 this.img_summary='This category needs discussion';
 // eslint-disable-next-line no-useless-escape
 this.talk_tag='{{subst:cdw|1='+pageName+'}}';
 this.talk_summary='[[:'+pageName+']] needs discussion';
 this.subpage_summary='Starting category discussion';

 // set up some page names we'll need later
 this.requestPage='Commons:Categories for discussion/'+this.formatDate('YYYY/MM/')+pageName;
 this.dailyLogPage='Commons:Categories for discussion/'+this.formatDate('YYYY/MM');

 // first schedule some API queries to fetch the info we need...
 this.addTask('findCreator');

 // ...then schedule the actual edits
 this.addTask('prependTemplate');
 this.addTask('createRequestSubpage');
 this.addTask('listRequestSubpage');
 this.addTask('notifyUploaders');

 // finally reload the page to show the deletion tag
 this.addTask('reloadPage');

 varlazyLoadNode=this.createLazyLoadNode(this.i18n.moreInformation,'MediaWiki:Gadget-AjaxQuickDelete.js/DiscussCategoryInfo','#AjaxQuickDeleteCatInfo');

 this.prompt([{
 message:'',
 prefill:'',
 returnvalue:'reason',
 cleanUp:true,
 appendNode:lazyLoadNode,
 noEmpty:true,
 parseReason:true
 }
 ],this.i18n.reasonForDiscussion);

 },
 nominateForDeletion:function(page){
 varo=this;

 // reset task list in case an earlier error left it non-empty
 this.initialize();

 mw.loader.using(['mediawiki.String','jquery.ui'],function(){
 o.pageName=(page||pageName).replace(/_/g,' ');
 o.startDate=newDate();

 // set up some page names we'll need later
 varrequestPage=o.pageName,
 mwString=require('mediawiki.String');

 // MediaWiki has an ugly limit of 255 bytes per title, excluding the namespace
 while(mwString.byteLength(requestPage)+mwString.byteLength(o.requestPagePrefix.replace(/^.+?:/,''))>=255){
 requestPage=requestPage.slice(0,requestPage.length-1).trim();
 }

 o.requestPage=o.requestPagePrefix+requestPage;
 o.dailyLogPage=o.requestPagePrefix+o.formatDate('YYYY/MM/DD');

 o.tag='{{delete|reason=%PARAMETER%|subpage='+requestPage+o.formatDate('|year=YYYY|month=MON|day=DAY}}\n');

 switch(nsNr){
 // On MediaWiki pages, wrap inside comments (for css and js)
 case8:
 o.tag='/*'+o.tag+'*/';
 break;
 // On templates and creator/institution-templates: Wrap inside <noinclude>s.
 case10:
 case100:
 case106:
 o.tag='<noinclude>'+o.tag+'</noinclude>';
 break;
 case828:// Lua comments
 o.tag='\n--[=[ '+o.tag+' ]=]\n';
 }

 if(o.templateReplace){
 o.declineReason=o.img_summary;
 }
 o.img_summary='Nominating for deletion';
 // eslint-disable-next-line no-useless-escape
 o.talk_tag='{{subst:idw|1='+requestPage+'}}';
 o.talk_summary='[[:'+o.pageName+']] has been nominated for deletion';
 o.subpage_summary='Starting deletion request';
 // without \n it breaks the redirect syntax
 if(conf.wgIsRedirect){
 o.tag+='\n';
 }

 // first schedule some API queries to fetch the info we need...
 o.addTask('findCreator');

 // ...then schedule the actual edits
 o.addTask(o.templateReplace?'replaceTemplate':'prependTemplate');
 o.addTask('createRequestSubpage');
 o.addTask('listRequestSubpage');
 o.addTask('purge');
 o.addTask('notifyUploaders');
 if(o.isMobile()){
 o.addTask('listMobileUpload');
 }

 // finally reload the page to show the deletion tag
 o.addTask('reloadPage');

 varlazyLoadNode=o.createLazyLoadNode(o.i18n.moreInformation,'MediaWiki:Gadget-AjaxQuickDelete.js/DeleteInfo','#AjaxQuickDeleteDeleteInfo');
 o.prevDRNode=$('<ul>').attr('id','AjaxDeletePrevRequests');
 o.secureCall('checkForFormerDR');
 vartoAppend=$('<div>').append($('<div>').attr('class','ajaxDeleteLazyLoad').css({
 'max-height':Math.max(Math.round($(window).height()/2)-250,100),
 'min-height':0,
 overflow:'auto'
 }).append(o.prevDRNode),'<br>',lazyLoadNode);

 o.prompt([{
 message:'',
 prefill:o.reason||'',
 returnvalue:'reason',
 cleanUp:true,
 noEmpty:true,
 appendNode:toAppend,
 parseReason:true
 }
 ],o.i18n.reasonForDeletion);
 });
 },

 // Check whether there was a deletion request for the same title in the past
 checkForFormerDR:function(){
 // Don't search for "kept" when nominating talk pages
 if(nsNr%2===0){
 this.talkPage=conf.wgFormattedNamespaces[nsNr+1]+':'+this.pageName.replace(conf.wgCanonicalNamespace+':','');
 this.queryAPI({
 prop:'templates',
 titles:this.talkPage,
 tltemplates:'Template:Kept',
 tllimit:1
 },'formerDRTalk');
 }
 this.queryAPI({
 list:'backlinks',
 bltitle:this.pageName,
 blnamespace:4,
 blfilterredir:'nonredirects',
 bllimit:500
 },'formerDRRequestpage');
 },
 formerDRTalk:function(r){
 varpgs=r.query.pages;
 $.each(pgs,function(id,pg){
 if(Array.isArray(pg.templates)){
 $('<li>').append($('<a>',{
 text:AQD.i18n.keptAfterDR,
 href:mw.util.getUrl(AQD.talkPage)
 })).prependTo(AQD.prevDRNode);
 }elseif(pg.missing===undefined){
 $('<li>').append($('<a>',{
 text:AQD.i18n.hasTalkpage,
 href:mw.util.getUrl(AQD.talkPage)
 })).appendTo(AQD.prevDRNode);
 }
 });
 },
 formerDRRequestpage:function(r){
 varbls=r.query.backlinks,
 _addItem=function(t,m,bl){
 $('<li>').append($('<a>',{
 text:t.replace('%PAGE%',bl.title),
 href:mw.util.getUrl(bl.title)
 }))[m](AQD.prevDRNode);
 };
 $.each(bls,function(i,bl){
 if(this.requestPage===bl.title){
 _addItem(AQD.i18n.mentionedInDR,'prependTo',bl);
 }elseif(/^Commons:Deletion requests\/\D/.test(bl.title)){
 _addItem(AQD.i18n.mentionedInDR,'appendTo',bl);
 }elseif(/^Commons:Village pump\//.test(bl.title)){
 _addItem(AQD.i18n.mentionedInForum,'appendTo',bl);
 }

 });
 },

 renderNode:function($node,remotecontent,selector){
 if(selector){
 selector=' '+selector;
 }

 $node.load(mw.util.wikiScript()+'?'+$.param({
 action:'render',
 title:remotecontent,
 uselang:conf.wgUserLanguage
 })+(selector||''),function(){
 $node.find('a').attr('href',function(i,v){
 returnv.replace('MediaWiki:Anoneditwarning',conf.wgPageName);
 });
 });
 return$node;
 },

 createLazyLoadNode:function(label,page,selector){
 return$('<div>',{style:'min-height:40px;'}).append($('<a>',{
 href:'#',
 text:label
 }).on('click',function(e){
 e.preventDefault();
 var$content=$(this).parent().find('.ajaxDeleteLazyLoad'),
 $contentInner=$content.find('.ajax-quick-delete-loading');
 if($contentInner.length){
 // first time invoked, do the XHR to load the content
 AQD.renderNode($content,$contentInner.data('aqdPage'),selector);
 }
 $content.toggle('fast');
 }),$('<div>',{
 // eslint-disable-next-line quote-props
 'class':'ajaxDeleteLazyLoad',
 style:'display:none;'
 }).append($('<span>',{
 // eslint-disable-next-line quote-props
 'class':'ajax-quick-delete-loading',
 text:this.i18n.loading
 }).data('aqdPage',page)));
 },
 extractFromHTML:function($el){
 $el=$($el).parent();

 // ...extract the regular expression from html
 this.templateRegExp=$el.find('.ctdr-regex').text();

 varm=this.templateRegExp.match(/^\/(.+)\/(i)?$/);
 if(!m||!m[1]){
 m=newError(this.i18n.templateRegExp);
 this.fail(m);
 throwm;
 }
 this.templateRegExp=newRegExp(m[1],m[2]);

 // ...and the decline reason
 this.declineReason=$el.find('.ctdr-template-decline-reason').text();

 // ...and the template name itself
 m=$el.find('.ctdr-template-name').text();

 this.reason='This file was initially tagged by %USER%'+(m?(' as \'\'\''+m+'\'\'\''):'');

 },
 removeProgress:function(){
 this.showProgress();
 returnthis.nextTask();
 },
 /**
 	* Remove any tag
 	* @context DOM-Element
 	* This function must be called with the DOM-Element as this-arg!
 	*/
 _removeAnyTag:function(e){
 AQD.extractFromHTML(e.currentTarget||this);
 AQD.removeAnyTag();
 returnfalse;
 },
 removeAnyTag:function(){
 // this.initialize();
 this.addTask('declineRequest');
 this.nextTask();
 },
 /**
 	* Convert any tag to a deletion request
 	* @context DOM-Element
 	* This function must be called with the DOM-Element as this-arg!
 	*/
 _convertToDR:function(e){
 e=e.currentTarget||this;
 AQD.extractFromHTML(e);
 AQD.convertToDR(e);
 returnfalse;
 },
 convertToDR:function(el){
 // reset task list in case an earlier error left it non-empty
 this.initialize();
 this.declineReason='This file does not qualify for [[COM:SPEEDY|speedy-deletion]] and a regular deletion request will be started.';
 this.templateReplace=true;
 // first schedule a API query to fetch the info we need...
 this.addTask('findTemplateAdder');
 this.addTask('getMoveToken');
 // prompt before conversion for user decision
 this.addTask('removeTemplate');
 this.addTask('removeProgress');
 this.addTask('nominateForDeletion');
 // Hide the buttons to prevent attempts of duplicate removal
 $(el).closest('.convert-to-dr').hide();
 // ... and go!
 this.nextTask();
 },
 findTemplateAdder:function(){
 varquery={
 prop:'revisions',
 rvprop:'content|user',
 titles:pageName.replace(/_/g,' '),
 rvlimit:50
 };
 this.queryAPI(query,'findTemplateAdderCB');
 },
 findTemplateAdderCB:function(result){
 varreason,
 user,
 pgRevs,// for debug
 template;
 $.each(result.query.pages,function(id,pg){
 pgRevs=pg.revisions;
 varlastM=null;
 for(vari=pgRevs.length-1;i>=0;i--){
 varm=pgRevs[i]['*'].match(AQD.templateRegExp);
 if(m){
 if(!lastM){// require tag to be an addition not there before
 user=pgRevs[i].user;
 if(m.length>1&&!template){
 template=m[1];
 }
 if(m.length>2&&!reason){
 reason=m[2];
 }
 }
 lastM=m;
 }else{
 lastM=null;
 }
 }
 });
 if(!user){
 mw.log.warn(pgRevs);
 thrownewError(this.i18n.findTemplateAdderErr);
 }
 this.reason=this.reason.replace('%USER%','[[User:'+user+'|'+user+']]');
 if(template){
 this.reason+=' ('+template+')';
 }

 if(reason){
 this.reason+=' and the most recent rationale was: <span style="font-family: monospace">'+reason+'</span>';
 }

 this.nextTask();
 },

 processDupes:function(){
 // reset task list in case an earlier error left it non-empty
 this.initialize();

 if($('#globalusage').length||!$('#mw-imagepage-nolinkstoimage').length){
 this.inUse=true;
 }

 this.addTask('getDupeDetails');
 this.addTask('compareDetails');
 this.addTask('mergeDescriptions');
 this.addTask('saveDescription');
 this.addTask('replaceUsage');
 this.addTask('queryRedirects');
 this.addTask('deletePage');
 this.addTask('redirectPage');
 this.addTask('reloadPage');
 this.destination=$('#AjaxDupeDestination').text();
 this.nextTask();
 },

 getDupeDetails:function(){
 this.queryAPI({
 curtimestamp:1,
 meta:'tokens',
 prop:'imageinfo|revisions|info',
 rvprop:'content|timestamp',
 inprop:'watched',
 iiprop:'sha1|size|url',
 iiurlwidth:365,
 redirects:1,
 titles:pageName.replace(/_/g,' ')+'|'+this.destination
 },'getDupeDetailsCB');
 this.showProgress('Fetching details');
 },

 getDupeDetailsCB:function(result){
 this.details=[];
 if(result){
 varq=result.query,
 id,
 pg,
 ii,
 n,
 pages=q.pages;

 for(idinpages){
 if(Object.prototype.hasOwnProperty.call(pages,id)){
 pg=pages[id];
 if(!pg.imageinfo){
 // Nothing we can change so prevent users reporting
 this.disableReport=true;
 thrownewError(((pg.title.trim()==='{{{1}}}')?
 this.i18n.dupeParaErr:
 this.i18n.dupeExistErr.replace('%TITLE%',pg.title))+' (pg.imageinfo is undefined)');
 }
 ii=pg.imageinfo[0];
 n={
 title:pg.title,
 size:ii.size,
 width:ii.width,
 height:ii.height,
 thumburl:ii.thumburl,
 thumbwidth:ii.thumbwidth,
 thumbheight:ii.thumbheight,
 descriptionurl:ii.descriptionurl,
 sha1:ii.sha1,
 content:pg.revisions[0]['*'],
 starttimestamp:result.curtimestamp
 };
 this.details.push(n);
 this.csrftoken=q.tokens.csrftoken;

 if(pg.watched!==undefined){
 this.pageWasWatched=true;
 }

 }
 }
 }
 if(this.details.length<2){
 this.disableReport=true;
 thrownewError(this.i18n.noPageFound);
 }
 // If order (old=0, new=1) is incorrect: Reverse
 if(this.details[0].title!==pageName.replace(/_/g,' ')){
 this.details.reverse();
 }

 this.nextTask();
 },

 /**
 	* Edit the current page to add the specified tag. Assumes that the page hasn't
 	* been tagged yet; if it is, a duplicate tag will be added.
 	*/
 prependTemplate:function(){
 varpage={
 title:this.pageName,
 text:this.tag,
 editType:'prependtext',
 watchlist:window.AjaxDeleteWatchFile?'watch':this.watchlist,
 minor:false
 };

 this.showProgress(this.i18n.addingAnyTemplate);
 this.savePage(page,this.img_summary,'nextTask');
 },

 /**
 	* Edit the current page to add the specified tag and the changed content.
 	*/
 replaceTemplate:function(text){
 varpage={
 title:this.destination||pageName,
 text:text||this.tag+this.pageContent,
 editType:'text',
 starttimestamp:this.starttimestamp,
 timestamp:this.timestamp,
 watchlist:window.AjaxDeleteWatchFile?'watch':this.watchlist,
 minor:false
 };

 this.templateReplace=false;
 this.showProgress(this.i18n.addingAnyTemplate);
 this.savePage(page,(this.declineReason||this.img_summary),'nextTask');
 },

 /**
 	* Create the DR subpage (or append a new request to an existing subpage).
 	* The request page will always be watchlisted.
 	*/
 createRequestSubpage:function(){
 this.templateAdded=true;// we've got this far; if something fails, user can follow instructions on template to finish
 varpage={
 title:this.requestPage,
 // eslint-disable-next-line no-useless-escape
 text:'\n=== [[:'+this.pageName+']] ===\n'+this.reason+' ~~~~\n',
 watchlist:'watch',
 editType:'appendtext'
 };
 if(this.isMobile()){
 page.text+='\n<noinclude>[[Category:MobileUpload-related deletion requests]]</noinclude>';
 }

 this.showProgress(this.i18n.creatingNomination);
 this.savePage(page,this.subpage_summary,'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).
 	*/
 listRequestSubpage:function(){
 varpage={};
 page.title=this.dailyLogPage;

 // Impossible when using appendtext. Shouldn't not be severe though, since DRBot creates those pages before they are needed.
 // if (!page.text) page.text = "{{"+"subst:" + this.requestPagePrefix + "newday}}"; // add header to new log pages
 page.text='\n{{'+this.requestPage+'}}\n';
 page.watchlist='preferences';
 page.editType='appendtext';

 this.showProgress(this.i18n.listingNomination);

 this.savePage(page,'Listing [['+this.requestPage+']]','nextTask');
 },

 isMobile:function(){
 varisMobile=false,
 cats=conf.wgCategories;

 // On mobile categories are not defined. Exit early to avoid .length error.
 if(!cats){
 returntrue;
 }
 for(vari=0,len=cats.length;i<len;i++){
 isMobile=isMobile||/^Uploaded with Mobile/.test(cats[i]);
 }

 returnisMobile;
 },

 listMobileUpload:function(){
 varpage={
 title:'Commons:Deletion requests/mobile tracking',
 text:'\n{{'+this.requestPage+'}}\n',
 watchlist:'preferences',
 editType:'appendtext'
 };

 this.showProgress(this.i18n.listingMobile);

 this.savePage(page,'Listing [['+this.requestPage+']]','nextTask');
 },

 listMobileUploadSpeedy:function(){
 varpage={
 title:'Commons:Mobile app/deletion request tracking',
 text:'\n# [[:'+this.pageName+']]',
 watchlist:'preferences',
 editType:'appendtext'
 };

 this.showProgress(this.i18n.listingMobile);

 this.savePage(page,'Listing [['+this.pageName+']]','nextTask');
 },

 /**
 	* Check the users talkpage is not blocked indefinite
 	*/
 verifyUserNotify:function(user){
 this.queryAPI({
 prop:'info',
 titles:this.userTalkPrefix+user,
 redirects:1,
 inprop:'protection'
 },'verifyUserNotifyCB');
 },
 verifyUserNotifyCB:function(result){
 varpage;
 this.notifyUser=true;// reset
 if(!result||!result.query||!result.query.pages){
 mw.log.warn('Verify user: result.query.pages is undefined. ',result);
 returnthis.uploaderNotified();
 }

 result=result.query.pages;
 for(varpginresult){
 pg=result[pg];
 page=pg.title;
 pg=pg.protection;
 if(pg){
 for(varp=0;p<pg.length;p++){
 varpt=pg[p];
 if(pt&&pt.type==='edit'&&pt.level==='sysop'){
 // Disable report for protected userpages
 this.disableReport=true;
 // Disable notify for indefinite protected
 if(pt.expiry==='infinity'){
 this.notifyUser=false;
 }

 }
 }
 }
 }
 if(this.notifyUser&&page){
 page={
 title:page,
 // eslint-disable-next-line no-useless-escape
 text:'\n'+this.talk_tag+' ~~~~\n',
 editType:'appendtext',
 redirect:true,
 minor:false
 };
 if(window.AjaxDeleteWatchUserTalk){
 page.watchlist='watch';
 }

 this.savePage(page,this.talk_summary,'uploaderNotified');
 }else{
 this.uploaderNotified();
 }
 },

 /**
 	* Notify any uploaders/creators of this page using {{idw}}.
 	*/
 notifyUploaders:function(){
 this.uploadersToNotify=0;
 if(this.notifyUser){
 for(varuserinthis.uploaders){
 if(Object.prototype.hasOwnProperty.call(this.uploaders,user)){
 if(user===conf.wgUserName){
 // notifying yourself is pointless
 continue;
 }
 this.verifyUserNotify(user);
 this.showProgress(this.i18n.notifyingUploader.replace('%USER%',user));
 this.uploadersToNotify++;
 }
 }
 }
 if(!this.uploadersToNotify){
 this.nextTask();
 }

 },

 uploaderNotified:function(){
 this.uploadersToNotify--;
 if(!this.uploadersToNotify){
 this.nextTask();
 }

 },

 /**
 	* Compile a list of uploaders to notify. Users who have only reverted the file to an
 	* earlier version will not be notified.
 	* DONE: notify creator of non-file pages
 	* DONE: notify fileimporter (2019年09月09日)
 	*/
 findCreator:function(){
 varq={
 curtimestamp:1,
 meta:'tokens',
 prop:'revisions',
 titles:this.pageName,
 rvprop:'timestamp|user',
 rvdir:'newer',
 rvslots:'main',
 rvlimit:1
 };

 if(nsNr===6){
 $.extend(q,{
 prop:q.prop+'|imageinfo',
 rvprop:q.rvprop+'|content',
 iiprop:'user|comment|sha1',
 iilimit:'50',
 list:'logevents',
 letype:'import',
 leprop:'user',
 letitle:this.pageName
 });
 }

 this.showProgress(this.i18n.preparingToEdit);
 this.queryAPI(q,'findCreatorCB');
 },

 findCreatorCB:function(r){
 this.uploaders={};

 if(!r||!r.query||!r.query.pages){
 this.disableReport=true;
 thrownewError(this.i18n.noPageFound);
 }
 varq=r.query,
 pg=_firstItem(q.pages),
 rv;

 if(!pg||!pg.revisions){
 thrownewError(this.i18n.noCreatorFound);
 }

 // The csrftoken only changes between sessions
 this.csrftoken=q.tokens.csrftoken;
 rv=pg.revisions[0];

 // First handle non-file pages
 if(nsNr!==6||!pg.imageinfo){
 this.starttimestamp=r.curtimestamp;
 this.timestamp=rv.timestamp;

 if((this.pageCreator=rv.user)){
 this.uploaders[this.pageCreator]=true;
 }

 }else{
 varinfo=pg.imageinfo,
 i=info.length,
 content=rv.slots.main['*'],
 seenHashes={};
 // Iterate in reverse order (sha1 check)
 for(--i;i>=0;i--){
 variii=info[i],
 rev=seenHashes[iii.sha1];
 // Skip reverts and remove users
 if(iii.sha1&&rev){
 for(rev;rev>i;rev--){
 varu=info[rev-1].user;
 if(this.uploaders[u]<rev){
 deletethis.uploaders[u];
 }

 }
 continue;
 }
 seenHashes[iii.sha1]=i+1;
 // No need to check again the whole shebang
 if(this.uploaders[iii.user]){
 continue;
 }

 // Now exclude bots which only reupload a new version:
 if(mw.libs.commons.isSmallChangesBot(iii.user)){
 continue;
 }

 // Outsourced to MediaWiki:Gadget-libCommons.js
 iii=mw.libs.commons.getUploadBotUser(iii.user,content,iii.comment,rv.user);
 if(iii){
 this.uploaders[iii]=i+1;
 }

 }
 // Get fileimporter
 if((info=q.logevents)&&(i=info.length)){
 for(--i;i>=0;i--){
 if(info[i].user){
 this.uploaders[info[i].user]=true;
 }
 }

 }

 }
 this.nextTask();
 },

 getMoveToken:function(){
 this.showProgress(this.i18n.preparingToEdit);
 varquery={
 curtimestamp:1,
 prop:'info|revisions',
 meta:'tokens',
 rvprop:'content|timestamp',
 inprop:'watched',
 titles:this.pageName||pageName.replace(/_/g,' ')
 };
 if(!this.declineReason){
 query.prop+='|imageinfo';
 query.iiprop='mediatype|mime|timestamp';
 }
 this.queryAPI(query,'getMoveTokenCB');
 },

 /**
 	* @brief [callback] Prepare page for saving before
 	* @param [in] result of query
 	* @return csrftoken, pageContent, starttimestamp, timestamp, imagetimestamp, mimeFileExtension, pageWasWatched
 	*/
 getMoveTokenCB:function(result){
 varq=result.query||{},
 pg=_firstItem(q.pages);
 if(!pg||!pg.revisions){
 this.disableReport=true;
 thrownewError(this.i18n.noPageFound);
 }
 // The csrftoken only changes between sessions
 $.extend(this,{
 csrftoken:q.tokens.csrftoken,
 pageContent:pg.revisions[0]['*'],
 starttimestamp:result.curtimestamp,
 timestamp:pg.revisions[0].timestamp
 });

 if(pg.watched!==undefined){
 this.pageWasWatched=true;
 }

 varii=pg.imageinfo;
 if(ii&&ii.length&&ii[0].mime){
 ii=ii[0];
 this.imagetimestamp=ii.timestamp;
 this.mimeFileExtension=ii.mime
 .toLowerCase()
 .replace('image/jpeg','jpg')
 .replace(/image\/(?:x-|vnd\.)?(png|gif|xcf|djvu|svg|tiff)(?:\+xml)?/,'1ドル')
 .replace(/application\/(ogg|pdf)/,'1ドル')
 .replace(/video\/(webm)/,'1ドル')
 .replace('audio/midi','mid')
 .replace(/audio\/(?:x-|vnd\.)?wave?/,'wav')
 .replace(/audio\/(?:x-)?flac/,'flac');
 if(this.mimeFileExtension.length>5){
 this.mimeFileExtension='';
 }elseif(this.mimeFileExtension==='ogg'){
 switch(ii.mediatype){
 case'AUDIO':
 this.mimeFileExtension='oga';
 break;
 case'VIDEO':
 this.mimeFileExtension='ogv';
 break;
 }
 }
 }
 this.nextTask();
 },

 doesFileExist:function(){
 if(!this.destination){
 // eslint-disable-next-line no-alert
 returnalert(this.i18n.moveDestination);
 }
 this.destination=this.cleanFileName(this.destination);
 varquery={
 prop:'info|revisions',
 titles:this.destination,
 rvprop:'content',
 rvlimit:2
 };
 // usually you would use 'redirects': 1, to detect the redirect target but
 // in this case you would get the revisions for the target and not the redirect

 this.showProgress(this.i18n.checkFileExists);
 this.queryAPI(query,'doesFileExistCB');
 },

 /**
 	* Return nextTask if the page does not exist
 	* or it is a redirect with one revision to the source
 	*/
 doesFileExistCB:function(result){
 if(!result||!result.query||!result.query.pages){
 thrownewError('Checking filename: result.query.pages is undefined. '+this.destination);
 }

 varexists=true,
 pg=_firstItem(result.query.pages),
 getRedirRegExp=function(title){
 title=title.replace(/^(File|Image):/,'').replace(/_/g,' ');
 returnnewRegExp('^\\s*#REDIRECT\\s*\\[\\[File\\:['+
 mw.util.escapeRegExp(title[0].toUpperCase())+mw.util.escapeRegExp(title[0].toLowerCase())+']'+
 mw.util.escapeRegExp(title.slice(1)).replace(/ /g,'[ _]')+
 '\\s*\\]\\]',
 '');
 };

 if(pg.missing!==undefined){
 exists=false;
 }elseif(!pg.revisions||pg.revisions.length===1&&getRedirRegExp(pageName)
 .test(pg.revisions[0]['*'].replace('Image:','File:'))){
 // There seems to be no way to find out whether a title is a redirect
 // and whether the redirect only consists of one revision
 exists=false;
 }

 if(exists){
 if(this.fileNameExistsCB){
 this[this.fileNameExistsCB](pg.title.replace(/^File:/,''));
 }
 return;
 }
 this.nextTask();
 },

 removeTemplate:function(){
 this.replaceWith=(this.replaceWith||(this.templateRegExp?'':'1ドル2ドル'));
 // Remove the template from the text. In case there is an empty line before, remove this also.
 varnewText=this.pageContent
 .replace(
 (this.templateRegExp||/(?:([^=])\n)?\{\{(?:rename|rename media|rename image|move|datei umbenennen)\s*\|.*?\}\}(?:\n([^=]))?/i),
 this.replaceWith
 );
 if(newText===this.pageContent){
 returnthis.nextTask();
 }

 this.showProgress(this.i18n.removingTemplate);
 newText=this.pageContent=newText.trim();

 // We have another save request
 if(this.templateReplace){
 this.img_summary=this.declineReason;
 returnthis.nextTask();
 }
 if(!this.declineReason){
 this.img_summary='Removing template; rename done';
 }

 // If nothing remains, add the no-license-template (this also to prevent abuse filter blocking this edit because of page blanking)
 this.replaceTemplate(newText||'{{subst:nld}}');
 },

 replaceUsage:function(){
 if(!this.inUse){
 returnthis.nextTask();
 }

 this.showProgress(this.i18n.replacingUsage);
 varreasonShort='[[COM:Duplicate|Duplicate]]:';

 if(!this.details){
 AQD.reason=AQD.reason.replace(/\[\[Commons:File[_ ]renaming[^[\]]*\]\]:? ?/i,'');
 reasonShort='[[COM:FR|File renamed]]:';
 }
 mw.loader.using('ext.gadget.libGlobalReplace',function(){
 if(AQD.replaceUsingCORS){
 mw.libs.globalReplace(pageName,AQD.destination,reasonShort,AQD.reason)
 .fail(function(err){
 thrownewError(err);
 })
 .done(function(){
 AQD.nextTask();
 })
 .progress(function(r){
 AQD.showProgress(r);
 mw.log(r);

 });
 }else{
 mw.libs.globalReplaceDelinker(pageName,AQD.destination,reasonShort+' '+AQD.reason,function(){
 AQD.nextTask();
 },function(err){
 thrownewError(err);
 });
 }
 });
 },
 redirectPage:function(){
 varpage={
 title:pageName,
 text:'#REDIRECT [['+this.destination+']]',
 editType:'text',
 watchlist:AQD.pageWasWatched?'watch':'preferences'
 };

 this.showProgress(this.i18n.redirectingFile);
 this.savePage(page,'Redirecting to duplicate file','nextTask');
 },
 saveDescription:function(){
 varpage={
 title:this.destination,
 text:this.newPageText,
 editType:'text',
 watchlist:AQD.pageWasWatched?'watch':'preferences'
 };

 this.showProgress(this.i18n.savingDescription);
 this.savePage(page,'Merging details from duplicate ([['+pageName+']])','nextTask');
 },

 /**
 	* Updates the redirects to the current page
 	* when moving or processing dupes immediately
 	* to prevent double redirects
 	*/
 queryRedirects:function(){
 mw.loader.using('mediawiki.api').then(function(){
 returnnewmw.Api().loadMessagesIfMissing([
 'Whatlinkshere'
 ]);
 }).then(function(){
 AQD.showProgress(mw.msg('Whatlinkshere'));
 // TODO: Replace also the redirects inclusions!?
 AQD.queryAPI({
 generator:'backlinks',
 gblfilterredir:'redirects',
 prop:'revisions',
 rvprop:'content',
 gbltitle:AQD.pageName||pageName.replace(/_/g,' ')
 },AQD.queryRedirectsCB?
 AQD.queryRedirectsCB:
 'updateRedirects');
 });
 },

 updateRedirects:function(result){
 AQD.redirectsToUpdate=0;
 if(result.query&&result.query.pages){
 this.showProgress(this.i18n.updRedir);
 $.each(result.query.pages,function(id,pg){
 varrv=pg.revisions[0];
 if(!rv||!rv['*']){
 return;
 }

 // Update only redirects with same mimetype
 if(AQD.checkFileExt(pg.title,AQD.destination,true)){
 returnmw.log('Redirect skipped, not same mimetype.',pg.title);
 }

 varpage={
 title:pg.title,
 text:rv['*'].replace(/#\s*REDIRECT\s*\[\[.+/,'#REDIRECT [['+AQD.destination+']]'),
 editType:'text',
 watchlist:'preferences'
 };

 AQD.savePage(page,'Updating redirect while processing [['+pageName.replace(/_/g,' ')+']]','updateRedirectsCB');
 AQD.redirectsToUpdate++;
 });
 }
 if(!AQD.redirectsToUpdate){
 AQD.nextTask();
 }

 },

 updateRedirectsCB:function(){
 AQD.redirectsToUpdate--;
 if(!AQD.redirectsToUpdate){
 AQD.nextTask();
 }

 },

 /**
 	* Pseudo-Modal JS windows.
 	*/
 prompt:function(questions,title,width){
 varo=this,
 dlgButtons={};
 dlgButtons[this.i18n.submitButtonLabel]=function(){
 questions.forEach(function(v,i){
 varresponse=document.getElementById('AjaxQuestion'+i);
 response=(v.type==='checkbox')?response.checked:response.value;
 if(v.cleanUp){
 if(v.returnvalue==='reason'){
 response=AQD.cleanReason(response);
 }

 if(v.returnvalue==='destination'){
 response=AQD.cleanFileName(response);
 }

 }
 AQD[v.returnvalue]=response;
 if(v.returnvalue==='reason'&&AQD.tag){
 AQD.tag=AQD.tag.replace('%PARAMETER%',response);
 if(AQD.talk_tag){
 AQD.talk_tag=AQD.talk_tag.replace('%PARAMETER%',response);
 }
 AQD.img_summary=AQD.img_summary.replace('%PARAMETER%',response)
 .replace('%PARAMETER-LINKED%','[[:'+response+']]');
 }
 });
 $(this).dialog('close');
 AQD.nextTask();
 };
 dlgButtons[this.i18n.cancelButtonLabel]=function(){
 $(this).dialog('close');
 };

 var$submitButton,
 $AjaxDeleteContainer=$('<div>',{id:'AjaxDeleteContainer'}),
 _parseReason=function(){
 var$el=$(this),
 $parserResultNode=$el.data('parserResultNode');

 if(!$parserResultNode){
 return;
 }

 $parserResultNode.css('color','#877');

 var_gotParsedText=function(r){
 try{
 $parserResultNode.html(r);
 $parserResultNode.css('color','#000');
 }catch(ex){}
 };
 mw.loader.using(['ext.gadget.libAPI'],function(){
 mw.libs.commons.api.parse($el.val(),conf.wgUserLanguage,pageName,_gotParsedText);
 });
 },

 _validateInput=function(event){
 var$el=$(this),
 v=$el.data('v');

 if(v.noEmpty){
 $submitButton.button('option','disabled',$el.val().trim().length<(v.minLength||8));
 }

 if(
 ($el.prop('nodeName')!=='TEXTAREA')&&
 (event.which===13)&&
 (v.enterToSubmit!==false)&&
 !$submitButton.button('option','disabled')
 ){
 $submitButton.trigger('click');
 }

 },

 _convertToTextarea=function(){
 var$el=$(this),
 $input=$el.data('toConvert'),
 $tarea=$('<textarea>',{
 id:$input.attr('id'),
 style:'height:10em; width:98%; display:none;'
 });

 $el.off().fadeOut();
 $input.parent().prepend(
 $tarea
 .data('v',$input.data('v')).data('parserResultNode',$input.data('parserResultNode'))
 .val($input.val()).on('keyup',_parseReason).on('keyup input',_validateInput));
 $tarea.slideDown();
 $input.remove();
 };

 questions.forEach(function(v,i){
 v.type=(v.type||'text');
 if(v.type==='textarea'){
 $AjaxDeleteContainer.append('<label for="AjaxQuestion'+i+'">'+v.message+'</label>')
 .append('<textarea rows=20 id="AjaxQuestion'+i+'">');
 }else{
 $AjaxDeleteContainer.append('<label for="AjaxQuestion'+i+'">'+v.message+'</label>')
 .append('<input type="'+v.type+'" id="AjaxQuestion'+i+'" style="width:97%;">');
 }

 varcurQuestion=$AjaxDeleteContainer.find('#AjaxQuestion'+i);

 if(v.parseReason){
 var$parserResultNode=$('<div>',{
 id:'AjaxQuestionParse'+i,
 html:'&nbsp;'
 });
 $AjaxDeleteContainer.append('<br><label for="AjaxQuestionParse'+i+'">'+
 o.i18n.previewLabel+'</label>').append($parserResultNode);

 curQuestion.data('parserResultNode',$parserResultNode).keyup(_parseReason);
 }
 if(v.type!=='textarea'){
 $AjaxDeleteContainer.append('<br>');
 }

 $AjaxDeleteContainer.append(v.appendNode?v.appendNode:'<br>');

 if(typeofv.byteLimit==='number'){
 mw.loader.using('jquery.lengthLimit',function(){
 curQuestion.byteLimit(v.byteLimit);
 });
 }

 curQuestion.data('v',v);
 curQuestion.on('keyup input',_validateInput);

 // SECURITY: prefill could contain evil jsCode. Never use it unescaped!
 // Use .val() or { value: prefill } or '<input value="' + mw.html.escape() + '" ...>
 curQuestion.val(v.prefill);
 if(v.type==='checkbox'){
 curQuestion.prop('checked',v.prefill).attr('style','margin-left: 5px');
 }

 });

 if(mw.user.isAnon()){
 AQD.renderNode($('<div>',{id:'ajaxDeleteAnonwarning'}),'MediaWiki:Anoneditwarning').appendTo($AjaxDeleteContainer);
 }

 $('<div>').append($AjaxDeleteContainer).dialog({
 width:(width||600),
 modal:true,
 title:title,
 dialogClass:'wikiEditor-toolbar-dialog',
 close:function(){
 $(this).dialog('destroy').remove();
 if(AQD.currentTask==='formerDRRequestpage'){
 $('.convert-to-dr').show();
 }
 },
 buttons:dlgButtons,
 open:function(){
 // Look out for http://bugs.jqueryui.com/ticket/6830 / jQuery UI 1.9
 var$buttons=$(this).parent().find('.ui-dialog-buttonpane button');
 $submitButton=$buttons.eq(0).specialButton('proceed');
 $buttons.eq(1).specialButton('cancel');
 }
 });

 questions.forEach(function(v,i){
 varcurQuestion=$AjaxDeleteContainer.find('#AjaxQuestion'+i);
 curQuestion.trigger('keyup');
 if(v.type==='text'){
 var$q=curQuestion.wrap('<div style="position:relative;">').parent(),
 $i=$.createIcon('ui-icon-arrow-4-diag').attr('title',AQD.i18n.expandToTextarea);
 $('<span>',{
 // eslint-disable-next-line quote-props
 'class':'ajaxTextareaConverter'}).append($i).appendTo($q).data('toConvert',curQuestion).on('click',_convertToTextarea);
 }
 });

 $('#AjaxQuestion0').trigger('focus').trigger('select');
 mw.hook('aqd.prompt').fire(o);
 },

 /**
 	* Open a jQuery dialog with preview-images and some options
 	* and information to compare the two files
 	*/
 compareDetails:function(){

 vard=this.details[0],
 f=this.details[1],
 $swapButton,
 $overlayButton;

 if(d.sha1===f.sha1){
 this.exactDupes=true;
 this.nextTask();
 return;
 }

 var$imgD=$('<div>').append($('<img>',{
 src:d.thumburl,
 height:d.thumbheight,
 width:d.thumbwidth
 }),$('<div>',{
 id:'AjaxDeleteImgDel',
 html:Math.round(d.size/1000)+' KiB <br>'+d.width+×ばつ'+d.height+'<br>'
 }).append(
 $('<a>',{
 href:d.descriptionurl,
 text:d.title,
 target:'_blank'
 }))),
 $imgF=$('<div>').append($('<img>',{
 src:f.thumburl,
 height:f.thumbheight,
 width:f.thumbwidth
 }),$('<div>',{
 id:'AjaxDeleteImgKeep',
 html:Math.round(f.size/1000)+' KiB <br>'+f.width+×ばつ'+f.height+'<br>'
 }).append(
 $('<a>',{
 href:f.descriptionurl,
 text:f.title,
 target:'_blank'
 }))),
 dlgButtons={};

 dlgButtons[this.i18n.submitButtonLabel]=function(){
 $(this).dialog('close');
 AQD.nextTask();
 };
 dlgButtons[this.i18n.inverseButtonLabel]=function(){
 $(this).dialog('close');
 AQD.destination=pageName.replace(/_/g,' ');
 pageName=f.title;
 AQD.details.reverse();
 AQD.inUse=true;
 setTimeout(function(){
 AQD.compareDetails();
 },20);
 };
 dlgButtons[this.i18n.swapImagesButtonLabel]=function(){
 if($imgD[0].nextSibling===$imgF[0]){
 $imgD.before($imgF);
 }else{
 $imgF.before($imgD);
 }
 };
 var$fClone;
 dlgButtons[this.i18n.overlayButtonLabel]=function(){
 if($fClone){
 $fClone.remove();
 $fClone=0;
 }else{
 $fClone=$imgF.clone().appendTo($imgF.parent());
 $fClone.css('position','absolute');
 varpos=$imgD.position();
 $fClone.css({
 top:pos.top-1,left:pos.left-1
 })
 .fadeTo(0,0.65);
 // These modules should be already loaded for the dialog but let's be sure
 mw.loader.using(['jquery.ui'],function(){
 // Set width to auto because AjaxQuickDelete.css sets it to a fixed size
 $fClone.css({
 background:'rgba(200, 200, 200, 0.5)',
 width:'auto',
 border:'1px solid #0c9'
 }).draggable();
 $fClone.find('img').resizable();
 // In IE, opacity is not fully inerhited
 $fClone.children('div').fadeTo(0,0.7);
 });
 }
 };

 this.showProgress();

 var$AjaxDupeContainer=$('<div>',{id:'AjaxDupeContainer'}).append($imgD,$imgF);
 $('<div>').append($AjaxDupeContainer).dialog({
 width:800,
 modal:true,
 title:this.i18n.compareDetails,
 draggable:false,
 dialogClass:'wikiEditor-toolbar-dialog',
 close:function(){
 $(this).dialog('destroy').remove();
 },
 buttons:dlgButtons,
 open:function(){
 var$buttons=$(this).parent().find('.ui-dialog-buttonpane button');
 $buttons.eq(0).specialButton('proceed');
 $buttons.eq(1).button({icons:{primary:'ui-icon-refresh'}});
 $swapButton=$buttons.eq(2).button({icons:{primary:'ui-icon-transfer-e-w'}});
 $overlayButton=$buttons.eq(3).button({icons:{primary:'ui-icon-newwin'}});
 $swapButton.css('float',(($swapButton.css('float')==='left')?'right':'left'));
 $overlayButton.css('float',(($overlayButton.css('float')==='left')?'right':'left'));
 }
 });
 mw.loader.load(['ext.gadget.libGlobalReplace','ext.gadget.libWikiDOM']);
 },

 mergeDescriptions:function(){
 varnewPageText=this.details[1].content;
 mw.loader.using(['ext.gadget.libGlobalReplace','ext.gadget.libWikiDOM'],function(){
 newPageText=mw.libs.wikiDOM.nowikiEscaper(newPageText).doCleanUp();

 AQD.showProgress();
 AQD.prompt([{
 message:'',
 prefill:AQD.details[0].content,
 returnvalue:'discard',
 cleanUp:false,
 noEmpty:false,
 type:'textarea',
 enterToSubmit:false
 },{
 message:'',
 prefill:newPageText,
 returnvalue:'newPageText',
 cleanUp:false,
 noEmpty:false,
 type:'textarea',
 enterToSubmit:false
 },{
 message:AQD.i18n.useCORSForReplace,
 prefill:!window.aqdCORSOptOut,
 returnvalue:'replaceUsingCORS',
 // cleanUp: false,
 noEmpty:false,
 type:'checkbox'
 }
 ],AQD.i18n.mergeDescription,800);

 AQD.destination=AQD.details[1].title;
 AQD.reason='Exact or scaled-down duplicate: [[:'+AQD.destination+']]';
 });
 },

 /**
 	* Correct the MIME-Type; Accepts only valid filenames (with extension)
 	* Either a filename is passed or the destination property is used
 	*/
 correctMIME:function(fn){
 // If the current mime-type is available to the script, check it;
 // MediaWiki sometimes allows uploading mismatching mimetypes but not moving
 varf=fn||this.destination;
 if(this.mimeFileExtension){
 f=f.replace(/\.\w{2,5}$/,'.'+this.mimeFileExtension);
 }

 if(!fn){
 this.destination=f;
 returnthis.nextTask();
 }else{
 returnf;
 }
 },

 cleanFileName:function(fn,ignoreMIME){
 // Remove Namespace
 fn=fn.replace(/^(?:Image|File):/i,'')
 // Convert extension to lower case
 .replace(/(\.\w{2,5})+$/,function($e){
 return$e.toLowerCase();
 })
 // jpeg -> jpg
 .replace(/\.jpe*g$/,'.jpg')
 // First cleanUp from Flinfo (FlinfoOut.php) by Flominator and Lupo
 .replace(/~{3,}/g,'')// "signature"
 .replace(/[\u00A0\u1680\u180E\u2000-\u200B\u2028\u2029\u202F\u205F\u3000]/,' ')// remove NBSP and other unusual spaces
 .replace(/\s+|_/g,' ')// (multiple) whitespace
 // eslint-disable-next-line no-control-regex
 .replace(/[\x00-\x1f\x7f]/g,'')
 .replace(/%([0-9A-Fa-f]{2})/g,'% 1ドル')// URL encoding stuff
 .replace(/&(([A-Za-z0-9\x80-\xff]+|#[0-9]+|#x[0-9A-Fa-f]+);)/g,'& 1ドル')// URL-params?
 .replace(/''/g,'"')
 .replace(/[:/|#]/g,'-')
 .replace(/[\]}>]/g,')')
 .replace(/[[{<]/g,'(');

 fn=this.checkFileExt(pageName,fn,ignoreMIME)||fn;

 // Capitalize the first letter and prefix the namespace
 return'File:'+$.ucFirst(fn);// own prototype
 },

 /**
 	* @brief Compare mimetype
 	* @param [in] of old filename
 	* @param [in] fn new filename
 	* @param [in] boolean
 	* @return false if same, otherwise new file with old extension
 	*/
 checkFileExt:function(of,fn,ignoreMIME){
 varcurrentExt=(!ignoreMIME&&this.mimeFileExtension)?
 this.mimeFileExtension:
 of.replace(/.*?\.(\w{2,5})$/,'1ドル').toLowerCase().replace('jpeg','jpg'),

 reCurrentExt=newRegExp('\\.'+mw.util.escapeRegExp(currentExt)+'$','i'),
 reDestExt=newRegExp('\\.'+mw.util.escapeRegExp(fn.replace(/.*?\.(\w{2,5})$/,'1ドル'))+'$','i');

 // If new filename is without (same) extension, add the one from the old name
 if(!reCurrentExt.test(fn)){
 // First, try to replace the old extension
 fn=fn.replace(reDestExt,'.'+currentExt);
 if(!reCurrentExt.test(fn)){
 // If this did not work, then simply append the old extension
 fn+='.'+currentExt;
 }
 }else{
 fn=false;
 }// is equal

 returnfn;
 },

 cleanReason:function(uncleanReason){
 returnuncleanReason
 .trim()// whitespace
 .replace(/(?:--|–|—)? ?~{3,5} ?/,'')// remove signature
 .replace(/\|\s/g,'&#124; ');// pipes
 },

 /**
 	* For display of progress messages.
 	*/
 showProgress:function(message){
 if(!message){
 if(this.progressDialog){
 this.progressDialog.remove();
 }

 this.progressDialog=0;
 document.body.style.cursor='default';
 return;
 }
 if($('#feedbackContainer').length){
 $('#feedbackContainer').html(message);
 }else{
 document.body.style.cursor='wait';

 this.progressDialog=$('<div>').html('<div id="feedbackContainer">'+(message||this.i18n.preparingToEdit)+'</div>').dialog({
 width:450,
 height:'auto',
 minHeight:90,
 modal:true,
 resizable:false,
 draggable:false,
 closeOnEscape:false,
 dialogClass:'ajaxDeleteFeedback',
 open:function(){
 $(this).parent().find('.ui-dialog-titlebar').hide();
 },
 close:function(){
 $(this).dialog('destroy').remove();
 }
 });
 }

 },
 /**
 	* Submit an edited page.
 	*/
 savePage:function(page,summary,callback){
 if(AQD.csrftoken){
 mw.user.tokens.set('csrfToken',AQD.csrftoken);
 }

 $.extend(true,page,{
 cb:function(r){
 AQD.secureCall(callback,r);
 },
 // text, result, query
 errCb:function(t,r){
 if(AQD.uploadersToNotify){
 // If user notify fails don't break next task (e.q. redirect to protected page, very rare)
 AQD.secureCall(callback,r);
 }
 AQD.fail(t,r);
 },
 summary:summary
 });

 mw.loader.using(['ext.gadget.libAPI'],function(){
 mw.libs.commons.api.editPage(page);
 });
 },

 movePage:function(){
 mw.user.tokens.set('csrfToken',AQD.csrftoken);
 // Some users don't get it: They want to move pages to themselves.
 if(pageName.replace(/_/g,' ')===AQD.destination){
 returnAQD.nextTask();
 }

 mw.loader.using(['ext.gadget.libAPI'],function(){
 varmoveArgs={
 cb:function(){
 AQD.nextTask();
 },
 // text, r-result, query
 errCb:function(t,r){
 if(r&&r.error&&/articleexists/.test(r.error.code)){
 AQD.disableReport=true;
 }

 AQD.fail(t,r);
 },
 from:pageName,
 to:AQD.destination,
 reason:AQD.reason,
 movetalk:true,
 watchlist:AQD.pageWasWatched?'watch':'preferences'
 };
 // Option to not leave a redirect behind, MediaWiki default does leave one behind
 // Just like movetalk, an empty parameter sets it to true
 if(AQD.wpLeaveRedirect===false){
 moveArgs.noredirect=true;
 }

 AQD.showProgress(AQD.i18n.movingFile);
 mw.libs.commons.api.movePage(moveArgs);
 });
 },

 deletePage:function(){
 mw.user.tokens.set('csrfToken',AQD.csrftoken);
 mw.loader.using(['ext.gadget.libAPI'],function(){
 AQD.showProgress(AQD.i18n.deletingFile);
 mw.libs.commons.api.deletePage({
 cb:function(){
 AQD.nextTask();
 },
 // text, result, query
 errCb:function(t,r){
 AQD.fail(t,r);
 },
 title:pageName,
 reason:AQD.reason
 });
 });
 },

 purge:function(){
 // No need for checking success, showing progress, nor for waiting for task to complete
 this.nextTask();
 $.post(this.apiURL,{
 format:'json',
 action:'purge',
 forcelinkupdate:1,
 titles:pageName
 });
 },

 /**
 	* Does a MediaWiki API request and passes the result to the supplied callback (method name).
 	*/
 queryAPI:function(params,callback){
 mw.loader.using(['ext.gadget.libAPI'],function(){
 params.action=params.action||'query';
 mw.libs.commons.api.query(params,{
 method:'GET',
 cache:false,
 cb:function(r){
 AQD.secureCall(callback,r);
 },
 // text, result, query
 errCb:function(t,r){
 AQD.fail(t,r);
 }
 });
 });
 },

 /**
 	* Method to catch errors and report where they occurred
 	*/
 secureCall:function(fn,r){
 varo=AQD;
 try{
 o.currentTask=arguments[0];
 if(typeoffn==='function'){
 // arguments is not of type array so we can't take .slice
 returnfn.apply(o,Array.prototype.slice.call(arguments,1));
 }elseif(typeoffn==='string'){
 returno[fn].apply(o,Array.prototype.slice.call(arguments,1));
 }else{
 mw.log.warn(fn,this.tasks);
 o.fail('This is not a function!');
 }
 }catch(ex){
 o.fail(ex,r);
 }
 },

 /**
 	* Simple task queue. addTask() adds a new task to the queue, nextTask() executes
 	* the next scheduled task. Tasks are specified as method names to call.
 	*/
 tasks:[],
 // list of pending tasks
 currentTask:'',
 // current task, for error reporting
 addTask:function(task){
 this.tasks.push(task);
 },
 nextTask:function(){
 this.secureCall(this.tasks.shift());
 },
 retryTask:function(){
 this.secureCall(this.currentTask);
 },

 /**
 	* Once we're all done, reload the page.
 	*/
 reloadPage:function(){
 this.showProgress();
 if(this.pageName&&this.pageName.replace(/ /g,'_')!==pageName){
 return;
 }

 location.href=mw.util.getUrl(this.destination||pageName);
 },

 /**
 	* Error handler. Throws an alert at the user and give him
 	* the possibility to retry or autoreport the error-message.
 	*/
 fail:function(err,r){
 varo=this,
 msg,
 dlgButtons={};

 if(typeoferr==='object'){
 msg=err.message+' \n\n '+err.name;
 if(err.lineNumber){
 msg+=' @line'+err.lineNumber;
 }

 err=msg;
 }
 // Mostly the same as err
 if(typeofr==='object'){
 if(r.error&&/tpt-target-page|readonly/.test(r.error.code)){
 this.disableReport=true;
 }
 }

 // err += '\n' + JSON.stringify( r );

 msg=this.i18n.taskFailure[this.currentTask]||this.i18n.genericFailure;

 // TODO: Needs cleanup
 if(this.img_summary==='Nominating for deletion'){
 msg+=' '+(this.templateAdded?this.i18n.completeRequestByHand:this.i18n.addTemplateByHand);
 }

 dlgButtons[this.i18n.retryButtonLabel]=function(){
 $(this).remove();
 o.retryTask();
 };

 if(['movePage','deletePage','notifyUploaders'].indexOf(o.currentTask)!==-1&&
 (/code 50\d|missingtitle/.test(err))){
 dlgButtons[this.i18n.ignoreButtonLabel]=function(){
 $(this).remove();
 o.nextTask();
 };
 }

 if(!this.disableReport){
 dlgButtons[this.i18n.reportButtonLabel]=function(){
 varrandomId=Math.round(Math.random()*1099511627776),
 toSend='\n== Autoreport by AjaxQuickDelete '+randomId+' ==\n'+err+
 '\nAQD version: '+o.version+
 '\n++++\n:Task: '+o.currentTask+'\n:NextTask: '+o.tasks[0]+'\n:LastTask: '+o.tasks[o.tasks.length-1]+
 '\n:Page: {{Page|1='+(o.pageName||pageName)+'}}\n:Skin: '+mw.user.options.get('skin')+
 '\n:[{{fullurl:Special:Contributions|target={{subst:urlencode:{{subst:REVISIONUSER}}}}&offset={{subst:REVISIONTIMESTAMP}}}} Contribs] '+
 '[{{fullurl:Special:Log|user={{subst:urlencode:{{subst:REVISIONUSER}}}}&offset={{subst:REVISIONTIMESTAMP}}}} Log] '+
 'before error [[User:{{subst:REVISIONUSER}}|]] ~~~~~\n\n';

 $('#feedbackContainer').contents().remove().end()
 .append($('<img>',{src:'//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif'})).css('text-align','center');

 $.post(o.apiURL,{
 action:'edit',
 format:'json',
 title:'MediaWiki talk:Gadget-AjaxQuickDelete.js/auto-errors',
 summary:'/*Autoreport by AjaxQuickDelete '+randomId+'*/ error with random id',
 appendtext:toSend,
 token:(o.csrftoken||mw.user.tokens.get('csrfToken'))
 },function(){
 o.reloadPage();
 });
 };
 }
 dlgButtons[this.i18n.abortButtonLabel]=function(){
 $(this).remove();
 };

 this.disableReport=false;
 this.showProgress();
 this.progressDialog=$('<div>').append($('<div>',{
 id:'feedbackContainer',
 html:(msg+'<br>'+this.i18n.errorDetails+'<br>'+mw.html.escape(err)+'<br>'+
 (this.tag?(this.i18n.tagWas+this.tag):'')+'<br><a href="'+mw.util.getUrl('MediaWiki talk:AjaxQuickDelete.js')+
 '" >'+this.i18n.errorReport.replace(/%BUTTON%/,'<tt>'+this.i18n.reportButtonLabel+'</tt>')+'</a>')
 })).dialog({
 width:550,
 modal:true,
 closeOnEscape:false,
 title:this.i18n.errorDlgTitle,
 dialogClass:'ajaxDeleteError',
 buttons:dlgButtons,
 close:function(){
 $(this).dialog('destroy').remove();
 }
 });
 if(mw.log.warn){
 mw.log.warn(err);
 }

 },

 /**
 	* Very simple date formatter. Replaces the substrings "YYYY", "MM" and "DD" in a
 	* given string with the UTC year, month and day numbers respectively.
 	* Also replaces "MON" with the English full month name and "DAY" with the unpadded day.
 	*/
 formatDate:function(fmt,date){
 returnmw.libs.commons.formatDate(fmt,date,
 (mw.libs.commons.api&&mw.libs.commons.api.getCurrentDate()||newDate())
 );
 },

 // Constants
 // DR subpage prefix
 requestPagePrefix:'Commons:Deletion requests/',
 // user talk page prefix
 userTalkPrefix:conf.wgFormattedNamespaces[3]+':',
 // MediaWiki API script URL
 apiURL:mw.util.wikiScript('api'),
 // Max number of errors that are allowed for silent retry
 apiErrorThreshold:10,

 // Translatable strings
 i18n:{
 toolboxLinkDelete:'Nominate for deletion',
 toolboxLinkDiscuss:'Nominate category for discussion',

 // GUI reason prompt form
 reasonForDeletion:'Why should this file be deleted?',
 reasonForDiscussion:'Why does this category need discussion?',
 moreInformation:'More information',
 loading:'Loading...',

 keptAfterDR:'This page was kept after a deletion request. Please contact the user who kept it before re-nominating.',
 hasTalkpage:'There is a talk page. Consider reading it or adding your remarks.',
 mentionedInDR:'Consider reading the deletion debate –%PAGE%– that links to this page.',
 mentionedInForum:'On %PAGE%, this page is part of a discussion.',

 // Labels
 previewLabel:'Preview:',
 submitButtonLabel:'Proceed',
 cancelButtonLabel:'Cancel',
 abortButtonLabel:'Abort',
 reportButtonLabel:'Report automatically',
 retryButtonLabel:'Retry',
 ignoreButtonLabel:'Ignore and continue',
 inverseButtonLabel:'Inverse. Keep this delete other',
 swapImagesButtonLabel:'Swap to compare',
 overlayButtonLabel:'Overlay to compare',
 expandToTextarea:'Expand to textarea',
 notifyUser:'Notify users',

 // GUI progress messages
 preparingToEdit:'Preparing to edit pages... ',
 creatingNomination:'Creating nomination page... ',
 listingNomination:'Adding nomination page to daily list... ',
 addingAnyTemplate:'Adding template to '+conf.wgCanonicalNamespace.toLowerCase()+' page... ',
 notifyingUploader:'Notifying %USER%... ',
 listingMobile:'Listing mobile upload',
 updRedir:'Updating redirects',

 // Extended version
 toolboxLinkSource:'No source',
 toolboxLinkLicense:'No license',
 toolboxLinkPermission:'No permission',
 toolboxLinkCopyvio:'Report copyright violation',
 reasonForCopyvio:'Why is this file a copyright violation?',

 // For moving files
 notAllowed:'You do not have the neccessary rights to move files',
 reasonForMove:'Why do you want to move this file?',
 moveDestination:'What should be the new filename?',
 moveOtherDestination:'The name you have specified exists. Choose a new name, please.',
 checkFileExists:'Checking whether file exists',
 movingFile:'Moving file',
 replacingUsage:'Ordering CommonsDelinker to replace all usage',
 dropdownMove:'Move & Replace',
 leaveRedirect:'Leave a redirect behind:',
 moveAndReplace:'Move file and replace all usage',
 warnRename:'File renaming was recently declined, be prudent!',

 // For declining any request
 removingTemplate:'Removing template',
 declineRequest:'Why do you want to decline the request?',
 anyDecline:'Decline request',

 // For Duplicates
 useCORSForReplace:'Try to replace usage immediately using your user account:',
 deletingFile:'Deleting file',
 compareDetails:'Please compare the images before merging the descriptions. The image with the bold text will be deleted.',
 mergeDescription:'Please now merge the file descriptions',
 redirectingFile:'Redirecting file',
 savingDescription:'Saving new details',
 processDupes:'Process Duplicates',

 // Errors
 errorDlgTitle:'Error',
 genericFailure:'An error occurred while trying to do the requested action. ',
 taskFailure:{
 listUploaders:'An error occurred while determining the '+(nsNr===6?' uploader(s) of this file':'creator of this page')+'.',
 loadPages:'An error occurred while preparing to nominate this '+conf.wgCanonicalNamespace.toLowerCase()+' for deletion.',
 prependDeletionTemplate:'An error occurred while adding the {{delete}} template to this '+conf.wgCanonicalNamespace.toLowerCase()+'.',
 createRequestSubpage:'An error occurred while creating the request subpage.',
 listRequestSubpage:'An error occurred while adding the deletion request to today’s log.',
 notifyUploaders:'An error occurred while notifying the '+(nsNr===6?' uploader(s) of this file':'creator of this page')+'.',
 movePage:'Error while moving the page.',
 deletePage:'Error deleting the page.'
 },
 addTemplateByHand:'To nominate this '+conf.wgCanonicalNamespace.toLowerCase()+' for deletion, please edit the page to add the {{delete}} template and follow the instructions shown on it.',
 completeRequestByHand:'Please follow the instructions on the deletion notice to complete the request.',
 errorDetails:'A detailed description of the error is shown below:',
 errorReport:'Manually report the error here or click on %BUTTON% to send an automatic error-report.',
 tagWas:'The tag to be inserted into this page was ',

 // Minor errors/warnings
 templateRegExp:'The template does not expose a valid regular expression for {{X-To-DR}}. Go the the template and fix it there.',
 findTemplateAdderErr:'Unable to find the person who added the template. This can occur if the template was already removed, the page is deleted or a redirect to the template is used. In this case you must add the redirect to the RegExp of the target template.',
 dupeParaErr:'Error in the duplicate-template, check your language version!',
 dupeExistErr:'Retrieving information about %TITLE% failed. It is possible that it is deleted, the last revision is corrupt or the file is a redirect.',
 noCreatorFound:'The page you are attempting to add a tag to was deleted or moved. Unable to retrieve the content.',
 noPageFound:'The page you are attempting to modify or move is corrupted, was deleted or moved: Unable to retrieve history and contents.'
 }
 };

 AQD.preinstall();

 if(conf.wgUserLanguage!=='en'){
 $.when(mw.loader.getScript(mw.util.wikiScript()+
 '?title=MediaWiki:Gadget-AjaxQuickDelete.js/'+
 conf.wgUserLanguage+'.js&action=raw&ctype=text/javascript'
 ),$.ready).always(function(){AQD.install();});
 }else{
 $(function(){
 AQD.install();
 });
 }

 }());
 // </nowiki>

AltStyle によって変換されたページ (->オリジナル) /