LLWiki正在建设中,欢迎加入我们

“MediaWiki:Gadget-Cat-a-lot.js”的版本间差异

跳转到导航 跳转到搜索
添加16,149字节 、​ 2022年4月5日 (二) 01:06
无编辑摘要
 
(未显示同一用户的36个中间版本)
//<nowiki>
/**
/**
* Cat-A-Lot
* Cat-a-lot
* Changes category of multiple files
* Changes category of multiple files
*
*
* Originally by Magnus Manske
* @rev 00:13, 10 February 2018 (UTC)
* RegExes by Ilmari Karonen
* @author Originally by Magnus Manske (2007)
* Completely rewritten by DieBuche
* @author RegExes by Ilmari Karonen (2010)
*
* @author Completely rewritten by DieBuche (2010-2012)
* Requires [[MediaWiki:Gadget-SettingsManager.js]] and [[MediaWiki:Gadget-SettingsUI.js]] (properly registered) for per-user-settings
* @author Rillke (2012-2014)
*
* @author Perhelion (2017)
* READ THIS PAGE IF YOU WANT TO TRANSLATE OR USE THIS ON ANOTHER SITE:
* http://commons.wikimirror.org/wiki/MediaWiki:Gadget-Cat-a-lot.js/translating
* <nowiki>
*/
 
