"மீடியாவிக்கி:Gadget-twinklespeedy.js" பக்கத்தின் திருத்தங்களுக்கிடையேயான வேறுபாடு

4,596 பைட்டுகள் சேர்க்கப்பட்டது ,  2 மாதங்களுக்கு முன்
update from enwiki
("//<nowiki> (function($){ /* *********************************..."-இப்பெயரில் புதிய பக்கம் உருவாக்கப்பட்டுள்ளது)
 
(update from enwiki)
 
// <nowiki>
 
 
(function($) {
 
 
* Mode of invocation: Tab ("CSD")
* Active on: Non-special, existing pages
* Config directives in: TwinkleConfig
*
* NOTE FOR DEVELOPERS:
}
 
Twinkle.addPortletLink( Twinkle.speedy.callback, "'CSD"', "'tw-csd"', Morebits.userIsInGroup('sysop')userIsSysop ? "'Delete page according to WP:CSD"' : "'Request speedy deletion according to WP:CSD" ');
};
 
// This function is run when the CSD tab/header link is clicked
Twinkle.speedy.callback = function twinklespeedyCallback() {
Twinkle.speedy.initDialog(Morebits.userIsInGroup( 'sysop' )userIsSysop ? Twinkle.speedy.callback.evaluateSysop : Twinkle.speedy.callback.evaluateUser, true);
};
 
// Used by unlink feature
Twinkle.speedy.dialog = null;
// Used throughout
 
Twinkle.speedy.hasCSD = !!$('#delete-reason').length;
// The speedy criteria list can be in one of several modes
Twinkle.speedy.mode = {
sysopSubmit: 1, // radio buttons, no subgroups, submit when "Submit" button is clicked
sysopRadioClick: 2, // radio buttons, no subgroups, submit when a radio button is clicked
userMultipleSubmit: 3, // check boxes, subgroups, "Submit" button already pressent
userMultipleRadioClick: 4, // check boxes, subgroups, need to add a "Submit" button
userSingleSubmit: 5, // radio buttons, subgroups, submit when "Submit" button is clicked
userSingleRadioClick: 6, // radio buttons, subgroups, submit when a radio button is clicked
 
// are we in "delete page" mode?
// (sysops can access both "delete page" [sysop] and "tag page only" [user] modes)
isSysop: function twinklespeedyModeIsSysop(mode) {
return mode === Twinkle.speedy.mode.sysopSubmit ||
mode === Twinkle.speedy.mode.sysopRadioClick;
},
// do we have a "Submit" button once the form is created?
hasSubmitButton: function twinklespeedyModeHasSubmitButton(mode) {
return mode === Twinkle.speedy.mode.sysopSubmit ||
mode === Twinkle.speedy.mode.userMultipleSubmit ||
mode === Twinkle.speedy.mode.userMultipleRadioClick ||
mode === Twinkle.speedy.mode.userSingleSubmit;
},
// is db-multiple the outcome here?
isMultiple: function twinklespeedyModeIsMultiple(mode) {
return mode === Twinkle.speedy.mode.userMultipleSubmit ||
mode === Twinkle.speedy.mode.userMultipleRadioClick;
},
// do we want subgroups? (if not we have to use prompt())
wantSubgroups: function twinklespeedyModeWantSubgroups(mode) {
return !Twinkle.speedy.mode.isSysop(mode);
}
};
 
// Prepares the speedy deletion dialog and displays it
Twinkle.speedy.initDialog = function twinklespeedyInitDialog(callbackfunc) {
var dialog;
Twinkle.speedy.dialog = new Morebits.simpleWindow( Twinkle.getPref('speedyWindowWidth'), Twinkle.getPref('speedyWindowHeight') );
dialog = Twinkle.speedy.dialog;
dialog.setTitle( "'Choose criteria for speedy deletion" ');
dialog.setScriptName( "'Twinkle" ');
dialog.addFooterLink( "'Speedy deletion policy"', "'WP:CSD" ');
dialog.addFooterLink('CSD "Twinkle help"prefs', "'WP:TW/DOCPREF#speedy" ');
dialog.addFooterLink('Twinkle help', 'WP:TW/DOC#speedy');
dialog.addFooterLink('Give feedback', 'WT:TW');
 
var form = new Morebits.quickForm( callbackfunc, (Twinkle.getPref('speedySelectionStyle') === 'radioClick' ? 'change' : null) );
if ( Morebits.userIsInGroup( 'sysop' ) userIsSysop) {
form.append( {
type: 'checkbox',
list: [
{
label: 'Tag page only, don\'t delete',
value: 'tag_only',
name: 'tag_only',
tooltip: 'If you just want to tag the page, instead of deleting it now',
checked : !(Twinkle.speedy.hasCSD || Twinkle.getPref('deleteSysopDefaultToTagdeleteSysopDefaultToDelete')),
event: function( event ) {
var cForm = event.target.form;
var cChecked = event.target.checked;
// enable/disable talk page checkbox
if (cForm.talkpage) {
cForm.talkpage.disabledchecked = !cChecked && Twinkle.getPref('deleteTalkPageOnDelete');
}
cForm.talkpage.checked = !cChecked && Twinkle.getPref('deleteTalkPageOnDelete');
// enable redirects checkbox
}
cForm.redirects.checked = !cChecked;
// enable/disable redirects checkbox
// enable delete multiple
cForm.redirects.disabled = cChecked;
cForm.redirectsdelmultiple.checked = !cCheckedfalse;
// enable notify checkbox
cForm.notify.checked = cChecked;
// enable deletion notification checkbox
cForm.warnusertalk.checked = !cChecked && !Twinkle.speedy.hasCSD;
// enable multiple
cForm.multiple.checked = false;
// enable requesting creation protection
cForm.salting.checked = false;
 
Twinkle.speedy.callback.modeChanged(cForm);
// enable/disable notify checkbox
cForm.notify.disabled = !cChecked;
cForm.notify.checked = cChecked;
// enable/disable multiple
cForm.multiple.disabled = !cChecked;
cForm.multiple.checked = false;
 
event.stopPropagation();
Twinkle.speedy.callback.modeChanged(cForm);
 
event.stopPropagation();
}
}
]}
} );]
});
form.append( { type: 'header', label: 'Delete-related options' } );
 
var deleteOptions = form.append({
type: 'div',
name: 'delete_options'
});
deleteOptions.append({
type: 'header',
label: 'Delete-related options'
});
if (mw.config.get('wgNamespaceNumber') % 2 === 0 && (mw.config.get('wgNamespaceNumber') !== 2 || (/\//).test(mw.config.get('wgTitle')))) { // hide option for user pages, to avoid accidentally deleting user talk page
formdeleteOptions.append( {
type: 'checkbox',
list: [
tooltip: "This option deletes the page's talk page in addition. If you choose the F8 (moved to Commons) criterion, this option is ignored and the talk page is *not* deleted.",
checked: Twinkle.getPref('deleteTalkPageOnDelete'),
event: function(event) {
disabled: Twinkle.getPref('deleteSysopDefaultToTag'),
event: function( event ) {
event.stopPropagation();
}
}
]
} );
}
formdeleteOptions.append( {
type: 'checkbox',
list: [
{
label: 'Also delete all redirects',
value: 'redirects',
name: 'redirects',
tooltip: "This option deletes all incoming redirects in addition. Avoid this option for procedural (e.g. move/merge) deletions.",
checked: Twinkle.getPref('deleteRedirectsOnDelete'),
disabled: Twinkle.getPref('deleteSysopDefaultToTag'),
event: function( event ) {
event.stopPropagation();
}
}
]
} );
form.append( { type: 'header', label: 'Tag-related options' } );
}
 
form.append( {
type: 'checkbox',
list: [
{
label: 'NotifyAlso pagedelete creatorall if possibleredirects',
value: 'notifyredirects',
name: 'notifyredirects',
tooltip: 'This option deletes all incoming redirects in addition. Avoid this option for procedural (e.g. move/merge) deletions.',
tooltip: "A notification template will be placed on the talk page of the creator, IF you have a notification enabled in your Twinkle preferences " +
checked: Twinkle.getPref('deleteRedirectsOnDelete'),
"for the criterion you choose AND this box is checked. The creator may be welcomed as well.",
event: function (event) {
checked: !Morebits.userIsInGroup( 'sysop' ) || Twinkle.getPref('deleteSysopDefaultToTag'),
disabled: Morebits.userIsInGroup( 'sysop' ) && !Twinkle.getPref('deleteSysopDefaultToTag'),
event: function( event ) {
event.stopPropagation();
}
},
]
} );
form.append( {
type: 'checkbox',
list: [
{
label: 'TagDelete withunder multiple criteria',
value: 'multipledelmultiple',
name: 'multipledelmultiple',
tooltip: "'When selected, you can select several criteria that apply to the page. For example, G11 and A7 are a common combination for articles."',
event: function(event) {
disabled: Morebits.userIsInGroup( 'sysop' ) && !Twinkle.getPref('deleteSysopDefaultToTag'),
Twinkle.speedy.callback.modeChanged(event.target.form);
event: function( event ) {
event.stopPropagation();
Twinkle.speedy.callback.modeChanged( event.target.form );
}
},
{
label: 'Notify page creator of page deletion',
value: 'warnusertalk',
name: 'warnusertalk',
tooltip: 'A notification template will be placed on the talk page of the creator, IF you have a notification enabled in your Twinkle preferences ' +
'for the criterion you choose AND this box is checked. The creator may be welcomed as well.',
checked: !Twinkle.speedy.hasCSD,
event: function(event) {
event.stopPropagation();
}
}
]
} );
}
 
var tagOptions = form.append( {
type: 'div',
name: 'work_areatag_options',
});
label: 'Failed to initialize the CSD module. Please try again, or tell the Twinkle developers about the issue.'
} );
 
if (Morebits.userIsSysop) {
if( Twinkle.getPref( 'speedySelectionStyle' ) !== 'radioClick' ) {
formtagOptions.append( { type: 'submit' } );
type: 'header',
label: 'Tag-related options'
});
}
 
tagOptions.append({
type: 'checkbox',
list: [
{
label: 'Notify page creator if possible',
value: 'notify',
name: 'notify',
tooltip: 'A notification template will be placed on the talk page of the creator, IF you have a notification enabled in your Twinkle preferences ' +
'for the criterion you choose AND this box is checked. The creator may be welcomed as well.',
checked: !Morebits.userIsSysop || !(Twinkle.speedy.hasCSD || Twinkle.getPref('deleteSysopDefaultToDelete')),
event: function(event) {
event.stopPropagation();
}
},
{
label: 'Tag for creation protection (salting) as well',
value: 'salting',
name: 'salting',
tooltip: 'When selected, the speedy deletion tag will be accompanied by a {{salt}} tag requesting that the deleting administrator apply creation protection. Only select if this page has been repeatedly recreated.',
event: function(event) {
event.stopPropagation();
}
},
{
label: 'Tag with multiple criteria',
value: 'multiple',
name: 'multiple',
tooltip: 'When selected, you can select several criteria that apply to the page. For example, G11 and A7 are a common combination for articles.',
event: function(event) {
Twinkle.speedy.callback.modeChanged(event.target.form);
event.stopPropagation();
}
}
]
});
 
form.append({
type: 'div',
id: 'prior-deletion-count',
style: 'font-style: italic'
});
 
form.append({
type: 'div',
name: 'work_area',
label: 'Failed to initialize the CSD module. Please try again, or tell the Twinkle developers about the issue.'
});
 
if (Twinkle.getPref('speedySelectionStyle') !== 'radioClick') {
form.append({ type: 'submit', className: 'tw-speedy-submit' }); // Renamed in modeChanged
}
 
var result = form.render();
dialog.setContent( result );
dialog.display();
 
Twinkle.speedy.callback.modeChanged( result );
 
// Check for prior deletions. Just once, upon init
Twinkle.speedy.callback.priorDeletionCount();
};
 
 
// first figure out what mode we're in
var mode = Twinkle.speedy.mode.userSingleSubmit;{
if isSysop: (!!form.tag_only && !form.tag_only.checked) {,
isMultiple: form.tag_only && !form.tag_only.checked ? form.delmultiple.checked : form.multiple.checked,
mode = Twinkle.speedy.mode.sysopSubmit;
isRadioClick: Twinkle.getPref('speedySelectionStyle') === 'radioClick'
};
 
if (mode.isSysop) {
$('[name=delete_options]').show();
$('[name=tag_options]').hide();
$('button.tw-speedy-submit').text('Delete page');
} else {
$('[name=delete_options]').hide();
if (form.multiple.checked) {
$('[name=tag_options]').show();
mode = Twinkle.speedy.mode.userMultipleSubmit;
$('button.tw-speedy-submit').text('Tag page');
} else {
mode = Twinkle.speedy.mode.userSingleSubmit;
}
}
if (Twinkle.getPref('speedySelectionStyle') === 'radioClick') {
mode++;
}
 
var work_area = new Morebits.quickForm.element( {
type: 'div',
name: 'work_area'
} );
 
if (mode.isMultiple ===&& Twinkle.speedy.mode.userMultipleRadioClickisRadioClick) {
var evaluateType = mode.isSysop ? 'evaluateSysop' : 'evaluateUser';
work_area.append( {
 
type: 'div',
work_area.append({
label: 'When finished choosing criteria, click:'
}type: );'div',
label: 'When finished choosing criteria, click:'
work_area.append( {
});
type: 'button',
work_area.append({
name: 'submit-multiple',
labeltype: 'Submit Querybutton',
name: 'submit-multiple',
event: function( event ) {
label: mode.isSysop ? 'Delete page' : 'Tag page',
Twinkle.speedy.callback.evaluateUser( event );
event.stopPropagation: function(event); {
Twinkle.speedy.callback[evaluateType](event);
}
event.stopPropagation();
} );
}
});
}
 
var radioOrCheckbox = (Twinkle.speedy.mode.isMultiple(mode) ? 'checkbox' : 'radio');
 
if (mode.isSysop && !mode.isMultiple) {
work_area.append({ type: 'header', label: 'Custom rationale' });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.customRationale, mode) });
}
 
