User:MacFan4000/common.js

/** * Cat-A-Lot * Changes category of multiple files * * Originally by Magnus Manske * RegExes by Ilmari Karonen * Completely rewritten by DieBuche * * Requires MediaWiki:Gadget-SettingsManager.js and MediaWiki:Gadget-SettingsUI.js (properly registered) for per-user-settings * * READ THIS PAGE IF YOU WANT TO TRANSLATE OR USE THIS ON ANOTHER SITE: * http://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js/translating * */

/*global jQuery:false, mediaWiki:false, alert:false, importStylesheet:false */ /*jshint curly:false, unused:true, unused:true, forin:false, smarttabs:true, loopfunc:true, browser:true */

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

var nsNumber = mw.config.get( 'wgNamespaceNumber' ), nsCat = 14, currentCat = mw.config.get( 'wgTitle' ), formattedNS = mw.config.get( 'wgFormattedNamespaces' ), nsIDs = mw.config.get( 'wgNamespaceIds' ), catALot;

var msgs = { // Preferences // new: added 2012-09-19. Please translate. // Use user language for i18n 'cat-a-lot-watchlistpref': "Watchlist preference concerning files edited with Cat-A-Lot", 'cat-a-lot-watch_pref': "According to your general preferences", 'cat-a-lot-watch_nochange': "Do not change watchstatus", 'cat-a-lot-watch_watch': "Watch pages edited with Cat-A-Lot", 'cat-a-lot-watch_unwatch': "Remove pages while editing with Cat-A-Lot from your watchlist", 'cat-a-lot-minorpref': "Mark edits as minor (if you generally mark your edits as minor, this won't change anything)", 'cat-a-lot-editpagespref': "Allow categorising pages (including categories) that are not files", 'cat-a-lot-docleanuppref': "Remove and other minor cleanup", 'cat-a-lot-subcatcountpref': "Sub-categories to show at most", 'cat-a-lot-config-settings': " ", // Use site language for i18n 'cat-a-lot-pref-save-summary': "Cat-a-lot is updating user preferences",

//Progress 'cat-a-lot-loading': 'Loading...', 'cat-a-lot-editing': 'Editing page', 'cat-a-lot-of': 'of ', 'cat-a-lot-skipped-already': 'The following NaN undefineds skipped, because the page was already in the category:', 'cat-a-lot-skipped-not-found': 'The following NaN undefineds skipped, because the old category could not be found:', 'cat-a-lot-skipped-server': 'The following NaN undefineds couldn\'t be changed, since there were problems connecting to the server:', 'cat-a-lot-all-done': 'All pages are processed.', 'cat-a-lot-done': 'Done!', 'cat-a-lot-added-cat': 'Added category $1', 'cat-a-lot-copied-cat': 'Copied to category $1', 'cat-a-lot-moved-cat': 'Moved to category $1', 'cat-a-lot-removed-cat': 'Removed from category $1', 'cat-a-lot-return-to-page': 'Return to page', 'cat-a-lot-cat-not-found': 'Category not found.',

//as in 17 files selected 'cat-a-lot-files-selected': 'NaN undefineds selected.',

//Actions 'cat-a-lot-copy': 'Copy', 'cat-a-lot-move': 'Move', 'cat-a-lot-add': 'Add', 'cat-a-lot-remove-from-cat': 'Remove from this category', 'cat-a-lot-enter-name': 'Enter category name', 'cat-a-lot-select': 'Select', 'cat-a-lot-all': 'all', 'cat-a-lot-none': 'none',

'cat-a-lot-none-selected': 'No files selected!',

//Summaries: 'cat-a-lot-summary-add': 'Cat-a-lot: Adding ', 'cat-a-lot-summary-copy': 'Cat-a-lot: Copying from to ', 'cat-a-lot-summary-move': 'Cat-a-lot: Moving from to ', 'cat-a-lot-summary-remove': 'Cat-a-lot: Removing from ' };	mw.messages.set( msgs ); function msg( /*params*/ ) { var args = Array.prototype.slice.call( arguments, 0 ); args[0] = 'cat-a-lot-' + args[0]; return mw.message.apply( mw.message, args ).parse; }	function msgPlain( key ) { return mw.message( 'cat-a-lot-' + key ).plain; }	// There is only one cat-a-lot on one page var $removeLink, $body, $container, $dataContainer, $searchInputContainer, $searchInput, $resultList, $markCounter, $selections, $selectAll, $selectNone, $settingsWrapper, $settingsLink, $head, $link; catALot = window.catALot = { apiUrl: mw.util.wikiScript( 'api' ), searchmode: false, version: 3.5, setHeight: 450, settings: {}, init: function { this._initSettings;

$body = $( document.body ); $container = $( ' ' ) .appendTo( $body ); $dataContainer = $( ' ' ) .appendTo( $container ); $searchInputContainer = $( ' ' ) .appendTo( $dataContainer ); $searchInput = $( '' ) .attr( 'placeholder', msgPlain( 'enter-name' ) ) .appendTo( $searchInputContainer ); $resultList = $( ' ' ) .appendTo( $dataContainer ); $markCounter = $( ' ' ) .appendTo( $dataContainer ); $selections = $( ' ' ) .text( msgPlain( 'select' ) ) .appendTo( $dataContainer ); $selectAll = $( '' ) .text( msgPlain( 'all' ) ) .appendTo( $selections.append(' ') ); $selectNone = $( '' ) .text( msgPlain( 'none' ) ) .appendTo( $selections.append(' • ') ); $settingsWrapper = $( ' ' ) .appendTo( $dataContainer ); $settingsLink = $( '' ) .text( msgPlain( 'config-settings' ) ) .appendTo( $settingsWrapper ); $head = $( ' ' ) .appendTo( $container ); $link = $( '' ) .text( 'Cat-a-lot' ) .appendTo( $head );

if ( !this.searchmode ) { $removeLink = $( '</a>' ) .html( msg( 'remove-from-cat' ) ) .appendTo( $selections ) .click( function {						catALot.remove;					} ); }

if ( ( 'MediaWiki:Gadget-Cat-a-lot.js' === mw.util.getParamValue( 'withJS' ) && !mw.util.getParamValue( 'withCSS' ) ) ||				mw.loader.getState('ext.gadget.Cat-a-lot') === 'registered' ) { importStylesheet( 'MediaWiki:Gadget-Cat-a-lot.css' ); }

var reCat = new RegExp( '^\\s*' + catALot.localizedRegex( nsCat, 'Category' ) + ':', '' );

$searchInput.keypress( function( e ) {					if ( e.which === 13 ) {						catALot.updateCats( $.trim( $( this )							.val ) );					}				} ) .bind( 'input keyup', function {					var oldVal = this.value,						newVal = oldVal.replace( reCat, '' );					if ( newVal !== oldVal ) this.value = newVal;				} ); if ( this.searchmode ) { $searchInput.val( mw.util.getParamValue( 'search' ) ); }			function initAutocomplete { if ( catALot.autoCompleteIsEnabled ) return; catALot.autoCompleteIsEnabled = true;

$searchInput.autocomplete( {					source: function( request, response ) {						catALot.doAPICall( { action: 'opensearch', search: request.term, redirects: 'resolve', namespace: nsCat }, function( data ) { if ( data[ 1 ] ) response( $( data[ 1 ] )								.map( function( index, item ) { return item.replace( reCat, '' ); } ) );						} );					},					open: function {						$( ".ui-autocomplete" )							.position( { my: $( 'body' ) .is( '.rtl' ) ? "left bottom" : "right bottom", at: $( 'body' ) .is( '.rtl' ) ? "left top" : "right top", of: $searchInput } );					},					appendTo: '#cat_a_lot'				} ); }

$selectAll .click( function {					catALot.toggleAll( true );				} ); $selectNone .click( function {					catALot.toggleAll( false );				} ); $link .click( function {					$( this ).toggleClass( 'cat_a_lot_enabled' );					// Load autocomplete on demand					mw.loader.using( ['jquery.ui.autocomplete'], initAutocomplete );					catALot.run;				} ); $settingsLink .click( function {					catALot.manageSettings;				} );

this.localCatName = formattedNS[ nsCat ]; },		findAllLabels: function { // It's possible to allow any kind of pages as well but what happens if you click on "select all" and don't expect it			if ( this.searchmode ) { this.labels = $( 'table.searchResultImage' ) .find( 'tr>td:eq(1)' ); if ( this.settings.editpages ) { this.labels = this.labels.add( 'div.mw-search-result-heading' ); }			} else { this.labels = $( 'div.gallerytext' ) .add( $( 'div#mw-category-media' )						.find( 'li[class!="gallerybox"]' ) );

if ( this.settings.editpages ) { var $pgs = $( 'div#mw-pages, div#mw-subcategories' ) .find( 'li' ); this.labels = this.labels.add( $pgs ); }			}		},

getTitleFromLink: function( href ) { try { return decodeURIComponent( href ) .match( /wiki\/(.+?)(?:#.+)?$/ )[ 1 ].replace( /_/g, ' ' ); } catch ( ex ) { return ''; }		},

getMarkedLabels: function { var marked = []; this.selectedLabels = this.labels.filter( '.cat_a_lot_selected' ); this.selectedLabels.each( function {				var file = $( this )					.find( 'a[title]' ),					title = file.attr( 'title' ) || catALot.getTitleFromLink( file.attr( 'href' ) ) || catALot.getTitleFromLink( $( this ) .find( 'a' ) .attr( 'href' ) );

marked.push( [ title, $( this ) ] ); } );			return marked;		},

updateSelectionCounter: function { this.selectedLabels = this.labels.filter( '.cat_a_lot_selected' ); $markCounter .show .html( msg( 'files-selected', this.selectedLabels.length ) ); },

makeClickable: function { this.findAllLabels; this.labels.catALotShiftClick( function {					catALot.updateSelectionCounter;				} ) .addClass( 'cat_a_lot_label' ); },

toggleAll: function( select ) { this.labels.toggleClass( 'cat_a_lot_selected', select ); this.updateSelectionCounter; },

getSubCats: function { var data = { action: 'query', list: 'categorymembers', cmtype: 'subcat', cmlimit: this.settings.subcatcount, cmtitle: 'Category:' + this.currentCategory };

this.doAPICall( data, function( result ) {

var cats = result.query.categorymembers;

catALot.subCats = []; for ( var i = 0; i < cats.length; i++ ) { catALot.subCats.push( cats[ i ].title.replace( /^[^:]+:/, "" ) ); }				catALot.catCounter++; if ( catALot.catCounter === 2 ) catALot.showCategoryList; } );		},

getParentCats: function { var data = { action: 'query', prop: 'categories', titles: 'Category:' + this.currentCategory };			this.doAPICall( data, function( result ) {				catALot.parentCats = [];				var cats, pages = result.query.pages;				if ( pages[ -1 ] && pages[ -1 ].missing === '' ) {					$resultList.html( '<span id="cat_a_lot_no_found">' + msg( 'cat-not-found' ) + ' ' );					document.body.style.cursor = 'auto';

$resultList.append( ' ' );

this.createCatLinks( "↑", this.parentCats ); this.createCatLinks( "→", thiscat ); this.createCatLinks( "↓", this.subCats );

document.body.style.cursor = 'auto'; //Reset width $container.width( '' ); $container.height( '' ); $container.width( Math.min( $container.width * 1.1 + 15, $( window ).width - 10 ) );

$resultList.css( {				maxHeight: this.setHeight + 'px',				height: ''			} ); },

updateCats: function( newcat ) { document.body.style.cursor = 'wait';

this.currentCategory = newcat; $resultList.html( '<div class="cat_a_lot_loading"> ' ).text( msgPlain( 'loading' ) ); this.getCategoryList; },		showProgress: function { document.body.style.cursor = 'wait';

this.progressDialog = $( ' ' ) .html( msg( 'editing' ) + ' <span id="cat_a_lot_current">' + this.counterCurrent + ' ' + msg( 'of' ) + this.counterNeeded ) .dialog( {					width: 450,					height: 90,					minHeight: 90,					modal: true,					resizable: false,					draggable: false,					closeOnEscape: false,					dialogClass: "cat_a_lot_feedback"				} ); $( '.ui-dialog-titlebar' ) .hide; this.domCounter = $( '#cat_a_lot_current' );

},

run: function { if ( $( '.cat_a_lot_enabled' ).length ) { this.makeClickable; $dataContainer .show; $container .resizable( {						handles: 'n',						alsoResize: '#cat_a_lot_category_list',						resize: function {							$( this )								.css( { left: '', top: '' } );							catALot.setHeight = $( this )								.height;							$resultList								.css( { maxHeight: '', width: '' } );						}					} );				$resultList .css( {						maxHeight: '450px'					} ); if ( this.searchmode ) this.updateCats( "Pictures and images" ); else this.updateCats( currentCat );

} else { $dataContainer .hide; $container .resizable( "destroy" ); //Unbind click handlers this.labels.unbind( 'click.catALot' ); }		},

manageSettings: function { mw.loader.using( [ 'ext.gadget.SettingsManager', 'ext.gadget.SettingsUI', 'jquery.ui.progressbar' ], function {				catALot._manageSettings;			} ); },		_manageSettings: function { window.mw.libs.SettingsUI( this.defaults, "Cat-A-Lot" ) .show .done( function( s, verbose, loc, settingsOut, $dlg ) {					var mustRestart = false,						_restart = function {							if ( !mustRestart ) return;

$container.remove; catALot.labels.unbind( 'click.catALot' ); catALot.init; },						_saveToJS = function { var opt = mw.libs.settingsManager.option( {									optionName: 'catALotPrefs',									value: catALot.settings,									encloseSignature: 'catALot',									encloseBlock: '////////// Cat-A-Lot user preferences //////////\n',									triggerSaveAt: /Cat.?A.?Lot/i,									editSummary: msgPlain( 'pref-save-summary' )								} ), oldHeight = $dlg.height, $prog = $( ' ' );

$dlg.css( 'height', oldHeight ) .html( '' ); $prog.css( {									'height': Math.round( oldHeight / 8 ),									'margin-top': Math.round( ( 7 * oldHeight ) / 16 )								} ) .appendTo( $dlg );

$dlg.parent .find( '.ui-dialog-buttonpane button' ) .button( 'option', 'disabled', true );

opt.save .done( function( text, progress ) {									$prog.progressbar( { value: progress } );									$prog.fadeOut( function { $dlg.dialog( 'close' ); _restart; } );								} )								.progress( function( text, progress ) {									$prog.progressbar( { value: progress } );									// TODO: Add "details" to progressbar								} ) .fail( function( text ) {									$prog.addClass( 'ui-state-error' );									$dlg.prepend( $( ' ' ) .text( text ) );								} ); };					$.each( settingsOut, function( n, v ) {						if ( v.forcerestart && catALot.settings[ v.name ] !== v.value ) {							mustRestart = true;						}						catALot.settings[ v.name ] = v.value;						window.catALotPrefs[ v.name ] = v.value;					} ); switch ( loc ) { case 'page': $dlg.dialog( 'close' ); _restart; break; case 'account-publicly': _saveToJS; break; }				} );		},		_initSettings: function {			if ( this.settings.watchlist ) return;			if ( !window.catALotPrefs ) window.catALotPrefs = {};			$.each( this.defaults, function( n, v ) { v.value = catALot.settings[ v.name ] = ( window.catALotPrefs[ v.name ] || v[ 'default' ] ); v.label = msgPlain( v.label_i18n ); if ( v.select_i18n ) { v.select = {}; $.each( v.select_i18n, function( i18nk, val ) {						v.select[ msgPlain( i18nk ) ] = val;					} ); }			} );		},		defaults: [ {			name: 'watchlist',			'default': 'preferences',			label_i18n: 'watchlistpref',			select_i18n: {				'watch_pref': 'preferences',				'watch_nochange': 'nochange',				'watch_watch': 'watch',				'watch_unwatch': 'unwatch'			}		}, {			name: 'minor',			'default': false,			label_i18n: 'minorpref'		}, {			name: 'editpages',			'default': true,			label_i18n: 'editpagespref',			forcerestart: true		}, {			name: 'docleanup',			'default': false,			label_i18n: 'docleanuppref'		}, {			name: 'subcatcount',			'default': 50,			'min': 5,			'max': 500,			label_i18n: 'subcatcountpref',			forcerestart: true		} ]	};

if ( ( nsNumber === -1 && mw.config.get( 'wgCanonicalSpecialPageName' ) === "Search" ) || nsNumber === nsCat ) { if ( nsNumber === -1 ) { catALot.searchmode = true; }		var loadingLocalizations = 1; var loadLocalization = function( lang, cb ) { loadingLocalizations++; switch ( lang ) { case 'zh-hk': case 'zh-mo': case 'zh-tw': lang = 'zh-hant'; break; case 'zh': case 'zh-cn': case 'zh-my': case 'zh-sg': lang = 'zh-hans'; break;

}			$.ajax( {				url: mw.util.wikiScript,				dataType: 'script',				data: {					title: 'MediaWiki:Gadget-Cat-a-lot.js/' + lang,					action: 'raw',					ctype: 'text/javascript',					// Allow caching for 28 days					maxage: 2419200,					smaxage: 2419200				},				cache: true,				success: cb,				error: cb			} ); };		var maybeLaunch = function { loadingLocalizations--; function init { $( document ).ready( function {						catALot.init;					} ); }			if ( 0 === loadingLocalizations ) { mw.loader.using( [ 'user' ], init, init ); }		};

if ( mw.config.get( 'wgUserLanguage' ) !== 'en' ) { loadLocalization( mw.config.get( 'wgUserLanguage' ), maybeLaunch ); }		if ( mw.config.get( 'wgContentLanguage' ) !== 'en' ) { loadLocalization( mw.config.get( 'wgContentLanguage' ), maybeLaunch ); }		maybeLaunch; }

} )( jQuery, mediaWiki );

/** * Derivative work of *  (replace "checkboxes" with cat-a-lot labels in your mind) */ /** * jQuery checkboxShiftClick * * This will enable checkboxes to be checked or unchecked in a row by clicking one, holding shift and clicking another one * * @author Krinkle <krinklemail@gmail.com> * @license GPL v2 */ ( function( $ ) {	$.fn.catALotShiftClick = function( cb ) {		var prevCheckbox = null,			$box = this;		// When our boxes are clicked..		$box.bind( 'click.catALot', function( e ) {

// Prevent following the link and text selection e.preventDefault;

// Highlight last selected $( '#cat_a_lot_last_selected' ) .removeAttr( 'id' ); var $thisControl = $( e.target ), method; if ( !$thisControl.hasClass( 'cat_a_lot_label' ) ) { $thisControl = $thisControl.parents( '.cat_a_lot_label' ); }			$thisControl.attr( 'id', 'cat_a_lot_last_selected' ) .toggleClass( 'cat_a_lot_selected' );

// And one has been clicked before... if ( prevCheckbox !== null && e.shiftKey ) { method = $thisControl.hasClass( 'cat_a_lot_selected' ) ? 'addClass' : 'removeClass';

// Check or uncheck this one and all in-between checkboxes $box.slice(					Math.min( $box.index( prevCheckbox ), $box.index( $thisControl ) ),					Math.max( $box.index( prevCheckbox ), $box.index( $thisControl ) ) + 1				)[ method ]( 'cat_a_lot_selected' ); }			// Either way, update the prevCheckbox variable to the one clicked now prevCheckbox = $thisControl;

if ( $.isFunction( cb ) ) cb; } );		return $box;	}; }( jQuery ) );

//