* READ THIS PAGE IF YOU WANT TO TRANSLATE OR USE THIS ON ANOTHER SITE:
/*global jQuery:false, mediaWiki:false, alert:false, importStylesheet:false */
* [http://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js/translating]
/*jshint curly:false, unused:true, unused:true, forin:false, smarttabs:true, loopfunc:true, browser:true */
*/
 
/* global jQuery, mediaWiki */
( function( $, mw ) {
/* eslint one-var:0, vars-on-top:0, no-underscore-dangle:0, valid-jsdoc:0,
'use strict';
curly:0, camelcase:0, no-useless-escape:0, no-alert:0 */ // extends: wikimedia
/* jshint unused:true, forin:false, smarttabs:true, loopfunc:true, browser:true */
 
( function ( $, mw ) {
var nsNumber = mw.config.get( 'wgNamespaceNumber' ),
'use strict';
nsCat = 14,
currentCat = mw.config.get( 'wgTitle' ),
formattedNS = mw.config.get( 'wgFormattedNamespaces' ),
nsIDs = mw.config.get( 'wgNamespaceIds' ),
catALot;
 
var ns = mw.config.get( 'wgNamespaceNumber' ),
var msgs = {
nsIDs = mw.config.get( 'wgNamespaceIds' ),
// Preferences
userGrp = mw.config.get( 'wgUserGroups' ),
// new: added 2012-09-19. Please translate.
project = mw.config.get( 'wgDBname' );
// 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",
 
var msgs = {
//Progress
// Preferences
'cat-a-lot-loading': 'Loading...',
// new: added 2012-09-19. Please translate.
'cat-a-lot-editing': 'Editing page',
// Use user language for i18n
'cat-a-lot-of': 'of ',
'cat-a-lot-uncatpref': '移除 {{Uncategorized}}',
'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-comment-label': wgULS('自定义编辑摘要','自定義編輯摘要'),
'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-edit-question': wgULS('请输入编辑摘要:','請輸入編輯摘要:'),
'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.',
 
// Progress
'cat-a-lot-editing': 'Editing page',
'cat-a-lot-of': 'of ',
'cat-a-lot-skipped-already': 'The following {{PLURAL:$1|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|1=page was|$1 pages were}} skipped, because the old category could not be found:',
'cat-a-lot-skipped-server': 'The following {{PLURAL:$1|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!', // mw.msg("Feedback-close")
'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',
 
// as in 17 files selected
'cat-a-lot-files-selected': '{{PLURAL:$1|1=One file|$1 files}} selected.',
'cat-a-lot-pe_file': '$1 {{PLURAL:$1|page|pages}} of $2 affected',
 
// 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-nameovercat': wgULS('Enter category name检测过度分类','檢測過度分類'),
'cat-a-lot-selectenter-name': 'SelectEnter category name',
'cat-a-lot-allselect': 'allSelect',
'cat-a-lot-noneall': 'noneall',
'cat-a-lot-none': 'none',
 
// Summaries (project language):
'cat-a-lot-none-selected': 'No files selected!',
'cat-a-lot-summary-add': 'Adding [[Category:$1]]',
'cat-a-lot-summary-copy': 'Copying from [[Category:$1]] to [[Category:$2]]',
'cat-a-lot-summary-move': 'Moving from [[Category:$1]] to [[Category:$2]]',
'cat-a-lot-summary-remove': 'Removing from [[Category:$1]]',
'cat-a-lot-prefix-summary': '使用Cat-a-lot小工具',
'cat-a-lot-using-summary': ''
};
mw.messages.set( msgs );
 
function msg( /* params */ ) {
//Summaries:
var args = Array.prototype.slice.call( arguments, 0 );
'cat-a-lot-summary-add': 'Cat-a-lot: Adding [[Category:$1]]',
args[ 0 ] = 'cat-a-lot-' + args[ 0 ];
'cat-a-lot-summary-copy': 'Cat-a-lot: Copying from [[Category:$1]] to [[Category:$2]]',
return args.length === 1 ?
'cat-a-lot-summary-move': 'Cat-a-lot: Moving from [[Category:$1]] to [[Category:$2]]',
mw.message( args[ 0 ] ).plain() :
'cat-a-lot-summary-remove': 'Cat-a-lot: Removing from [[Category:$1]]'
mw.message.apply( mw.message, args ).parse();
};
}
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();
 
// There is only one Cat-a-lot on one page
$body = $( document.body );
var $body, $container, $dataContainer, $searchInputContainer, $searchInput, $resultList, $markCounter, $selections,
$container = $( '<div id="cat_a_lot"></div>' )
$selectFiles, $selectPages, $selectNone, $selectInvert, $head, $link, $overcat,
.appendTo( $body );
commonsURL = 'https://commons.wikimedia.org/w/index.php',
$dataContainer = $( '<div id="cat_a_lot_data"></div>' )
is_rtl = $( 'body' ).hasClass( 'rtl' ),
.appendTo( $container );
reCat, // localized category search regexp
$searchInputContainer = $( '<div>' )
non,
.appendTo( $dataContainer );
r; // result file count for overcat
$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 );
 
var CAL = mw.libs.catALot = {
if ( !this.searchmode ) {
apiUrl: mw.util.wikiScript( 'api' ),
$removeLink = $( '<a id="cat_a_lot_remove"></a>' )
origin: '',
.html( msg( 'remove-from-cat' ) )
searchmode: false,
.appendTo( $selections )
version: '4.77',
.click( function() {
setHeight: 450,
catALot.remove();
changeTag: 'Cat-a-lot',
} );
}
 
settings: {
if ( ( 'MediaWiki:Gadget-Cat-a-lot.js' === mw.util.getParamValue( 'withJS' ) &&
/* Any category in this category is deemed a disambiguation category; i.e., a category that should not contain
!mw.util.getParamValue( 'withCSS' ) ) ||
any items, but that contains links to other categories where stuff should be categorized. If you don't have
mw.loader.getState('ext.gadget.Cat-a-lot') === 'registered' ) {
that concept on your wiki, set it to null. Use blanks, not underscores. */
importStylesheet( 'MediaWiki:Gadget-Cat-a-lot.css' );
disambig_category: null, // Commons and EnWP
}
/* Any category in this category is deemed a (soft) redirect to some other category defined by a link
* to another non-blacklisted category. If your wiki doesn't have soft category redirects, set this to null.
* If a soft-redirected category contains more than one link to another non-blacklisted category, it's considered
* a disambiguation category instead. */
redir_category: null
},
 
init: function () {
var reCat = new RegExp( '^\\s*' + catALot.localizedRegex( nsCat, 'Category' ) + ':', '' );
// TODO: better extern project support for possible change-tag? (needs currently change after init)
if ( project === 'commonswiki' ) { mw.messages.set( { 'cat-a-lot-using-summary': '' } ); } else { // Reset
this.changeTag = '';
this.settings.redir_category = '';
}
 
this._initSettings();
$searchInput.keypress( function( e ) {
if$body = $( edocument.which === 13body ) {;
$container = $( '<div>' )
catALot.updateCats( $.trim( $( this )
.valattr() )'id', 'cat_a_lot' );
.appendTo( $body );
}
$dataContainer = $( '<div>' )
.attr( 'id', 'cat_a_lot_data' )
.appendTo( $container );
$searchInputContainer = $( '<div>' )
.appendTo( $dataContainer );
$searchInput = $( '<input>', {
id: 'cat_a_lot_searchcatname',
placeholder: msg( 'enter-name' ),
type: 'text'
} )
.appendTo( $searchInputContainer );
$resultList = $( '<div>' )
.attr( 'id', 'cat_a_lot_category_list' )
.appendTo( $dataContainer );
$markCounter = $( '<div>' )
.attr( 'id', 'cat_a_lot_mark_counter' )
.appendTo( $dataContainer );
$selections = $( '<div>' )
.attr( 'id', 'cat_a_lot_selections' )
.text( msg( 'select' ) + ':' )
.appendTo( $dataContainer );
$head = $( '<div>' )
.attr( 'id', 'cat_a_lot_head' )
.appendTo( $container );
$link = $( '<a>' )
.attr( 'id', 'cat_a_lot_toggle' )
.text( 'Cat-a-lot' )
.appendTo( $head );
 
if ( this.origin && !non ) {
$overcat = $( '<a>' )
.attr( 'id', 'cat_a_lot_overcat' )
.html( msg( 'overcat' ) )
.on( 'click', function ( e ) {
CAL.getOverCat( e );
} )
.insertBefore( $selections );
.on( 'input keyup', function() {
}
var oldVal = this.value,
 
newVal = oldVal.replace( reCat, '' );
reCat = new RegExp( '^\\s*' + CAL.localizedRegex( 'Category' ) + ':', '' );
if ( newVal !== oldVal ) this.value = newVal;
 
} );
$searchInput.on( 'keypress', function ( e ) {
if ( this.searchmode ) {
if ( e.which === 13 ) {
$searchInput.val( mw.util.getParamValue( 'search' ) );
CAL.updateCats( $.trim( $( this ).val().replace( /[\u200E\u200F\u202A-\u202E]/g, '' ) ) );
mw.cookie.set( 'catAlot', CAL.currentCategory );
}
} )
function initAutocomplete() {
.on( 'input keyup', function () {
if ( catALot.autoCompleteIsEnabled ) return;
var oldVal = this.value,
catALot.autoCompleteIsEnabled = true;
newVal = oldVal.replace( reCat, '' );
if ( newVal !== oldVal ) { this.value = newVal; }
 
if ( !newVal ) { mw.cookie.set( 'catAlot', null ); }
$searchInput.autocomplete( {
} );
source: function( request, response ) {
 
catALot.doAPICall( {
function initAutocomplete() {
action: 'opensearch',
if ( CAL.autoCompleteIsEnabled ) { return; }
search: request.term,
 
namespace: nsCat
CAL.autoCompleteIsEnabled = true;
}, function( data ) {
 
if ( data[ 1 ] ) response( $( data[ 1 ] )
if ( !$searchInput.val() && mw.cookie && mw.cookie.get( 'catAlot' ) ) { $searchInput.val( mw.cookie.get( 'catAlot' ) ); }
.map( function( index, item ) {
 
$searchInput.autocomplete( {
source: function ( request, response ) {
CAL.doAPICall( {
action: 'opensearch',
search: request.term,
redirects: 'resolve',
namespace: 14
}, function ( data ) {
if ( data[ 1 ] ) {
response( $( data[ 1 ] )
.map( function ( index, item ) {
return item.replace( reCat, '' );
} ) );
}
} );
},
open: function () {
$( '.ui-autocomplete' )
.position( {
my: is_rtl ? 'left bottom' : 'right bottom',
at: is_rtl ? 'left top' : 'right top',
of: $searchInput
} );
},
openappendTo: function() {'#cat_a_lot'
} );
$( ".ui-autocomplete" )
}
.position( {
my: $( 'body<a>' )
.text( msg( 'all' ) )
.is( '.rtl' ) ? "left bottom" : "right bottom",
at: $.on( 'bodyclick', function () {
CAL.toggleAll( true );
.is( '.rtl' ) ? "left top" : "right top",
} )
of: $searchInput
.appendTo( $selections.append( ' ' ) );
} );
if ( this.settings.editpages ) {
},
$selectFiles = $( '<a>' )
appendTo: '#cat_a_lot'
.on( 'click', function () {
CAL.toggleAll( 'files' );
} );
$selectPages = $( '<a>' )
}
.on( 'click', function () {
 
CAL.toggleAll( 'pages' );
$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'], initAutocomplete );
catALot.run();
} );
$settingsLink
.click( function() {
catALot.manageSettings();
} );
$selections.append( $( '<span>' ).hide().append( [ ' / ', $selectFiles, ' / ', $selectPages ] ) );
}
$selectNone = $( '<a>' )
.text( msg( 'none' ) )
.on( 'click', function () {
CAL.toggleAll( false );
} );
$selectInvert = $( '<a>' )
.on( 'click', function () {
CAL.toggleAll( null );
} );
$selections.append( [ ' • ', $selectNone, ' • ', $selectInvert,
$( '<div>' ).append( [
$( '<label>' )
.attr( {
'for': 'cat_a_lot_comment',
style: 'line-height:1.5em;vertical-align:bottom'
} )
.text( msg( 'comment-label' ) ),
$( '<input>' )
.attr( {
id: 'cat_a_lot_comment',
type: 'checkbox'
} )
] )
] );
 
$link
this.localCatName = formattedNS[ nsCat ];
.on( 'click', function () {
},
$( this ).toggleClass( 'cat_a_lot_enabled' );
findAllLabels: function() {
// Load autocomplete on demand
// 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
initAutocomplete ();
if ( this.searchmode ) {
 
this.labels = $( 'table.searchResultImage' )
if ( !CAL.executed ) {
.find( 'tr>td:eq(1)' );
if $.when( thismw.settingsloader.editpages )using( {[
'mediawiki.api',
this.labels = this.labels.add( 'div.mw-search-result-heading' );
'mediawiki.jqueryMsg'
] ), $.ready )
.then( function () {
return new mw.Api().loadMessagesIfMissing( [
'Cancel',
'Categorytree-not-found',
// 'Checkuser-all',
// 'Code-field-select',
// 'Export-addcat',
'Filerevert-submit',
'Mobile-frontend-return-to-page',
'Ooui-selectfile-placeholder',
// 'Visualeditor-clipboard-copy',
'Wikieditor-loading',
'Prefs-files',
'Categories',
'Checkbox-invert',
'Centralnotice-remove', // 'Ooui-item-remove'
'Apifeatureusage-warnings'
] );
} ).then( function () {
CAL.run();
} );
} else { CAL.run(); }
} );
this.localCatName = 'Category:';
mw.loader.using( 'mediawiki.cookie', function () { // Let catAlot stay open
var val = mw.cookie.get( 'catAlotO' );
if ( val && Number( val ) === ns ) { $link.click(); }
}
);
},
 
getOverCat: function ( e ) {
var files = [];
r = 0; // result counter
if ( e ) {
e.preventDefault();
this.files = this.getMarkedLabels(); // .toArray() not working
for ( var f = 0; f < this.files.length; f++ ) { files.push( this.files[ f ] ); }
 
}
if ( !files.length || !( files instanceof Array ) ) { return alert( mw.msg( 'Ooui-selectfile-placeholder' ) ); }
this.files = files;
mw.loader.using( [ 'jquery.spinner' ], function () {
$markCounter.injectSpinner( 'overcat' );
CAL.getFileCats();
} );
},
 
getFileCats: function () {
var aLen = this.files.length;
var bLen = this.selectedLabels.length;
var file = this.files[ aLen - 1 ][ 0 ];
$overcat.text( '…' + aLen + '\/' + bLen );
if ( file ) {
this.doAPICall( {
prop: 'categories',
titles: file
}, this.checkFileCats
);
}
 
},
 
checkFileCats: function ( data ) {
var cc = 0; // current cat counter;
var file = CAL.files.pop();
if ( data.query && data.query.pages ) {
$.each( data.query.pages, function ( id, page ) {
if ( page.categories ) {
var target = file[ 1 ].removeClass( 'cat_a_lot_selected' );
$.each( page.categories, function ( c, cat ) {
var title = cat.title.replace( reCat, '' ),
color = 'orange',
mark = function ( kind ) { // kind of category
// TODO: store data to use this for special remove function
if ( kind === 'sub' ) { color = 'green'; }
var border = '3px dotted ';
if ( $.inArray( title, CAL[ kind + 'Cats' ] ) !== -1 ) {
cc++;
target = target.parents( '.gallerybox' );
target = target[ 0 ] ? target : file[ 1 ];
target.css( {
border: border + color
} ).prop( 'title', msg( kind + '-cat' ) + title );
color = 'red';
return false;
}
};
mark( 'sub' );
return mark( 'parent' );
} );
if ( cc ) { r++; }
}
} else {);
} else { mw.log( 'Api-fail', file, data ); }
this.labels = $( 'div.gallerytext' )
if ( CAL.files[ 0 ] ) { return setTimeout( function () { CAL.getFileCats(); }, 100 ); } // Api has bad performance here, so we can get only each file separately
.add( $( 'div#mw-category-media' )
$overcat.text( msg( 'pe_file', r, CAL.selectedLabels.length ) );
.find( 'li[class!="gallerybox"]' ) );
$.removeSpinner( 'overcat' );
},
 
findAllLabels: function ( searchmode ) {
// 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
switch ( searchmode ) {
case 'search':
this.labels = this.labels.add( $( 'table.searchResultImage' ).find( 'tr>td:eq(1)' ) );
if ( this.settings.editpages ) { this.labels = this.labels.add( 'div.mw-search-result-heading' ); }
break;
case 'category':
this.findAllLabels( 'gallery' );
this.labels = this.labels.add( $( '#mw-category-media' ).find( 'li[class!="gallerybox"]' ) );
if ( this.settings.editpages ) {
var $pgsthis.pageLabels = $( 'div#mw-pages, div#mw-subcategories' ).find( 'li' );
// this.find(files 'li'= )this.labels;
this.labels = this.labels.add( $pgsthis.pageLabels );
}
} break;
case 'contribs':
},
this.labels = this.labels.add( $( 'ul.mw-contributions-list li' ) );
// FIXME: Filter if !this.settings.editpages
break;
case 'prefix':
this.labels = this.labels.add( $( 'ul.mw-prefixindex-list li' ) );
break;
case 'listfiles':
// this.labels = this.labels.add( $( 'table.listfiles>tbody>tr' ).find( 'td:eq(1)' ) );
this.labels = this.labels.add( $( '.TablePager_col_img_name' ) );
break;
case 'gallery':
// this.labels = this.labels.add( '.gallerybox' ); // TODO incombatible with GalleryDetails
this.labels = this.labels.add( '.gallerytext' );
break;
}
},
 
getTitleFromLink: function ( href$a ) {
try {
return decodeURIComponent( $a.attr( 'href' ) )
.match( /wikizh\/(.+?)(?:#.+)?$/ )[ 1 ].replace( /_/g, ' ' );
} catch ( ex ) {
return '';
}
},
 
/**
getMarkedLabels: function() {
* @brief Get title from selected pages
var marked = [];
* @return [array] touple of page title and $object
this.selectedLabels = this.labels.filter( '.cat_a_lot_selected' );
*/
this.selectedLabels.each( function() {
getMarkedLabels: function () {
var file = $( this )
this.selectedLabels = this.labels.filter( '.cat_a_lot_selected:visible' );
.find( 'a[title]' ),
return this.selectedLabels.map( function () {
title = file.attr( 'title' ) || catALot.getTitleFromLink( file.attr( 'href' ) ) || catALot.getTitleFromLink( $( this )
var label = $( this ), file = label.find( 'a[title][class$="title"]' );
file = file.length ? file : label.find( 'a[title]' );
.attr( 'href' ) );
var title = file.attr( 'title' ) ||
CAL.getTitleFromLink( file ) ||
CAL.getTitleFromLink( label.find( 'a' ) ) ||
CAL.getTitleFromLink( label.parent().find( 'a' ) ); // TODO needs optimization
if ( title.indexOf( 'User:' ) ) { return [ [ title, label ] ]; }
} );
},
 
updateSelectionCounter: function () {
marked.push( [ title, $( this ) ] );
this.selectedLabels = this.labels.filter( '.cat_a_lot_selected:visible' );
var first = $markCounter.is( ':hidden' );
$markCounter
.html( msg( 'files-selected', this.selectedLabels.length ) )
.show();
if ( first && !$dataContainer.is( ':hidden' ) ) { // Workaround to fix position glitch
first = $markCounter.innerHeight();
$container
.offset( { top: $container.offset().top - first } )
.height( $container.height() + first );
$( window ).on( 'beforeunload', function () {
if ( CAL.labels.filter( '.cat_a_lot_selected:visible' )[ 0 ] ) { return 'You have pages selected!'; } // There is a default message in the browser
} );
}
return marked;
},
 
updateSelectionCounter makeClickable: function () {
this.labels = $();
this.selectedLabels = this.labels.filter( '.cat_a_lot_selected' );
this.pageLabels = $(); // only for distinct all selections
$markCounter
this.findAllLabels( this.searchmode );
.show()
this.labels.catALotShiftClick( function () {
.html( msg( 'files-selected', this.selectedLabels.length ) );
CAL.updateSelectionCounter();
},
} )
.addClass( 'cat_a_lot_label' );
},
 
makeClickable toggleAll: function ( select ) {
if ( typeof select === 'string' && select === 'files' ) {
this.findAllLabels();
if ( this.pageLabels[ 0 ] ) // pages remain unchanged
this.labels.catALotShiftClick( function() {
{ this.pageLabels.toggleClass( 'cat_a_lot_selected' ); }
catALot.updateSelectionCounter();
this.labels.toggleClass( 'cat_a_lot_selected' );
} )
} else if ( typeof select === 'string' && select === 'pages' ) {
.addClass( 'cat_a_lot_label' );
if ( this.pageLabels[ 0 ] ) // files remain unchanged
},
{ this.pageLabels.toggleClass( 'cat_a_lot_selected' ); }
 
} else {
toggleAll: function( select ) {
// invert / none / all
this.labels.toggleClass( 'cat_a_lot_selected', select );
}
this.updateSelectionCounter();
this.updateSelectionCounter();
},
},
 
getSubCats: function () {
var data = {
actionlist: 'querycategorymembers',
listcmtype: 'categorymemberssubcat',
cmlimit: this.settings.subcatcount,
cmtype: 'subcat',
cmtitle: 'Category:' + this.currentCategory
cmlimit: this.settings.subcatcount,
};
cmtitle: 'Category:' + this.currentCategory
};
 
this.doAPICall( data, function ( result ) {
var cats = result.query.categorymembers;
CAL.subCats = [];
for ( var i = 0; i < cats.length; i++ ) { CAL.subCats.push( cats[ i ].title.replace( /^[^:]+:/, '' ) ); }
 
CAL.catCounter++;
var cats = result.query.categorymembers;
if ( CAL.catCounter === 2 ) { CAL.showCategoryList(); }
 
} );
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 = {
actionprop: 'querycategories',
titles: 'Category:' + this.currentCategory
prop: 'categories',
};
titles: 'Category:' + this.currentCategory
this.doAPICall( data, function ( result ) {
};
CAL.parentCats = [];
this.doAPICall( data, function( result ) {
var cats,
catALot.parentCats = [];
var cats, pages = result.query.pages;,
table = $( '<table>' );
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';
 
if ( pages[ -1 ] && pages[ -1 ].missing === '' ) {
$resultList.append( '<table></table>' );
catALot$resultList.createCatLinkshtml( '<span id="cat_a_lot_no_found",>' [+ catALotmw.msg( 'Categorytree-not-found', this.currentCategory ]) + '</span>' );
document.body.style.cursor = 'auto';
return;
CAL.createCatLinks( '→', [ CAL.currentCategory ], table );
}
$resultList.append( table );
// there should be only one, but we don't know its ID
return;
for ( var id in pages ) {
}
cats = pages[ id ].categories;
// there should be only one, but we don't know its ID
}
for ( var iid =in 0;pages i) <{ cats = pages[ id ].length;categories i++|| )[]; {}
catALot.parentCats.push( cats[ i ].title.replace( /^[^:]+:/, "" ) );
}
 
for ( var i = 0; i < cats.length; i++ ) { CAL.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' );
 
CAL.catCounter++;
var createRegexStr = function( name ) {
if ( !name || nameCAL.lengthcatCounter === 02 ) return{ ""CAL.showCategoryList(); }
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 );
localizedRegex: function ( fallback ) {
if ( fallback && canonical !== fallback ) RegexString += '|' + createRegexStr( fallback );
// Copied from HotCat, thanks Lupo.
for ( var catName in nsIDs ) {
var wikiTextBlank = '[\\t _\\xA0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]+';
if ( typeof( catName ) === 'string' && catName.toLowerCase() !== canonical && catName.toLowerCase() !== fallback && nsIDs[ catName ] === namespaceNumber ) {
var wikiTextBlankRE = new RegExp( wikiTextBlank, 'g' );
RegexString += '|' + createRegexStr( catName );
var createRegexStr = function ( name ) {
}
if ( !name || !name.length ) { return ''; }
 
var regexName = '';
for ( var i = 0; i < name.length; i++ ) {
var ii = name[ i ];
var ll = ii.toLowerCase();
var ul = ii.toUpperCase();
regexName += ll === ul ? ii : '[' + ll + ul + ']';
}
return regexName.replace( '/([\\\^\$\.\?:' + RegexString \*\+\(\)])/g, ')\\$1' );
.replace( wikiTextBlankRE, wikiTextBlank );
},
};
 
fallback = fallback.toLowerCase();
var canonical = 'category';
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 ] === ns ) { RegexString += '|' + createRegexStr( catName ); } }
 
return '(?:' + RegexString + ')';
},
 
regexCatBuilder: function ( category ) {
var catname = this.localizedRegex( 'Category' );
// 繁简转换
findAllVariants: function( category ) {
if ( window.CatALotSourceCat && window.CatALotSourceCat.includes( category.replace(/_/g, ' ') ) ) {
var result = [],
category = window.CatALotSourceCat;
baseUrl = '/w/api.php?action=parse&text=' + encodeURIComponent(category) + '&title=temp&format=json&variant=';
if} (else { this._variantCache[category] !== undefined[category]; ) {}
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.trim() );
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.map(ele => ele.replace( /^[\s_]+|[\s_]+$/g, ""'' ));
.replace( /[\s_]+$/, "" );
 
// escape regexp metacharacters (= any ASCII punctuation except _)
// Find all variants
category = category.map(ele => mw.util.escapeRegExp( ele ));
variants = this.findAllVariants( category );
 
// any sequence of spaces and underscores should match any other
// escape regexp metacharacters (= any ASCII punctuation except _)
category = category.map(ele => ele.replace( /[\s_]+/g, '[\\s_]+' ));
$.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 = variantcategory.substr( 0, 1 );
//if ( first.toUpperCase() !== first.toLowerCase() ) { category = '[' + first.toUpperCase() + first.toLowerCase() + ']' + category.substr( 1 ); }
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' );
},
 
// Compile it into a RegExp that matches MediaWiki category syntax (yeah, it looks ugly):
getContent: function( file, targetcat, mode ) {
// 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_]*(\\|[^\\]]*(?:\\][^\\]]+)*)?\\]\\]\\s*', 'gi' );
},
 
getContent: function ( page, targetcat, mode ) {
var data = {
if ( !this.cancelled ) {
action: 'query',
this.doAPICall( {
prop: 'info|revisions',
curtimestamp: 1,
// meta: 'tokens',
prop: 'revisions',
rvprop: 'content|timestamp',
intokentitles: 'edit',page[ 0 ]
}, function ( result ) {
titles: file[ 0 ]
CAL.editCategories( result, page, targetcat, mode );
};
} );
}
 
},
 
getTargetCat: function ( pages, targetcat, mode ) {
if ( !this.cancelled ) {
this.doAPICall( {
meta: 'tokens',
prop: 'categories|categoryinfo',
titles: 'Category:' + targetcat
}, function ( result ) {
if ( !result || !result.query ) { return; }
CAL.edittoken = result.query.tokens.csrftoken;
result = CAL._getPageQuery( result );
CAL.checkTargetCat( result );
for ( var i = 0; i < pages.length; i++ ) { CAL.getContent( pages[ i ], targetcat, mode ); }
 
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 checkTargetCat: function ( textpage ) {
var is_dab = false; // disambiguation
if ( this.settings.docleanup ) {
var is_redir = typeof page.redirect === 'string'; // Hard redirect?
return text.replace( /\{\{\s*[Ch]eck categories\s*(\|?.*?)\}\}/, "" );
if ( typeof page.missing === 'string' ) { return alert( mw.msg( 'Apifeatureusage-warnings', mw.msg( 'Categorytree-not-found', page.title ) ) ); }
} else {
var cats = page.categories;
return text;
this.is_hidden = page.categoryinfo && typeof page.categoryinfo.hidden === 'string';
 
if ( !is_redir && cats && ( CAL.disambig_category || CAL.redir_category ) ) {
for ( var c = 0; c < cats.length; c++ ) {
var cat = cats[ c ].title;
if ( cat ) { // Strip namespace prefix
cat = cat.substring( cat.indexOf( ':' ) + 1 ).replace( /_/g, ' ' );
if ( cat === CAL.disambig_category ) {
is_dab = true; break;
} else if ( cat === CAL.redir_category ) {
is_redir = true; break;
}
}
}
},
 
if ( !is_redir && !is_dab ) { return; }
editCategories: function( result, file, targetcat, mode ) {
alert( mw.msg( 'Apifeatureusage-warnings', page.title + ' is a ' + CAL.disambig_category ) );
var otext, starttimestamp, timestamp;
},
if ( !result ) {
 
//Happens on unstable wifi connections..
// Remove {{Uncategorized}} (also with comment). No need to replace it with anything.
this.connectionError.push( file[ 0 ] );
removeUncat: function ( text ) {
return this.settings.uncat ? text.replace( /\{\{\s*[Uu]ncategorized\s*[^}]*\}\}\s*(<!--.*?-->\s*)?/, '' ) : text;
},
 
doCleanup: function ( text ) {
return this.settings.docleanup ? text.replace( /\{\{\s*[Cc]heck categories\s*(\|?.*?)\}\}/, '' ) : text;
},
 
editCategories: function ( result, file, targetcat, mode ) {
if ( !result || !result.query ) {
// Happens on unstable wifi connections..
this.connectionError.push( file[ 0 ] );
this.updateCounter();
return;
}
var otext,
timestamp,
page = CAL._getPageQuery( result );
if ( page.ns === 2 ) { return; }
var id = page.revisions[ 0 ],
catNS = this.localCatName; // canonical cat-name
 
this.starttimestamp = result.curtimestamp;
otext = id[ '*' ];
timestamp = id.timestamp;
 
var sourcecat = this.origin;
// Check if that file is already in that category
if ( mode !== 'remove' && this.regexCatBuilder( targetcat ).test( otext ) ) {
// If the new cat is already there, just remove the old one
if ( mode === 'move' ) {
mode = 'remove';
targetcat = sourcecat;
} else {
this.alreadyThere.push( file[ 0 ] );
this.updateCounter();
return;
}
}
var pages = result.query.pages;
 
// Text modification (following 3 functions are partialy taken from HotCat)
// there should be only one, but we don't know its ID
var wikiTextBlankOrBidi = '[\\t _\\xA0\\u1680\\u180E\\u2000-\\u200B\\u200E\\u200F\\u2028-\\u202F\\u205F\\u3000]*';
for ( var id in pages ) {
// Whitespace regexp for handling whitespace between link components. Including the horizontal tab, but not \n\r\f\v:
// The edittoken only changes between logins
// a link must be on one single line.
this.edittoken = pages[ id ].edittoken;
// MediaWiki also removes Unicode bidi override characters in page titles (and namespace names) completely.
otext = pages[ id ].revisions[ 0 ][ '*' ];
// This is *not* handled, as it would require us to allow any of [\u200E\u200F\u202A-\u202E] between any two
starttimestamp = pages[ id ].starttimestamp;
// characters inside a category link. It _could_ be done though... We _do_ handle strange spaces, including the
timestamp = pages[ id ].revisions[ 0 ].timestamp;
// zero-width space \u200B, and bidi overrides between the components of a category link (adjacent to the colon,
}
// or adjacent to and inside of "[[" and "]]").
var findCatsRE = new RegExp( '\\[\\[' + wikiTextBlankOrBidi + this.localizedRegex( 'Category' ) + wikiTextBlankOrBidi + ':[^\\]]+\\]\\]', 'g' );
 
function replaceByBlanks( match ) {
return match.replace( /(\s|\S)/g, ' ' ); // /./ doesn't match linebreaks. /(\s|\S)/ does.
}
 
function find_insertionpoint( wikitext ) {
var sourcecat = currentCat;
var copiedtext = wikitext
// Check if that file is already in that category
.replace( /<!--(\s|\S)*?-->/g, replaceByBlanks )
if ( mode !== "remove" && this.regexBuilder( targetcat )
.replace( /<nowiki>(\s|\S)*?<\/nowiki>/g, replaceByBlanks );
.test( otext ) ) {
// Search in copiedtext to avoid that we insert inside an HTML comment or a nowiki "element".
var index = -1;
findCatsRE.lastIndex = 0;
while ( findCatsRE.exec( copiedtext ) !== null ) { index = findCatsRE.lastIndex; }
 
return index;
//If the new cat is already there, just remove the old one.
}
if ( mode === 'move' ) {
 
mode = 'remove';
/**
* @brief Adds the new Category by searching the right insert point,
* if there is text after the category section
* @param [string] wikitext
* @param [string] toAdd
* @return Return wikitext
*/
function addCategory( wikitext, toAdd ) {
if ( toAdd && toAdd[ 0 ] ) {
// TODO: support sort key
var cat_point = find_insertionpoint( wikitext ); // Position of last category
var newcatstring = '[[' + catNS + toAdd + ']]';
if ( cat_point > -1 ) {
var suffix = wikitext.substring( cat_point );
wikitext = wikitext.substring( 0, cat_point ) + ( cat_point ? '\n' : '' ) + newcatstring;
if ( suffix[ 0 ] && suffix.substr( 0, 1 ) !== '\n' ) { wikitext += '\n'; }
wikitext += suffix;
} else {
if ( wikitext[ 0 ] && wikitext.substr( wikitext.length - 1, 1 ) !== '\n' ) { wikitext += '\n'; }
this.alreadyThere.push( file[ 0 ] );
 
this.updateCounter();
wikitext += ( wikitext[ 0 ] ? '\n' : '' ) + newcatstring;
return;
}
}
return wikitext;
}
// End HotCat functions
 
var text = otext;,
arr = is_rtl ? '\u2190' : '\u2192', // left and right arrows. Don't use ← and → in the code.
var comment;
sumCmt, // summary comment
sumCmtShort;
// Fix text
switch ( mode ) {
case 'add':
text = addCategory( text, targetcat );
sumCmt = msg( 'summary-add' ).replace( /\$1/g, targetcat );
sumCmtShort = '+[[' + catNS + targetcat + ']]';
break;
case 'copy':
text = text.replace( this.regexCatBuilder( sourcecat ), '[[' + catNS + sourcecat + '$1]]\n[[' + catNS + targetcat + '$1]]\n' );
sumCmt = msg( 'summary-copy' ).replace( /\$1/g, sourcecat ).replace( /\$2/g, targetcat );
sumCmtShort = '+[[' + catNS + sourcecat + ']]' + arr + '[[' + catNS + targetcat + ']]';
// If category is added through template:
if ( otext === text ) { text = addCategory( text, targetcat ); }
 
// Fix text break;
case 'move':
switch ( mode ) {
text = text.replace( this.regexCatBuilder( sourcecat ), '[[' + catNS + targetcat + '$1]]\n' );
case 'add':
textsumCmt += "\n[["msg( +'summary-move' this).localCatNamereplace( +/\$1/g, ":"sourcecat +).replace( /\$2/g, targetcat + "]]\n");
commentsumCmtShort = msgPlain('±[[' + catNS + sourcecat + 'summary-add]]' ).replace(+ arr + '$1[[', + catNS + targetcat )+ ']]';
break;
case 'copyremove':
text = text.replace( this.regexBuilderregexCatBuilder( sourcecattargetcat ), "[[" + this.localCatName + ":" + sourcecat + "$1]]\n[[" + this.localCatName + ":" + targetcat + "$1]]"'' );
commentsumCmt = msgPlainmsg( 'summary-copyremove' ).replace( '/\$1', sourcecat ).replace( '$2'/g, targetcat );
sumCmtShort = '-[[' + catNS + targetcat + ']]';
//If category is added through template:
break;
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;
}
otext = text;
 
// 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' && ( !non || userGrp.indexOf( 'autoconfirmed' ) > -1 ) ) {
textif = this.doCleanup( !this.removeUncat( textis_hidden ) );{
text = this.removeUncat( text );
if ( text.length !== otext.length ) { sumCmt += '; ' + msg( 'uncatpref' ); }
}
text = this.doCleanup( text );
var data = {
}
action: 'edit',
summary: comment,
title: file[ 0 ],
text: text,
bot: true,
starttimestamp: starttimestamp,
basetimestamp: timestamp,
watchlist: this.settings.watchlist,
token: this.edittoken
};
if ( this.settings.minor ) data.minor = true;
 
sumCmt += this.summary ? ' ' + this.summary : '';
this.doAPICall( data, function() {
catALot.updateCounter();
} );
this.markAsDone( file[ 1 ], mode, targetcat );
},
markAsDone: function( label, mode, targetcat ) {
 
label.addClassvar preM = msg( 'cat_a_lot_markAsDoneprefix-summary' );
var usgM = msg( 'using-summary' );
switch ( mode ) {
// Try shorten summary
case 'add':
if ( preM || usgM ) {
label.append( '<br>' + msg( 'added-cat', targetcat ) );
sumCmt = sumCmt.length > 250 - preM.length - usgM.length ?
break;
sumCmt + ' (CatAlot)' : preM + sumCmt + usgM;
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() {
 
if ( sumCmt.length > 254 ) // Try short summary
this.counterCurrent++;
{ sumCmt = sumCmtShort; }
if ( this.counterCurrent > this.counterNeeded ) this.displayResult();
else this.domCounter.text( this.counterCurrent );
},
 
var data = {
displayResult: function() {
action: 'edit',
assert: 'user',
summary: sumCmt,
title: file[ 0 ],
text: text,
bot: true,
starttimestamp: this.starttimestamp,
basetimestamp: timestamp,
watchlist: this.settings.watchlist,
minor: this.settings.minor,
tags: this.changeTag,
token: this.edittoken
};
 
this.doAPICall( data, function ( r ) {
document.body.style.cursor = 'auto';
delete CAL.XHR[ file[ 0 ] ];
$( '.cat_a_lot_feedback' )
return CAL.updateUndoCounter( r );
.addClass( 'cat_a_lot_done' );
} );
$( '.ui-dialog-content' )
this.markAsDone( file[ 1 ], mode, targetcat );
.height( 'auto' );
},
var rep = this.domCounter.parent();
rep.html( '<h3>' + msg( 'done' ) + '</h3>' );
rep.append( msg( 'all-done' ) + '<br />' );
 
markAsDone: function ( label, mode, targetcat ) {
var close = $( '<a>' )
.textmode = ( msgPlainfunction ( 'return-to-page'm ) );{
close.click(switch function( m ) {
case 'add': return 'added-cat';
catALot.progressDialog.remove();
case 'copy': return 'copied-cat';
catALot.toggleAll( false );
case 'move': return 'moved-cat';
} );
case 'remove': return 'removed-cat';
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>' ) );
}
}( mode ) );
label.addClass( 'cat_a_lot_markAsDone' ).append( '<br>' + msg( mode, targetcat ) );
},
 
updateUndoCounter: function ( r ) {
},
this.updateCounter();
if ( !r.edit || r.edit.result !== 'Success' ) { return; }
r = r.edit;
 
this.undoList.push( {
moveHere: function( targetcat ) {
title: r.title,
this.doSomething( targetcat, 'move' );
id: r.newrevid,
},
timestamp: r.newtimestamp
} );
},
 
copyHere updateCounter: function ( targetcat ) {
this.counterCurrent++;
this.doSomething( targetcat, 'copy' );
if ( this.counterCurrent > this.counterNeeded ) { this.displayResult(); } else { this.domCounter.text( this.counterCurrent ); }
},
},
 
addHere displayResult: function ( targetcat ) {
document.body.style.cursor = 'auto';
this.doSomething( targetcat, 'add' );
$.removeSpinner( 'fb-dialog' );
},
this.progressDialog.parent()
.addClass( 'cat_a_lot_done' )
.find( '.ui-dialog-buttonpane button span' ).eq( 0 )
.text( mw.msg( 'cat-a-lot-return-to-page' ) );
var rep = this.domCounter.parent()
.height( 'auto' )
.html( '<h3>' + msg( 'done' ) + '</h3>' )
.append( msg( 'all-done' ) + '<br>' );
if ( this.alreadyThere.length ) {
rep.append( '<h5>' + msg( 'skipped-already', this.alreadyThere.length ) + '</h5>' )
.append( this.alreadyThere.join( '<br>' ) );
}
 
if ( this.notFound.length ) {
remove: function() {
rep.append( '<h5>' + msg( 'skipped-not-found', this.notFound.length ) + '</h5>' )
this.doSomething( '', 'remove' );
.append( this.notFound.join( '<br>' ) );
},
}
 
if ( this.connectionError.length ) {
doSomething: function( targetcat, mode ) {
rep.append( '<h5>' + msg( 'skipped-server', this.connectionError.length ) + '</h5>' )
var files = this.getMarkedLabels();
.append( this.connectionError.join( '<br>' ) );
if ( files.length === 0 ) {
}
alert( msgPlain( 'none-selected' ) );
 
return;
},
}
 
this.notFound = [];
/**
this.alreadyThere = [];
* @brief set parameters for API call,
this.connectionError = [];
* convert targetcat to string, get selected pages/files
this.counterCurrent = 1;
* @param [dom object] targetcat with data
this.counterNeeded = files.length;
* @param [string] mode action
mw.loader.using( ['jquery.ui', 'mediawiki.util'], function() {
* @return Return API call getTargetCat with pages
catALot.showProgress();
*/
for ( var i = 0; i < files.length; i++ ) {
catALot.getContent( doSomething: files[function i ],( targetcat, mode ); {
var pages = this.getMarkedLabels();
}
if ( !pages.length ) { return alert( mw.msg( 'Ooui-selectfile-placeholder' ) ); }
targetcat = $( targetcat ).closest( 'tr' ).data( 'cat' );
 
this.notFound = [];
this.alreadyThere = [];
this.connectionError = [];
this.counterCurrent = 1;
this.counterNeeded = pages.length;
this.undoList = [];
this.XHR = {};
this.cancelled = 0;
this.summary = '';
 
if ( $( '#cat_a_lot_comment' ).prop( 'checked' ) ) { this.summary = window.prompt( msg( 'edit-question' ), '' ); } // TODO custom pre-value
if ( this.summary !== null ) {
mw.loader.using( 'jquery.spinner', function () {
CAL.showProgress();
CAL.getTargetCat( pages, targetcat, mode );
} );
},
 
},
doAPICall: function( params, callback ) {
 
params.format = 'json';
doAPICall: function ( params, callback ) {
var i = 0;
params = $.extend( {
var apiUrl = this.apiUrl;
action: 'query',
var handleError = function( jqXHR, textStatus, errorThrown ) {
format: 'json'
if ( window.console && $.isFunction( window.console.log ) ) {
}, params );
window.console.log( 'Error: ', jqXHR, textStatus, errorThrown );
 
}
var i = 0,
apiUrl = this.apiUrl,
doCall,
handleError = function ( jqXHR, textStatus, errorThrown ) {
mw.log( 'Error: ', jqXHR, textStatus, errorThrown );
if ( i < 4 ) {
window.setTimeout( doCall, 300 );
}
};
var doCall = function () {
var xhr = $.ajax( {
url: apiUrl,
cache: false,
dataType: 'json',
data: params,
type: 'POST',
success: callback,
error: handleError
} );
};
doCall();
},
 
if ( params.action === 'edit' && !CAL.cancelled ) { CAL.XHR[ params.title ] = xhr; }
createCatLinks: function( symbol, list ) {
};
list.sort();
doCall();
var domlist = $resultList.find( 'table' );
},
for ( var i = 0; i < list.length; i++ ) {
var $tr = $( '<tr>' );
 
createCatLinks: function ( symbol, list, table ) {
var $link = $( '<a>' ),
list.sort();
$add, $move, $copy;
var button = this.settings.button ? 1 : 0;
for ( var c = 0; c < list.length; c++ ) {
var $tr = $( '<tr>' ),
$link = $( '<a>', {
href: mw.util.getUrl( CAL.localCatName + list[ c ] ),
text: list[ c ]
} ),
$buttons = [];
$tr.data( 'cat', list[ c ] );
$link.on( 'click', function ( e ) {
if ( !e.ctrlKey ) {
e.preventDefault();
CAL.updateCats( $( this ).closest( 'tr' ).data( 'cat' ) );
}
} );
 
$linktr.textappend( list[$( i'<td>' ]).text( symbol ) );
$tr.dataappend( $( 'cat<td>', list[).append( i$link ]) );
 
$link.click( function() {
$buttons.push( $( '<a>' )
catALot.updateCats( $( this ).closest('tr').data( 'cat' ) );
.text( msg( 'remove-from-cat' ) )
.on( 'click', function () {
CAL.doSomething( this, 'remove' );
} )
.addClass( 'cat_a_lot_move' )
);
if ( button ) {
$buttons.slice( -1 )[ 0 ].button( {
icons: { primary: 'ui-icon-minusthick' },
showLabel: false,
text: false
} );
}
 
if ( this.searchmodeorigin ) {
// Can't move to source category
$add = $( '<a class="cat_a_lot_action"></a>' )
if ( list[ c ] !== this.origin ) {
.text( msgPlain( 'add' ) )
$buttons.clickpush( function$() {'<a>' )
catALot.addHeretext( $( this ).closest('tr').datamsg( 'catmove' ) );
}.on( 'click', function (); {
CAL.doSomething( this, 'move' );
} else {
} )
$move = $( '<a class="cat_a_lot_move"></a>' )
.text( msgPlainaddClass( 'movecat_a_lot_move' ) )
.click( function() {;
if ( button ) {
catALot.moveHere( $( this ).closest('tr').data( 'cat' ) );
$buttons.slice( -1 )[ 0 ].button( {
icons: { primary: 'ui-icon-arrowthick-1-e' },
showLabel: false,
text: false
} );
}
 
$copy =buttons.push( $( '<a class="cat_a_lot_action"></a>' )
.text( msgPlainmsg( 'copy' ) )
.clickon( 'click', function () {
catALotCAL.copyHere( $doSomething( this, ).closest('trcopy').data( 'cat' ) );
} )
.addClass( 'cat_a_lot_action' )
);
if ( button ) {
$buttons.slice( -1 )[ 0 ].button( {
icons: { primary: 'ui-icon-plusthick' },
showLabel: false,
text: false
} );
}
 
}
} else {
$buttons.push( $( '<a>' )
.text( msg( 'add' ) )
.on( 'click', function () {
CAL.doSomething( this, 'add' );
} )
.addClass( 'cat_a_lot_action' )
);
if ( button ) {
$buttons.slice( -1 )[ 0 ].button( {
icons: { primary: 'ui-icon-plusthick' },
showLabel: false,
text: false
} );
}
 
}
$tr.append( $('<td>').text( symbol ) )
// TODO CSS may extern
.append( $('<td>').append( $link ) );
var css = button ? { fontSize: '.6em', margin: '0', width: '2.5em' } : {};
for ( var b = 0; b < $buttons.length; b++ ) { $tr.append( $( '<td>' ).append( $buttons[ b ].css( css ) ) ); }
 
table.append( $tr );
// 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 ) );
}
 
getCategoryList: function () {
domlist.append( $tr );
this.catCounter = 0;
this.getParentCats();
this.getSubCats();
},
 
_getPageQuery: function ( data ) {
// There should be only one, but we don't know its ID
if ( data && data.query && data.query.pages ) {
data = data.query.pages;
for ( var p in data ) { return data[ p ]; }
}
},
 
/**
* @brief takes this.currentCategory if redir_category is configured
** Cat pages with more than one cat link are still not supported for sure
* @return soft redirected cat
*/
solveSoftRedirect: function () {
this.doAPICall( {
prop: 'links', // TODO: For more accuracy the revisions could be checked
titles: 'Category:' + this.currentCategory,
// 'rvprop': 'content',
// 'pllimit': 'max',
plnamespace: 14
}, function ( page ) {
page = CAL._getPageQuery( page );
if ( page ) {
var lks = page.links;
if ( lks && lks.length === 1 && lks[ 0 ].title ) {
CAL.currentCategory = lks[ 0 ].title.replace( reCat, '' );
$searchInput.val( CAL.currentCategory );
return CAL.getCategoryList();
} else {
// TODO? better translatable warning message: "Please solve the category soft redirect manually!"
$resultList.html( '<span id="cat_a_lot_no_found">' + mw.msg( 'Apifeatureusage-warnings', mw.msg( 'Categorytree-not-found', CAL.currentCategory ) ) + '</span>' );
}
}
}, );
},
 
getCategoryList showCategoryList: function () {
if ( this.settings.redir_category && this.settings.redir_category === this.parentCats[ 0 ] ) { return this.solveSoftRedirect(); }
this.catCounter = 0;
this.getParentCats();
this.getSubCats();
},
 
var table = $( '<table>' );
showCategoryList: function() {
var thiscat = [ this.currentCategory ];
 
this.createCatLinks( '↑', this.parentCats, table );
$resultList.empty();
this.createCatLinks( '→', [ this.currentCategory ], table );
$resultList.append( '<table></table>' );
// Show on soft-redirect
if ( $searchInput.val() === this.currentCategory && this.origin !== this.currentCategory ) { this.createCatLinks( '→', [ this.origin ], table ); }
this.createCatLinks( '↓', this.subCats, table );
 
$resultList.empty();
this.createCatLinks( "↑", this.parentCats );
$resultList.append( table );
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 ) );
 
// Reset width
$resultList.css( {
$container.width( '' );
maxHeight: this.setHeight + 'px',
$container.height:( '' );
$container.width( Math.min( table.width() * 1.1 + 15, $( window ).width() - 10 ) );
 
$resultList.css( {
maxHeight: Math.min( this.setHeight, $( window ).height() - $container.position().top - $selections.outerHeight() - 15 ),
height: ''
} );
table.width( '100%' );
$container.height( Math.min( $container.height(), $head.offset().top - $container.offset().top + 10 ) );
$container.offset( { left: $( window ).width() - $container.outerWidth() } ); // Fix overlap
},
 
updateCats: function ( newcat ) {
document.body.style.cursor = 'wait';
this.currentCategory = newcat;
$resultList.html( '<div class="cat_a_lot_loading">' + mw.msg( 'Wikieditor-loading' ) + '</div>' );
this.getCategoryList();
},
 
doUndo: function () {
this.cancelled = 0;
this.doAbort();
if ( !this.undoList.length ) { return; }
 
$( '.cat_a_lot_feedback' ).removeClass( 'cat_a_lot_done' );
this.counterNeeded = this.undoList.length;
this.counterCurrent = 1;
 
document.body.style.cursor = 'wait';
 
var query = {
action: 'edit',
user: mw.config.get( 'wgUserName' ),
bot: true,
minor: this.settings.minor,
starttimestamp: this.starttimestamp,
watchlist: this.settings.watchlist,
tags: this.changeTag,
token: this.edittoken
};
for ( var i = 0; i < this.undoList.length; i++ ) {
var uID = this.undoList[ i ];
query.title = uID.title;
query.undo = uID.id;
query.basetimestamp = uID.timestamp;
this.doAPICall( query, function ( r ) {
// TODO: Add "details" to progressbar?
// $resultList.append( [mw.msg('Filerevert-submit') + " done " + r.edit.title, '<br>' ] );
if ( r && r.edit ) { mw.log( 'Revert done', r.edit.title ); }
CAL.updateCounter();
} );
},
},
 
updateCats doAbort: function ( newcat ) {
for ( var t in this.XHR ) { this.XHR[ t ].abort(); }
document.body.style.cursor = 'wait';
 
if ( this.cancelled ) { // still not for undo
this.currentCategory = newcat;
this.progressDialog.remove();
$resultList.html( '<div class="cat_a_lot_loading"></div>' ).text( msgPlain( 'loading' ) );
this.getCategoryListtoggleAll( false );
$head.last().show();
},
}
showProgress: function() {
this.cancelled = 1;
document.body.style.cursor = 'wait';
},
 
showProgress: function () {
this.progressDialog = $( '<div></div>' )
document.body.style.cursor = 'wait';
.html( msg( 'editing' ) + ' <span id="cat_a_lot_current">' + this.counterCurrent + '</span> ' + msg( 'of' ) + this.counterNeeded )
this.progressDialog = $( '<div>' )
.dialog( {
.html( ' ' + msg( 'editing' ) + ' <span id="cat_a_lot_current">' + CAL.counterCurrent + '</span> ' + msg( 'of' ) + CAL.counterNeeded )
width: 450,
.prepend( $.createSpinner( { id: 'fb-dialog', size: 'large' } ) )
height: 90,
minHeight:.dialog( 90,{
modalwidth: true450,
resizableheight: false180,
draggableminHeight: false90,
closeOnEscapemodal: falsetrue,
resizable: false,
dialogClass: "cat_a_lot_feedback"
}draggable: );false,
// closeOnEscape: true,
$( '.ui-dialog-titlebar' )
dialogClass: 'cat_a_lot_feedback',
.hide();
buttons: [ {
this.domCounter = $( '#cat_a_lot_current' );
text: mw.msg( 'Cancel' ), // Stops all actions
click: function () {
$( this ).dialog( 'close' );
}
} ],
close: function () {
CAL.cancelled = 1;
CAL.doAbort();
$( this ).remove();
},
open: function ( event, ui ) { // Workaround modify
ui = $( this ).parent();
ui.find( '.ui-dialog-titlebar' ).hide();
ui.find( '.ui-dialog-buttonpane.ui-widget-content' )
.removeClass( 'ui-widget-content' );
/* .find( 'span' ).css( { fontSize: '90%' } )*/
}
} );
if ( $head.children().length < 3 ) {
$( '<span>' )
.css( {
'float': 'right',
fontSize: '75%'
} )
.append( [ '[ ',
$( '<a>', { title: 'Revert all last done edits' } ) // TODO i18n
.on( 'click', function () {
if ( window.confirm( mw.msg( 'Apifeatureusage-warnings', this.title + '⁉' ) ) ) {
CAL.doUndo();
$( this ).parent().remove();
}
return false;
} )
.addClass( 'new' )
.text( mw.msg( 'Filerevert-submit' ) ),
' ]'
] ).insertAfter( $link );
}
 
this.domCounter = $( '#cat_a_lot_current' );
},
},
 
run minimize: function ( e ) {
CAL.top = Math.max( 0, $container.position().top );
if ( $( '.cat_a_lot_enabled' ).length ) {
CAL.height = $container.height();
this.makeClickable();
$dataContainer.hide();
$container.animate( {
.show();
height: $head.height(),
$container
top: $( window ).height() - $head.height() * 1.4
}, function () {
$( e.target ).one( 'click', CAL.maximize );
} );
},
 
maximize: function ( e ) {
$dataContainer.show();
$container.animate( {
top: CAL.top,
height: CAL.height
}, function () {
$( e.target ).one( 'click', CAL.minimize );
} );
},
 
run: function () {
if ( $( '.cat_a_lot_enabled' )[ 0 ] ) {
this.makeClickable();
if ( !this.executed ) { // only once
$selectInvert.text( mw.msg( 'Checkbox-invert' ) );
if ( this.settings.editpages && this.pageLabels[ 0 ] ) {
$selectFiles.text( mw.msg( 'Prefs-files' ) );
$selectPages.text( mw.msg( 'Categories' ) ).parent().show();
}
$link.after( $( '<a>' )
.text( '–' )
.css( { fontWeight: 'bold', marginLeft: '.7em' } )
.one( 'click', this.minimize )
);
}
$dataContainer.show();
$container.one( 'mouseover', function () {
$( this )
.resizable( {
handles: 'n',
alsoResize: '#cat_a_lot_category_list',
resize: function () {
$( this )
.css( {
left: '',
top: ''
} );
catALot.setHeight = $( this )
.height();
$resultList
.css( {
width: ''
} );
},
start: function ( e, ui ) { // Otherwise box get static if sametime resize with draggable
ui.helper.css( {
top: ui.helper.offset().top - $( window ).scrollTop(),
position: 'fixed'
} );
},
stop: function () {
CAL.setHeight = $resultList.height();
}
} )
.draggable( {
cursor: 'move',
start: function ( e, ui ) {
ui.helper.on( 'click.prevent',
function ( e ) { e.preventDefault(); }
);
ui.helper.css( 'height', ui.helper.height() );
},
stop: function ( e, ui ) {
setTimeout(
function () {
ui.helper.off( 'click.prevent' );
}, 300
);
}
} )
.one( 'mousedown', function () {
$container.height( $container.height() ); // Workaround to calculate
} );
$resultList
.css( { maxHeight: 450 } );
} );
maxHeight: '450px'
this.updateCats( this.origin || 'Images' );
} );
if ( this.searchmode ) this.updateCats( "Pictures and images" );
else this.updateCats( currentCat );
 
$link.html( $( '<span>' )
} else {
$dataContainer.text( '×' )
.css( { font: 'bold 2em monospace', lineHeight: '.75em' } )
.hide();
$container);
$link.resizablenext().show( "destroy" );
if ( this.cancelled ) { $head.last().show(); }
//Unbind click handlers
mw.cookie.set( 'catAlotO', ns ); // Let stay open on new window
this.labels.off( 'click.catALot' );
} else { // Reset
$dataContainer.hide();
$container
.draggable( 'destroy' )
.resizable( 'destroy' )
.removeAttr( 'style' );
// Unbind click handlers
this.labels.off( 'click.catALot' );
this.setHeight = 450;
$link.text( 'Cat-a-lot' )
.nextAll().hide();
this.executed = 1;
mw.cookie.set( 'catAlotO', null );
}
},
 
_initSettings: function () {
if ( this.settings.watchlist ) { return; }
this.catALotPrefs = window.catALotPrefs || {};
for ( var i = 0; i < this.defaults.length; i++ ) {
var v = this.defaults[ i ];
v.value = this.settings[ v.name ] = this.catALotPrefs[ v.name ] || v['default'];
v.label = msg( v.label_i18n );
if ( v.select_i18n ) {
v.select = {};
$.each( v.select_i18n, function ( i18nk, val ) {
v.select[ msg( i18nk ) ] = val;
} );
}
},
},
/* eslint-disable camelcase */
defaults: [ {
name: 'watchlist',
'default': 'preferences'
}, {
name: 'minor',
'default': false
}, {
name: 'editpages',
'default': project !== 'commonswiki', // on Commons false
forcerestart: true
}, {
name: 'docleanup',
'default': false
}, {
name: 'subcatcount',
'default': 50,
min: 5,
max: 500,
forcerestart: true
}, {
name: 'uncat',
'default': false
}, {
name: 'button',
'default': true
} ]
/* eslint-enable camelcase */
};
 
// The gadget is not immediately needed, so let the page load normally
manageSettings: function() {
$( function () {
/* mw.loader.using( [ 'ext.gadget.SettingsManager', 'ext.gadget.SettingsUI', 'jquery.ui' ], function() {
non = mw.config.get( 'wgUserName' );
catALot._manageSettings();
if ( non ) {
} ); */
if ( mw.config.get( 'wgRelevantUserName' ) === non ) { non = 0; } else {
},
$.each( [ 'sysop', 'filemover', 'editor', 'rollbacker', 'patroller', 'autopatrolled', 'image-reviewer', 'reviewer', 'extendedconfirmed' ], function ( i, v ) {
_manageSettings: function() {
non = $.inArray( v, userGrp ) === -1;
window.mw.libs.SettingsUI( this.defaults, "Cat-A-Lot" )
.show()return non;
} );
.done( function( s, verbose, loc, settingsOut, $dlg ) {
}
var mustRestart = false,
} else { non = 1; }
_restart = function() {
if ( !mustRestart ) return;
 
switch ( ns ) {
$container.remove();
case 14:
catALot.labels.off( 'click.catALot' );
CAL.searchmode = 'category';
catALot.init();
CAL.origin = mw.config.get( 'wgTitle' );
},
break;
_saveToJS = function() {
/* 其他namespace无法正常使用
var opt = mw.libs.settingsManager.option( {
case -1:
optionName: 'catALotPrefs',
CAL.searchmode = {
value: catALot.settings,
// list of accepted special page names mapped to search mode names
encloseSignature: 'catALot',
Contributions: 'contribs',
encloseBlock: '////////// Cat-A-Lot user preferences //////////\n',
Listfiles: non ? null : 'listfiles',
triggerSaveAt: /Cat.?A.?Lot/i,
Prefixindex: non ? null : 'prefix',
editSummary: msgPlain( 'pref-save-summary' )
}Search: )'search',
Uncategorizedimages: 'gallery'
oldHeight = $dlg.height(),
}[ mw.config.get( 'wgCanonicalSpecialPageName' ) ];
$prog = $( '<div>' );
break;
 
case 2:
$dlg.css( 'height', oldHeight )
case 0:
.html( '' );
CAL.searchmode = 'gallery';
$prog.css( {
var parents = $( '#mw-normal-catlinks ul' ).find( 'a[title]' ), n;
'height': Math.round( oldHeight / 8 ),
parents.each( function ( i ) {
'margin-top': Math.round( ( 7 * oldHeight ) / 16 )
if ( new RegExp( mw.config.get( 'wgTitle' ), 'i' ).test( $( this ).text() ) ) {
} )
.appendTo(n $dlg= )i;
return false;
 
$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;
} );
}
} );
CAL.origin = parents.eq( n || 0 ).text();
},
*/
defaults: [ {
}
name: 'watchlist',
 
'default': 'preferences',
if ( CAL.searchmode ) {
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 ) {
lang = 'zh-hans';
break;
 
}
 
$.ajax( {
url: '//commons.wikimirror.org/w/index.php'commonsURL,
dataType: 'script',
data: {
},
cache: true,
success: cb,function() {
mw.messages.set({
'cat-a-lot-summary-add': wgULS('加入分类', '加入分類') + '[[Category:$1]]',
'cat-a-lot-summary-copy': wgULS('分类间复制:从', '分類間複製:從') + '[[Category:$1]]到[[Category:$2]]',
'cat-a-lot-summary-move': wgULS('分类间移动:从', '分類間移動:從') + '[[Category:$1]]到[[Category:$2]]',
'cat-a-lot-summary-remove': wgULS('从分类', '從分類') + '移除:[[Category:$1]]'
});
cb();
},
error: cb
} );
};
var maybeLaunch = function () {
loadingLocalizations--;
function init() {
$( documentfunction ).ready( function() {
catALotCAL.init();
} );
}
if ( 0 === loadingLocalizations ) {
mw.loader.using( [ 'user' ], init, init );
}
if ( !loadingLocalizations ) { init(); }
};
 
ifvar (userlang = mw.config.get( 'wgUserLanguage' ) !== 'en' ) {;
loadLocalization(if mw.config.get( userlang !== 'wgUserLanguageen' ) { loadLocalization( userlang, maybeLaunch ); }
// if ( $.inArray( contlang, [ 'en', userlang ] ) === -1 ) { loadLocalization( contlang, maybeLaunch ); }
}
if ( mw.config.get( 'wgContentLanguage' ) !== 'en' ) {
loadLocalization( mw.config.get( 'wgContentLanguage' ), maybeLaunch );
}
maybeLaunch();
}
} );
*/
} )( jQuery, mediaWiki );
 
/**
* When clicking a cat-a-lot label with Shift pressed, select all labels between the current and last-clicked one.
* Derivative work of
* (replace "checkboxes" with cat-a-lot labels in your mind)
*/
$.fn.catALotShiftClick = function ( cb ) {
/**
var prevCheckbox = null,
* jQuery checkboxShiftClick
$box = this;
*
// When our boxes are clicked..
* This will enable checkboxes to be checked or unchecked in a row by clicking one, holding shift and clicking another one
$box.on( 'click.catALot', function ( e ) {
*
// Prevent following the link and text selection
* @author Krinkle <krinklemail@gmail.com>
if ( !e.ctrlKey ) { e.preventDefault(); }
* @license GPL v2
// Highlight last selected
*/
$( '#cat_a_lot_last_selected' )
( function( $ ) {
.removeAttr( 'id' );
$.fn.catALotShiftClick = function( cb ) {
var prevCheckbox$thisControl = null$( e.target ),
$box = thismethod;
if ( !$thisControl.hasClass( 'cat_a_lot_label' ) ) { $thisControl = $thisControl.parents( '.cat_a_lot_label' ); }
// When our boxes are clicked..
$box.on( 'click.catALot', function( e ) {
 
$thisControl.attr( 'id', 'cat_a_lot_last_selected' )
// Highlight last selected
.toggleClass( 'cat_a_lot_selected' );
$( '#cat_a_lot_last_selected' )
// And one has been clicked before…
.removeAttr( 'id' );
varif $thisControl( prevCheckbox !== $(null && e.targetshiftKey ), {
method = $thisControl.hasClass( 'cat_a_lot_selected' ) ? 'addClass' : 'removeClass';
method;
// Check or uncheck this one and all in-between checkboxes
if ( !$thisControl.hasClass( 'cat_a_lot_label' ) ) {
$box.slice(
$thisControl = $thisControl.parents( '.cat_a_lot_label' );
Math.min( $box.index( prevCheckbox ), $box.index( $thisControl ) ),
}
Math.max( $box.index( prevCheckbox ), $box.index( $thisControl ) ) + 1
$thisControl.attr( 'id', 'cat_a_lot_last_selected' )
.toggleClass)[ method ]( 'cat_a_lot_selected' );
}
 
// AndEither oneway, hasupdate beenthe prevCheckbox variable to the one clicked before...now
if ( prevCheckbox !== null && e.shiftKey ) {$thisControl;
if ( $.isFunction( cb ) ) { cb(); }
// Prevent selection
} );
e.preventDefault();
return $box;
 
};
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 ) );
 
}( jQuery, mediaWiki ) );
// </nowiki>
//</nowiki>
16,874

个编辑

导航菜单