کاربر:جواد/vector.js
ظاهر
کدهایی که در این صفحه قرار میدهید، ممکن است حاوی محتوای مخربی باشند که حساب کاربری شما را به خطر میاندازند. اگر با استفاده از دستور «importScript» یا الگوی «نصب اسکریپت کاربری» اسکریپتی را از صفحهای دیگر درونریزی میکنید، دقت داشتهباشید که این کار باعث میشود تا بهطور سیال اسکریپتی را بارگیری کنید که امکان تغییر آن توسط دیگران وجود دارد. اگر از امنیت کدهایی که به این صفحه میافزایید مطمئن نیستید، در قهوهخانهٔ فنی درخواست کمک کنید. هرگاه پیشنمایش تغییراتی که در این صفحه اعمال کردهاید را مشاهده کنید، کد اجرا خواهد شد. |
![]() | صفحهٔ همراه .css برای این پوسته در کاربر:جواد/vector.css قرار دارد. |
// <source lang="javascript">
//
// Cat-A-Lot
// Changes category of multiple files (or pages)
//
// Originally by Magnus Manske
// RegExes by Ilmari Karonen
// Completely rewritten by DieBuche
//
// Modified to work on regular pages instead of files, + Hebrew translation: קיפודנחש
//
// READ THIS PAGE IF YOU WANT TO TRANSLATE OR USE THIS ON ANOTHER SITE:
// http://commons.wikimedia.org/wiki/MediaWiki_talk:Gadget-Cat-a-lot.js/translating
//
var catALot = {
apiUrl: mw.config.get('wgScriptPath') + "/api.php",
searchmode: false,
version: 2.18,
setHeight: 450,
init: function () {
$("body")
.append('<div id="cat_a_lot">' + '<div id="cat_a_lot_data"><div>' + '<input type="text" id="cat_a_lot_searchcatname" placeholder="' + this.i18n.enterName + '"/>'
+ '</div><div id="cat_a_lot_category_list"style="white-space:nowrap;"></div>' + '<div id="cat_a_lot_mark_counter"> </div>' + '<div id="cat_a_lot_selections">' + this.i18n.select
+ ' <a id="cat_a_lot_select_all">' + this.i18n.all + '</a> / ' + '<a id="cat_a_lot_select_none">' + this.i18n.none + '</a>'
+ '</div></div><div id="cat_a_lot_head">' + '<a id="cat_a_lot_toggle">Cat-a-lot</a></div></div>');
if (!this.searchmode) $('#cat_a_lot_selections').append('<br><a id="cat_a_lot_remove"><b>' + this.i18n.removeFromCat + '</b></a>');
$('#cat_a_lot_remove').click(function () {
catALot.remove();
});
$('#cat_a_lot_select_all').click(function () {
catALot.toggleAll(true);
});
$('#cat_a_lot_select_none').click(function () {
catALot.toggleAll(false);
});
$('#cat_a_lot_toggle').click(function () {
$(this).toggleClass('cat_a_lot_enabled');
catALot.run();
});
$('#cat_a_lot_searchcatname')
.keypress(function (e) {
if (e.which == 13)
catALot.updateCats($(this).val());
})
.autocomplete({
source: function(request, response) {
catALot.doAPICall({action:'opensearch', search: request.term, namespace: 14},
function(data){
if(data[1])
response($(data[1]).map(function(index,item){return item.replace(/.*:/, '');}));
}
);
},
open:function(){
$(".ui-autocomplete")
.position({
my: "left bottom",
at: "left top",
of: $('#cat_a_lot_searchcatname')
});
}
});
importStylesheet('MediaWiki:Gadget-Cat-a-lot.css');
this.localCatName = mw.config.get('wgFormattedNamespaces')[14];
},
findAllLabels: function () {
this.labels = $('#mw-pages').find('li');
var subCats = $('#mw-subcategories').find('.CategoryTreeItem');
for (var sub = 0; sub < subCats.length; sub++) {
var a = $(subCats[sub]).find('a');
if (a.length) {
a[0]['title'] = catALot.localCatName + ":" + a[0].innerHTML;
this.labels.push(subCats[sub]);
}
}
$('li a, .CategoryTreeLabel', mw.util.$content).attr({href: '#noSuchAnchor'});
},
getMarkedLabels: function () {
var marked = [];
this.selectedLabels = this.labels.filter('.cat_a_lot_selected');
this.selectedLabels.each(function () {
var file = $(this).find('a[title]');
marked.push([file.attr('title'), $(this)]);
});
return marked;
},
updateSelectionCounter: function () {
this.selectedLabels = this.labels.filter('.cat_a_lot_selected');
$('#cat_a_lot_mark_counter').show().html(this.selectedLabels.length + this.i18n.filesSelected );
},
makeClickable: function () {
this.findAllLabels();
this.labels.click(function () {
$(this).toggleClass('cat_a_lot_selected');
catALot.updateSelectionCounter();
});
},
toggleAll: function (select) {
this.labels.toggleClass('cat_a_lot_selected', select);
this.updateSelectionCounter();
},
getSubCats: function (cmcontinue) {
var data = {
action: 'query',
list: 'categorymembers',
cmnamespace: 14,
cmlimit: 50,
cmtitle: this.localCatName + ':' + this.currentCategory
};
if (cmcontinue)
data.cmcontinue = cmcontinue;
else
this.subCats = [];
this.doAPICall(data, function (result) {
var cats = result.query.categorymembers;
for (var i = 0; i < cats.length; i++) {
catALot.subCats.push(cats[i].title.replace(/^[^:]+:/, ""));
}
if (result['query-continue'])
catALot.getSubCats(result['query-continue'].categorymembers.cmcontinue);
else {
catALot.catCounter++;
if (catALot.catCounter == 2) catALot.showCategoryList();
}
});
},
getParentCats: function () {
var data = {
action: 'query',
prop: 'categories',
cllimit: 500,
titles: this.localCatName + ':' + this.currentCategory
};
this.doAPICall(data, function (result) {
catALot.parentCats = new Array();
var pages = result.query.pages;
if (pages[-1] && pages[-1].missing == '') {
catALot.catlist.html('<span id="cat_a_lot_no_found">' + catALot.i18n.catNotFound + '</span>');
document.body.style.cursor = 'auto';
catALot.catlist.append('<ul></ul>');
catALot.createCatLinks("→", [catALot.currentCategory]);
return;
}
// there should be only one, but we don't know its ID
for (var id in pages) {
var 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();
});
},
regexBuilder: function (category) {
var catname = ( this.localCatName == 'Category' ) ? this.localCatName: this.localCatName + '|Category';
catname = '(' + catname + ')';
// Build a regexp string for matching the given category:
// trim leading/trailing whitespace and underscores
category = category.replace(/^[\s_]+/, "").replace(/[\s_]+$/, "");
// escape regexp metacharacters (= any ASCII punctuation except _)
category = category.replace(/([!-\/:-@\[-^`{-~])/g, '\\$1');
// any sequence of spaces and underscores should match any other
category = category.replace(/[\s_]+/g, '[\\s_]+');
// Make the first character case-insensitive:
var first = category.substr(0, 1);
if (first.toUpperCase() != first.toLowerCase()) category = '[' + first.toUpperCase() + first.toLowerCase() + ']' + category.substr(1);
// 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 + '[\\s_]*(\\|[^\\]]*(?:\\][^\\]]+)*)?\\]\\]', 'ig');
},
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);
});
},
editCategories: function (result, file, targetcat, mode) {
if (result == null) {
//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;
var otext = pages[id].revisions[0]['*'];
var starttimestamp = pages[id].starttimestamp;
var timestamp = pages[id].revisions[0]['timestamp'];
}
var sourcecat = mw.config.get('wgTitle');
// 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.replace("رده:","") + "]]\n";
text=text.replace("رده:رده:","رده:");
comment = this.i18n.summaryAdd + targetcat.replace("رده:","") + "]]";
break;
case 'copy':
text = text.replace(this.regexBuilder(sourcecat), "[[" + this.localCatName + ":" + sourcecat + "$2]]\n[[" + this.localCatName + ":" + targetcat.replace("رده:","") + "$2]]");
text=text.replace("رده:رده:","رده:");
comment = this.i18n.summaryCopy + sourcecat + "]] " + this.i18n.to + targetcat.replace("رده:","") + "]]";
break;
case 'move':
text = text.replace(this.regexBuilder(sourcecat), "[[" + this.localCatName + ":" + targetcat.replace("رده:","") + "$2]]");
text=text.replace("رده:رده:","رده:");
comment = this.i18n.summaryMove + sourcecat + "]] " + this.i18n.to + targetcat.replace("رده:","") + "]]";
break;
case 'remove':
text = text.replace(this.regexBuilder(sourcecat), "");
text=text.replace("رده:رده:","رده:");
comment = this.i18n.summaryRemove + sourcecat + "]]";
break;
}
if (text == otext) {
this.notFound.push(file[0]);
this.updateCounter();
return;
}
var data = {
action: 'edit',
summary: comment,
title: file[0],
token: this.edittoken,
starttimestamp: starttimestamp,
basetimestamp: timestamp,
text: text
};
var isBot=$.inArray('bot', mw.config.get('wgUserGroups'))>-1;
if(isBot)
data.bot = '1';
this.doAPICall(data, function (ret) {
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>' + this.i18n.addedCat + ' ' + targetcat);
break;
case 'copy':
label.append('<br>' + this.i18n.copiedCat + ' ' + targetcat);
break;
case 'move':
label.append('<br>' + this.i18n.movedCat + ' ' + targetcat);
break;
case 'remove':
label.append('<br>' + this.i18n.movedCat );
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>' + this.i18n.done + '</h3>');
rep.append( this.i18n.allDone + '<br />');
var close = $('<a>').append( this.i18n.returnToPage );
close.click(function () {
catALot.progressDialog.remove();
catALot.toggleAll(false);
});
rep.append(close);
if (this.alreadyThere.length) {
rep.append( this.i18n.skippedAlready );
rep.append(this.alreadyThere.join('<br>'));
}
if (this.notFound.length) {
rep.append( this.i18n.skippedNotFound );
rep.append(this.notFound.join('<br>'));
}
if (this.connectionError.length) {
rep.append( this.i18n.skippedServer );
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( this.i18n.noneSelected );
return;
}
this.notFound = [];
this.alreadyThere = [];
this.connectionError = [];
this.counterCurrent = 1;
this.counterNeeded = files.length;
this.showProgress();
for (var i = 0; i < files.length; i++) {
this.getContent(files[i], targetcat, mode);
}
},
doAPICall: function (params, callback) {
params.format = 'json';
$.ajax({
url: this.apiUrl,
cache: false,
dataType: 'json',
data: params,
type: 'POST',
success: callback
});
},
createCatLinks: function (symbol, list) {
list.sort();
var domlist = this.catlist.find('ul');
for (var i = 0; i < list.length; i++) {
var li = $('<li></li>');
var link = $('<a></a>');
link.text(list[i]);
li.data('cat', list[i]);
link.click(function () {
catALot.updateCats($(this).parent().data('cat'));
});
if (this.searchmode) {
var add = $('<a class="cat_a_lot_action"><b>' + this.i18n.add + '</b></a>');
add.click(function () {
catALot.addHere($(this).parent().data('cat'));
});
} else {
var move = $('<a class="cat_a_lot_move"><b>' + this.i18n.move + '</b></a>');
move.click(function () {
catALot.moveHere($(this).parent().data('cat'));
});
var copy = $('<a class="cat_a_lot_action"><b>' + this.i18n.copy + '</b></a>');
copy.click(function () {
catALot.copyHere($(this).parent().data('cat'));
});
}
// Can't move to source category
if (list[i] != mw.config.get('wgTitle') && this.searchmode) li.append(' ').append(add);
else if (list[i] != mw.config.get('wgTitle') && !this.searchmode) li.append(' ').append(move).append(' ').append(copy);
li.append(symbol).append(' ').append(link);
domlist.append(li);
}
},
getCategoryList: function () {
this.catCounter = 0;
this.getParentCats();
this.getSubCats();
},
showCategoryList: function () {
var thiscat = [this.currentCategory];
this.catlist.empty();
this.catlist.append('<ul></ul>');
this.createCatLinks("↑", this.parentCats);
this.createCatLinks("→", thiscat);
this.createCatLinks("↓", this.subCats);
document.body.style.cursor = 'auto';
//Reset width
var cat = $('#cat_a_lot');
cat.width('');
cat.height('');
cat.width( cat.width() * 1.05 );
var list = $('#cat_a_lot_category_list');
list.css({maxHeight: this.setHeight+'px', height: ''});
},
updateCats: function (newcat) {
document.body.style.cursor = 'wait';
this.currentCategory = newcat;
this.catlist = $('#cat_a_lot_category_list');
this.catlist.html('<div class="cat_a_lot_loading">' + this.i18n.loading + '</div>');
this.getCategoryList();
},
showProgress: function () {
document.body.style.cursor = 'wait';
this.progressDialog = $('<div></div>')
.html( this.i18n.editing + ' <span id="cat_a_lot_current">' + this.counterCurrent + '</span> ' + this.i18n.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();
$("#cat_a_lot_data").show();
$('#cat_a_lot').resizable({
handles: 'n',
alsoResize: '#cat_a_lot_category_list',
resize: function(event, ui) {
$(this).css({left:"", top:""});
catALot.setHeight = $(this).height();
$('#cat_a_lot_category_list').css({maxHeight: '', width: ''});
}
});
$('#cat_a_lot_category_list').css({maxHeight: '450px'});
if (this.searchmode) this.updateCats("Pictures and images");
else this.updateCats(mw.config.get('wgTitle'));
} else {
$("#cat_a_lot_data").hide();
$("#cat_a_lot").resizable( "destroy" );
//Unbind click handlers
this.labels.unbind('click');
}
},
i18n: (mw.config.get('wgUserLanguage') == "fa") ? {
loading: 'بارگیری...',
editing: 'ویرایش صفحه',
of: ' ',
skippedAlready: '<h5>صفحهٔ انتخاب شده رها شد، چون صفحه در همان رده قرار دارد.:</h5>',
skippedNotFound: '<h5>صفحهٔ انتخاب شده رها شد چون رده قدیمی پیدا نشد!:</h5>',
skippedServer: '<h5>صفحههای انتخاب شده را نمیتوان تغییر داد چون ارتباط با سرور فعلا برقرار نیست:</h5>',
allDone: 'درخواست برای تمام صفحهها انجام شدند.',
done: 'انجام شد!',
addedCat: 'افزودن رده',
copiedCat: 'کپی به ردهٔ',
movedCat: 'انتقال به ردهٔ',
removedCat: 'حذف از ردهٔ',
returnToPage: 'بازگشت به صفحه',
catNotFound: 'رده یافت نشد.',
//as in 17 files selected
filesSelected: ' صفحه انتخاب شده.',
//Actions
copy: 'کپی',
move: 'انتقال',
add: 'افزودن',
removeFromCat: 'حذف از رده',
enterName: 'نام رده مورد نظر را بنویسید',
select: 'انتخاب',
all: 'همه',
none: 'هیچکدام',
noneSelected: 'صفحهای انتخاب نشدهاست!',
//Summaries:
summaryAdd: '[[وپ:رده انبوه|ردهانبوه]]: افزودن [[رده:',
summaryCopy: '[[وپ:رده انبوه|ردهانبوه]]: کپی از [[رده:',
to: 'به [[رده:',
summaryMove: '[[وپ:رده انبوه|ردهانبوه]]: انتقال از [[رده:',
summaryRemove: '[[وپ:رده انبوه|ردهانبوه]]: حذف از [[رده:'
}: {
//Progress
loading: 'Loading...',
editing: 'Editing page',
of: 'of ',
skippedAlready: '<h5>The following pages were skipped, because the page was already in the category:</h5>',
skippedNotFound: '<h5>The following pages were skipped, because the old category could not be found:</h5>',
skippedServer: '<h5>The following pages couldn\'t be changed, since there were problems connecting to the server:</h5>',
allDone: 'All pages are processed.',
done: 'Done!',
addedCat: 'Added category',
copiedCat: 'Copied to category',
movedCat: 'Moved to category',
removedCat: 'Removed from category',
returnToPage: 'Return to page',
catNotFound: 'Category not found.',
//as in 17 files selected
filesSelected: ' files selected.',
//Actions
copy: 'Copy',
move: 'Move',
add: 'Add',
removeFromCat: 'Remove from this category',
enterName: 'Enter category name',
select: 'Select',
all: 'all',
none: 'none',
noneSelected: 'No files selected!',
//Summaries:
summaryAdd: 'Cat-a-lot: Adding [[Category:',
summaryCopy: 'Cat-a-lot: Copying from [[Category:',
to: 'to [[Category:',
summaryMove: 'Cat-a-lot: Moving from [[Category:',
summaryRemove: 'Cat-a-lot: Removing from [[Category:'
}
};
if ((mw.config.get('wgNamespaceNumber') == -1 && mw.config.get('wgCanonicalSpecialPageName') == "Search") || mw.config.get('wgNamespaceNumber') == 14) {
if ( mw.config.get('wgNamespaceNumber') == -1 ) catALot.searchmode = true;
mediaWiki.loader.using(['jquery.ui'], function () {
$(function () {
catALot.init();
});
});
}
// </source>