if (namespace % 2 === 1 && namespace !== 3) {
// show db-talk on talk pages, but not user talk pages
work_area.append( { type: 'header', label: 'Talk pages' } );
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.talkList, mode) } );
}
 
if (!Morebits.isPageRedirect()) {
switch (namespace) {
switch (namespace) {
case 0: // article
case 10: // talkarticle
case 1: // talk
work_area.append( { type: 'header', label: 'Articles' } );
work_area.append( { type: radioOrCheckbox'header', namelabel: 'csdArticles', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.articleList, mode) } );
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.articleList, mode) });
break;
break;
 
case 2: // user
case 3: // user talk
work_area.append( { type: 'header', label: 'User pages' } );
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.userList, mode) } );
break;
 
case 6: // file
case 7: // file talk
work_area.append( { type: 'header', label: 'Files' } );
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.fileList, mode) } );
if (!Twinkle.speedy.mode.isSysop(mode)) {
work_area.append( { type: 'div', label: 'Tagging for CSD F4 (no license), F5 (orphaned fair use), F6 (no fair use rationale), and F11 (no permission) can be done using Twinkle\'s "DI" tab.' } );
}
break;
 
case 1014: // templatecategory
case 1115: // templatecategory talk
work_area.append( { type: 'header', label: 'TemplatesCategories' } );
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.templateListcategoryList, mode) } );
break;
 
case 14100: // categoryportal
case 15101: // categoryportal talk
work_area.append( { type: 'header', label: 'CategoriesPortals' } );
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.categoryListportalList, mode) } );
break;
 
default:
case 100: // portal
break;
case 101: // portal talk
}
work_area.append( { type: 'header', label: 'Portals' } );
} else {
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.portalList, mode) } );
if (namespace === 2 || namespace === 3) {
break;
work_area.append({ type: 'header', label: 'User pages' });
 
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.userList, mode) });
default:
break;}
work_area.append({ type: 'header', label: 'Redirects' });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.redirectList, mode) });
}
 
var generalCriteria = Twinkle.speedy.generalList;
work_area.append( { type: 'header', label: 'General criteria' } );
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.generalList, mode) });
 
// custom rationale lives under general criteria when tagging
work_area.append( { type: 'header', label: 'Redirects' } );
if (!mode.isSysop) {
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.redirectList, mode) } );
generalCriteria = Twinkle.speedy.customRationale.concat(generalCriteria);
}
work_area.append({ type: 'header', label: 'General criteria' });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(generalCriteria, mode) });
 
var old_area = Morebits.quickForm.getElements(form, "'work_area"')[0];
form.replaceChild(work_area.render(), old_area);
 
// if sysop, check if CSD is already on the page and fill in custom rationale
if (mode.isSysop && Twinkle.speedy.hasCSD) {
var customOption = $('input[name=csd][value=reason]')[0];
if (customOption) {
if (Twinkle.getPref('speedySelectionStyle') !== 'radioClick') {
// force listeners to re-init
customOption.click();
customOption.parentNode.appendChild(customOption.subgroup);
}
customOption.subgroup.querySelector('input').value = decodeURIComponent($('#delete-reason').text()).replace(/\+/g, ' ');
}
}
};
 
Twinkle.speedy.callback.priorDeletionCount = function () {
var query = {
action: 'query',
format: 'json',
list: 'logevents',
letype: 'delete',
leaction: 'delete/delete', // Just pure page deletion, no redirect overwrites or revdel
letitle: mw.config.get('wgPageName'),
leprop: '', // We're just counting we don't actually care about the entries
lelimit: 5 // A little bit goes a long way
};
 
new Morebits.wiki.api('Checking for past deletions', query, function(apiobj) {
var response = apiobj.getResponse();
var delCount = response.query.logevents.length;
if (delCount) {
var message = delCount + ' previous deletion';
if (delCount > 1) {
message += 's';
if (response.continue) {
message = 'More than ' + message;
}
 
// 3+ seems problematic
if (delCount >= 3) {
$('#prior-deletion-count').css('color', 'red');
}
}
 
// Provide a link to page logs (CSD templates have one for sysops)
var link = Morebits.htmlNode('a', '(logs)');
link.setAttribute('href', mw.util.getUrl('Special:Log', {page: mw.config.get('wgPageName')}));
link.setAttribute('target', '_blank');
 
$('#prior-deletion-count').text(message + ' '); // Space before log link
$('#prior-deletion-count').append(link);
}
}).post();
};
 
 
Twinkle.speedy.generateCsdList = function twinklespeedyGenerateCsdList(list, mode) {
 
// mode switches
var pageNamespace = mw.config.get('wgNamespaceNumber');
var isSysop = Twinkle.speedy.mode.isSysop(mode);
var multiple = Twinkle.speedy.mode.isMultiple(mode);
var wantSubgroups = Twinkle.speedy.mode.wantSubgroups(mode);
var hasSubmitButton = Twinkle.speedy.mode.hasSubmitButton(mode);
 
var openSubgroupHandler = function(e) {
};
var submitSubgroupHandler = function(e) {
Twinkle.speedy.callbackvar evaluateType = mode.isSysop ? 'evaluateSysop' : 'evaluateUser(e)';
Twinkle.speedy.callback[evaluateType](e);
e.stopPropagation();
};
var criterion = $.extend({}, critElement);
 
if (!wantSubgroupsmode.isMultiple) {
criterion.subgroup = null;
}
 
if (multiple) {
if (criterion.hideWhenMultiple) {
return null;
}
 
if (mode.isSysop) {
if (criterion.hideWhenSysop) {
return null;
}
 
if (criterionMorebits.subgroupisPageRedirect() && !hasSubmitButtoncriterion.hideWhenRedirect) {
return null;
if ($.isArray(criterion.subgroup)) {
}
criterion.subgroup.push({
 
if (criterion.showInNamespaces && criterion.showInNamespaces.indexOf(pageNamespace) < 0) {
return null;
}
if (criterion.hideInNamespaces && criterion.hideInNamespaces.indexOf(pageNamespace) > -1) {
return null;
}
 
if (criterion.subgroup && !mode.isMultiple && mode.isRadioClick) {
if (Array.isArray(criterion.subgroup)) {
criterion.subgroup = criterion.subgroup.concat({
type: 'button',
name: 'submit',
label: mode.isSysop ? 'Delete page' : 'SubmitTag Querypage',
event: submitSubgroupHandler
});
type: 'button',
name: 'submit', // ends up being called "csd.submit" so this is OK
label: mode.isSysop ? 'Delete page' : 'SubmitTag Querypage',
event: submitSubgroupHandler
}
];
}
// FIXME: does this do anything?
criterion.event = openSubgroupHandler;
}
});
};
 
Twinkle.speedy.customRationale = [
{
label: 'Custom rationale' + (Morebits.userIsSysop ? ' (custom deletion reason)' : ' using {{db}} template'),
value: 'reason',
tooltip: '{{db}} is short for "delete because". At least one of the other deletion criteria must still apply to the page, and you must make mention of this in your rationale. This is not a "catch-all" for when you can\'t find any criteria that fit.',
subgroup: {
name: 'reason_1',
type: 'input',
label: 'Rationale: ',
size: 60
},
hideWhenMultiple: true
}
];
 
Twinkle.speedy.talkList = [
},
{
label: 'F2: Corrupt, missing, or blankempty file',
value: 'noimage',
tooltip: 'Before deleting this type of file, verify that the MediaWiki engine cannot read it by previewing a resized thumbnail of it. This also includes empty (i.e., no content) file description pages for Commons files'
},
{
label: 'F5: Unused unfreenon-free copyrighted file',
value: 'unfreef5',
tooltip: 'Files that are not under a free license or in the public domain that are not used in any article, andwhose thatonly haveuse beenis tagged within a templatedeleted thatarticle, placesand themthat inare avery datedunlikely subcategoryto ofbe Category:Orphanedused fairuseon filesany forother more than seven daysarticle. Reasonable exceptions may be made for filefiles uploaded for an upcoming article. UseFor other unused non-free files, use the "Orphaned fair use" option in Twinkle\'s DI module to tag files for forthcoming deletiontab.',
hideWhenUser: true
},
tooltip: 'This is only for files with a clearly invalid fair-use tag, such as a {{Non-free logo}} tag on a photograph of a mascot. For cases that require a waiting period (replaceable images or otherwise disputed rationales), use the options on Twinkle\'s DI tab.',
subgroup: {
name: 'badfairuse_reasonbadfairuse_rationale',
type: 'input',
label: 'Optional explanation: ',
tooltip: 'Non-free images or media from a commercial source (e.g., Associated Press, Getty), where the file itself is not the subject of sourced commentary, are considered an invalid claim of fair use and fail the strict requirements of WP:NFCC.',
subgroup: {
name: 'badfairuse_reasonbadfairuse_rationale',
type: 'input',
label: 'Optional explanation: ',
{
label: 'F8: File available as an identical or higher-resolution copy on Wikimedia Commons',
value: 'nowcommonscommons',
tooltip: 'Provided the following conditions are met: 1: The file format of both images is the same. 2: The file\'s license and source status is beyond reasonable doubt, and the license is undoubtedly accepted at Commons. 3: All information on the file description page is present on the Commons file description page. That includes the complete upload history with links to the uploader\'s local user pages. 4: The file is not protected, and the file description page does not contain a request not to move it to Commons. 5: If the file is available on Commons under a different name than locally, all local references to the file must be updated to point to the title used at Commons. 6: For {{c-uploaded}} files: They may be speedily deleted as soon as they are off the Main Page',
subgroup: {
name: 'nowcommons_filenamecommons_filename',
type: 'input',
label: 'Filename on Commons: ',
value: 'imgcopyvio',
tooltip: 'The file was copied from a website or other source that does not have a license compatible with Wikipedia, and the uploader neither claims fair use nor makes a credible assertion of permission of free use. Sources that do not have a license compatible with Wikipedia include stock photo libraries such as Getty Images or Corbis. Non-blatant copyright infringements should be discussed at Wikipedia:Files for deletion',
subgroup: {[
{
name: 'imgcopyvio_url',
type name: 'inputimgcopyvio_url',
type: 'input',
label: 'URL of the copyvio, including the "http://". If you cannot provide a URL, please do not use CSD F9. (Exception: for copyvios of non-Internet sources, leave the box blank.) ',
label: 'URL of the copyvio, including the "http://". If the copyvio is of a non-internet source and you cannot provide a URL, you must use the deletion rationale box. ',
size: 60
size: 60
}
},
{
name: 'imgcopyvio_rationale',
type: 'input',
label: 'Deletion rationale for non-internet copyvios: ',
size: 60
}
]
},
{
label: 'G8: File description page with no corresponding file',
value: 'imagepage',
tooltip: 'This is only for use when the file doesn\'t exist at all. Corrupt files, and local description pages for files on Commons, should use F2; implausible redirects should use R3; and broken Commons redirects should use G6R4.'
}
];
label: 'A5: Transwikied articles',
value: 'transwiki',
tooltip: 'Any article that has been discussed at Articles for Deletion (et al), where the outcome was to transwiki, and where the transwikification has been properly performed and the author information recorded. Alternately, any article that consists of only a dictionary definition, where the transwikification has been properly performed and the author information recorded',
subgroup: {
name: 'transwiki_location',
type: 'input',
label: 'Link to where the page has been transwikied: ',
tooltip: 'For example, https://en.wiktionary.org/wiki/twinkle or [[wikt:twinkle]]'
}
},
{
label: 'A7: UnremarkableNo indication of importance (people, groups, companies, web content, individual animals, or organized events)',
value: 'a7',
tooltip: 'An article about a real person, group of people, band, club, company, web content, individual animal, tour, or party that does not assert the importance or significance of its subject. If controversial, or if a previous AfD has resulted in the article being kept, the article should be nominated for AfD instead',
},
{
label: 'A7: UnremarkableNo indication of importance (person)',
value: 'person',
tooltip: 'An article about a real person that does not assert the importance or significance of its subject. If controversial, or if there has been a previous AfD that resulted in the article being kept, the article should be nominated for AfD instead',
},
{
label: 'A7: UnremarkableNo indication of importance (musician(s) or band)',
value: 'band',
tooltip: 'Article about a band, singer, musician, or musical ensemble that does not assert the importance or significance of the subject',
},
{
label: 'A7: UnremarkableNo indication of importance (club, society or group)',
value: 'club',
tooltip: 'Article about a club, society or group that does not assert the importance or significance of the subject',
hideWhenMultiple: true
},
{
label: 'A7: UnremarkableNo indication of importance (company or organization)',
value: 'corp',
tooltip: 'Article about a company or organization that does not assert the importance or significance of the subject',
},
{
label: 'A7: UnremarkableNo indication of importance (website or web content)',
value: 'web',
tooltip: 'Article about a web site, blog, online forum, webcomic, podcast, or similar web content that does not assert the importance or significance of its subject',
},
{
label: 'A7: UnremarkableNo indication of importance (individual animal)',
value: 'animal',
tooltip: 'Article about an individual animal (e.g. pet) that does not assert the importance or significance of its subject',
},
{
label: 'A7: UnremarkableNo indication of importance (organized event)',
value: 'event',
tooltip: 'Article about an organized event (tour, function, meeting, party, etc.) that does not assert the importance or significance of its subject',
label: 'C1: Empty categories',
value: 'catempty',
tooltip: 'Categories that have been unpopulated for at least fourseven days. This does not apply to categories being discussed at WP:CFD, disambiguation categories, and certain other exceptions. If the category isn\'t relatively new, it possibly contained articles earlier, and deeper investigation is needed'
},
{
label: 'G8: Categories populated by a deleted or retargeted template',
value: 'templatecat',
tooltip: 'This is for situations where a category is effectively empty, because the template(s) that formerly placed pages in that category are now deleted. This excludes categories that are still in use.',
subgroup: {
name: 'templatecat_rationale',
type: 'input',
label: 'Optional explanation: ',
size: 60
}
},
{
label: 'G8: Redirects to non-existent targets',
value: 'redirnone',
tooltip: 'This excludes any page that is useful to the project, and in particular: deletion discussions that are not logged elsewhere, user and user talk pages, talk page archives, plausible redirects that can be changed to valid targets, and file pages or talk pages for files that exist on Wikimedia Commons.',
hideWhenMultiple: true
}
];
value: 'userreq',
tooltip: 'Personal subpages, upon request by their user. In some rare cases there may be administrative need to retain the page. Also, sometimes, main user pages may be deleted as well. See Wikipedia:User page for full instructions and guidelines',
subgroup: ((mw.config.get('wgNamespaceNumber') === 3 && mw.config.get('wgTitle').indexOf('/') === -1) ? {
name: 'userreq_rationale',
type: 'input',
tooltip: 'User talk pages are deleted only in highly exceptional circumstances. See WP:DELTALK.',
size: 60
} : null),
hideSubgroupWhenMultiple: true
},
label: 'U3: Non-free galleries',
value: 'gallery',
tooltip: 'Galleries in the userspace which consist mostly of "fair use" or non-free files. Wikipedia\'s non-free content policy forbids users from displaying non-free files, even ones they have uploaded themselves, in userspace. It is acceptable to have free files, GFDL-files, Creative Commons and similar licenses along with public domain material, but not "fair use" files',
hideWhenRedirect: true
},
{
label: 'U5: Blatant WP:NOTWEBHOST violations',
value: 'notwebhost',
tooltip: 'Pages in userspace consisting of writings, information, discussions, and/or activities not closely related to Wikipedia\'s goals, where the owner has made few or no edits outside of userspace, with the exception of plausible drafts, and pages adhering to WP:UPYES, and résumé-style pages.',
hideWhenRedirect: true
},
{
value: 'spamuser',
tooltip: 'A promotional user page, with a username that promotes or implies affiliation with the thing being promoted. Note that simply having a page on a company or product in one\'s userspace does not qualify it for deletion. If a user page is spammy but the username is not, then consider tagging with regular G11 instead.',
hideWhenMultiple: true,
hideWhenRedirect: true
}
];
 
