檢視 MediaWiki:Gadget-Cat-a-lot.js 的原始碼
←
MediaWiki:Gadget-Cat-a-lot.js
跳至導覽
跳至搜尋
由於以下原因,您無權編輯此頁面:
本頁用來提供此 Wiki 軟體介面上的文字,並且已被設為保護以防止惡意修改。 如欲增加或修改 Wiki 的翻譯,請至
translatewiki.net
上的 MediaWiki 在地化專案。
您沒有權限來編輯此 JavaScript 頁面,因為這會影響到所有的網站訪客。
您可以檢視並複製此頁面的原始碼。
/** * 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 * <nowiki> */ /*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 {{Check categories}} and other minor cleanup", 'cat-a-lot-subcatcountpref': "Sub-categories to show at most", 'cat-a-lot-config-settings': "Preferences", // Use site language for i18n 'cat-a-lot-pref-save-summary': "[[Help:Gadget-Cat-a-lot|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 {{PLURAL:$1|page was|$1 pages were}} skipped, because the page was already in the category:', 'cat-a-lot-skipped-not-found': 'The following {{PLURAL:$1|page was|$1 pages were}} skipped, because the old category could not be found:', 'cat-a-lot-skipped-server': 'The following {{PLURAL:$1|page|$1 pages}} 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': '{{PLURAL:$1|One file|$1 files}} 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': '[[Help:Cat-a-lot|Cat-a-lot]]: Adding [[Category:$1]]', 'cat-a-lot-summary-copy': '[[Help:Cat-a-lot|Cat-a-lot]]: Copying from [[Category:$1]] to [[Category:$2]]', 'cat-a-lot-summary-move': '[[Help:Cat-a-lot|Cat-a-lot]]: Moving from [[Category:$1]] to [[Category:$2]]', 'cat-a-lot-summary-remove': '[[Help:Cat-a-lot|Cat-a-lot]]: Removing from [[Category:$1]]' }; 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: {}, _variantCache: {}, init: function() { this._initSettings(); $body = $( document.body ); $container = $( '<div id="cat_a_lot"></div>' ) .appendTo( $body ); $dataContainer = $( '<div id="cat_a_lot_data"></div>' ) .appendTo( $container ); $searchInputContainer = $( '<div>' ) .appendTo( $dataContainer ); $searchInput = $( '<input type="text" id="cat_a_lot_searchcatname" />' ) .attr( 'placeholder', msgPlain( 'enter-name' ) ) .appendTo( $searchInputContainer ); $resultList = $( '<div id="cat_a_lot_category_list"></div>' ) .appendTo( $dataContainer ); $markCounter = $( '<div id="cat_a_lot_mark_counter"> </div>' ) .appendTo( $dataContainer ); $selections = $( '<div id="cat_a_lot_selections"></div>' ) .text( msgPlain( 'select' ) ) .appendTo( $dataContainer ); $selectAll = $( '<a id="cat_a_lot_select_all"></a>' ) .text( msgPlain( 'all' ) ) .appendTo( $selections.append(' ') ); $selectNone = $( '<a id="cat_a_lot_select_none"></a>' ) .text( msgPlain( 'none' ) ) .appendTo( $selections.append(' • ') ); $settingsWrapper = $( '<div id="cat_a_lot_settings"></div>' ) .appendTo( $dataContainer ); $settingsLink = $( '<a id="cat_a_lot_config_settings"></a>' ) .text( msgPlain( 'config-settings' ) ) .appendTo( $settingsWrapper ); $head = $( '<div id="cat_a_lot_head"></div>' ) .appendTo( $container ); $link = $( '<a id="cat_a_lot_toggle"></a>' ) .text( 'Cat-a-lot' ) .appendTo( $head ); if ( !this.searchmode ) { $removeLink = $( '<a id="cat_a_lot_remove"></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, 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' ) + '</span>' ); document.body.style.cursor = 'auto'; $resultList.append( '<table></table>' ); catALot.createCatLinks( "→", [ catALot.currentCategory ] ); return; } // there should be only one, but we don't know its ID for ( var id in pages ) { cats = pages[ id ].categories; } for ( var i = 0; i < cats.length; i++ ) { catALot.parentCats.push( cats[ i ].title.replace( /^[^:]+:/, "" ) ); } catALot.catCounter++; if ( catALot.catCounter === 2 ) catALot.showCategoryList(); } ); }, localizedRegex: function( namespaceNumber, fallback ) { //Copied from HotCat. Thanks Lupo. var wikiTextBlank = '[\\t _\\xA0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]+'; var wikiTextBlankRE = new RegExp( wikiTextBlank, 'g' ); var createRegexStr = function( name ) { if ( !name || name.length === 0 ) return ""; var regex_name = ""; for ( var i = 0; i < name.length; i++ ) { var initial = name.substr( i, 1 ); var ll = initial.toLowerCase(); var ul = initial.toUpperCase(); if ( ll === ul ) { regex_name += initial; } else { regex_name += '[' + ll + ul + ']'; } } return regex_name.replace( /([\\\^\$\.\?\*\+\(\)])/g, '\\$1' ) .replace( wikiTextBlankRE, wikiTextBlank ); }; fallback = fallback.toLowerCase(); var canonical = formattedNS[ namespaceNumber ].toLowerCase(); var RegexString = createRegexStr( canonical ); if ( fallback && canonical !== fallback ) RegexString += '|' + createRegexStr( fallback ); for ( var catName in nsIDs ) { if ( typeof( catName ) === 'string' && catName.toLowerCase() !== canonical && catName.toLowerCase() !== fallback && nsIDs[ catName ] === namespaceNumber ) { RegexString += '|' + createRegexStr( catName ); } } return ( '(?:' + RegexString + ')' ); }, findAllVariants: function( category ) { var result = [], baseUrl = '/w/api.php?action=parse&text=' + encodeURIComponent(category) + '&title=temp&format=json&variant='; if ( this._variantCache[category] !== undefined ) { return this._variantCache[category]; } $.each( ['zh-hans', 'zh-hant', 'zh-cn', 'zh-tw', 'zh-hg', 'zh-mo'], function( idx, variant ) { var r = ( $( $.ajax( { url: baseUrl + variant, async: false } ) .responseJSON.parse.text['*'] ) .get( 0 ).textContent ); if ( result.indexOf( r ) === -1 ) { result.push( r ); } } ); this._variantCache[category] = result; return result; }, regexBuilder: function( category ) { var variants, catname = this.localizedRegex( nsCat, 'Category' ); // Build a regexp string for matching the given category: // trim leading/trailing whitespace and underscores category = category.replace( /^[\s_]+/, "" ) .replace( /[\s_]+$/, "" ); // Find all variants variants = this.findAllVariants( category ); // escape regexp metacharacters (= any ASCII punctuation except _) category = []; $.each( variants, function( idx, variant ) { variant = mw.RegExp.escape( variant ); // any sequence of spaces and underscores should match any other variant = variant.replace( /[\s_]+/g, '[\\s_]+' ); // Make the first character case-insensitive: var first = variant.substr( 0, 1 ); if ( first.toUpperCase() !== first.toLowerCase() ) { variant = '[' + first.toUpperCase() + first.toLowerCase() + ']' + variant.substr( 1 ); } category.push( variant ); } ); // Compile it into a RegExp that matches MediaWiki category syntax (yeah, it looks ugly): // XXX: the first capturing parens are assumed to match the sortkey, if present, including the | but excluding the ]] return new RegExp( '\\[\\[[\\s_]*' + catname + '[\\s_]*:[\\s_]*(?:' + category.join( '|' ) + ')[\\s_]*(\\|[^\\]]*(?:\\][^\\]]+)*)?\\]\\]', 'g' ); }, getContent: function( file, targetcat, mode ) { var data = { action: 'query', prop: 'info|revisions', rvprop: 'content|timestamp', intoken: 'edit', titles: file[ 0 ] }; this.doAPICall( data, function( result ) { catALot.editCategories( result, file, targetcat, mode ); } ); }, // Remove {{Uncategorized}}. No need to replace it with anything. removeUncat: function( text ) { return text.replace( /\{\{\s*[Uu]ncategorized\s*(\|?.*?)\}\}/, "" ); }, doCleanup: function( text ) { if ( this.settings.docleanup ) { return text.replace( /\{\{\s*[Ch]eck categories\s*(\|?.*?)\}\}/, "" ); } else { return text; } }, editCategories: function( result, file, targetcat, mode ) { var otext, starttimestamp, timestamp; if ( !result ) { //Happens on unstable wifi connections.. this.connectionError.push( file[ 0 ] ); this.updateCounter(); return; } var pages = result.query.pages; // there should be only one, but we don't know its ID for ( var id in pages ) { // The edittoken only changes between logins this.edittoken = pages[ id ].edittoken; otext = pages[ id ].revisions[ 0 ][ '*' ]; starttimestamp = pages[ id ].starttimestamp; timestamp = pages[ id ].revisions[ 0 ].timestamp; } var sourcecat = currentCat; // Check if that file is already in that category if ( mode !== "remove" && this.regexBuilder( targetcat ) .test( otext ) ) { //If the new cat is already there, just remove the old one. if ( mode === 'move' ) { mode = 'remove'; } else { this.alreadyThere.push( file[ 0 ] ); this.updateCounter(); return; } } var text = otext; var comment; // Fix text switch ( mode ) { case 'add': text += "\n[[" + this.localCatName + ":" + targetcat + "]]\n"; comment = msgPlain( 'summary-add' ).replace( '$1', targetcat ); break; case 'copy': text = text.replace( this.regexBuilder( sourcecat ), "[[" + this.localCatName + ":" + sourcecat + "$1]]\n[[" + this.localCatName + ":" + targetcat + "$1]]" ); comment = msgPlain( 'summary-copy' ).replace( '$1', sourcecat ).replace( '$2', targetcat ); //If category is added through template: if ( otext === text ) { text += "\n[[" + this.localCatName + ":" + targetcat + "]]"; } break; case 'move': text = text.replace( this.regexBuilder( sourcecat ), "[[" + this.localCatName + ":" + targetcat + "$1]]" ); comment = msgPlain( 'summary-move' ).replace( '$1', sourcecat ).replace( '$2', targetcat ); break; case 'remove': text = text.replace( this.regexBuilder( sourcecat ), "" ); comment = msgPlain( 'summary-remove' ).replace( '$1', sourcecat ); break; } if ( text === otext ) { this.notFound.push( file[ 0 ] ); this.updateCounter(); return; } // Remove uncat after we checked whether we changed the text successfully. // Otherwise we might fail to do the changes, but still replace {{uncat}} if ( mode !== 'remove' ) { text = this.doCleanup( this.removeUncat( text ) ); } var data = { action: 'edit', summary: comment, title: file[ 0 ], text: text, starttimestamp: starttimestamp, basetimestamp: timestamp, watchlist: this.settings.watchlist, token: this.edittoken }; if ( this.settings.minor ) data.minor = true; this.doAPICall( data, function() { catALot.updateCounter(); } ); this.markAsDone( file[ 1 ], mode, targetcat ); }, markAsDone: function( label, mode, targetcat ) { label.addClass( 'cat_a_lot_markAsDone' ); switch ( mode ) { case 'add': label.append( '<br>' + msg( 'added-cat', targetcat ) ); break; case 'copy': label.append( '<br>' + msg( 'copied-cat', targetcat ) ); break; case 'move': label.append( '<br>' + msg( 'moved-cat', targetcat ) ); break; case 'remove': label.append( '<br>' + msg( 'removed-cat' ) ); break; } }, updateCounter: function() { this.counterCurrent++; if ( this.counterCurrent > this.counterNeeded ) this.displayResult(); else this.domCounter.text( this.counterCurrent ); }, displayResult: function() { document.body.style.cursor = 'auto'; $( '.cat_a_lot_feedback' ) .addClass( 'cat_a_lot_done' ); $( '.ui-dialog-content' ) .height( 'auto' ); var rep = this.domCounter.parent(); rep.html( '<h3>' + msg( 'done' ) + '</h3>' ); rep.append( msg( 'all-done' ) + '<br />' ); var close = $( '<a>' ) .text( msgPlain( 'return-to-page' ) ); close.click( function() { catALot.progressDialog.remove(); catALot.toggleAll( false ); } ); rep.append( close ); if ( this.alreadyThere.length ) { rep.append( '<h5>' + msg( 'skipped-already', this.alreadyThere.length ) + '</h5>' ); rep.append( this.alreadyThere.join( '<br>' ) ); } if ( this.notFound.length ) { rep.append( '<h5>' + msg( 'skipped-not-found', this.notFound.length ) + '</h5>' ); rep.append( this.notFound.join( '<br>' ) ); } if ( this.connectionError.length ) { rep.append( '<h5>' + msg( 'skipped-server', this.connectionError.length ) + '</h5>' ); rep.append( this.connectionError.join( '<br>' ) ); } }, moveHere: function( targetcat ) { this.doSomething( targetcat, 'move' ); }, copyHere: function( targetcat ) { this.doSomething( targetcat, 'copy' ); }, addHere: function( targetcat ) { this.doSomething( targetcat, 'add' ); }, remove: function() { this.doSomething( '', 'remove' ); }, doSomething: function( targetcat, mode ) { var files = this.getMarkedLabels(); if ( files.length === 0 ) { alert( msgPlain( 'none-selected' ) ); return; } this.notFound = []; this.alreadyThere = []; this.connectionError = []; this.counterCurrent = 1; this.counterNeeded = files.length; mw.loader.using( ['jquery.ui.dialog', 'mediawiki.RegExp'], function() { catALot.showProgress(); for ( var i = 0; i < files.length; i++ ) { catALot.getContent( files[ i ], targetcat, mode ); } } ); }, doAPICall: function( params, callback ) { params.format = 'json'; var i = 0; var apiUrl = this.apiUrl; var handleError = function( jqXHR, textStatus, errorThrown ) { if ( window.console && $.isFunction( window.console.log ) ) { window.console.log( 'Error: ', jqXHR, textStatus, errorThrown ); } if ( i < 4 ) { window.setTimeout( doCall, 300 ); i++; } else if ( params.title ) { this.connectionError.push( params.title ); this.updateCounter(); return; } }; var doCall = function() { $.ajax( { url: apiUrl, cache: false, dataType: 'json', data: params, type: 'POST', success: callback, error: handleError } ); }; doCall(); }, createCatLinks: function( symbol, list ) { list.sort(); var domlist = $resultList.find( 'table' ); for ( var i = 0; i < list.length; i++ ) { var $tr = $( '<tr>' ); var $link = $( '<a>' ), $add, $move, $copy; $link.text( list[ i ] ); $tr.data( 'cat', list[ i ] ); $link.click( function() { catALot.updateCats( $( this ).closest('tr').data( 'cat' ) ); } ); if ( this.searchmode ) { $add = $( '<a class="cat_a_lot_action"></a>' ) .text( msgPlain( 'add' ) ) .click( function() { catALot.addHere( $( this ).closest('tr').data( 'cat' ) ); } ); } else { $move = $( '<a class="cat_a_lot_move"></a>' ) .text( msgPlain( 'move' ) ) .click( function() { catALot.moveHere( $( this ).closest('tr').data( 'cat' ) ); } ); $copy = $( '<a class="cat_a_lot_action"></a>' ) .text( msgPlain( 'copy' ) ) .click( function() { catALot.copyHere( $( this ).closest('tr').data( 'cat' ) ); } ); } $tr.append( $('<td>').text( symbol ) ) .append( $('<td>').append( $link ) ); // Can't move to source category if ( list[ i ] !== currentCat && this.searchmode ) { $tr.append( $('<td>').append( $add ) ); } else if ( list[ i ] !== currentCat && !this.searchmode ) { $tr.append( $('<td>').append( $move ), $('<td>').append( $copy ) ); } domlist.append( $tr ); } }, getCategoryList: function() { this.catCounter = 0; this.getParentCats(); this.getSubCats(); }, showCategoryList: function() { var thiscat = [ this.currentCategory ]; $resultList.empty(); $resultList.append( '<table></table>' ); 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"></div>' ).text( msgPlain( 'loading' ) ); this.getCategoryList(); }, showProgress: function() { document.body.style.cursor = 'wait'; this.progressDialog = $( '<div></div>' ) .html( msg( 'editing' ) + ' <span id="cat_a_lot_current">' + this.counterCurrent + '</span> ' + 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 = $( '<div>' ); $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( $( '<p>' ) .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: '//commons.wikimedia.org/w/index.php', 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 ) { // 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 ) { // Prevent selection e.preventDefault(); 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 ) ); // </nowiki>
返回到「
MediaWiki:Gadget-Cat-a-lot.js
」。
導覽選單
個人工具
尚未登入
討論
貢獻
建立帳號
登入
命名空間
訊息
討論
English
視圖
閱讀
檢視原始碼
檢視歷史
更多
搜尋
導覽
首頁
近期變更
最新頁面
隨機頁面
建立一個新項目
建立一個新屬性
說明
歡迎
方針與指引
留言板
工具
連結至此的頁面
相關變更
特殊頁面
頁面資訊