MediaWiki:RenameRequest.js

/** Request renaming of an image composed in 2012 by Rillke

Thanks to all translators. 2018-08: translation blocks outsourced (by Perhelion)

@Revision: 20:43, 5 October 2019 (UTC) // /* eslint indent:[error,tab,{outerIIFEBody:0}]*/ /* global jQuery:false, mediaWiki:false, AjaxQuickDelete*/

( function ( $, mw ) { 'use strict';

if ( window.rRename || mw.config.get( 'wgNamespaceNumber' ) !== 6 ) { return; }

var RR, pn = mw.config.get( 'wgPageName' ), lang = mw.config.get( 'wgUserLanguage' ), user = mw.config.get( 'wgUserName' ), winHeight = $( window ).height, // Please update: real existing subpages, but in fact they are just fallback i18n = [ 'ar', 'az', 'be-tarask', 'bn', 'ca', 'cs', 'de', 'es', 'fa', 'fr', 'gl', 'hr', 'id', 'it', 'ja', 'kk', 'ko', 'ml', 'nl', 'pl', 'pt', 'ro', 'ru', 'sk', 'sv', 'tr', 'uk', 'yue', 'zh-hant' ];

RR = window.rRename = {

rInitPolicy: function { var hovertable = $, rInjectRationale = function ( $el, $tr ) { var data = $el.data( 'com-v' ); if ( data && $tr[ 0 ].firstElementChild && !data[ $el[ 0 ].selectedIndex ] ) { data[ $el[ 0 ].selectedIndex ] = $tr[ 0 ].firstElementChild.title; }				hovertable.siblings( '.ui-state-focus' ).removeClass( 'ui-state-focus' ); $tr.addClass( 'ui-state-focus' ); },			selectionHandler = function ( e ) { var $this = e.target; if ( $this.tagName !== 'A' || !$this.href || $this.getAttribute( 'href' )[ 0 ] !== '#' ) { e.preventDefault; }				$this = $( this ); if ( $this.index ) { RR.$selRationale.val( ( $this.data( 'com-owner' ) || $this ).data( 'v' ) ); rInjectRationale( RR.$selRationale, $this ); RR.$selRationale.triggerHandler( 'change.conv' ); }			},			skip = 0, option = 1, $owner,

rowMap = {};

this.$selRationale = $( ' ' ).attr( {			id: 'selRationale',			style: 'width: 99%',			size: 1		} ).tipsy( {			gravity: 's',			fallback: this.rI18n.tRationale,			trigger: 'focus'		} ).append( $( ' ', { value: 0 } ).text( this.rI18n.pRationale ) )/* .val(0)*/ .on( 'change', function {				var val = Number( this.value );				if ( val ) {					val = hovertable.eq( val );					rInjectRationale( $( this ), val );					RR.rPolicy.animate( { scrollTop: val.offset.top - RR.rPolicy.offset.top + RR.rPolicy.scrollTop } );				}			} );

mw.util.addCSS( 'table.hovertable tr:hover{background-color:white!important;border:1px solid #ADF!important;outline:1px solid #ADF}table.hovertable tr:hover>td{background-color:white!important;border:1px solid #ADF!important}table.hovertable tr:active>td{background:orange!important}table.hovertable tr:focus>td{background:orange!important}table.hovertable tr.ui-state-focus{outline:1px solid #7E7!important}table.hovertable{cursor:pointer}' ); hovertable = this.rPolicy .css( {				maxHeight: winHeight - 300,				overflow: 'auto'			} ) .find( 'table' ) .addClass( 'hovertable' );

this.rPolicy.data( 'com-rowmap', rowMap ); hovertable = hovertable.find( 'tr' ).each( function ( i, el ) {			if ( !i ) {				return;			}

var $el = $( el ), $tds = $el.find( 'td' ), tdVerbose = $tds.eq( 1 ).find( 'b' ).text;

$( this ).on( 'click', selectionHandler ); rowMap[ i ] = option; if ( --skip > 0 ) { $el.data( 'com-owner', $owner ); return; }			var rowspan = $tds.eq( 0 ).attr( 'rowspan' ); if ( rowspan ) { skip = Number( rowspan ); }

$owner = $el;

RR.$selRationale.append( $( ' ', { value: i } ).text( option + '. ' + tdVerbose.substr( 0, 80 ) + ( tdVerbose.length > 70 ? '…' : '' ) ) ); $el.data( 'v', i ); option++; } );		this.$selRationaleL = $( ' ', { 'for': 'txtReason', text: this.rI18n.lRationale } );	},

rInjectPolicy: function { var $dlgNode = $( '#AjaxDeleteContainer' ), reason = $( '#AjaxQuestion1' ).val, regReason = this.rConfig.addReason;

if ( !this.$injectNode.length ) { return; }

if ( !$dlgNode.length ) { $dlgNode = this.$injectNode.parent.parent; }

this.rInitPolicy; $dlgNode = $dlgNode.parent; $dlgNode.dialog( 'option', 'width', Math.max( $dlgNode.dialog( 'option', 'width' ), this.rConfig.dlg.width ) ) .prepend( this.rPolicy ) .dialog( 'option', 'position', 'center top' );

this.$injectNode.after(			this.$selRationaleL, ' ',			this.$selRationale, ' '		); this.$injectNode.remove; // Convert to RegExp regReason = mw.util.escapeRegExp( regReason ); regReason = this.rConfig.regReason = new RegExp( regReason.replace( /%NUMBER%/g, '(\\d)' ) ); if ( reason ) { if ( regReason.test( reason ) && RegExp.$1 ) { var v = Number( RegExp.$1 ); this.$selRationale.prop( 'selectedIndex', v ) .data( 'com-v', {} ); }			if ( reason.indexOf( this.rConfig.reasonSeparator ) < 0 ) { // Maybe better fallback if ( /\)( [^\s] )/.test( reason ) && RegExp.$1 ) {					this.rConfig.reasonSeparator = RegExp.$1;				} else {					this.rConfig.reasonSeparator = ;				}			}		} else {			this.rConfig.reasonSeparator = ;		}		this.$selRationale.on( 'change.conv', function { RR.convertRationale( this ); } );		this.showProgress;	},

convertRationale: function ( $selRationale ) { // TODO: id is not for sure var $reason = $( '#AjaxQuestion1' ), reason = '', rationale = '', // rationaleTmp = '', rationaleNr = 0; $selRationale = $( $selRationale ); if ( !$reason.length || !$selRationale.length ) { return; }

if ( ( rationaleNr = Number( $selRationale.val ) ) ) { rationaleNr = this.rPolicy.data( 'com-rowmap' )[ rationaleNr ]; rationale = this.rConfig.addReason.replace( /%NUMBER%/g, rationaleNr ); if ( ( reason = $selRationale.data( 'com-v' ) ) ) { if ( ( rationaleNr = reason[ rationaleNr ] ) ) { rationale += ' (' + rationaleNr + ')'; }			}			reason = $reason.val; if ( this.rConfig.reasonSeparator ) { reason = reason.split( this.rConfig.reasonSeparator ); reason = reason[ ( reason[ 1 ] ? 1 : 0 ) ]; }

rationaleNr = new RegExp( this.rConfig.regReason.source + '( \\([^\\n]+\\))?' ); reason = reason.replace( rationaleNr, '' ); reason = reason ? this.rConfig.reasonSeparator + reason : ''; $reason.val( rationale + reason ); }	},

rDialog: function { var dlgButtons = {}, $submitButton, $txtNewNameL = $( ' ', {				'for': 'txtNewName',				text: this.rI18n.lNewName			} ), $txtReasonL = $( ' ', {				'for': 'txtReason',				text: this.rI18n.lReason			} );

this.$txtNewName = $( ' ', {			id: 'txtNewName',			type: 'text',			style: 'width: 99%',			maxLength: 255,			placeholder: this.rI18n.pNewName,			value: pn		} ).on( 'change', function {			var val = RR.cleanFileName( this.value ).replace( /%/g, ' ' );			if ( val !== this.value ) {				this.value = val;			}

} ).trigger( 'keyup' ).tipsy( { gravity: 's', fallback: this.rI18n.tNewName, trigger: 'focus' } );		this.$txtReason = $( ' ' ).attr( { id: 'txtReason', type: 'text', style: 'width: 99%', placeholder: this.rI18n.pReason } ).tipsy( { gravity: 's', fallback: this.rI18n.tReason, trigger: 'focus' } );

this.rInitPolicy;

[ this.$txtNewName, this.$selRationale, this.$txtReason ].forEach( function ( el ) {			el.on( 'keyup', function ( e ) { $submitButton.submitOnEnter( e ); } );		} );

this.$dlgNode = $( ' ', { style: 'border:1px solid white' } ).append(			this.rPolicy,			$txtNewNameL, ' ',			this.$txtNewName, ' ',			this.$selRationaleL, ' ',			this.$selRationale, '  ',			$txtReasonL, ' ',			this.$txtReason		);

dlgButtons[ this.rI18n.submitButtonLabel ] = function { RR.tasks = []; RR.$dButtons.button( 'option', 'disabled', true ); RR.addTask( 'rCheckInputs' ); RR.addTask( 'doesFileExist' ); RR.fileNameExistsCB = 'rFileExists'; RR.addTask( 'rIsOnBlackList' ); RR.addTask( 'rSendRequest' ); RR.addTask( 'rReady' ); RR.nextTask; };		dlgButtons[ this.rI18n.cancelButtonLabel ] = function { $( this ).dialog( 'close' ); };		this.showProgress;

this.$dlgNode.dialog( {			modal: true,			closeOnEscape: true,			position: 'center',			title: this.rConfig.helpLink + this.rI18n.headline,			height: this.rConfig.dlg.height,			width: Math.min( $( window ).width, this.rConfig.dlg.width ),			buttons: dlgButtons,			close: function {				$( this ).dialog( 'destroy' );				$( this ).remove;				$( '.tipsy' ).remove;				RR.dlgPresent = false;			},			open: function  {				var $dlg = $( this );				$dlg.parents( '.ui-dialog' ).css( { position: 'fixed', top: Math.round( ( winHeight - Math.min( winHeight, $( '.ui-dialog.ui-widget' ).height ) ) / 2 ) + 'px' } );				RR.$dButtons = $dlg.parent.find( '.ui-dialog-buttonpane' ).find( 'button' );				$submitButton = RR.$dButtons.eq( 0 )					.specialButton( 'proceed' ).button;				$submitButton.submitOnEnter = function ( e ) {						if ( e.which === 13 && !this.button( 'option', 'disabled' ) ) {							this.trigger( 'click' );						}

};				RR.$dButtons.eq( 1 ).specialButton( 'cancel' ); },			create: function { $( this ).dialog( 'option', 'position', 'center' ); }		} );

this.dlgPresent = true; },

rGetPolicy: function { if ( this.rPolicy ) { return this.nextTask; }

$.ajax( {			url: mw.config.get( 'wgScript' ),			dataType: 'html',			data: {				action: 'render',				title: RR.rConfig.reasonPage,				uselang: lang			},			cache: true,			success: function ( result ) {				RR.rPolicy = $( result ).find( '#onlyinclude' );				RR.nextTask;			},			error: function ( x, status, error ) {				RR.fail( 'RenameLink: Error getting policy. Server status: ' + x.status + ' - Error: ' + error );			}		} ); },	rAbort: function ( $el, text ) { this.tasks = []; setTimeout( function {			RR.$txtReason.removeAttr( 'title' );			RR.$selRationale.removeAttr( 'title' );			RR.$txtNewName.removeAttr( 'title' );			RR.$dButtons.button( 'option', 'disabled', false );			$el.removeClass( 'ui-state-error' );		}, 4000 ); this.showProgress; $el.attr( 'title', text ).trigger( 'focus' ); $el.addClass( 'ui-state-error' ); },	rCheckInputs: function { this.showProgress( this.rI18n.progress.input ); this.destination = this.rNewName = this.cleanFileName( this.$txtNewName.val ).replace( /^File:/, '' ); if ( !Number( this.$selRationale.val ) ) { return this.rAbort( this.$selRationale, this.rI18n.invalidRationale ); }

if ( this.rNewName.length < 5 ) { return this.rAbort( this.$txtNewName, this.rI18n.nameToShort ); }

if ( this.rNewName.length > 255 ) { return this.rAbort( this.$txtNewName, this.rI18n.genericFailure ); }

if ( this.rNewName === this.cleanFileName( pn ).replace( /^File:/, '' ) ) { return this.rAbort( this.$txtNewName, this.rI18n.newName ); }

// Test whether user selected first reason if ( Number( this.$selRationale.val ) === 1 ) { var query = { prop: 'imageinfo', iiprop: 'user', iilimit: 100, titles: pn.replace( /_/g, ' ' ) };			return this.queryAPI( query, 'rCheckInputsCB' ); }		this.nextTask; },	rCheckInputsCB: function ( result ) { if ( !result || !result.query || !result.query.pages ) { return this.nextTask; }

var hasRevisions, isByUser; $.each( result.query.pages, function ( id, pg ) {			var info = pg.imageinfo;			if ( info ) {				hasRevisions = true;				for ( var i = 0, ii; i < info.length; i++ ) {					ii = info[ i ];					if ( ii.user === user ) {						isByUser = true;						break;					}				}			}		} ); if ( hasRevisions && !isByUser ) { return this.rAbort( this.$selRationale, this.rI18n.notTheUploader ); } else { return this.nextTask; }

},	rFileExists: function ( /* r*/ ) { return this.rAbort( this.$txtNewName, this.rI18n.moveOtherDestination ); },	rIsOnBlackList: function { var query = { action: 'titleblacklist', tbtitle: 'File:' + this.rNewName, tbaction: 'create' };		this.showProgress( this.rI18n.progress.blacklisted ); this.queryAPI( query, 'rIsBlacklistedCB' ); },	rIsBlacklistedCB: function ( result ) { if ( !result || !result.titleblacklist || !result.titleblacklist.result ) { throw new Error( 'RenameLink: result.titleblacklist is undefined.' ); }

if ( result.titleblacklist.result === 'blacklisted' ) { return this.rAbort( this.$txtNewName, this.rI18n.blacklisted ); }

return this.nextTask; },	rSendRequest: function { this.edittoken = this.edittoken || mw.user.tokens.get( 'csrfToken' ); var doEdit = function ( result ) { var editType, comRationale = RR.rPolicy.data( 'com-rowmap' )[ Number( RR.$selRationale.val ) ], newText = RR.rConfig.addTmpl .replace( '%NEWFILE%', RR.rNewName ) .replace( '%REASON%', RR.$txtReason.val ) .replace( '%NUMBER%', comRationale );

if ( result ) { newText += result.replace( RR.rConfig.regRmvTmpl, '' ); editType = 'text'; } else { editType = 'prependtext'; }

var page = { title: pn.replace( /_/g, ' ' ), text: newText, editType: editType, tags: 'RenameLink' };			RR.showProgress( RR.rI18n.progress.edit ); RR.savePage( page, RR.rConfig.summary				.replace( '%NEWFILE%', RR.rNewName )				.replace( '%REASON%', RR.$txtReason.val )				.replace( '%NUMBER%', comRationale )				.replace( ' Reason: ;', '' ), 'nextTask' ); };		$.get( mw.config.get( 'wgScript' ), {			action: 'raw',			title: pn,			maxage: 0,			// smaxage: 0,			dummy: Math.round( Math.random * 1073741824 )		}, doEdit ) .fail( function ( jqXHR, textStatus/*, errorThrown*/ ) {				if ( jqXHR.status === 404 ) {					return doEdit( '' );				}

RR.fail( 'Error retrieving wikitext. Server status ' + jqXHR.status + ' \nERR: ' + textStatus + '.' ); } );		this.showProgress( this.rI18n.progress.load );	},	rReady: function ( /* r*/ ) {		this.showProgress;		document.location.reload;	},	rRun: function {		if ( RR.initDone ) {			return;		}

$.extend( true, AjaxQuickDelete, RR ); RR = AjaxQuickDelete; // save some code-lines by assigning similar languages // merge languages $.extend( true, RR.rI18n, RR.rI18n[ lang ] ); RR.initDone = true;

mw.hook( 'aqd.renamerequest.run' ).add( function ( c ) {			if ( !c ) {				return;			}

if ( c === 'start' ) { RR.showProgress( RR.rI18n.progress.policy ); RR.tasks = []; RR.addTask( 'rGetPolicy' ); RR.addTask( 'rDialog' ); RR.nextTask; } else if ( typeof c === 'object' && 'exec' in c ) { RR.showProgress( RR.rI18n.progress.policy ); RR.$injectNode = $( c.exec ); RR.tasks.unshift( 'rInjectPolicy' ); RR.tasks.unshift( 'rGetPolicy' ); RR.nextTask; }		} );		mw.hook( 'aqd.renamerequest.ready' ).fire;

},	rInit: function ( rI18n ) { if ( lang === 'en' || RR.initDone ) { return $.Deferred.resolve; }

if ( rI18n && ( rI18n = Object.keys( rI18n ) ).length ) { i18n = rI18n; }

// Take fallback language if not exist in i18n list. if ( i18n.indexOf( lang ) === -1 ) { var i,				chain = mw.language.getFallbackLanguages; for ( i = chain.length - 1; i >= 0; i-- ) { if ( i18n.indexOf( chain[ i ] ) !== -1 ) { lang = chain[ i ]; }

}

}		// Import another set of messages, which either // does nothing (if the subpage doesn't exist) // or re-sets one or more messages into the user language return mw.loader.getScript(			mw.util.wikiScript + '?title=MediaWiki:RenameRequest.js/' + lang + '.js&action=raw&ctype=text/javascript'		); },	// Translation // This should be changed when gadg ets 2.0 are available rI18n: { submitButtonLabel: 'Request renaming', proceedButtonLabel: 'Proceed', cancelButtonLabel: 'Cancel', headline: 'Renaming a file', lNewName: 'Enter the new name', tNewName: 'Enter the desired file name', pNewName: 'new name', lRationale: 'Rationale according to the policy', tRationale: 'Provide a valid reason or select one from the table', pRationale: 'Select a reason', lReason: 'Additional explanation / reason / justification', tReason: 'Optional: Provide details', pReason: 'additional reason or justification', lAccept: 'I acknowledge that repeated non-justified rename requests will block this feature for me.', invalidRationale: 'Select a valid rationale', nameToShort: 'Name is too short', newName: 'Please specify a *new* name', notTheUploader: 'Be honest: You are not the uploader', // nameExists: 'There is already a file with the specified file name - Please choose another name', blacklisted: 'This name is blacklisted - Please choose another name', progress: { policy: 'Loading policy', input: 'Checking input', blacklisted: 'Checking whether the new file name is blacklisted', load: 'Loading Wikitext', edit: 'Requesting a filemover to move this file' }	},	// Configuration rConfig: { reasonPage: 'Template:File renaming reasons/render', regRmvTmpl: /\{\{\s*(?:[Rr]ename|[Bb]ad name)[^\{\}]*\}\}(?:\s*)?/, addTmpl: '\n', addReason: 'Criterion %NUMBER%', // Match Template:Rename/Sub reasonSeparator: ' · ', // Match Template:Rename/Sub summary: 'Requesting renaming this file to ; Reason: %REASON%; Criterion %NUMBER%', dlg: { width: 850, height: ( winHeight > 770 ? 'auto' : winHeight ) },		helpLink: ' ' } };

$.when( mw.loader.using( [ 'ext.gadget.AjaxQuickDelete', 'ext.gadget.libJQuery', 'jquery.tipsy', 'mediawiki.language' ] ), $.ready ) .always( function {		mw.hook( 'aqd.renamerequest.i18n' ).add( function ( l ) { RR.rInit( l ).always( RR.rRun ); } );	} );

}( jQuery, mediaWiki ) ); //