Twinkle.speedy.templateList = [
{
label: 'T2: Templates that are blatant misrepresentations of established policy',
value: 'policy',
tooltip: 'This includes "speedy deletion" templates for issues that are not speedy deletion criteria and disclaimer templates intended to be used in articles'
},
{
label: 'T3G13: DuplicateAfC templatesdraft submission or hardcodeda blank draft, stale by over 6 instancesmonths',
value: 'duplicatetemplateafc',
tooltip: 'Any rejected or unsubmitted AfC draft submission or a blank draft, that has not been edited in over 6 months (excluding bot edits).',
tooltip: 'Templates that are either substantial duplications of another template or hardcoded instances of another template where the same functionality could be provided by that other template',
hideWhenMultiple: true,
subgroup: {
hideWhenRedirect: true
name: 'duplicatetemplate_2',
type: 'input',
label: 'Template this is redundant to: ',
tooltip: 'The "Template:" prefix is not needed.'
},
hideWhenMultiple: true
}
];
label: 'P1: Portal that would be subject to speedy deletion if it were an article',
value: 'p1',
tooltip: 'You must specify thea single article criterion that applies in this case (A1, A3, A7, or A10).',
subgroup: {
name: 'p1_1p1_criterion',
type: 'selectinput',
label: 'Article criterion that would apply: '
},
hideWhenMultiple: true
},
{
label: 'P2: Underpopulated portal (fewer than three non-stub articles)',
value: 'emptyportal',
tooltip: 'Any Portal based on a topic for which there is not a non-stub header article, and at least three non-stub articles detailing subject matter that would be appropriate to discuss under the title of that Portal'
 
Twinkle.speedy.generalList = [
{
label: 'Custom rationale' + (Morebits.userIsInGroup('sysop') ? ' (custom deletion reason)' : ' using {{db}} template'),
value: 'reason',
tooltip: '{{db}} is short for "delete because". At least one of the other deletion criteria must still apply to the page, and you must make mention of this in your rationale. This is not a "catch-all" for when you can\'t find any criteria that fit.',
subgroup: {
name: 'reason_1',
type: 'input',
label: 'Rationale: ',
size: 60
},
hideWhenMultiple: true,
hideSubgroupWhenSysop: true
},
{
label: 'G1: Patent nonsense. Pages consisting purely of incoherent text or gibberish with no meaningful content or history.',
value: 'nonsense',
tooltip: 'This does not include poor writing, partisan screeds, obscene remarks, vandalism, fictional material, material not in English, poorly translated material, implausible theories, or hoaxes. In short, if you can understand it, G1 does not apply.',
hideInNamespaces: [ 2 ] // Not applicable in userspace
},
{
label: 'G2: Test page',
value: 'test',
tooltip: 'A page created to test editing or other Wikipedia functions. Pages in the User namespace are not included, nor are valid but unused or duplicate templates (although criterion T3 may apply).',
hideInNamespaces: [ 2 ] // Not applicable in userspace
},
{
tooltip: 'A copy, by any title, of a page that was deleted via an XfD process or Deletion review, provided that the copy is substantially identical to the deleted version. This clause does not apply to content that has been "userfied", to content undeleted as a result of Deletion review, or if the prior deletions were proposed or speedy deletions, although in this last case, other speedy deletion criteria may still apply',
subgroup: {
name: 'repost_1repost_xfd',
type: 'input',
label: 'Page where the deletion discussion took place: ',
},
{
label: 'G5: BannedCreated by a banned or blocked user',
value: 'banned',
tooltip: 'Pages created by banned or blocked users in violation of their ban or block, and which have no substantial edits by others',
subgroup: {
name: 'banned_1banned_user',
type: 'input',
label: 'Username of banned user (if available): ',
tooltip: 'Should not start with "User:"'
},
hideSubgroupWhenMultiple: true
},
{
label: 'G6: History merge',
value: 'histmerge',
tooltip: 'Temporarily deleting a page in order to merge page histories',
subgroup: {
name: 'histmerge_1',
type: 'input',
label: 'Page to be merged into this one: '
},
hideWhenMultiple: true
},
{
subgroup: [
{
name: 'move_1move_page',
type: 'input',
label: 'Page to be moved here: '
},
{
name: 'move_2move_reason',
type: 'input',
label: 'Reason: ',
label: 'G6: XfD',
value: 'xfd',
tooltip: 'An admin has closed aA deletion discussion (at AfD, FfD, RfD, TfD, CfD, or MfD) was closed as "delete", but theythe page didnwasn\'t actually delete the pagedeleted.',
subgroup: {
name: 'xfd_fullvotepage',
type: 'input',
label: 'Page where the deletion discussion was held: ',
tooltip: 'Must start with "Wikipedia:"',
size: 40
},
hideWhenMultiple: true
},
{
label: 'G6: Unnecessary disambiguation page',
value: 'disambig',
tooltip: 'This only applies for orphaned disambiguation pages which either: (1) disambiguate two or fewer existing Wikipedia pages and whose title ends in "(disambiguation)" (i.e., there is a primary topic); or (2) disambiguates no (zero) existing Wikipedia pages, regardless of its title.',
hideWhenMultiple: true
},
{
label: 'G6: Redirect to malplaced disambiguation page',
value: 'movedab',
tooltip: 'This only applies for redirects to disambiguation pages ending in (disambiguation) where a primary topic does not exist.',
hideWhenMultiple: true
},
tooltip: 'This only applies for a copy-and-paste page move of another page that needs to be temporarily deleted to make room for a clean page move.',
subgroup: {
name: 'copypaste_1copypaste_sourcepage',
type: 'input',
label: 'Original page that was copy-pasted here: '
},
{
label: 'G6: Housekeeping and non-controversial cleanup',
value: 'g6',
tooltip: 'Other non-controversialroutine "housekeeping"maintenance tasks',
subgroup: {
name: 'g6_rationale',
tooltip: 'Perhaps linking to where the author requested this deletion.',
size: 60
},
hideSubgroupWhenSysop: true
},
{
label: 'G8: Pages dependent on a non-existent or deleted page',
value: 'g8',
tooltip: 'such as talk pages with no corresponding subject page; subpages with no parent page; file pages without a corresponding file; redirects to invalidnon-existent targets, such as nonexistent targets, redirect loops, and bad titles; or categories populated by deleted or retargeted templates. This excludes any page that is useful to the project, and in particular: deletion discussions that are not logged elsewhere, user and user talk pages, talk page archives, plausible redirects that can be changed to valid targets, and file pages or talk pages for files that exist on Wikimedia Commons.',
subgroup: {
name: 'g8_rationale',
label: 'Optional explanation: ',
size: 60
},
hideSubgroupWhenSysop: true
},
{
value: 'subpage',
tooltip: 'This excludes any page that is useful to the project, and in particular: deletion discussions that are not logged elsewhere, user and user talk pages, talk page archives, plausible redirects that can be changed to valid targets, and file pages or talk pages for files that exist on Wikimedia Commons.',
hideWhenMultiple: true,
hideInNamespaces: [ 0, 6, 8 ] // hide in main, file, and mediawiki-spaces
},
{
label: 'G10: Attack page',
value: 'attack',
tooltip: 'Pages that serve no purpose but to disparage or threaten their subject or some other entity (e.g., "John Q. Doe is an imbecile"). This includes a biography of a living person that is negative in tone and unsourced, where there is no NPOV version in the history to revert to. Administrators deleting such pages should not quote the content of the page in the deletion summary!'
},
{
},
{
label: 'G11: Unambiguous advertising or promotion',
value: 'spam',
tooltip: 'Pages which exclusively promote a company, product, group, service, or person and which would need to be fundamentally rewritten in order to become encyclopedic. Note that an article about a company or a product which describes its subject from a neutral point of view does not qualify for this criterion; an article that is blatant advertising should have inappropriate content as well'
type: 'input',
label: 'URL (if available): ',
tooltip: 'If the material was copied from an online source, put the URL here, including the "http://" or "https://" protocol. If the URL is on the spam blacklist, you can leave off the protocol.',
size: 60
},
type: 'input',
label: 'Additional URL: ',
tooltip: 'Optional. Should begin with "http://" or "https://"',
size: 60
},
type: 'input',
label: 'Additional URL: ',
tooltip: 'Optional. Should begin with "http://" or "https://"',
size: 60
}
},
{
label: 'G13: OldPage in draft namespace or userspace AfC submission, abandonedstale Articlesby forover Creation6 submissionsmonths',
value: 'afc',
tooltip: 'Any rejected or unsubmitted AfC submission in userspace or any non-redirect page in draft namespace, that has not been edited for more than 6 months. Blank drafts in either namespace are also included.',
hideWhenRedirect: true,
showInNamespaces: [2, 118] // user, draft namespaces only
},
{
label: 'G14: Unnecessary disambiguation page',
value: 'disambig',
tooltip: 'This only applies for orphaned disambiguation pages which either: (1) disambiguate only one existing Wikipedia page and whose title ends in "(disambiguation)" (i.e., there is a primary topic); or (2) disambiguate no (zero) existing Wikipedia pages, regardless of its title. It also applies to orphan "Foo (disambiguation)" redirects that target pages that are not disambiguation or similar disambiguation-like pages (such as set index articles or lists)'
}
];
Twinkle.speedy.redirectList = [
{
label: 'R2: RedirectsRedirect from mainspace to any other namespace except the Category:, Template:, Wikipedia:, Help: and Portal: namespaces',
value: 'rediruser',
tooltip: '(thisThis does not include the Wikipedia shortcut pseudo-namespaces)namespace shortcuts. If this was the result of a page move, consider waiting a day or two before deleting the redirect',
showInNamespaces: [ 0 ]
},
{
label: 'R3: RedirectsRecently ascreated aredirect result offrom an implausible typo thator were recently createdmisnomer',
value: 'redirtypo',
tooltip: 'However, redirects from common misspellings or misnomers are generally useful, as are redirects in other languages'
},
{
label: 'R4: File namespace redirect with a name that matches a Commons page',
label: 'G8: Redirects to invalid targets, such as nonexistent targets, redirect loops, and bad titles',
value: 'redircom',
tooltip: 'The redirect should have no incoming links (unless the links are cleary intended for the file or redirect at Commons).',
showInNamespaces: [ 6 ]
},
{
label: 'G6: Redirect to malplaced disambiguation page',
value: 'movedab',
tooltip: 'This only applies for redirects to disambiguation pages ending in (disambiguation) where a primary topic does not exist.',
hideWhenMultiple: true
},
{
label: 'G8: Redirects to non-existent targets',
value: 'redirnone',
tooltip: 'This excludes any page that is useful to the project, and in particular: deletion discussions that are not logged elsewhere, user and user talk pages, talk page archives, plausible redirects that can be changed to valid targets, and file pages or talk pages for files that exist on Wikimedia Commons.',
hideWhenMultiple: true
}
];
 
Twinkle.speedy.normalizeHash = {
'reason': 'db',
'nonsense': 'g1',
'test': 'g2',
'vandalism': 'g3',
'hoax': 'g3',
'repost': 'g4',
'banned': 'g5',
'histmerge'move: 'g6',
'move'xfd: 'g6',
'xfd'movedab: 'g6',
'disambig'copypaste: 'g6',
'movedab'g6: 'g6',
'copypaste'author: 'g6g7',
'g6'g8: 'g6g8',
'author'talk: 'g7g8',
'g8'subpage: 'g8',
'talk'redirnone: 'g8',
'subpage'templatecat: 'g8',
'redirnone'imagepage: 'g8',
'templatecat'attack: 'g8g10',
'imagepage'negublp: 'g8g10',
'attack'spam: 'g10g11',
'negublp'spamuser: 'g10g11',
'spam'copyvio: 'g11g12',
'spamuser'afc: 'g11g13',
'copyvio'disambig: 'g12g14',
'afc'nocontext: 'g13a1',
'nocontext'foreign: 'a1a2',
'foreign'nocontent: 'a2a3',
'nocontent'transwiki: 'a3a5',
'transwiki'a7: 'a5a7',
'a7'person: 'a7',
'person'corp: 'a7',
'corp'web: 'a7',
'web'band: 'a7',
'band'club: 'a7',
'club'animal: 'a7',
'animal'event: 'a7',
'event'a9: 'a7a9',
'a9'a10: 'a9a10',
'a10'madeup: 'a10a11',
'madeup'rediruser: 'a11r2',
'rediruser'redirtypo: 'r2r3',
'redirtypo'redircom: 'r3r4',
'redundantimage': 'f1',
'noimage': 'f2',
'fpcfail': 'f2',
'noncom': 'f3',
'unksource': 'f4',
'unfree': 'f5',
'norat'f5: 'f6f5',
'badfairuse'norat: 'f7f6',
'nowcommons'badfairuse: 'f8f7',
'imgcopyvio'commons: 'f9f8',
'badfiletype'imgcopyvio: 'f10f9',
'nopermission'badfiletype: 'f11f10',
'catempty'nopermission: 'c1f11',
'userreq'catempty: 'u1c1',
'nouser'userreq: 'u2u1',
'gallery'nouser: 'u3u2',
'notwebhost'gallery: 'u5u3',
'policy'notwebhost: 't2u5',
'duplicatetemplate'p1: 't3p1',
'p1'emptyportal: 'p1p2',
'emptyportal': 'p2'
};
 
// keep this synched with [[MediaWiki:Deletereason-dropdown]]
Twinkle.speedy.reasonHash = {
'reason': '',
// General
'nonsense': '[[WP:PN|Patent nonsense]], meaningless, or incomprehensible',
'test': 'Test page',
'vandalism': '[[WP:Vandalism|Vandalism]]',
'hoax': 'Blatant [[WP:Do not create hoaxes|hoax]]',
'repost': 'Recreation of a page that was [[WP:DEL|deleted]] per a [[WP:XFD|deletion discussion]]',
'banned': 'Creation by a [[WP:BLOCK|blocked]] or [[WP:BAN|banned]] user in violation of block or ban',
'histmerge': 'Temporary deletion in order to merge page histories',
'move': 'Making way for a non-controversial move',
'xfd': 'Deleting page per result of [[WP:XfD|deletion discussion]]',
'disambig': 'Unnecessary disambiguation page',
'movedab': 'Redirect to [[WP:MALPLACED|malplaced disambiguation page]]',
'copypaste': '[[WP:CPMV|Copy-and-paste]] page move',
'g6': 'Housekeeping and routine (non-controversial) cleanup',
'author': 'One author who has requested deletion or blanked the page',
'g8': 'Page dependent on a deleted or nonexistent page',
'talk': '[[Help:Talk page|Talk page]] of a deleted or nonexistent page',
'subpage': '[[WP:Subpages|Subpage]] of a deleted or nonexistent page',
'redirnone': '[[Wikipedia:Redirect|redirect]] to a deleted or nonexistent page',
'templatecat': 'Populated by deleted or retargeted templates',
'imagepage': 'File description page for a file that does not exist',
'attack': '[[WP:ATP|Attack page]] or negative unsourced [[WP:BLP|BLP]]',
'negublp': 'Negative unsourced [[WP:BLP|BLP]]',
'spam': 'Unambiguous [[WP:NOTADVERTISING|advertising]] or promotion',
'copyvio': 'Unambiguous [[WP:CV|copyright infringement]]',
'afc': 'Abandoned [[WP:AFC|Article for creation]] – to retrieve it, see [[WP:REFUND/G13]]',
// Articles
'nocontext': 'Short article without enough context to identify the subject',
'foreign': 'Article in a foreign language that exists on another project',
'nocontent': 'Article that has no meaningful, substantive content',
'transwiki': 'Article that has been transwikied to another project',
'a7': 'No credible indication of importance (individuals, animals, organizations, web content, events)',
'person' : 'No credible indication of importance (real person)',
'web': 'No credible indication of importance (web content)',
'corp': 'No credible indication of importance (organization)',
'club': 'No credible indication of importance (organization)',
'band': 'No credible indication of importance (band/musician)',
'animal': 'No credible indication of importance (individual animal)',
'event': 'No credible indication of importance (event)',
'a9': 'Music recording by redlinked artist and no indication of importance or significance',
'a10': 'Recently created article that duplicates an existing topic',
'madeup': 'Made up by article creator or an associate, and no indication of importance/significance',
// Images and media
// Keep synched with [[MediaWiki:Filedelete-reason-dropdown]]
'redundantimage': 'Redundant copy of non-Commons file in the same file format',
'noimage': 'Corrupt or empty file',
'fpcfail': 'Unneeded file description page for a file on Commons',
'noncom': 'Invalid licence, eg. "for non-commercial use only" or "for Wikipedia use only"',
'unksource': 'Lack of licensing information',
'unfree': 'Unused non-free media',
'norat': 'Non-free file with no [[WP:RAT|non-free use rationale]]',
'badfairuse': 'Violates [[WP:F|non-free use policy]]',
'nowcommons': 'Media file available on Commons',
'imgcopyvio': 'Unambiguous [[WP:COPYVIO|copyright violation]]',
'badfiletype': 'Useless media file (not an image, audio or video)',
'nopermission': 'No evidence of permission',
// Categories
'catempty': 'Empty category',
// User pages
'userreq': 'User request to delete page in own userspace',
'nouser': 'Userpage or subpage of a nonexistent user',
'gallery': '[[WP:NFC|Non-free]] [[Help:Gallery|gallery]]',
'notwebhost': '[[WP:NOTWEBHOST|Misuse of Wikipedia as a web host]]',
// Templates
'policy': 'Template that unambiguously misrepresents established policy',
'duplicatetemplate': 'Unused, redundant template',
// Portals
'p1': '[[WP:P|Portal]] page that would be subject to speedy deletion as an article',
'emptyportal': '[[WP:P|Portal]] without a substantial topic base',
// Redirects
'rediruser': 'Cross-[[WP:NS|namespace]] [[WP:R|redirect]] from mainspace',
'redirtypo': 'Recently created, implausible [[WP:R|redirect]]'
};
 
Twinkle.speedy.callbacks = {
getTemplateCodeAndParams: function(params) {
sysop: {
var code, parameters, i;
main: function( params ) {
if (params.normalizeds.length > 1) {
var thispage;
code = '{{db-multiple';
params.utparams = {};
$.each(params.normalizeds, function(index, norm) {
code += '|' + norm.toUpperCase();
parameters = params.templateParams[index] || [];
for (var i in parameters) {
if (typeof parameters[i] === 'string' && !parseInt(i, 10)) { // skip numeric parameters - {{db-multiple}} doesn't understand them
code += '|' + i + '=' + parameters[i];
}
}
$.extend(params.utparams, Twinkle.speedy.getUserTalkParameters(norm, parameters));
});
code += '}}';
} else {
parameters = params.templateParams[0] || [];
code = '{{db-' + params.values[0];
for (i in parameters) {
if (typeof parameters[i] === 'string') {
code += '|' + i + '=' + parameters[i];
}
}
if (params.usertalk) {
code += '|help=off';
}
code += '}}';
params.utparams = Twinkle.speedy.getUserTalkParameters(params.normalizeds[0], parameters);
}
 
return [code, params.utparams];
Morebits.wiki.addCheckpoint(); // prevent actionCompleted from kicking in until user interaction is done
},
 
parseWikitext: function(wikitext, callback) {
// look up initial contributor. If prompting user for deletion reason, just display a link.
var query = {
// Otherwise open the talk page directly
action: 'parse',
if( params.openusertalk ) {
prop: 'text',
thispage = new Morebits.wiki.page( mw.config.get('wgPageName') ); // a necessary evil, in order to clear incorrect status text
pst: 'true',
thispage.setCallbackParameters( params );
text: wikitext,
thispage.lookupCreator( Twinkle.speedy.callbacks.sysop.openUserTalkPage );
contentmodel: 'wikitext',
title: mw.config.get('wgPageName'),
disablelimitreport: true,
format: 'json'
};
 
var statusIndicator = new Morebits.status('Building deletion summary');
var api = new Morebits.wiki.api('Parsing deletion template', query, function(apiobj) {
var reason = decodeURIComponent($(apiobj.getResponse().parse.text).find('#delete-reason').text()).replace(/\+/g, ' ');
if (!reason) {
statusIndicator.warn('Unable to generate summary from deletion template');
} else {
statusIndicator.info('complete');
}
callback(reason);
}, statusIndicator);
api.post();
},
 
noteToCreator: function(pageobj) {
// delete page
var params = pageobj.getCallbackParameters();
var reason;
var initialContrib = pageobj.getCreator();
thispage = new Morebits.wiki.page( mw.config.get('wgPageName'), "Deleting page" );
 
if (params.normalized === 'db') {
// disallow notifying yourself
reason = prompt("Enter the deletion summary to use, which will be entered into the deletion log:", "");
if (initialContrib === mw.config.get('wgUserName')) {
Morebits.status.warn('You (' + initialContrib + ') created this page; skipping user notification');
initialContrib = null;
 
// don't notify users when their user talk page is nominated/deleted
} else if (initialContrib === mw.config.get('wgTitle') && mw.config.get('wgNamespaceNumber') === 3) {
Morebits.status.warn('Notifying initial contributor: this user created their own user talk page; skipping notification');
initialContrib = null;
 
// quick hack to prevent excessive unwanted notifications, per request. Should actually be configurable on recipient page...
} else if ((initialContrib === 'Cyberbot I' || initialContrib === 'SoxBot') && params.normalizeds[0] === 'f2') {
Morebits.status.warn('Notifying initial contributor: page created procedurally by bot; skipping notification');
initialContrib = null;
 
// Check for already existing tags
} else if (Twinkle.speedy.hasCSD && params.warnUser && !confirm('The page is has a deletion-related tag, and thus the creator has likely been notified. Do you want to notify them for this deletion as well?')) {
Morebits.status.info('Notifying initial contributor', 'canceled by user; skipping notification.');
initialContrib = null;
}
 
if (initialContrib) {
var usertalkpage = new Morebits.wiki.page('User talk:' + initialContrib, 'Notifying initial contributor (' + initialContrib + ')'),
notifytext, i, editsummary;
 
// special cases: "db" and "db-multiple"
if (params.normalizeds.length > 1) {
notifytext = '\n{{subst:db-' + (params.warnUser ? 'deleted' : 'notice') + '-multiple|1=' + Morebits.pageNameNorm;
var count = 2;
$.each(params.normalizeds, function(index, norm) {
notifytext += '|' + count++ + '=' + norm.toUpperCase();
});
} else if (params.normalizeds[0] === 'db') {
notifytext = '\n{{subst:db-reason-' + (params.warnUser ? 'deleted' : 'notice') + '|1=' + Morebits.pageNameNorm;
} else {
notifytext = '\n{{subst:db-csd-' + (params.warnUser ? 'deleted' : 'notice') + '-custom|1=';
var presetReason = "[[WP:CSD#" + params.normalized.toUpperCase() + "|" + params.normalized.toUpperCase() + "]]: " + params.reason;
if (Twinkle.getPref("promptForSpeedyDeletionSummary").indexOf(params.normalized)values[0] !=== -1'copypaste') {
notifytext += params.templateParams[0].sourcepage;
reason = prompt("Enter the deletion summary to use, or press OK to accept the automatically generated one.", presetReason);
} else {
reasonnotifytext += presetReasonMorebits.pageNameNorm;
}
notifytext += '|2=' + params.values[0];
}
 
if (reason === null) {
for (i in params.utparams) {
Morebits.status.error("Asking for reason", "User cancelled");
if (typeof params.utparams[i] === 'string') {
Morebits.wiki.removeCheckpoint();
notifytext += '|' + i + '=' + params.utparams[i];
return;
}
} else if (!reason || !reason.replace(/^\s*/, "").replace(/\s*$/, "")) {
Morebits.status.error("Asking for reason", "you didn't give one. I don't know... what with admins and their apathetic antics... I give up...");
Morebits.wiki.removeCheckpoint();
return;
}
notifytext += (params.welcomeuser ? '' : '|nowelcome=yes') + '}} ~~~~';
thispage.setEditSummary( reason + Twinkle.getPref('deletionSummaryAd') );
 
thispage.deletePage(function() {
editsummary = 'Notification: speedy deletion' + (params.warnUser ? '' : ' nomination');
thispage.getStatusElement().info("done");
if (params.normalizeds.indexOf('g10') === -1) { // no article name in summary for G10 taggings
Twinkle.speedy.callbacks.sysop.deleteTalk( params );
editsummary += ' of [[:' + Morebits.pageNameNorm + ']].';
} else {
editsummary += ' of an attack page.';
}
 
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary(editsummary);
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append(function onNotifySuccess() {
// add this nomination to the user's userspace log, if the user has enabled it
if (params.lognomination) {
Twinkle.speedy.callbacks.user.addToLog(params, initialContrib);
}
}, function onNotifyError() {
// if user could not be notified, log nomination without mentioning that notification was sent
if (params.lognomination) {
Twinkle.speedy.callbacks.user.addToLog(params, null);
}
});
} else if (params.lognomination) {
Morebits.wiki.removeCheckpoint();
// log nomination even if the user notification wasn't sent
Twinkle.speedy.callbacks.user.addToLog(params, null);
}
},
 
sysop: {
main: function(params) {
var reason;
if (!params.normalizeds.length && params.normalizeds[0] === 'db') {
reason = prompt('Enter the deletion summary to use, which will be entered into the deletion log:', '');
Twinkle.speedy.callbacks.sysop.deletePage(reason, params);
} else {
var code = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params)[0];
Twinkle.speedy.callbacks.parseWikitext(code, function(reason) {
if (params.promptForSummary) {
reason = prompt('Enter the deletion summary to use, or press OK to accept the automatically generated one.', reason);
}
Twinkle.speedy.callbacks.sysop.deletePage(reason, params);
});
}
},
deletePage: function(reason, params) {
var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), 'Deleting page');
 
if (reason === null) {
return Morebits.status.error('Asking for reason', 'User cancelled');
} else if (!reason || !reason.replace(/^\s*/, '').replace(/\s*$/, '')) {
return Morebits.status.error('Asking for reason', "you didn't give one. I don't know... what with admins and their apathetic antics... I give up...");
}
 
var deleteMain = function(callback) {
thispage.setEditSummary(reason);
thispage.setChangeTags(Twinkle.changeTags);
thispage.setWatchlist(params.watch);
thispage.deletePage(function() {
thispage.getStatusElement().info('done');
typeof callback === 'function' && callback();
Twinkle.speedy.callbacks.sysop.deleteTalk(params);
});
};
 
// look up initial contributor. If prompting user for deletion reason, just display a link.
// Otherwise open the talk page directly
if (params.warnUser) {
thispage.setCallbackParameters(params);
thispage.lookupCreation(function(pageobj) {
deleteMain(function() {
Twinkle.speedy.callbacks.noteToCreator(pageobj);
});
});
} else {
deleteMain();
}
},
deleteTalk: function( params ) {
// delete talk page
if (params.deleteTalkPage &&
params.normalized !== 'f8' &&
document.getElementById( 'ca-talk' ).className !== 'new') {
var talkpage = new Morebits.wiki.page( Morebitsmw.wikipediaconfig.namespacesget('wgFormattedNamespaces')[ mw.config.get('wgNamespaceNumber') + 1 ] + ':' + mw.config.get('wgTitle'), "'Deleting talk page" ');
talkpage.setEditSummary('[[WP:CSD#G8|G8]]: Talk page of deleted page "' + Morebits.pageNameNorm + '"' + Twinkle.getPref('deletionSummaryAd'));
talkpage.setChangeTags(Twinkle.changeTags);
talkpage.deletePage();
// this is ugly, but because of the architecture of wiki.api, it is needed
// (otherwise success/failure messages for the previous action would be suppressed)
window.setTimeout(function() { Twinkle.speedy.callbacks.sysop.deleteRedirects( params ); }, 1800);
Twinkle.speedy.callbacks.sysop.deleteRedirects(params);
}, 1800);
} else {
Twinkle.speedy.callbacks.sysop.deleteRedirects( params );
}
},
deleteRedirects: function( params ) {
// delete redirects
if (params.deleteRedirects) {
var query = {
'action': 'query',
'titles': mw.config.get('wgPageName'),
'prop': 'redirects',
'rdlimit': 5000 'max', // 500 is max for normal users, 5000 for bots and sysops
format: 'json'
};
var wikipedia_api = new Morebits.wiki.api( 'getting list of redirects...', query, Twinkle.speedy.callbacks.sysop.deleteRedirectsMain,
new Morebits.status( 'Deleting redirects' ) );
wikipedia_api.params = params;
wikipedia_api.post();
// promote Unlink tool
var $link, $bigtext;
if( (mw.config.get('wgNamespaceNumber') === 6 && params.normalized !== 'f8' ) {
$link = $('<a/>', {
'href': '#',
'text': 'click here to go to the Unlink tool',
'css': { 'fontSize': '130%', 'fontWeight': 'bold' },
'click': function() {
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.speedy.dialog.close();
Twinkle.unlink.callback("'Removing usages of and/or links to deleted file "' + Morebits.pageNameNorm);
}
});
$bigtext = $('<span/>', {
'text': 'To orphan backlinks and remove instances of file usage',
'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
});
Morebits.status.info($bigtext[0], $link[0]);
} else if (params.normalized !== 'f8') {
$link = $('<a/>', {
'href': '#',
'text': 'click here to go to the Unlink tool',
'css': { 'fontSize': '130%', 'fontWeight': 'bold' },
'click': function() {
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.speedy.dialog.close();
Twinkle.unlink.callback("'Removing links to deleted page "' + Morebits.pageNameNorm);
}
});
$bigtext = $('<span/>', {
'text': 'To orphan backlinks',
'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
});
Morebits.status.info($bigtext[0], $link[0]);
}
},
openUserTalkPagedeleteRedirectsMain: function( pageobj apiobj) {
var response = apiobj.getResponse();
pageobj.getStatusElement().unlink(); // don't need it anymore
var usersnapshot = pageobjresponse.getCreator()query.pages[0].redirects || [];
var paramstotal = pageobjsnapshot.getCallbackParameters()length;
 
var query = {
'title': 'User talk:' + user,
'action': 'edit',
'preview': 'yes',
'vanarticle': Morebits.pageNameNorm
};
 
if (params.normalized === 'db' || Twinkle.getPref("promptForSpeedyDeletionSummary").indexOf(params.normalized) !== -1) {
// provide a link to the user talk page
var $link, $bigtext;
$link = $('<a/>', {
'href': mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ),
'text': 'click here to open User talk:' + user,
'target': '_blank',
'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
});
$bigtext = $('<span/>', {
'text': 'To notify the page creator',
'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
});
Morebits.status.info($bigtext[0], $link[0]);
} else {
// open the initial contributor's talk page
var statusIndicator = new Morebits.status('Opening user talk page edit form for ' + user, 'opening...');
 
switch( Twinkle.getPref('userTalkPageMode') ) {
case 'tab':
window.open( mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ), '_blank' );
break;
case 'blank':
window.open( mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ), '_blank', 'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
break;
case 'window':
/* falls through */
default:
window.open( mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ),
( window.name === 'twinklewarnwindow' ? '_blank' : 'twinklewarnwindow' ),
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
break;
}
 
statusIndicator.info( 'complete' );
}
},
deleteRedirectsMain: function( apiobj ) {
var xmlDoc = apiobj.getXML();
var $snapshot = $(xmlDoc).find('redirects rd');
var total = $snapshot.length;
var statusIndicator = apiobj.statelem;
 
if ( !total ) {
statusIndicator.status("'no redirects found"');
return;
}
 
statusIndicator.status("'0%"');
 
var current = 0;
var onsuccess = function( apiobjInner ) {
var now = parseInt( 100 * (++current) / total, 10 ) + '%';
statusIndicator.update( now );
apiobjInner.statelem.unlink();
if ( current >= total ) {
statusIndicator.info( now + ' (completed)' );
Morebits.wiki.removeCheckpoint();
}
Morebits.wiki.addCheckpoint();
 
$snapshot.eachforEach(function(key, value) {
var title = $(value).attr('title');
var page = new Morebits.wiki.page(title, 'Deleting redirect "' + title + '"');
page.setEditSummary('[[WP:CSD#G8|G8]]: Redirect to deleted page "' + Morebits.pageNameNorm + '"' + Twinkle.getPref('deletionSummaryAd'));
page.setChangeTags(Twinkle.changeTags);
page.deletePage(onsuccess);
});
 
if (!pageobj.exists()) {
statelem.error( "It seems that the page doesn't exist; perhaps it has already been deleted" );
return;
}
 
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
 
// given the params, builds the template and also adds the user talk page parameters to the params that were passed in
statelem.status( 'Checking for tags on the page...' );
// returns => [<string> wikitext, <object> utparams]
var buildData = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params),
code = buildData[0];
params.utparams = buildData[1];
 
// Set the correct value for |ts= parameter in {{db-g13}}
// check for existing deletion tags
if (params.normalizeds.indexOf('g13') !== -1) {
var tag = /(?:\{\{\s*(db|delete|db-.*?|speedy deletion-.*?)(?:\s*\||\s*\}\}))/.exec( text );
code = code.replace('$TIMESTAMP', pageobj.getLastEditTime());
if( tag ) {
statelem.error( [ Morebits.htmlNode( 'strong', tag[1] ) , " is already placed on the page." ] );
return;
}
 
// Tag if possible, post on talk if not
var xfd = /(?:\{\{([rsaiftcm]fd|md1|proposed deletion)[^{}]*?\}\})/i.exec( text );
if (pageobj.canEdit() && ['wikitext', 'Scribunto', 'javascript', 'css', 'sanitized-css'].indexOf(pageobj.getContentModel()) !== -1) {
if( xfd && !confirm( "The deletion-related template {{" + xfd[1] + "}} was found on the page. Do you still want to add a CSD template?" ) ) {
var text = pageobj.getPageText();
return;
 
}
statelem.status('Checking for tags on the page...');
 
// check for existing deletion tags
var tag = /(?:\{\{\s*(db|delete|db-.*?|speedy deletion-.*?)(?:\s*\||\s*\}\}))/.exec(text);
// This won't make use of the db-multiple template but it probably should
if (tag && !confirm('The page already has the CSD-related template {{' + tag[1] + '}} on it. Do you want to add another CSD template?')) {
return;
}
 
var xfd = /\{\{((?:article for deletion|proposed deletion|prod blp|template for discussion)\/dated|[cfm]fd\b)/i.exec(text) || /#invoke:(Redirect for discussion)/.exec(text);
if (xfd && !confirm('The deletion-related template {{' + xfd[1] + '}} was found on the page. Do you still want to add a CSD template?')) {
return;
}
 
// curate/patrol the page
if (Twinkle.getPref('markSpeedyPagesAsPatrolled')) {
pageobj.triage();
}
 
// Wrap SD template in noinclude tags if we are in template space.
var code, parameters, i;
// Won't work with userboxes in userspace, or any other transcluded page outside template space
if (params.normalizeds.length > 1) {
if (mw.config.get('wgNamespaceNumber') === 10) { // Template:
code = "{{db-multiple";
code = '<noinclude>' + code + '</noinclude>';
params.utparams = {};
}
$.each(params.normalizeds, function(index, norm) {
 
code += "|" + norm.toUpperCase();
// Remove tags that become superfluous with this action
parameters = params.templateParams[index] || [];
text = text.replace(/\{\{\s*([Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, '');
for (var i in parameters) {
if (mw.config.get('wgNamespaceNumber') === 6) {
if (typeof parameters[i] === 'string' && !parseInt(i, 10)) { // skip numeric parameters - {{db-multiple}} doesn't understand them
// remove "move to Commons" tag - deletion-tagged files cannot be moved to Commons
code += "|" + i + "=" + parameters[i];
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, '');
}
}
 
if (params.requestsalt) {
if (params.normalizeds.indexOf('g10') === -1) {
code += '\n{{salt}}';
} else {
code = '{{salt}}\n' + code;
}
}
$.extend(params.utparams, Twinkle.speedy.getUserTalkParameters(norm, parameters));
 
});
if (mw.config.get('wgPageContentModel') === 'Scribunto') {
code += "}}";
// Scribunto isn't parsed like wikitext, so CSD templates on modules need special handling to work
} else {
var equals = '';
parameters = params.templateParams[0] || [];
while (code.indexOf(']' =+ "{{db-"equals + params.values[0'];') !== -1) {
equals += '=';
for (i in parameters) {
if (typeof parameters[i] === 'string') {
code += "|" + i + "=" + parameters[i];
}
code = "require('Module:Module wikitext')._addText([" + equals + '[' + code + ']' + equals + ']);';
} else if (['javascript', 'css', 'sanitized-css'].indexOf(mw.config.get('wgPageContentModel')) !== -1) {
// Likewise for JS/CSS pages
code = '/* ' + code + ' */';
}
 
if (params.usertalk) {
// Generate edit summary for edit
code += "|help=off";
var editsummary;
if (params.normalizeds.length > 1) {
editsummary = 'Requesting speedy deletion (';
$.each(params.normalizeds, function(index, norm) {
editsummary += '[[WP:CSD#' + norm.toUpperCase() + '|CSD ' + norm.toUpperCase() + ']], ';
});
editsummary = editsummary.substr(0, editsummary.length - 2); // remove trailing comma
editsummary += ').';
} else if (params.normalizeds[0] === 'db') {
editsummary = 'Requesting [[WP:CSD|speedy deletion]] with rationale "' + params.templateParams[0]['1'] + '".';
} else {
editsummary = 'Requesting speedy deletion ([[WP:CSD#' + params.normalizeds[0].toUpperCase() + '|CSD ' + params.normalizeds[0].toUpperCase() + ']]).';
}
code += "}}";
params.utparams = Twinkle.speedy.getUserTalkParameters(params.normalizeds[0], parameters);
}
 
// Blank attack pages
var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'));
if (params.normalizeds.indexOf('g10') !== -1) {
// patrol the page, if reached from Special:NewPages
text = code;
if( Twinkle.getPref('markSpeedyPagesAsPatrolled') ) {
} else {
thispage.patrol();
// Insert tag after short description or any hatnotes
}
var wikipage = new Morebits.wikitext.page(text);
text = wikipage.insertAfterTemplates(code + '\n', Twinkle.hatnoteRegex).getText();
}
 
// Wrap SD template in noinclude tags if we are in template space.
// Won't work with userboxes in userspace, or any other transcluded page outside template space
if (mw.config.get('wgNamespaceNumber') === 10) { // Template:
code = "<noinclude>" + code + "</noinclude>";
}
 
pageobj.setPageText(text);
// Remove tags that become superfluous with this action
pageobj.setEditSummary(editsummary);
text = text.replace(/\{\{\s*([Nn]ew unreviewed article|[Uu]nreviewed|[Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, "");
pageobj.setWatchlist(params.watch);
if (mw.config.get('wgNamespaceNumber') === 6) {
pageobj.save(Twinkle.speedy.callbacks.user.tagComplete);
// remove "move to Commons" tag - deletion-tagged files cannot be moved to Commons
} else { // Attempt to place on talk page
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, "");
var talkName = new mw.Title(pageobj.getPageName()).getTalkPage().toText();
}
if (talkName !== pageobj.getPageName()) {
if (params.requestsalt) {
code += '\n{{salt}}';
}
 
pageobj.getStatusElement().warn('Unable to edit page, placing tag on talk page');
// Generate edit summary for edit
 
var editsummary;
var talk_page = new Morebits.wiki.page(talkName, 'Automatically placing tag on talk page');
if (params.normalizeds.length > 1) {
talk_page.setNewSectionTitle(pageobj.getPageName() + ' nominated for CSD, request deletion');
editsummary = 'Requesting speedy deletion (';
talk_page.setNewSectionText(code + '\n\nI was unable to tag ' + pageobj.getPageName() + ' so please delete it. ~~~~');
$.each(params.normalizeds, function(index, norm) {
talk_page.setCreateOption('recreate');
editsummary += '[[WP:CSD#' + norm.toUpperCase() + '|CSD ' + norm.toUpperCase() + ']], ';
talk_page.setFollowRedirect(true);
});
talk_page.setWatchlist(params.watch);
editsummary = editsummary.substr(0, editsummary.length - 2); // remove trailing comma
talk_page.setChangeTags(Twinkle.changeTags);
editsummary += ').';
talk_page.setCallbackParameters(params);
} else if (params.normalizeds[0] === "db") {
talk_page.newSection(Twinkle.speedy.callbacks.user.tagComplete);
editsummary = 'Requesting [[WP:CSD|speedy deletion]] with rationale \"' + parameters["1"] + '\".';
} else if (params.values[0] === "histmerge") {
pageobj.getStatusElement().error('Page protected and nowhere to add an edit request, aborting');
editsummary = "Requesting history merge with [[" + parameters["1"] + "]] ([[WP:CSD#G6|CSD G6]]).";
} else {
editsummary = "Requesting speedy deletion ([[WP:CSD#" + params.normalizeds[0].toUpperCase() + "|CSD " + params.normalizeds[0].toUpperCase() + "]]).";
}
 
pageobj.setPageText(code + ((params.normalizeds.indexOf('g10') !== -1) ? '' : ("\n" + text) )); // cause attack pages to be blanked
pageobj.setEditSummary(editsummary + Twinkle.getPref('summaryAd'));
pageobj.setWatchlist(params.watch);
pageobj.setCreateOption('nocreate');
pageobj.save(Twinkle.speedy.callbacks.user.tagComplete);
},
 
var params = pageobj.getCallbackParameters();
 
// Notification to first contributor, will also log nomination to the user's userspace log
if (params.usertalk) {
var callback = function(pageobj) {
var initialContrib = pageobj.getCreator();
 
// disallow warning yourself
if (initialContrib === mw.config.get('wgUserName')) {
Morebits.status.warn("You (" + initialContrib + ") created this page; skipping user notification");
 
// don't notify users when their user talk page is nominated
} else if (initialContrib === mw.config.get('wgTitle') && mw.config.get('wgNamespaceNumber') === 3) {
Morebits.status.warn("Notifying initial contributor: this user created their own user talk page; skipping notification");
 
// quick hack to prevent excessive unwanted notifications, per request. Should actually be configurable on recipient page...
} else if ((initialContrib === "Cyberbot I" || initialContrib === "SoxBot") && params.normalizeds[0] === "f2") {
Morebits.status.warn("Notifying initial contributor: page created procedurally by bot; skipping notification");
 
} else {
var usertalkpage = new Morebits.wiki.page('User talk:' + initialContrib, "Notifying initial contributor (" + initialContrib + ")"),
notifytext, i;
 
// specialcase "db" and "db-multiple"
if (params.normalizeds.length > 1) {
notifytext = "\n{{subst:db-notice-multiple|1=" + Morebits.pageNameNorm;
var count = 2;
$.each(params.normalizeds, function(index, norm) {
notifytext += "|" + (count++) + "=" + norm.toUpperCase();
});
} else if (params.normalizeds[0] === "db") {
notifytext = "\n{{subst:db-reason-notice|1=" + Morebits.pageNameNorm;
} else {
notifytext = "\n{{subst:db-csd-notice-custom|1=" + Morebits.pageNameNorm + "|2=" + params.values[0];
}
 
for (i in params.utparams) {
if (typeof params.utparams[i] === 'string') {
notifytext += "|" + i + "=" + params.utparams[i];
}
}
notifytext += (params.welcomeuser ? "" : "|nowelcome=yes") + "}} ~~~~";
 
var editsummary = "Notification: speedy deletion nomination";
if (params.normalizeds.indexOf("g10") === -1) { // no article name in summary for G10 deletions
editsummary += " of [[" + Morebits.pageNameNorm + "]].";
} else {
editsummary += " of an attack page.";
}
 
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary(editsummary + Twinkle.getPref('summaryAd'));
usertalkpage.setCreateOption('recreate');
usertalkpage.setFollowRedirect(true);
usertalkpage.append();
}
 
// add this nomination to the user's userspace log, if the user has enabled it
if (params.lognomination) {
Twinkle.speedy.callbacks.user.addToLog(params, initialContrib);
}
};
var thispage = new Morebits.wiki.page(Morebits.pageNameNorm);
thispage.lookupCreatorsetCallbackParameters(callbackparams);
thispage.lookupCreation(Twinkle.speedy.callbacks.noteToCreator);
}
// or, if not notifying, add this nomination to the user's userspace log without the initial contributor's name
} else if (params.lognomination) {
Twinkle.speedy.callbacks.user.addToLog(params, null);
}
},
 
// note: this code is also invoked from twinkleimage
// the params used are:
// for CSD: params.values, params.normalizeds (note: normalizeds is an array)
// for DI: params.fromDI = true, params.templatename, params.normalized (note: normalized is a string)
addToLog: function(params, initialContrib) {
var wikipedia_pageusl = new Morebits.wiki.pageuserspaceLogger("User:" + mw.config.get('wgUserName') + "/" + Twinkle.getPref('speedyLogPageName'), "Adding entry to userspace log");
usl.initialText =
params.logInitialContrib = initialContrib;
"This is a log of all [[WP:CSD|speedy deletion]] nominations made by this user using [[WP:TW|Twinkle]]'s CSD module.\n\n" +
wikipedia_page.setCallbackParameters(params);
'If you no longer wish to keep this log, you can turn it off using the [[Wikipedia:Twinkle/Preferences|preferences panel]], and ' +
wikipedia_page.load(Twinkle.speedy.callbacks.user.saveLog);
'nominate this page for speedy deletion under [[WP:CSD#U1|CSD U1]].' +
},
(Morebits.userIsSysop ? '\n\nThis log does not track outright speedy deletions made using Twinkle.' : '');
 
saveLog: var formatParamLog = function(pageobjnormalize, csdparam, input) {
if ((normalize === 'G4' && csdparam === 'xfd') ||
var text = pageobj.getPageText();
(normalize === 'G6' && csdparam === 'page') ||
var params = pageobj.getCallbackParameters();
(normalize === 'G6' && csdparam === 'fullvotepage') ||
(normalize === 'G6' && csdparam === 'sourcepage') ||
(normalize === 'A2' && csdparam === 'source') ||
(normalize === 'A10' && csdparam === 'article') ||
(normalize === 'F1' && csdparam === 'filename')) {
input = '[[:' + input + ']]';
} else if (normalize === 'G5' && csdparam === 'user') {
input = '[[:User:' + input + ']]';
} else if (normalize === 'G12' && csdparam.lastIndexOf('url', 0) === 0 && input.lastIndexOf('http', 0) === 0) {
input = '[' + input + ' ' + input + ']';
} else if (normalize === 'F8' && csdparam === 'filename') {
input = '[[commons:' + input + ']]';
} else if (normalize === 'P1' && csdparam === 'criterion') {
input = '[[WP:CSD#' + input + ']]';
}
return ' {' + normalize + ' ' + csdparam + ': ' + input + '}';
};
 
var appendTextextraInfo = ""'';
 
// If a logged file is deleted but exists on commons, the wikilink will be blue, so provide a link to the log
// add blurb if log page doesn't exist
var fileLogLink = mw.config.get('wgNamespaceNumber') === 6 ? ' ([{{fullurl:Special:Log|page=' + mw.util.wikiUrlencode(mw.config.get('wgPageName')) + '}} log])' : '';
if (!pageobj.exists()) {
appendText +=
"This is a log of all [[WP:CSD|speedy deletion]] nominations made by this user using [[WP:TW|Twinkle]]'s CSD module.\n\n" +
"If you no longer wish to keep this log, you can turn it off using the [[Wikipedia:Twinkle/Preferences|preferences panel]], and " +
"nominate this page for speedy deletion under [[WP:CSD#U1|CSD U1]].";
if (Morebits.userIsInGroup("sysop")) {
appendText += "\n\nThis log does not track outright speedy deletions made using Twinkle.";
}
}
 
var editsummary = 'Logging speedy deletion nomination';
// create monthly header
var dateappendText = new'# Date()[[:' + Morebits.pageNameNorm;
 
var headerRe = new RegExp("^==+\\s*" + date.getUTCMonthName() + "\\s+" + date.getUTCFullYear() + "\\s*==+", "m");
if (params.normalizeds.indexOf('g10') === -1) { // no article name in log for G10 taggings
if (!headerRe.exec(text)) {
appendText += "\n\n=== " + date.getUTCMonthName() + " "']]' + date.getUTCFullYear()fileLogLink + "': ==="';
editsummary += ' of [[:' + Morebits.pageNameNorm + ']].';
} else {
appendText += '|This]] attack page' + fileLogLink + ': ';
editsummary += ' of an attack page.';
}
if (params.normalizeds.length > 1) {
appendText += 'multiple criteria (';
$.each(params.normalizeds, function(index, norm) {
appendText += '[[WP:CSD#' + norm.toUpperCase() + '|' + norm.toUpperCase() + ']], ';
});
appendText = appendText.substr(0, appendText.length - 2); // remove trailing comma
appendText += ')';
} else if (params.normalizeds[0] === 'db') {
appendText += '{{tl|db-reason}}';
} else {
appendText += '[[WP:CSD#' + params.normalizeds[0].toUpperCase() + '|CSD ' + params.normalizeds[0].toUpperCase() + ']] ({{tl|db-' + params.values[0] + '}})';
}
 
// If params is "empty" it will still be full of empty arrays, but ask anyway
appendText += "\n# [[:" + Morebits.pageNameNorm + "]]: ";
if (params.fromDItemplateParams) {
// Treat custom rationale individually
appendText += "DI [[WP:CSD#" + params.normalized.toUpperCase() + "|CSD " + params.normalized.toUpperCase() + "]] ({{tl|di-" + params.templatename + "}})";
if (params.normalizeds[0] && params.normalizeds[0] === 'db') {
} else {
extraInfo += formatParamLog('Custom', 'rationale', params.templateParams[0]['1']);
if (params.normalizeds.length > 1) {
} else {
appendText += "multiple criteria (";
$params.eachtemplateParams.forEach(params.normalizeds, function(indexitem, normindex) {
var keys = Object.keys(item);
appendText += "[[WP:CSD#" + norm.toUpperCase() + "|" + norm.toUpperCase() + ']], ';
if (keys[0] !== undefined && keys[0].length > 0) {
// Second loop required since some items (G12, F9) may have multiple keys
keys.forEach(function(key, keyIndex) {
if (keys[keyIndex] === 'blanked' || keys[keyIndex] === 'ts') {
return true; // Not worth logging
}
extraInfo += formatParamLog(params.normalizeds[index].toUpperCase(), keys[keyIndex], item[key]);
});
}
});
appendText = appendText.substr(0, appendText.length - 2); // remove trailing comma
appendText += ')';
} else if (params.normalizeds[0] === "db") {
appendText += "{{tl|db-reason}}";
} else {
appendText += "[[WP:CSD#" + params.normalizeds[0].toUpperCase() + "|CSD " + params.normalizeds[0].toUpperCase() + "]] ({{tl|db-" + params.values[0] + "}})";
}
}
 
if (params.logInitialContribrequestsalt) {
appendText += "'; notifiedrequested {{user|1="creation +protection params.logInitialContrib + "}}"([[WP:SALT|salting]])';
}
if (extraInfo) {
appendText += '; additional information:' + extraInfo;
}
if (initialContrib) {
appendText += '; notified {{user|1=' + initialContrib + '}}';
}
appendText += "' ~~~~~\n"';
 
usl.changeTags = Twinkle.changeTags;
pageobj.setAppendText(appendText);
usl.log(appendText, editsummary);
pageobj.setEditSummary("Logging speedy deletion nomination of [[" + Morebits.pageNameNorm + "]]." + Twinkle.getPref('summaryAd'));
pageobj.setCreateOption("recreate");
pageobj.append();
}
}
switch (value) {
case 'reason':
if (form["'csd.reason_1"']) {
var dbrationale = form["'csd.reason_1"'].value;
if (!dbrationale || !dbrationale.trim()) {
alert( 'Custom rationale: Please specify a rationale.' );
parameters = null;
return false;
}
currentParams["'1"'] = dbrationale;
}
break;
 
case 'userreq': // U1
if (form["'csd.userreq_rationale"']) {
var u1rationale = form["'csd.userreq_rationale"'].value;
if (mw.config.get('wgNamespaceNumber') === 3 && !((/\//).test(mw.config.get('wgTitle'))) &&
(!u1rationale || !u1rationale.trim())) {
alert( 'CSD U1: Please specify a rationale when nominating user talk pages.' );
parameters = null;
return false;
 
case 'repost': // G4
if (form["'csd.repost_1"repost_xfd']) {
var deldisc = form["'csd.repost_1"repost_xfd'].value;
if (deldisc) {
if (!new RegExp('^:?' + Morebits.namespaceRegex(4) + ':', 'i').test(deldisc)) {
if (deldisc.substring(0, 9) !== "Wikipedia" && deldisc.substring(0, 3) !== "WP:") {
alert( 'CSD G4: The deletion discussion page name, if provided, must start with "Wikipedia:".' );
parameters = null;
return false;
}
currentParams["1"].xfd = deldisc;
}
}
 
case 'banned': // G5
if (form["'csd.banned_1"banned_user'] && form["'csd.banned_1"banned_user'].value) {
currentParams["1"].user = form["'csd.banned_1"banned_user'].value.replace(/^\s*User:/i, ""'');
}
break;
 
case 'histmerge': // G6
if (form["csd.histmerge_1"]) {
var merger = form["csd.histmerge_1"].value;
if (!merger || !merger.trim()) {
alert( 'CSD G6 (histmerge): Please specify the page to be merged.' );
parameters = null;
return false;
}
currentParams["1"] = merger;
}
break;
 
case 'move': // G6
if (form["'csd.move_1"move_page'] && form["'csd.move_2"move_reason']) {
var movepage = form["'csd.move_1"move_page'].value,
movereason = form["'csd.move_2"move_reason'].value;
if (!movepage || !movepage.trim()) {
alert( 'CSD G6 (move): Please specify the page to be moved here.' );
parameters = null;
return false;
}
if (!movereason || !movereason.trim()) {
alert( 'CSD G6 (move): Please specify the reason for the move.' );
parameters = null;
return false;
}
currentParams["1"].page = movepage;
currentParams["2"].reason = movereason;
}
break;
 
case 'xfd': // G6
if (form["'csd.xfd_fullvotepage"']) {
var xfd = form["'csd.xfd_fullvotepage"'].value;
if (xfd) {
if (xfd.substring(0, 9) !==new "Wikipedia"RegExp('^:?' &&+ xfdMorebits.substringnamespaceRegex(0, 34) !==+ "WP':"', 'i').test(xfd)) {
alert( 'CSD G6 (XFD): The deletion discussion page name, if provided, must start with "Wikipedia:".' );
parameters = null;
return false;
 
case 'copypaste': // G6
if (form["'csd.copypaste_1"copypaste_sourcepage']) {
var copypaste = form["'csd.copypaste_1"copypaste_sourcepage'].value;
if (!copypaste || !copypaste.trim()) {
alert( 'CSD G6 (copypaste): Please specify the source page name.' );
parameters = null;
return false;
}
currentParams["1"].sourcepage = copypaste;
}
break;
 
case 'g6': // G6
if (form["'csd.g6_rationale"'] && form["'csd.g6_rationale"'].value) {
currentParams.rationale = form["'csd.g6_rationale"'].value;
}
break;
 
case 'author': // G7
if (form["'csd.author_rationale"'] && form["'csd.author_rationale"'].value) {
currentParams.rationale = form["'csd.author_rationale"'].value;
}
break;
 
case 'g8': // G8
if (form["'csd.g8_rationale"'] && form["'csd.g8_rationale"'].value) {
currentParams.rationale = form["'csd.g8_rationale"'].value;
}
break;
 
case 'templatecat': // G8
if (form['csd.templatecat_rationale'] && form['csd.templatecat_rationale'].value) {
currentParams.rationale = form['csd.templatecat_rationale'].value;
}
break;
 
case 'copyvio': // G12
if (form["'csd.copyvio_url"'] && form["'csd.copyvio_url"'].value) {
currentParams.url = form["'csd.copyvio_url"'].value;
}
if (form["'csd.copyvio_url2"'] && form["'csd.copyvio_url2"'].value) {
currentParams.url2 = form["'csd.copyvio_url2"'].value;
}
if (form["'csd.copyvio_url3"'] && form["'csd.copyvio_url3"'].value) {
currentParams.url3 = form["'csd.copyvio_url3"'].value;
}
break;
 
case 'afc': // G13
currentParams.ts = '$TIMESTAMP'; // to be replaced by the last revision timestamp when page is saved
var query = {
action: "query",
titles: mw.config.get("wgPageName"),
prop: "revisions",
rvprop: "timestamp"
},
api = new Morebits.wiki.api( 'Grabbing the last revision timestamp', query, function( apiobj ) {
var xmlDoc = apiobj.getXML(),
isoDateString = $(xmlDoc).find("rev").attr("timestamp");
 
currentParams.ts = isoDateString;
});
 
// Wait for API call to finish
api.post({
async: false
});
 
break;
 
case 'redundantimage': // F1
if (form["'csd.redundantimage_filename"']) {
var redimage = form["'csd.redundantimage_filename"'].value;
if (!redimage || !redimage.trim()) {
alert( 'CSD F1: Please specify the filename of the other file.' );
parameters = null;
return false;
}
currentParams.filename = redimage.replacenew RegExp(/'^\\s*' + Morebits.namespaceRegex(Image|File6) + ':/i', ""'i').test(redimage) ? redimage : 'File:' + redimage;
}
break;
 
case 'badfairuse': // F7
if (form["'csd.badfairuse_reason"badfairuse_rationale'] && form["'csd.badfairuse_reason"badfairuse_rationale'].value) {
currentParams.reasonrationale = form["'csd.badfairuse_reason"badfairuse_rationale'].value;
}
break;
 
case 'nowcommonscommons': // F8
if (form["'csd.nowcommons_filename"commons_filename']) {
var filename = form["'csd.nowcommons_filename"commons_filename'].value;
if (filename && filename.trim() && filename !== Morebits.pageNameNorm) {
currentParams.filename = new RegExp('^\\s*' + Morebits.namespaceRegex(6) + ':', 'i').test(filename) ? filename : 'File:' + filename;
if (filename.indexOf("Image:") === 0 || filename.indexOf("File:") === 0) {
currentParams["1"] = filename;
} else {
currentParams["1"] = "File:" + filename;
}
}
}
currentParams.date = "~~~~~";
break;
 
case 'imgcopyvio': // F9
if (form["'csd.imgcopyvio_url"'] && form["'csd.imgcopyvio_url"imgcopyvio_rationale'].value) {
currentParams.urlvar f9url = form["'csd.imgcopyvio_url"'].value;
var f9rationale = form['csd.imgcopyvio_rationale'].value;
if ((!f9url || !f9url.trim()) && (!f9rationale || !f9rationale.trim())) {
alert('CSD F9: You must enter a url or reason (or both) when nominating a file under F9.');
parameters = null;
return false;
}
if (form['csd.imgcopyvio_url'].value) {
currentParams.url = f9url;
}
if (form['csd.imgcopyvio_rationale'].value) {
currentParams.rationale = f9rationale;
}
}
break;
 
case 'foreign': // A2
if (form["'csd.foreign_source"']) {
var foreignlink = form["'csd.foreign_source"'].value;
if (!foreignlink || !foreignlink.trim()) {
alert( 'CSD A2: Please specify an interwiki link to the article of which this is a copy.' );
parameters = null;
return false;
}
currentParams.source = foreignlink;
}
break;
 
case 'transwiki': // A5
if (form['csd.transwiki_location'] && form['csd.transwiki_location'].value) {
currentParams.location = form['csd.transwiki_location'].value;
}
break;
 
case 'a10': // A10
if (form["'csd.a10_article"']) {
var duptitle = form["'csd.a10_article"'].value;
if (!duptitle || !duptitle.trim()) {
alert( 'CSD A10: Please specify the name of the article which is duplicated.' );
parameters = null;
return false;
}
currentParams.article = duptitle;
}
break;
 
case 'duplicatetemplate': // T3
if (form["csd.duplicatetemplate_2"]) {
var t3template = form["csd.duplicatetemplate_2"].value;
if (!t3template || !t3template.trim()) {
alert( 'CSD T3: Please specify the name of a template duplicated by this one.' );
parameters = null;
return false;
}
currentParams["1"] = "~~~~~";
currentParams["2"] = t3template.replace(/^\s*Template:/i, "");
}
break;
 
case 'p1': // P1
if (form["'csd.p1_criterion"']) {
var criterion = form["'csd.p1_criterion"'].value;
if (!criterion || !criterion.trim()) {
alert( 'CSD P1: Please specify a single criterion and/or associated rationale.' );
parameters = null;
return false;
}
currentParams["1"].criterion = criterion;
}
break;
};
 
// functionFunction for processing talk page notification template parameters
// key1/value1: for {{db-criterion-[notice|deleted]}} (via {{db-csd-[notice|deleted]-custom}})
// utparams.param: for {{db-[notice|deleted]-multiple}}
Twinkle.speedy.getUserTalkParameters = function twinklespeedyGetUserTalkParameters(normalized, parameters) {
var utparams = [];
 
switch (normalized) {
// Special cases
case 'db':
if (normalized === 'db') {
utparams["2"] = parameters["1"];
utparams['2'] = parameters['1'];
break;
} else if (normalized === 'g6') {
case 'g12':
utparams.key1 = "url"'to';
utparams.value1 = utparams.url = parametersMorebits.urlpageNameNorm;
} else if (normalized === 'g12') {
break;
['url', 'url2', 'url3'].forEach(function(item, idx) {
case 'a10':
if (parameters[item]) {
utparams.key1 = "article";
idx++;
utparams.value1 = utparams.article = parameters.article;
utparams['key' + idx] = item;
break;
utparams['value' + idx] = utparams[item] = parameters[item];
default:
break;}
});
} else {
// Handle the rest
var param;
switch (normalized) {
case 'g4':
param = 'xfd';
break;
case 'a2':
param = 'source';
break;
case 'a5':
param = 'location';
break;
case 'a10':
param = 'article';
break;
case 'f9':
param = 'url';
break;
case 'p1':
param = 'criterion';
break;
default:
break;
}
// No harm in providing a usertalk template with the others' parameters
if (param && parameters[param]) {
utparams.key1 = param;
utparams.value1 = utparams[param] = parameters[param];
}
}
return utparams;
};
 
/**
 
* @param {Event} e
* @returns {Array}
*/
Twinkle.speedy.resolveCsdValues = function twinklespeedyResolveCsdValues(e) {
var values = (e.target.form ? e.target.form : e.target).getChecked('csd');
if (values.length === 0) {
alert( "'Please select a criterion!" ');
return null;
}
 
Twinkle.speedy.callback.evaluateSysop = function twinklespeedyCallbackEvaluateSysop(e) {
var form = (e.target.form ? e.target.form : e.target);
 
if (e.target.type === 'checkbox' || e.target.type === 'text' ||
e.target.type === 'select') {
return;
}
 
var tag_only = form.tag_only;
if ( tag_only && tag_only.checked ) {
Twinkle.speedy.callback.evaluateUser(e);
return;
}
 
var valuevalues = Twinkle.speedy.resolveCsdValues(e)[0];
if (!valuevalues) {
return;
}
var templateParams = Twinkle.speedy.getParameters(form, values);
if (!templateParams) {
return;
}
 
var normalized = Twinkle.speedy.normalizeHash[ value ];
var normalizeds = values.map(function(value) {
return Twinkle.speedy.normalizeHash[value];
});
 
// analyse each criterion to determine whether to watch the page, prompt for summary, or notify the creator
var watchPage, promptForSummary;
normalizeds.forEach(function(norm) {
if (Twinkle.getPref('watchSpeedyPages').indexOf(norm) !== -1) {
watchPage = Twinkle.getPref('watchSpeedyExpiry');
}
if (Twinkle.getPref('promptForSpeedyDeletionSummary').indexOf(norm) !== -1) {
promptForSummary = true;
}
});
 
var warnusertalk = form.warnusertalk.checked && normalizeds.some(function (norm, index) {
return Twinkle.getPref('warnUserOnSpeedyDelete').indexOf(norm) !== -1 &&
!(norm === 'g6' && values[index] !== 'copypaste');
});
 
var welcomeuser = warnusertalk && normalizeds.some(function (norm) {
return Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').indexOf(norm) !== -1;
});
 
var params = {
valuevalues: valuevalues,
normalizeds: normalizeds,
normalized: normalized,
watch: watchPage,
watch: Twinkle.getPref('watchSpeedyPages').indexOf( normalized ) !== -1,
reason: Twinkle.speedy.reasonHash[ value ],
openusertalk: Twinkle.getPref('openUserTalkPageOnSpeedyDelete').indexOf( normalized ) !== -1,
deleteTalkPage: form.talkpage && form.talkpage.checked,
deleteRedirects: form.redirects.checked,
warnUser: warnusertalk,
welcomeuser: welcomeuser,
promptForSummary: promptForSummary,
templateParams: templateParams
};
 
Morebits.simpleWindow.setButtonsEnabled( false );
Morebits.status.init( form );
 
Twinkle.speedy.callbacks.sysop.main( params );
};
 
Twinkle.speedy.callback.evaluateUser = function twinklespeedyCallbackEvaluateUser(e) {
var form = (e.target.form ? e.target.form : e.target);
 
if (e.target.type === "'checkbox"' || e.target.type === "'text"' ||
e.target.type === "'select"') {
return;
}
return;
}
var templateParams = Twinkle.speedy.getParameters(form, values);
//var multiple = form.multiple.checked;
if (!templateParams) {
var normalizeds = [];
return;
$.each(values, function(index, value) {
}
var norm = Twinkle.speedy.normalizeHash[ value ];
 
// var multiple = form.multiple.checked;
normalizeds.push(norm);
 
var normalizeds = values.map(function(value) {
return Twinkle.speedy.normalizeHash[value];
});
 
// analyse each criterion to determine whether to watch the page/notify the creator
var watchPage = false;normalizeds.some(function(norm) {
return Twinkle.getPref('watchSpeedyPages').indexOf(norm) !== -1 && Twinkle.getPref('watchSpeedyExpiry');
$.each(normalizeds, function(index, norm) {
});
if (Twinkle.getPref('watchSpeedyPages').indexOf(norm) !== -1) {
var notifyuser = form.notify.checked && normalizeds.some(function(norm, index) {
watchPage = true;
return Twinkle.getPref('notifyUserOnSpeedyDeletionNomination').indexOf(norm) !== -1 &&
return false; // break
!(norm === 'g6' && values[index] !== 'copypaste');
}
});
var welcomeuser = notifyuser && normalizeds.some(function(norm) {
return Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').indexOf(norm) !== -1;
});
var csdlog = Twinkle.getPref('logSpeedyNominations') && normalizeds.some(function(norm) {
return Twinkle.getPref('noLogOnSpeedyNomination').indexOf(norm) === -1;
});
 
var notifyuser = false;
if (form.notify.checked) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('notifyUserOnSpeedyDeletionNomination').indexOf(norm) !== -1) {
if (norm === 'g6' && ['disambig', 'copypaste'].indexOf(values[index]) === -1) {
return true;
}
notifyuser = true;
return false; // break
}
});
}
 
var welcomeuser = false;
if (notifyuser) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').indexOf(norm) !== -1) {
welcomeuser = true;
return false; // break
}
});
}
 
var csdlog = false;
if (Twinkle.getPref('logSpeedyNominations')) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('noLogOnSpeedyNomination').indexOf(norm) === -1) {
csdlog = true;
return false; // break
}
});
}
 
var params = {
welcomeuser: welcomeuser,
lognomination: csdlog,
requestsalt: form.salting.checked,
templateParams: Twinkle.speedy.getParameters( form, values )
templateParams: templateParams
};
if (!params.templateParams) {
return;
}
 
Morebits.simpleWindow.setButtonsEnabled( false );
Morebits.status.init( form );
 
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = "'Tagging complete"';
 
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "'Tagging page"');
wikipedia_page.setChangeTags(Twinkle.changeTags); // Here to apply to triage
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.speedy.callbacks.user.main);
};
 
Twinkle.addInitCallback(Twinkle.speedy, 'speedy');
})(jQuery);
 
 
// </nowiki>
10,498

தொகுப்புகள்

"https://ta.wikipedia.org/wiki/சிறப்பு:MobileDiff/3108508" இருந்து மீள்விக்கப்பட்டது