User:逆襲的天邪鬼/Twinkle-lzh/twinklespeedy.js: Difference between revisions

From TestWiki
Content added Content deleted
(Created page with "//<nowiki> // vim: set noet sts=0 sw=8: (function($){ /* **************************************** *** twinklespeedy.js: CSD module *************************************...")
 
m (via Wikiplus)
Line 22: Line 22:


Twinkle.speedy = function twinklespeedy() {
Twinkle.speedy = function twinklespeedy() {
// Disable on:
// Disable on:
// * special pages
// * special pages
// * Flow pages
// * Flow pages
// * non-existent pages
// * non-existent pages
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgPageContentModel') === 'flow-board' || !mw.config.get('wgArticleId')) {
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgPageContentModel') === 'flow-board' || !mw.config.get('wgArticleId')) {
return;
return;
}
}


Twinkle.addPortletLink( Twinkle.speedy.callback, "速", "tw-csd", Morebits.userIsInGroup('sysop') ? "快速删除" : "请求快删除" );
Twinkle.addPortletLink( Twinkle.speedy.callback, "速", "tw-csd", "速" );
};
};


// This function is run when the CSD tab/header link is clicked
// This function is run when the CSD tab/header link is clicked
Twinkle.speedy.callback = function twinklespeedyCallback() {
Twinkle.speedy.callback = function twinklespeedyCallback() {
Twinkle.speedy.initDialog(Morebits.userIsInGroup( 'sysop' ) ? Twinkle.speedy.callback.evaluateSysop : Twinkle.speedy.callback.evaluateUser, true);
Twinkle.speedy.initDialog(Morebits.userIsInGroup( 'sysop' ) ? Twinkle.speedy.callback.evaluateSysop : Twinkle.speedy.callback.evaluateUser, true);
};
};


Line 43: Line 43:
// The speedy criteria list can be in one of several modes
// The speedy criteria list can be in one of several modes
Twinkle.speedy.mode = {
Twinkle.speedy.mode = {
sysopSingleSubmit: 1, // radio buttons, no subgroups, submit when "Submit" button is clicked
sysopSingleSubmit: 1, // radio buttons, no subgroups, submit when "Submit" button is clicked
sysopRadioClick: 2, // radio buttons, no subgroups, submit when a radio button is clicked
sysopRadioClick: 2, // radio buttons, no subgroups, submit when a radio button is clicked
sysopMultipleSubmit: 3, // check boxes, subgroups, "Submit" button already present
sysopMultipleSubmit: 3, // check boxes, subgroups, "Submit" button already present
sysopMultipleRadioClick: 4, // check boxes, subgroups, need to add a "Submit" button
sysopMultipleRadioClick: 4, // check boxes, subgroups, need to add a "Submit" button
userMultipleSubmit: 5, // check boxes, subgroups, "Submit" button already pressent
userMultipleSubmit: 5, // check boxes, subgroups, "Submit" button already pressent
userMultipleRadioClick: 6, // check boxes, subgroups, need to add a "Submit" button
userMultipleRadioClick: 6, // check boxes, subgroups, need to add a "Submit" button
userSingleSubmit: 7, // radio buttons, subgroups, submit when "Submit" button is clicked
userSingleSubmit: 7, // radio buttons, subgroups, submit when "Submit" button is clicked
userSingleRadioClick: 8, // radio buttons, subgroups, submit when a radio button is clicked
userSingleRadioClick: 8, // radio buttons, subgroups, submit when a radio button is clicked


// are we in "delete page" mode?
// are we in "delete page" mode?
// (sysops can access both "delete page" [sysop] and "tag page only" [user] modes)
// (sysops can access both "delete page" [sysop] and "tag page only" [user] modes)
isSysop: function twinklespeedyModeIsSysop(mode) {
isSysop: function twinklespeedyModeIsSysop(mode) {
return mode === Twinkle.speedy.mode.sysopSingleSubmit ||
return mode === Twinkle.speedy.mode.sysopSingleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopRadioClick ||
mode === Twinkle.speedy.mode.sysopRadioClick ||
mode === Twinkle.speedy.mode.sysopMultipleRadioClick;
mode === Twinkle.speedy.mode.sysopMultipleRadioClick;
},
},
// do we have a "Submit" button once the form is created?
// do we have a "Submit" button once the form is created?
hasSubmitButton: function twinklespeedyModeHasSubmitButton(mode) {
hasSubmitButton: function twinklespeedyModeHasSubmitButton(mode) {
return mode === Twinkle.speedy.mode.sysopSingleSubmit ||
return mode === Twinkle.speedy.mode.sysopSingleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleRadioClick ||
mode === Twinkle.speedy.mode.sysopMultipleRadioClick ||
mode === Twinkle.speedy.mode.userMultipleSubmit ||
mode === Twinkle.speedy.mode.userMultipleSubmit ||
mode === Twinkle.speedy.mode.userMultipleRadioClick ||
mode === Twinkle.speedy.mode.userMultipleRadioClick ||
mode === Twinkle.speedy.mode.userSingleSubmit;
mode === Twinkle.speedy.mode.userSingleSubmit;
},
},
// is db-multiple the outcome here?
// is db-multiple the outcome here?
isMultiple: function twinklespeedyModeIsMultiple(mode) {
isMultiple: function twinklespeedyModeIsMultiple(mode) {
return mode === Twinkle.speedy.mode.userMultipleSubmit ||
return mode === Twinkle.speedy.mode.userMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.userMultipleRadioClick ||
mode === Twinkle.speedy.mode.userMultipleRadioClick ||
mode === Twinkle.speedy.mode.sysopMultipleRadioClick;
mode === Twinkle.speedy.mode.sysopMultipleRadioClick;
},
},
};
};


// Prepares the speedy deletion dialog and displays it
// Prepares the speedy deletion dialog and displays it
Twinkle.speedy.initDialog = function twinklespeedyInitDialog(callbackfunc) {
Twinkle.speedy.initDialog = function twinklespeedyInitDialog(callbackfunc) {
var dialog;
var dialog;
Twinkle.speedy.dialog = new Morebits.simpleWindow( Twinkle.getPref('speedyWindowWidth'), Twinkle.getPref('speedyWindowHeight') );
Twinkle.speedy.dialog = new Morebits.simpleWindow( Twinkle.getPref('speedyWindowWidth'), Twinkle.getPref('speedyWindowHeight') );
dialog = Twinkle.speedy.dialog;
dialog = Twinkle.speedy.dialog;
dialog.setTitle( "选择快删除理由" );
dialog.setTitle( "選擇理由" );
dialog.setScriptName( "Twinkle" );
dialog.setScriptName( "Twinkle" );
dialog.addFooterLink( "快速删除方针", "WP:CSD" );
// dialog.addFooterLink( "快速删除方针", "WP:CSD" );
dialog.addFooterLink( "Twinkle帮助", "WP:TW/DOC#speedy" );
// dialog.addFooterLink( "Twinkle帮助", "WP:TW/DOC#speedy" );


var form = new Morebits.quickForm( callbackfunc, (Twinkle.getPref('speedySelectionStyle') === 'radioClick' ? 'change' : null) );
var form = new Morebits.quickForm( callbackfunc, (Twinkle.getPref('speedySelectionStyle') === 'radioClick' ? 'change' : null) );
if( Morebits.userIsInGroup( 'sysop' ) ) {
if( Morebits.userIsInGroup( 'sysop' ) ) {
form.append( {
form.append( {
type: 'checkbox',
type: 'checkbox',
list: [
list: [
{
{
label: '只标记,不除',
label: '只標記,不除',
value: 'tag_only',
value: 'tag_only',
name: 'tag_only',
name: 'tag_only',
tooltip: '如果您只想标记面而不是',
tooltip: '如果您只想標記面而不是除',
checked : Twinkle.getPref('deleteSysopDefaultToTag'),
checked : Twinkle.getPref('deleteSysopDefaultToTag'),
event: function( event ) {
event: function( event ) {
var cForm = event.target.form;
var cForm = event.target.form;
var cChecked = event.target.checked;
var cChecked = event.target.checked;
// enable/disable talk page checkbox
// enable/disable talk page checkbox
if (cForm.talkpage) {
if (cForm.talkpage) {
cForm.talkpage.disabled = cChecked;
cForm.talkpage.disabled = cChecked;
cForm.talkpage.checked = !cChecked && Twinkle.getPref('deleteTalkPageOnDelete');
cForm.talkpage.checked = !cChecked && Twinkle.getPref('deleteTalkPageOnDelete');
}
}
// enable/disable redirects checkbox
// enable/disable redirects checkbox
cForm.redirects.disabled = cChecked;
cForm.redirects.disabled = cChecked;
cForm.redirects.checked = !cChecked;
cForm.redirects.checked = !cChecked;
// enable/disable delete multiple
// enable/disable delete multiple
cForm.delmultiple.disabled = cChecked;
cForm.delmultiple.disabled = cChecked;
cForm.delmultiple.checked = false;
cForm.delmultiple.checked = false;
// enable/disable open talk page checkbox
// enable/disable open talk page checkbox
cForm.openusertalk.disabled = cChecked;
cForm.openusertalk.disabled = cChecked;
cForm.openusertalk.checked = false;
cForm.openusertalk.checked = false;


// enable/disable notify checkbox
// enable/disable notify checkbox
cForm.notify.disabled = !cChecked;
// cForm.notify.disabled = !cChecked;
cForm.notify.checked = cChecked;
// cForm.notify.checked = cChecked;
// enable/disable multiple
// enable/disable multiple
cForm.multiple.disabled = !cChecked;
cForm.multiple.disabled = !cChecked;
cForm.multiple.checked = false;
cForm.multiple.checked = false;


Twinkle.speedy.callback.modeChanged(cForm);
Twinkle.speedy.callback.modeChanged(cForm);


event.stopPropagation();
event.stopPropagation();
}
}
}
}
]
]
} );
} );


var deleteOptions = form.append( {
var deleteOptions = form.append( {
type: 'div',
type: 'div',
name: 'delete_options'
name: 'delete_options'
} );
} );
deleteOptions.append( {
deleteOptions.append( {
type: 'header',
type: 'header',
label: '除相关选项'
label: '除相關設定'
} );
} );
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
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
deleteOptions.append( {
deleteOptions.append( {
type: 'checkbox',
type: 'checkbox',
list: [
list: [
{
{
label: '讨论页',
label: '討論頁',
value: 'talkpage',
value: 'talkpage',
name: 'talkpage',
name: 'talkpage',
tooltip: "带删除此面的讨论页。",
tooltip: "帶刪除此面的討論頁。",
checked: Twinkle.getPref('deleteTalkPageOnDelete'),
checked: Twinkle.getPref('deleteTalkPageOnDelete'),
disabled: Twinkle.getPref('deleteSysopDefaultToTag'),
disabled: Twinkle.getPref('deleteSysopDefaultToTag'),
event: function( event ) {
event: function( event ) {
event.stopPropagation();
event.stopPropagation();
}
}
}
}
]
]
} );
} );
}
}
deleteOptions.append( {
deleteOptions.append( {
type: 'checkbox',
type: 'checkbox',
list: [
list: [
{
{
label: '除重定向',
label: '除重定向',
value: 'redirects',
value: 'redirects',
name: 'redirects',
name: 'redirects',
tooltip: "除到此的重定向。",
tooltip: "除到此的重定向。",
checked: Twinkle.getPref('deleteRedirectsOnDelete'),
checked: Twinkle.getPref('deleteRedirectsOnDelete'),
disabled: Twinkle.getPref('deleteSysopDefaultToTag'),
disabled: Twinkle.getPref('deleteSysopDefaultToTag'),
event: function( event ) {
event: function( event ) {
event.stopPropagation();
event.stopPropagation();
}
}
}
}
]
]
} );
} );
deleteOptions.append( {
deleteOptions.append( {
type: 'checkbox',
type: 'checkbox',
list: [
list: [
{
{
label: '用多理由除',
label: '用多理由除',
value: 'delmultiple',
value: 'delmultiple',
name: 'delmultiple',
name: 'delmultiple',
tooltip: "您可选择应于该页的多个理由。",
tooltip: "您可選擇應於該頁的多个理由。",
event: function( event ) {
event: function( event ) {
Twinkle.speedy.callback.modeChanged( event.target.form );
Twinkle.speedy.callback.modeChanged( event.target.form );
event.stopPropagation();
event.stopPropagation();
}
}
}
}
]
]
} );
} );
deleteOptions.append( {
deleteOptions.append( {
type: 'checkbox',
type: 'checkbox',
list: [
list: [
{
{
label: '开启户对话页',
label: '開啟戶對話頁',
value: 'openusertalk',
value: 'openusertalk',
name: 'openusertalk',
name: 'openusertalk',
tooltip: '此默认您的开启对话页设置。在您选择应用多理由项将保持不。',
tooltip: '此預設為開啟您的對話頁設定。在您選擇應用多理由項將保持不。',
checked : false
checked : false
}
}
]
]
} );
} );
}
}


var tagOptions = form.append( {
var tagOptions = form.append( {
type: 'div',
type: 'div',
name: 'tag_options'
name: 'tag_options'
} );
} );


if( Morebits.userIsInGroup( 'sysop' ) ) {
if( Morebits.userIsInGroup( 'sysop' ) ) {
tagOptions.append( {
tagOptions.append( {
type: 'header',
type: 'header',
label: '标记关选项'
label: '標記關設定'
} );
} );
}
}


/*
tagOptions.append( {
tagOptions.append( {
type: 'checkbox',
type: 'checkbox',
list: [
list: [
{
{
label: '如可能,通知创建者',
label: '如可能,通知建立者',
value: 'notify',
name: 'notify',
value: 'notify',
name: 'notify',
tooltip: "一个通知模板将会被加入创建者的对话页,如果您启用了该理据的通知。",
tooltip: "如果開啟,提請刪除時將會在建立者的對話頁加入一个通知模板。",
checked: !Morebits.userIsInGroup( 'sysop' ) || Twinkle.getPref('deleteSysopDefaultToTag'),
disabled: Morebits.userIsInGroup( 'sysop' ) && !Twinkle.getPref('deleteSysopDefaultToTag'),
checked: !Morebits.userIsInGroup( 'sysop' ) || Twinkle.getPref('deleteSysopDefaultToTag'),
disabled: Morebits.userIsInGroup( 'sysop' ) && !Twinkle.getPref('deleteSysopDefaultToTag'),
event: function( event ) {
event: function( event ) {
event.stopPropagation();
event.stopPropagation();
}
}
}
}
]
]
} );
} );
tagOptions.append( {
*/
type: 'checkbox',
tagOptions.append( {
list: [
type: 'checkbox',
{
list: [
label: '应用多个理由',
{
value: 'multiple',
label: '應用多个理由',
name: 'multiple',
value: 'multiple',
tooltip: "您可选择应用于该页的多个理由。",
name: 'multiple',
disabled: Morebits.userIsInGroup( 'sysop' ) && !Twinkle.getPref('deleteSysopDefaultToTag'),
tooltip: "您可選擇應用於該頁的多個理由。",
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 );
}
event.stopPropagation();
}
}
]
}
} );
]
} );


form.append( {
form.append( {
type: 'div',
type: 'div',
name: 'work_area',
name: 'work_area',
label: '初始化CSD模块失败,请重试,或将这报告给Twinkle开发者。'
label: '初始化CSD模块失败,请重试,或将这报告给Twinkle开发者。'
} );
} );


if( Twinkle.getPref( 'speedySelectionStyle' ) !== 'radioClick' ) {
if( Twinkle.getPref( 'speedySelectionStyle' ) !== 'radioClick' ) {
form.append( { type: 'submit' } );
form.append( { type: 'submit' } );
}
}


var result = form.render();
var result = form.render();
dialog.setContent( result );
dialog.setContent( result );
dialog.display();
dialog.display();


Twinkle.speedy.callback.modeChanged( result );
Twinkle.speedy.callback.modeChanged( result );


// if sysop, check if CSD is already on the page and fill in custom rationale
// if sysop, check if CSD is already on the page and fill in custom rationale
if (Morebits.userIsInGroup('sysop') && $("#delete-reason").length) {
if (Morebits.userIsInGroup('sysop') && $("#delete-reason").length) {
var customOption = $("input[name=csd][value=reason]")[0];
var customOption = $("input[name=csd][value=reason]")[0];


if (Twinkle.getPref('speedySelectionStyle') !== 'radioClick') {
if (Twinkle.getPref('speedySelectionStyle') !== 'radioClick') {
// force listeners to re-init
// force listeners to re-init
customOption.click();
customOption.click();
customOption.parentNode.appendChild(customOption.subgroup);
customOption.parentNode.appendChild(customOption.subgroup);
}
}


customOption.subgroup.querySelector('input').value = decodeURIComponent($("#delete-reason").text()).replace(/\+/g, ' ');
customOption.subgroup.querySelector('input').value = decodeURIComponent($("#delete-reason").text()).replace(/\+/g, ' ');
}
}
};
};


Twinkle.speedy.callback.getMode = function twinklespeedyCallbackGetMode(form) {
Twinkle.speedy.callback.getMode = function twinklespeedyCallbackGetMode(form) {
var mode = Twinkle.speedy.mode.userSingleSubmit;
var mode = Twinkle.speedy.mode.userSingleSubmit;
if (form.tag_only && !form.tag_only.checked) {
if (form.tag_only && !form.tag_only.checked) {
if (form.delmultiple.checked) {
if (form.delmultiple.checked) {
mode = Twinkle.speedy.mode.sysopMultipleSubmit;
mode = Twinkle.speedy.mode.sysopMultipleSubmit;
} else {
} else {
mode = Twinkle.speedy.mode.sysopSingleSubmit;
mode = Twinkle.speedy.mode.sysopSingleSubmit;
}
}
} else {
} else {
if (form.multiple.checked) {
if (form.multiple.checked) {
mode = Twinkle.speedy.mode.userMultipleSubmit;
mode = Twinkle.speedy.mode.userMultipleSubmit;
} else {
} else {
mode = Twinkle.speedy.mode.userSingleSubmit;
mode = Twinkle.speedy.mode.userSingleSubmit;
}
}
}
}
if (Twinkle.getPref('speedySelectionStyle') === 'radioClick') {
if (Twinkle.getPref('speedySelectionStyle') === 'radioClick') {
mode++;
mode++;
}
}


return mode;
return mode;
};
};


Twinkle.speedy.callback.modeChanged = function twinklespeedyCallbackModeChanged(form) {
Twinkle.speedy.callback.modeChanged = function twinklespeedyCallbackModeChanged(form) {
var namespace = mw.config.get('wgNamespaceNumber');
var namespace = mw.config.get('wgNamespaceNumber');


// first figure out what mode we're in
// first figure out what mode we're in
var mode = Twinkle.speedy.callback.getMode(form);
var mode = Twinkle.speedy.callback.getMode(form);


if (Twinkle.speedy.mode.isSysop(mode)) {
if (Twinkle.speedy.mode.isSysop(mode)) {
$("[name=delete_options]").show();
$("[name=delete_options]").show();
$("[name=tag_options]").hide();
$("[name=tag_options]").hide();
} else {
} else {
$("[name=delete_options]").hide();
$("[name=delete_options]").hide();
$("[name=tag_options]").show();
$("[name=tag_options]").show();
}
}


var work_area = new Morebits.quickForm.element( {
var work_area = new Morebits.quickForm.element( {
type: 'div',
type: 'div',
name: 'work_area'
name: 'work_area'
} );
} );


if (mode === Twinkle.speedy.mode.userMultipleRadioClick || mode === Twinkle.speedy.mode.sysopMultipleRadioClick) {
if (mode === Twinkle.speedy.mode.userMultipleRadioClick || mode === Twinkle.speedy.mode.sysopMultipleRadioClick) {
var evaluateType = Twinkle.speedy.mode.isSysop(mode) ? 'evaluateSysop' : 'evaluateUser';
var evaluateType = Twinkle.speedy.mode.isSysop(mode) ? 'evaluateSysop' : 'evaluateUser';


work_area.append( {
work_area.append( {
type: 'div',
type: 'div',
label: '当选择完成点击:'
label: '當選擇完成點選:'
} );
} );
work_area.append( {
work_area.append( {
type: 'button',
type: 'button',
name: 'submit-multiple',
name: 'submit-multiple',
label: '提交',
label: '提交',
event: function( event ) {
event: function( event ) {
Twinkle.speedy.callback[evaluateType]( event );
Twinkle.speedy.callback[evaluateType]( event );
event.stopPropagation();
event.stopPropagation();
}
}
} );
} );
}
}


var radioOrCheckbox = (Twinkle.speedy.mode.isMultiple(mode) ? 'checkbox' : 'radio');
var radioOrCheckbox = (Twinkle.speedy.mode.isMultiple(mode) ? 'checkbox' : 'radio');


if (Twinkle.speedy.mode.isSysop(mode) && !Twinkle.speedy.mode.isMultiple(mode)) {
if (Twinkle.speedy.mode.isSysop(mode) && !Twinkle.speedy.mode.isMultiple(mode)) {
work_area.append( { type: 'header', label: '自定义理由' } );
work_area.append( { type: 'header', label: '自理由' } );
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.customRationale, mode) } );
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.customRationale, mode) } );
}
}


switch (namespace) {
switch (namespace) {
case 0: // article
case 0: // article
work_area.append( { type: 'header', label: '目' } );
work_area.append( { type: 'header', label: '目' } );
work_area.append( { type: radioOrCheckbox, name: 'csd', 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 14: // category
work_area.append( { type: 'header', label: '分類' } );
case 3: // user talk
work_area.append( { type: 'header', label: '用户页' } );
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.categoryList, mode) } );
break;
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.userList, mode) } );
break;


default:
case 6: // file
break;
work_area.append( { type: 'header', label: '文件' } );
}
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: '标记CSD F3、F4,请使用Twinkle的“图权”功能。' } );
}
break;


// custom rationale lives under general criteria when tagging
case 14: // category
var generalCriteria = Twinkle.speedy.generalList;
work_area.append( { type: 'header', label: '分类' } );
if(!Twinkle.speedy.mode.isSysop(mode)) {
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.categoryList, mode) } );
generalCriteria = Twinkle.speedy.customRationale.concat(generalCriteria);
break;
}
work_area.append( { type: 'header', label: '常規' } );
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(generalCriteria, mode) });


if (mw.config.get('wgIsRedirect') || Morebits.userIsInGroup('sysop')) {
default:
work_area.append( { type: 'header', label: '重定向' } );
break;
if (namespace === 0 || namespace === 118) {
}
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.redirectArticleList, mode) } );
}
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.redirectList, mode) } );
}


var old_area = Morebits.quickForm.getElements(form, "work_area")[0];
// custom rationale lives under general criteria when tagging
form.replaceChild(work_area.render(), old_area);
var generalCriteria = Twinkle.speedy.generalList;
if(!Twinkle.speedy.mode.isSysop(mode)) {
generalCriteria = Twinkle.speedy.customRationale.concat(generalCriteria);
}
work_area.append( { type: 'header', label: '常规' } );
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(generalCriteria, mode) });
if (!Twinkle.speedy.mode.isSysop(mode)) {
work_area.append( { type: 'div', label: '标记CSD G16,请使用Twinkle的“侵权”功能。' } );
}

if (mw.config.get('wgIsRedirect') || Morebits.userIsInGroup('sysop')) {
work_area.append( { type: 'header', label: '重定向' } );
if (namespace === 0 || namespace === 118) {
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.redirectArticleList, mode) } );
}
work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.redirectList, mode) } );
}

var old_area = Morebits.quickForm.getElements(form, "work_area")[0];
form.replaceChild(work_area.render(), old_area);
};
};


Twinkle.speedy.generateCsdList = function twinklespeedyGenerateCsdList(list, mode) {
Twinkle.speedy.generateCsdList = function twinklespeedyGenerateCsdList(list, mode) {
// mode switches
// mode switches
var isSysop = Twinkle.speedy.mode.isSysop(mode);
var isSysop = Twinkle.speedy.mode.isSysop(mode);
var multiple = Twinkle.speedy.mode.isMultiple(mode);
var multiple = Twinkle.speedy.mode.isMultiple(mode);
var hasSubmitButton = Twinkle.speedy.mode.hasSubmitButton(mode);
var hasSubmitButton = Twinkle.speedy.mode.hasSubmitButton(mode);


var openSubgroupHandler = function(e) {
var openSubgroupHandler = function(e) {
$(e.target.form).find('input').prop('disabled', true);
$(e.target.form).find('input').prop('disabled', true);
$(e.target.form).children().css('color', 'gray');
$(e.target.form).children().css('color', 'gray');
$(e.target).parent().css('color', 'black').find('input').prop('disabled', false);
$(e.target).parent().css('color', 'black').find('input').prop('disabled', false);
$(e.target).parent().find('input:text')[0].focus();
$(e.target).parent().find('input:text')[0].focus();
e.stopPropagation();
e.stopPropagation();
};
};
var submitSubgroupHandler = function(e) {
var submitSubgroupHandler = function(e) {
var evaluateType = Twinkle.speedy.mode.isSysop(mode) ? 'evaluateSysop' : 'evaluateUser';
var evaluateType = Twinkle.speedy.mode.isSysop(mode) ? 'evaluateSysop' : 'evaluateUser';
Twinkle.speedy.callback[evaluateType](e);
Twinkle.speedy.callback[evaluateType](e);
e.stopPropagation();
e.stopPropagation();
};
};


return $.map(list, function(critElement) {
return $.map(list, function(critElement) {
var criterion = $.extend({}, critElement);
var criterion = $.extend({}, critElement);


if (multiple) {
// hack to get the g11 radio / checkbox right
if (criterion.value === 'g11') {
if (criterion.hideWhenMultiple) {
return null;
criterion.style = Twinkle.getPref('enlargeG11Input') ? 'height: 2em; width: 2em; height: -moz-initial; width: -moz-initial; -moz-transform: scale(2); -o-transform: scale(2);' : '';
}
}
if (criterion.hideSubgroupWhenMultiple) {
criterion.subgroup = null;
}
} else {
if (criterion.hideWhenSingle) {
return null;
}
if (criterion.hideSubgroupWhenSingle) {
criterion.subgroup = null;
}
}


if (multiple) {
if (isSysop) {
if (criterion.hideWhenMultiple) {
if (criterion.hideWhenSysop) {
return null;
return null;
}
}
if (criterion.hideSubgroupWhenMultiple) {
if (criterion.hideSubgroupWhenSysop) {
criterion.subgroup = null;
criterion.subgroup = null;
}
}
} else {
} else {
if (criterion.hideWhenSingle) {
if (criterion.hideWhenUser) {
return null;
return null;
}
}
if (criterion.hideSubgroupWhenSingle) {
if (criterion.hideSubgroupWhenUser) {
criterion.subgroup = null;
criterion.subgroup = null;
}
}
}
}


if (mw.config.get('wgIsRedirect') && criterion.hideWhenRedirect) {
if (isSysop) {
return null;
if (criterion.hideWhenSysop) {
}
return null;
}
if (criterion.hideSubgroupWhenSysop) {
criterion.subgroup = null;
}
} else {
if (criterion.hideWhenUser) {
return null;
}
if (criterion.hideSubgroupWhenUser) {
criterion.subgroup = null;
}
}


if (criterion.subgroup && !hasSubmitButton) {
if (mw.config.get('wgIsRedirect') && criterion.hideWhenRedirect) {
if ($.isArray(criterion.subgroup)) {
return null;
criterion.subgroup.push({
}
type: 'button',
name: 'submit',
label: '提交',
event: submitSubgroupHandler
});
} else {
criterion.subgroup = [
criterion.subgroup,
{
type: 'button',
name: 'submit', // ends up being called "csd.submit" so this is OK
label: '提交',
event: submitSubgroupHandler
}
];
}
// FIXME: does this do anything?
criterion.event = openSubgroupHandler;
}


if ( isSysop ) {
if (criterion.subgroup && !hasSubmitButton) {
var originalEvent = criterion.event;
if ($.isArray(criterion.subgroup)) {
criterion.subgroup.push({
criterion.event = function(e) {
if (multiple) return originalEvent(e);
type: 'button',
name: 'submit',
label: '提交',
event: submitSubgroupHandler
});
} else {
criterion.subgroup = [
criterion.subgroup,
{
type: 'button',
name: 'submit', // ends up being called "csd.submit" so this is OK
label: '提交',
event: submitSubgroupHandler
}
];
}
// FIXME: does this do anything?
criterion.event = openSubgroupHandler;
}


var normalizedCriterion = Twinkle.speedy.normalizeHash[e.target.value];
if ( isSysop ) {
$('[name=openusertalk]').prop('checked',
var originalEvent = criterion.event;
Twinkle.getPref('openUserTalkPageOnSpeedyDelete').indexOf(normalizedCriterion) !== -1
criterion.event = function(e) {
);
if (multiple) return originalEvent(e);
if ( originalEvent ) {
return originalEvent(e);
}
};
}


return criterion;
var normalizedCriterion = Twinkle.speedy.normalizeHash[e.target.value];
});
$('[name=openusertalk]').prop('checked',
Twinkle.getPref('openUserTalkPageOnSpeedyDelete').indexOf(normalizedCriterion) !== -1
);
if ( originalEvent ) {
return originalEvent(e);
}
};
}

return criterion;
});
};
};


Twinkle.speedy.customRationale = [
Twinkle.speedy.customRationale = [
{
{
label: '自定义理由' + (Morebits.userIsInGroup('sysop') ? '(自定义删除理由)' : ''),
label: '自理由' + (Morebits.userIsInGroup('sysop') ? '(自訂刪除理由)' : ''),
value: 'reason',
value: 'reason',
tooltip: '該頁應明顯不適合維基大典。如有疑問,請使用「議刪」而非「速刪」。',
tooltip: '该页至少应该符合一条快速删除的标准,并且您必须在理由中提到。这不是万能的删除理由。',
subgroup: {
subgroup: {
name: 'reason_1',
name: 'reason_1',
type: 'input',
type: 'input',
label: '理由:',
label: '理由:',
size: 60
size: 60
},
},
hideWhenMultiple: true
hideWhenMultiple: true
}
}
];

Twinkle.speedy.fileList = [
{
label: 'F1: 重复的档案(完全相同或缩小),而且不再被条目使用',
value: 'f1',
subgroup: {
name: 'f1_filename',
type: 'input',
label: '与此文件相同的文件名:',
tooltip: '可不含“File:”前缀。'
}
},
{
label: 'F3: 所有未知版权的档案和来源不明档案',
value: 'f3',
hideWhenUser: true
},
{
label: 'F4: 没有提供版权状况、来源等资讯的档案',
value: 'f4',
hideWhenUser: true
},
{
label: 'F5: 被高分辨率或SVG档案取代的图片',
value: 'f5',
subgroup: {
name: 'f5_filename',
type: 'input',
label: '新文件名:',
tooltip: '可不含“File:”前缀。'
}
},
{
label: 'F6: 没有被条目使用的非自由版权档案',
value: 'f6',
},
{
label: 'F7: 与维基共享资源档案重复的档案',
value: 'f7',
subgroup: {
name: 'f7_filename',
type: 'input',
label: '维基共享资源上的文件名:',
value: Morebits.pageNameNorm,
tooltip: '如与本文件名相同则可留空,可不含“File:”前缀。'
},
hideWhenMultiple: true
}
];
];


Twinkle.speedy.articleList = [
Twinkle.speedy.articleList = [
{
{
label: 'A1: 非常,而没有定义或内容。',
label: '短且不知所云',
value: 'a1',
value: '極短且不知所云',
},
tooltip: '例如:“他是一个很有趣的人,他创建了工厂和庄园。并且,顺便提一下,他的妻子也很好。”如果能够发现任何相关的内容,可以将这个页面重定向到相关的条目上。'
{
},
label: '生不立傳',
{
value: '生不立傳',
label: 'A2: 内容只包括外部连接、参见、图书参考、类别标签、模板标签、跨语言连接的条目。',
},
value: 'a2',
{
tooltip: '请注意:有些维基人创建条目时会分开多次保存,请避免删除有人正在工作的页面。带有{{inuse}}的不适用。'
label: '非文言',
},
value: '非文言'
{
},
label: 'A3: 复制自其他中文维基计划,或是与其他中文维基计划内容相同的文章。',
value: 'a3'
},
{
label: 'A5: 条目建立时之内容即与其他现有条目内容完全相同,且名称不适合做为其他条目之重定向。',
value: 'a5',
tooltip: '条目被建立时,第一个版本的内容与当时其他现存条目完全相同,且这个条目的名称不适合改为重定向,就可以提送快速删除。如果名称可以作为重定向,就应直接改重定向,不要提送快速删除。如果是多个条目合并产生的新条目,不适用。如果是从主条目拆分产生的条目,不适用;如有疑虑,应提送存废讨论处理。',
subgroup: {
name: 'a5_pagename',
type: 'input',
label: '现有条目名:',
size: 60
}
},
{
label: 'A6: 复制自其他维基百科语言版本,且完全没有翻译。',
value: 'a6',
tooltip: '如果并不是复制于任何其他的维基百科语言版本,请换用{{notmandarin}}。带有{{inuse}}和{{translating}}模板的不适用。'
}
];
];


Twinkle.speedy.categoryList = [
Twinkle.speedy.categoryList = [
{
{
label: '空類',
label: 'O4: 空的类别(没有条目也没有子类别)。',
value: 'o4',
value: '空類',
tooltip: '不于Category:不要删除的分类中空分类。'
tooltip: '不於維護性質類別。'
}
}
];

Twinkle.speedy.userList = [
{
label: 'O1: 用户请求删除自己的用户页或其子页面。',
value: 'o1',
tooltip: '如果是从其他名字空间移动来的,须附有合理原因。'
},
{
label: 'O3: 匿名用户的用户讨论页,其中的内容不再有用。',
value: 'o3',
tooltip: '避免给使用同一IP地址的用户带来混淆。不适用于用户讨论页的存盘页面。'
}
];
];


Twinkle.speedy.generalList = [
Twinkle.speedy.generalList = [
{
{
label: 'G1: 没有实际内容的页面',
label: '作者請求',
value: 'g1',
value: '作者請求',
tooltip: '僅在頁面沒有其他作者(或者只有提刪者本人有實質編輯)的情況下適用。'
tooltip: '如“adfasddd”。参见Wikipedia:胡言乱语。但注意:图片也算是内容。'
},
},
{
{
label: 'G2: 测试页面',
label: '毀我大典',
value: 'g2',
value: '毀我大典',
},
tooltip: '例如:“这是一个测试。”'
{
},
label: '廣告宣傳',
{
value: '廣告宣傳',
label: 'G3: 纯粹破坏,包括但不限于明显的恶作剧、错误信息、人身攻击等',
},
value: 'g3',
{
tooltip: '包括明显的错误信息、明显的恶作剧、信息明显错误的图片,以及清理移动破坏时留下的重定向。'
label: 'G8: 管理员因技术原因删除页面',
},
value: 'g8',
{
tooltip: '包括解封用户后删除用户页、因用户夺取而删除、删除MediaWiki页面、因移动请求而删除页面。',
label: 'G5: 曾经根据页面存废讨论、侵权审核或文件存废讨论结果删除后又重新创建的内容,而有关内容与已删除版本相同或非常相似,无论标题是否相同',
hideWhenUser: true
value: 'g5',
},
tooltip: '该内容之前必须是经存废讨论删除,如之前属于快速删除,请以相同理由重新提送快速删除。该内容如与被删除的版本明显不同,而提删者认为需要删除,请交到存废讨论,如果提删者对此不肯定,请先联络上次执行删除的管理人员。不适用于根据存废复核结果被恢复的内容。在某些情况下,重新创建的条目有机会发展。那么不应提交快速删除,而应该提交存废复核或存废讨论重新评核。',
{
subgroup: {
label: 'G10: 原作者清空页面或提出删除,且贡献者只有一人',
name: 'g5_1',
type: 'input',
value: 'g10',
tooltip: '对条目内容无实际修改的除外;提请须出于善意,及附有合理原因。',
label: '删除讨论位置:',
subgroup: {
tooltip: '必须以“Wikipedia:”开头',
name: 'g10_rationale',
size: 60
type: 'input',
},
label: '可选的解释:',
hideSubgroupWhenMultiple: true
tooltip: '比如作者在哪里请求了删除。',
},
size: 60
{
},
label: 'G8: 管理员因技术原因删除页面',
hideSubgroupWhenSysop: true
value: 'g8',
},
tooltip: '包括解封用户后删除用户页、因用户夺取而删除、删除MediaWiki页面、因移动请求而删除页面。',
{
hideWhenUser: true
label: 'G11: 明显的广告宣传页面,或只有相关人物或团体的联系方法的页面',
},
value: 'g11',
{
tooltip: '页面只收宣传之用,并须完全重写才能贴合百科全书要求。须注意,仅仅以某公司或产品为主题的条目,并不直接导致其自然满足此速删标准。'
label: 'G10: 原作者清空页面或提出删除,且贡献者只有一人',
},
value: 'g10',
{
tooltip: '对条目内容无实际修改的除外;提请须出于善意,及附有合理原因。',
label: 'G12: 未列明来源且语调负面的生者传记',
subgroup: {
value: 'g12',
name: 'g10_rationale',
tooltip: '注意是未列明来源且语调负面,必须2项均符合。'
type: 'input',
},
label: '可选的解释:',
{
tooltip: '比如作者在哪里请求了删除。',
label: 'G13: 明显、拙劣的机器翻译',
size: 60
value: 'g13'
},
},
hideSubgroupWhenSysop: true
{
},
label: 'G14: 超过两周没有进行任何翻译的非现代标准汉语页面',
{
value: 'g14',
label: 'G11: 明显的广告宣传页面,或只有相关人物或团体的联系方法的页面',
tooltip: '包括所有未翻译的外语、汉语方言以及文言文。',
value: 'g11',
hideWhenUser: true
tooltip: '页面只收宣传之用,并须完全重写才能贴合百科全书要求。须注意,仅仅以某公司或产品为主题的条目,并不直接导致其自然满足此速删标准。'
},
},
{
{
label: 'G15: 孤立页面,比如没有主页面的讨论页、指向空页面的重定向等',
label: 'G12: 未列明来源且语调负面的生者传记',
value: 'g12',
value: 'g15',
tooltip: '包括以下几种类型:1. 没有对应文件的文件页面;2. 没有对应母页面的子页面,用户页子页面除外;3. 指向不存在页面的重定向;4. 没有对应内容页面的讨论页,讨论页存档和用户讨论页除外;5. 不存在注册用户的用户页及用户页子页面,随用户更名产生的用户页重定向除外。请在删除时注意有无将内容移至他处的必要。不包括在主页面挂有{{CSD Placeholder}}模板的讨论页。'
tooltip: '注意是未列明来源且语调负面,必须2项均符合。'
},
},
{
{
label: 'G16: 因为主页面侵权而创建的临时页面仍然侵权',
label: 'G13: 明显、拙劣的机器翻译',
value: 'g13'
value: 'g16',
hideWhenUser: true
},
}
{
label: 'G14: 超过两周没有进行任何翻译的非现代标准汉语页面',
value: 'g14',
tooltip: '包括所有未翻译的外语、汉语方言以及文言文。',
hideWhenUser: true
},
{
label: 'G15: 孤立页面,比如没有主页面的讨论页、指向空页面的重定向等',
value: 'g15',
tooltip: '包括以下几种类型:1. 没有对应文件的文件页面;2. 没有对应母页面的子页面,用户页子页面除外;3. 指向不存在页面的重定向;4. 没有对应内容页面的讨论页,讨论页存档和用户讨论页除外;5. 不存在注册用户的用户页及用户页子页面,随用户更名产生的用户页重定向除外。请在删除时注意有无将内容移至他处的必要。不包括在主页面挂有{{CSD Placeholder}}模板的讨论页。'
},
{
label: 'G16: 因为主页面侵权而创建的临时页面仍然侵权',
value: 'g16',
hideWhenUser: true
}
];
];


Twinkle.speedy.redirectArticleList = [
Twinkle.speedy.redirectArticleList = [
{
{
label: 'R2: 跨名字空间重定向。',
label: 'R2: 跨名字空间重定向。',
value: 'r2',
value: 'r2',
tooltip: '由条目的名字空间重定向至非条目名字空间,或将用户页移出条目名字空间时遗留的重定向。'
tooltip: '由条目的名字空间重定向至非条目名字空间,或将用户页移出条目名字空间时遗留的重定向。'
}
}
];
];


Twinkle.speedy.redirectList = [
Twinkle.speedy.redirectList = [
{
{
label: 'R3: 格式错误,或明显笔误的重定向。',
label: 'R3: 格式错误,或明显笔误的重定向。',
value: 'r3',
value: 'r3',
tooltip: '非一眼能看出的拼写错误和翻译或标题用字的争议应交由存废讨论处理。',
tooltip: '非一眼能看出的拼写错误和翻译或标题用字的争议应交由存废讨论处理。',
subgroup: {
subgroup: {
name: 'r3_type',
name: 'r3_type',
type: 'select',
type: 'select',
label: '适用类别:',
label: '适用类别:',
list: [
list: [
{ label: '请选择', value: '' },
{ label: '请选择', value: '' },
{ label: '标题繁简混用', value: '标题繁简混用。' },
{ label: '标题繁简混用', value: '标题繁简混用。' },
{ label: '消歧义使用的括号或空格错误', value: '消歧义使用的括号或空格错误。' },
{ label: '消歧义使用的括号或空格错误', value: '消歧义使用的括号或空格错误。' },
{ label: '间隔号使用错误', value: '间隔号使用错误。' },
{ label: '间隔号使用错误', value: '间隔号使用错误。' },
{ label: '标题中使用非常见的错别字', value: '标题中使用非常见的错别字。' },
{ label: '标题中使用非常见的错别字', value: '标题中使用非常见的错别字。' },
{ label: '移动侵权页面的临时页后所产生的重定向', value: '移动侵权页面的临时页后所产生的重定向。' }
{ label: '移动侵权页面的临时页后所产生的重定向', value: '移动侵权页面的临时页后所产生的重定向。' }
]
]
},
},
hideSubgroupWhenSysop: true
hideSubgroupWhenSysop: true
},
},
{
{
label: 'R5: 指向本身的重定向或循环的重定向。',
label: 'R5: 指向本身的重定向或循环的重定向。',
value: 'r5',
value: 'r5',
tooltip: '如A→B→C→……→A。'
tooltip: '如A→B→C→……→A。'
}
}
];
];


Twinkle.speedy.normalizeHash = {
Twinkle.speedy.normalizeHash = {
'reason': 'db',
'reason': 'db',
'multiple': 'multiple',
'multiple': 'multiple',
'multiple-finish': 'multiple-finish',
'multiple-finish': 'multiple-finish',
'g1': 'g1',
'g1': 'g1',
'g2': 'g2',
'g2': 'g2',
'g3': 'g3',
'g3': 'g3',
'g5': 'g5',
'g5': 'g5',
'g8': 'g8',
'g8': 'g8',
'g10': 'g10',
'g10': 'g10',
'g11': 'g11',
'g11': 'g11',
'g12': 'g12',
'g12': 'g12',
'g13': 'g13',
'g13': 'g13',
'g14': 'g14',
'g14': 'g14',
'g15': 'g15',
'g15': 'g15',
'g16': 'g16',
'g16': 'g16',
'a1': 'a1',
'a1': 'a1',
'a2': 'a2',
'a2': 'a2',
'a3': 'a3',
'a3': 'a3',
'a5': 'a5',
'a5': 'a5',
'a6': 'a6',
'a6': 'a6',
'r2': 'r2',
'r2': 'r2',
'r3': 'r3',
'r3': 'r3',
'r5': 'r5',
'r5': 'r5',
'f1': 'f1',
'f1': 'f1',
'f3': 'f3',
'f3': 'f3',
'f4': 'f4',
'f4': 'f4',
'f5': 'f5',
'f5': 'f5',
'f6': 'f6',
'f6': 'f6',
'f7': 'f7',
'f7': 'f7',
'o1': 'o1',
'o1': 'o1',
'o3': 'o3',
'o3': 'o3',
'o4': 'o4'
'o4': 'o4'
};
};


// keep this synched with [[MediaWiki:Deletereason-dropdown]]
// keep this synched with [[MediaWiki:Deletereason-dropdown]]
Twinkle.speedy.reasonHash = {
Twinkle.speedy.reasonHash = {
'reason': '',
'reason': '',
// General
// General
'g1': '无实际内容',
'g1': '无实际内容',
'g2': '测试页',
'g2': '测试页',
'g3': '破坏',
'g3': '破坏',
'g5': '曾经依存废讨论被删除的重建内容',
'g5': '曾经依存废讨论被删除的重建内容',
'g8': '技术原因',
'g8': '技术原因',
'g10': '作者请求',
'g10': '作者请求',
'g11': '广告或宣传',
'g11': '广告或宣传',
'g12': '未列明来源或违反生者传记的负面内容',
'g12': '未列明来源或违反生者传记的负面内容',
'g13': '明显且拙劣的机器翻译',
'g13': '明显且拙劣的机器翻译',
'g14': '超过两周没有翻译的非现代标准汉语页面',
'g14': '超过两周没有翻译的非现代标准汉语页面',
'g15': '孤立页面',
'g15': '孤立页面',
'g16': '临时页面依然侵权',
'g16': '临时页面依然侵权',
// Articles
// Articles
'a1': '非常短而无定义或内容',
'a1': '非常短而无定义或内容',
'a2': '内容只包含参考、链接、模板或/及分类',
'a2': '内容只包含参考、链接、模板或/及分类',
'a3': '与其他中文维基计划内容相同的文章',
'a3': '与其他中文维基计划内容相同的文章',
'a5': '条目建立时之内容即与其他现有条目内容相同',
'a5': '条目建立时之内容即与其他现有条目内容相同',
'a6': '复制自其他维基百科语言版本',
'a6': '复制自其他维基百科语言版本',
// Redirects
// Redirects
'r2': '跨名字空间重定向',
'r2': '跨名字空间重定向',
'r3': '标题错误的重定向',
'r3': '标题错误的重定向',
'r5': '指向本身的重定向或循环的重定向',
'r5': '指向本身的重定向或循环的重定向',
// Images and media
// Images and media
'f1': '重复的图片',
'f1': '重复的图片',
'f3': '[[:Category:未知版权的档案]]',
'f3': '[[:Category:未知版权的档案]]',
'f4': '[[:Category:來源不明檔案]]',
'f4': '[[:Category:來源不明檔案]]',
'f5': '已有高分辨率的图片取代',
'f5': '已有高分辨率的图片取代',
'f6': '孤立而没有被条目使用的非自由版权图片',
'f6': '孤立而没有被条目使用的非自由版权图片',
'f7': '[[:Category:与维基共享资源重复的档案]]',
'f7': '[[:Category:与维基共享资源重复的档案]]',
// User pages
// User pages
'o1': '用户请求删除自己的用户页或其子页面',
'o1': '用户请求删除自己的用户页或其子页面',
'o3': '匿名用户的讨论页',
'o3': '匿名用户的讨论页',
// Categories
// Categories
'o4': '空的类别'
'o4': '空的类别'
// Templates
// Templates
// Portals
// Portals
Line 812: Line 697:


Twinkle.speedy.callbacks = {
Twinkle.speedy.callbacks = {
getTemplateCodeAndParams: function(params) {
getTemplateCodeAndParams: function(params) {
var code, parameters, i;
var code, parameters, i;
if (params.normalizeds.length > 1) {
if (params.normalizeds.length > 1) {
code = "{{delete";
code = "{{delete";
params.utparams = {};
params.utparams = {};
$.each(params.normalizeds, function(index, norm) {
$.each(params.normalizeds, function(index, norm) {
code += "|" + norm.toUpperCase();
code += "|" + norm.toUpperCase();
parameters = params.templateParams[index] || [];
parameters = params.templateParams[index] || [];
for (var i in parameters) {
for (var i in parameters) {
if (typeof parameters[i] === 'string') {
if (typeof parameters[i] === 'string') {
code += "|" + parameters[i];
code += "|" + parameters[i];
}
}
}
}
$.extend(params.utparams, Twinkle.speedy.getUserTalkParameters(norm, parameters));
$.extend(params.utparams, Twinkle.speedy.getUserTalkParameters(norm, parameters));
});
});
code += "}}";
code += "}}";
} else {
} else {
parameters = params.templateParams[0] || [];
parameters = params.templateParams[0] || [];
code = "{{delete";
code = "{{delete";
if (params.values[0] !== 'reason') {
if (params.values[0] !== 'reason') {
code += '|' + params.values[0];
code += '|' + params.values[0];
}
}
for (i in parameters) {
for (i in parameters) {
if (typeof parameters[i] === 'string') {
if (typeof parameters[i] === 'string') {
code += "|" + parameters[i];
code += "|" + parameters[i];
}
}
}
}
code += "}}";
code += "}}";
params.utparams = Twinkle.speedy.getUserTalkParameters(params.normalizeds[0], parameters);
params.utparams = Twinkle.speedy.getUserTalkParameters(params.normalizeds[0], parameters);
}
}


return [code, params.utparams];
return [code, params.utparams];
},
},


parseWikitext: function(wikitext, callback) {
parseWikitext: function(wikitext, callback) {
var query = {
var query = {
action: "parse",
action: "parse",
prop: "text",
prop: "text",
pst: "true",
pst: "true",
text: wikitext,
text: wikitext,
contentmodel: "wikitext",
contentmodel: "wikitext",
title: mw.config.get("wgPageName")
title: mw.config.get("wgPageName")
};
};


var statusIndicator = new Morebits.status( '构造删除理由' );
var statusIndicator = new Morebits.status( '构造删除理由' );
var api = new Morebits.wiki.api( '解析删除模板', query, function(apiObj) {
var api = new Morebits.wiki.api( '解析删除模板', query, function(apiObj) {
var reason = decodeURIComponent($(apiObj.getXML().querySelector('text').childNodes[0].nodeValue).find('#delete-reason').text()).replace(/\+/g, ' ');
var reason = decodeURIComponent($(apiObj.getXML().querySelector('text').childNodes[0].nodeValue).find('#delete-reason').text()).replace(/\+/g, ' ');
if (!reason) {
if (!reason) {
statusIndicator.warn( '未能从删除模板生成删除理由' );
statusIndicator.warn( '未能从删除模板生成删除理由' );
} else {
} else {
statusIndicator.info( '完成' );
statusIndicator.info( '完成' );
}
}
callback(reason);
callback(reason);
}, statusIndicator);
}, statusIndicator);
api.post();
api.post();
},
},


sysop: {
sysop: {
main: function( params ) {
main: function( params ) {
var reason;
var reason;


if (!params.normalizeds.length && params.normalizeds[0] === 'db') {
if (!params.normalizeds.length && params.normalizeds[0] === 'db') {
reason = prompt("输入删除理由:", "");
reason = prompt("输入删除理由:", "");
Twinkle.speedy.callbacks.sysop.deletePage( reason, params );
Twinkle.speedy.callbacks.sysop.deletePage( reason, params );
} else {
} else {
var code = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params)[0];
var code = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params)[0];
Twinkle.speedy.callbacks.parseWikitext(code, function(reason) {
Twinkle.speedy.callbacks.parseWikitext(code, function(reason) {
if (params.promptForSummary) {
if (params.promptForSummary) {
reason = prompt("输入删除理由,或点击确定以接受自动生成的:", presetReason);
reason = prompt("输入删除理由,或点击确定以接受自动生成的:", presetReason);
}
}
Twinkle.speedy.callbacks.sysop.deletePage( reason, params );
Twinkle.speedy.callbacks.sysop.deletePage( reason, params );
});
});
}
}
},
},
deletePage: function( reason, params ) {
deletePage: function( reason, params ) {
var thispage = new Morebits.wiki.page( mw.config.get('wgPageName'), "删除页面" );
var thispage = new Morebits.wiki.page( mw.config.get('wgPageName'), "删除页面" );


if (reason === null) {
if (reason === null) {
return Morebits.status.error("询问理由", "用户取消操作。");
return Morebits.status.error("询问理由", "用户取消操作。");
} else if (!reason || !reason.replace(/^\s*/, "").replace(/\s*$/, "")) {
} else if (!reason || !reason.replace(/^\s*/, "").replace(/\s*$/, "")) {
return Morebits.status.error("询问理由", "你不给我理由…我就…不管了…");
return Morebits.status.error("询问理由", "你不给我理由…我就…不管了…");
}
}
thispage.setEditSummary( reason + Twinkle.getPref('deletionSummaryAd') );
thispage.setEditSummary( reason + Twinkle.getPref('deletionSummaryAd') );
thispage.deletePage(function() {
thispage.deletePage(function() {
thispage.getStatusElement().info("完成");
thispage.getStatusElement().info("完成");
Twinkle.speedy.callbacks.sysop.deleteTalk( params );
Twinkle.speedy.callbacks.sysop.deleteTalk( params );
});
});


// look up initial contributor. If prompting user for deletion reason, just display a link.
// look up initial contributor. If prompting user for deletion reason, just display a link.
// Otherwise open the talk page directly
// Otherwise open the talk page directly
if( params.openUserTalk ) {
if( params.openUserTalk ) {
thispage.setCallbackParameters( params );
thispage.setCallbackParameters( params );
thispage.lookupCreator( Twinkle.speedy.callbacks.sysop.openUserTalkPage );
thispage.lookupCreator( Twinkle.speedy.callbacks.sysop.openUserTalkPage );
}
}
},
},
deleteTalk: function( params ) {
deleteTalk: function( params ) {
// delete talk page
// delete talk page
if (params.deleteTalkPage &&
if (params.deleteTalkPage &&
params.normalized !== 'f7' &&
params.normalized !== 'f7' &&
params.normalized !== 'o1' &&
params.normalized !== 'o1' &&
document.getElementById( 'ca-talk' ).className !== 'new') {
document.getElementById( 'ca-talk' ).className !== 'new') {
var talkpage = new Morebits.wiki.page( Morebits.wikipedia.namespaces[ mw.config.get('wgNamespaceNumber') + 1 ] + ':' + mw.config.get('wgTitle'), "删除讨论页" );
var talkpage = new Morebits.wiki.page( Morebits.wikipedia.namespaces[ mw.config.get('wgNamespaceNumber') + 1 ] + ':' + mw.config.get('wgTitle'), "删除讨论页" );
talkpage.setEditSummary('[[WP:CSD#G15|G15]]: 孤立页面: 已删除页面“' + Morebits.pageNameNorm + "”的讨论页" + Twinkle.getPref('deletionSummaryAd'));
talkpage.setEditSummary('[[WP:CSD#G15|G15]]: 孤立页面: 已删除页面“' + Morebits.pageNameNorm + "”的讨论页" + Twinkle.getPref('deletionSummaryAd'));
talkpage.deletePage();
talkpage.deletePage();
// this is ugly, but because of the architecture of wiki.api, it is needed
// 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)
// (otherwise success/failure messages for the previous action would be suppressed)
window.setTimeout(function() { Twinkle.speedy.callbacks.sysop.deleteRedirects( params ); }, 1800);
window.setTimeout(function() { Twinkle.speedy.callbacks.sysop.deleteRedirects( params ); }, 1800);
} else {
} else {
Twinkle.speedy.callbacks.sysop.deleteRedirects( params );
Twinkle.speedy.callbacks.sysop.deleteRedirects( params );
}
}
},
},
deleteRedirects: function( params ) {
deleteRedirects: function( params ) {
// delete redirects
// delete redirects
if (params.deleteRedirects) {
if (params.deleteRedirects) {
var query = {
var query = {
'action': 'query',
'action': 'query',
'titles': mw.config.get('wgPageName'),
'titles': mw.config.get('wgPageName'),
'prop': 'redirects',
'prop': 'redirects',
'rdlimit': 5000 // 500 is max for normal users, 5000 for bots and sysops
'rdlimit': 5000 // 500 is max for normal users, 5000 for bots and sysops
};
};
var wikipedia_api = new Morebits.wiki.api( '取得重定向列表…', query, Twinkle.speedy.callbacks.sysop.deleteRedirectsMain,
var wikipedia_api = new Morebits.wiki.api( '取得重定向列表…', query, Twinkle.speedy.callbacks.sysop.deleteRedirectsMain,
new Morebits.status( '删除重定向' ) );
new Morebits.status( '删除重定向' ) );
wikipedia_api.params = params;
wikipedia_api.params = params;
wikipedia_api.post();
wikipedia_api.post();
}
}


// prompt for protect on G11
// prompt for protect on G11
var $link, $bigtext;
var $link, $bigtext;
if (params.normalized === 'g11') {
if (params.normalized === 'g11') {
$link = $('<a/>', {
$link = $('<a/>', {
'href': '#',
'href': '#',
'text': '点击这里施行保护',
'text': '点击这里施行保护',
'css': { 'fontSize': '130%', 'fontWeight': 'bold' },
'css': { 'fontSize': '130%', 'fontWeight': 'bold' },
'click': function(){
'click': function(){
Morebits.wiki.actionCompleted.redirect = null;
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.speedy.dialog.close();
Twinkle.speedy.dialog.close();
mw.config.set('wgArticleId', 0);
mw.config.set('wgArticleId', 0);
Twinkle.protect.callback();
Twinkle.protect.callback();
}
}
});
});
$bigtext = $('<span/>', {
$bigtext = $('<span/>', {
'text': '白纸保护该页',
'text': '白纸保护该页',
'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
});
});
Morebits.status.info($bigtext[0], $link[0]);
Morebits.status.info($bigtext[0], $link[0]);
}
}


// promote Unlink tool
// promote Unlink tool
var $link, $bigtext;
var $link, $bigtext;
if( mw.config.get('wgNamespaceNumber') === 6 && params.normalized !== 'f7' ) {
if( mw.config.get('wgNamespaceNumber') === 6 && params.normalized !== 'f7' ) {
$link = $('<a/>', {
$link = $('<a/>', {
'href': '#',
'href': '#',
'text': '点击这里前往反链工具',
'text': '点击这里前往反链工具',
'css': { 'fontWeight': 'bold' },
'css': { 'fontWeight': 'bold' },
'click': function(){
'click': function(){
Morebits.wiki.actionCompleted.redirect = null;
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.speedy.dialog.close();
Twinkle.speedy.dialog.close();
Twinkle.unlink.callback("取消对已删除文件 " + Morebits.pageNameNorm + " 的使用");
Twinkle.unlink.callback("取消对已删除文件 " + Morebits.pageNameNorm + " 的使用");
}
}
});
});
$bigtext = $('<span/>', {
$bigtext = $('<span/>', {
'text': '取消对已删除文件的使用',
'text': '取消对已删除文件的使用',
'css': { 'fontWeight': 'bold' }
'css': { 'fontWeight': 'bold' }
});
});
Morebits.status.info($bigtext[0], $link[0]);
Morebits.status.info($bigtext[0], $link[0]);
} else if (params.normalized !== 'f7') {
} else if (params.normalized !== 'f7') {
$link = $('<a/>', {
$link = $('<a/>', {
'href': '#',
'href': '#',
'text': '点击这里前往反链工具',
'text': '点击这里前往反链工具',
'css': { 'fontWeight': 'bold' },
'css': { 'fontWeight': 'bold' },
'click': function(){
'click': function(){
Morebits.wiki.actionCompleted.redirect = null;
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.speedy.dialog.close();
Twinkle.speedy.dialog.close();
Twinkle.unlink.callback("取消对已删除页面 " + Morebits.pageNameNorm + " 的链接");
Twinkle.unlink.callback("取消对已删除页面 " + Morebits.pageNameNorm + " 的链接");
}
}
});
});
$bigtext = $('<span/>', {
$bigtext = $('<span/>', {
'text': '取消对已删除页面的链接',
'text': '取消对已删除页面的链接',
'css': { 'fontWeight': 'bold' }
'css': { 'fontWeight': 'bold' }
});
});
Morebits.status.info($bigtext[0], $link[0]);
Morebits.status.info($bigtext[0], $link[0]);
}
}
},
},
openUserTalkPage: function( pageobj ) {
openUserTalkPage: function( pageobj ) {
pageobj.getStatusElement().unlink(); // don't need it anymore
pageobj.getStatusElement().unlink(); // don't need it anymore
var user = pageobj.getCreator();
var user = pageobj.getCreator();
var params = pageobj.getCallbackParameters();
var params = pageobj.getCallbackParameters();


var query = {
var query = {
'title': 'User talk:' + user,
'title': 'User talk:' + user,
'action': 'edit',
'action': 'edit',
'preview': 'yes',
'preview': 'yes',
'vanarticle': Morebits.pageNameNorm
'vanarticle': Morebits.pageNameNorm
};
};


if (params.normalized === 'db' || Twinkle.getPref("promptForSpeedyDeletionSummary").indexOf(params.normalized) !== -1) {
if (params.normalized === 'db' || Twinkle.getPref("promptForSpeedyDeletionSummary").indexOf(params.normalized) !== -1) {
// provide a link to the user talk page
// provide a link to the user talk page
var $link, $bigtext;
var $link, $bigtext;
$link = $('<a/>', {
$link = $('<a/>', {
'href': mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ),
'href': mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ),
'text': '点此打开User talk:' + user,
'text': '点此打开User talk:' + user,
'target': '_blank',
'target': '_blank',
'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
});
});
$bigtext = $('<span/>', {
$bigtext = $('<span/>', {
'text': '通知页面创建者',
'text': '通知页面创建者',
'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
});
});
Morebits.status.info($bigtext[0], $link[0]);
Morebits.status.info($bigtext[0], $link[0]);
} else {
} else {
// open the initial contributor's talk page
// open the initial contributor's talk page
var statusIndicator = new Morebits.status('打开用户' + user + '对话页编辑表单', '打开中…');
var statusIndicator = new Morebits.status('打开用户' + user + '对话页编辑表单', '打开中…');


switch( Twinkle.getPref('userTalkPageMode') ) {
switch( Twinkle.getPref('userTalkPageMode') ) {
case 'tab':
case 'tab':
window.open( mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ), '_blank' );
window.open( mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ), '_blank' );
break;
break;
case 'blank':
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' );
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;
break;
case 'window':
case 'window':
/* falls through */
/* falls through */
default:
default:
window.open( mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ),
window.open( mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ),
( window.name === 'twinklewarnwindow' ? '_blank' : 'twinklewarnwindow' ),
( window.name === 'twinklewarnwindow' ? '_blank' : 'twinklewarnwindow' ),
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
break;
break;
}
}


statusIndicator.info( '完成' );
statusIndicator.info( '完成' );
}
}
},
},
deleteRedirectsMain: function( apiobj ) {
deleteRedirectsMain: function( apiobj ) {
var xmlDoc = apiobj.getXML();
var xmlDoc = apiobj.getXML();
var $snapshot = $(xmlDoc).find('redirects rd');
var $snapshot = $(xmlDoc).find('redirects rd');
var total = $snapshot.length;
var total = $snapshot.length;
var statusIndicator = apiobj.statelem;
var statusIndicator = apiobj.statelem;


if( !total ) {
if( !total ) {
statusIndicator.status("未发现重定向");
statusIndicator.status("未发现重定向");
return;
return;
}
}


statusIndicator.status("0%");
statusIndicator.status("0%");


var current = 0;
var current = 0;
var onsuccess = function( apiobjInner ) {
var onsuccess = function( apiobjInner ) {
var now = parseInt( 100 * (++current)/total, 10 ) + '%';
var now = parseInt( 100 * (++current)/total, 10 ) + '%';
statusIndicator.update( now );
statusIndicator.update( now );
apiobjInner.statelem.unlink();
apiobjInner.statelem.unlink();
if( current >= total ) {
if( current >= total ) {
statusIndicator.info( now + '(完成)' );
statusIndicator.info( now + '(完成)' );
Morebits.wiki.removeCheckpoint();
Morebits.wiki.removeCheckpoint();
}
}
};
};


Morebits.wiki.addCheckpoint();
Morebits.wiki.addCheckpoint();


$snapshot.each(function(key, value) {
$snapshot.each(function(key, value) {
var title = $(value).attr('title');
var title = $(value).attr('title');
var page = new Morebits.wiki.page(title, '删除重定向 "' + title + '"');
var page = new Morebits.wiki.page(title, '删除重定向 "' + title + '"');
page.setEditSummary('[[WP:CSD#G15|G15]]: 孤立页面: 重定向到已删除页面“' + Morebits.pageNameNorm + "”" + Twinkle.getPref('deletionSummaryAd'));
page.setEditSummary('[[WP:CSD#G15|G15]]: 孤立页面: 重定向到已删除页面“' + Morebits.pageNameNorm + "”" + Twinkle.getPref('deletionSummaryAd'));
page.deletePage(onsuccess);
page.deletePage(onsuccess);
});
});
}
}
},
},


user: {
user: {
main: function(pageobj) {
main: function(pageobj) {
var statelem = pageobj.getStatusElement();
var statelem = pageobj.getStatusElement();


if (!pageobj.exists()) {
if (!pageobj.exists()) {
statelem.error( "页面不存在,可能已被删除" );
statelem.error( "页面不存在,可能已被删除" );
return;
return;
}
}


var text = pageobj.getPageText();
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var params = pageobj.getCallbackParameters();


statelem.status( '检查页面已有标记…' );
statelem.status( '检查页面已有标记…' );


// check for existing deletion tags
// check for existing deletion tags
var tag = /(?:\{\{\s*(db|d|delete|db-.*?)(?:\s*\||\s*\}\}))/i.exec( text );
var tag = /(?:\{\{\s*(db|d|delete|db-.*?)(?:\s*\||\s*\}\}))/i.exec( text );
if ( tag ) {
if ( tag ) {
statelem.error( [ Morebits.htmlNode( 'strong', tag[1] ) , " 已被置于页面中。" ] );
statelem.error( [ Morebits.htmlNode( 'strong', tag[1] ) , " 已被置于页面中。" ] );
return;
return;
}
}


var copyvio = /(?:\{\{\s*(copyvio)[^{}]*?\}\})/i.exec( text );
var copyvio = /(?:\{\{\s*(copyvio)[^{}]*?\}\})/i.exec( text );
if ( copyvio ) {
if ( copyvio ) {
statelem.error( '页面中已有版权验证模板。' );
statelem.error( '页面中已有版权验证模板。' );
return;
return;
}
}


var xfd = /(?:\{\{([rsaiftcmv]fd|md1|proposed deletion)[^{}]*?\}\})/i.exec( text );
var xfd = /(?:\{\{([rsaiftcmv]fd|md1|proposed deletion)[^{}]*?\}\})/i.exec( text );
if ( xfd && !confirm( "删除相关模板{{" + xfd[1] + "}}已被置于页面中,您是否仍想添加一个快速删除模板?" ) ) {
if ( xfd && !confirm( "删除相关模板{{" + xfd[1] + "}}已被置于页面中,您是否仍想添加一个快速删除模板?" ) ) {
statelem.error( '页面已被提交至存废讨论。' );
statelem.error( '页面已被提交至存废讨论。' );
return;
return;
}
}


// given the params, builds the template and also adds the user talk page parameters to the params that were passed in
// given the params, builds the template and also adds the user talk page parameters to the params that were passed in
// returns => [<string> wikitext, <object> utparams]
// returns => [<string> wikitext, <object> utparams]
var buildData = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params),
var buildData = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params),
code = buildData[0];
code = buildData[0];
params.utparams = buildData[1];
params.utparams = buildData[1];


var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'));
var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'));
// patrol the page, if reached from Special:NewPages
// patrol the page, if reached from Special:NewPages
if( Twinkle.getPref('markSpeedyPagesAsPatrolled') ) {
if( Twinkle.getPref('markSpeedyPagesAsPatrolled') ) {
thispage.patrol();
thispage.patrol();
}
}


// Wrap SD template in noinclude tags if we are in template space.
// 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
// Won't work with userboxes in userspace, or any other transcluded page outside template space
if (mw.config.get('wgNamespaceNumber') === 10) { // Template:
if (mw.config.get('wgNamespaceNumber') === 10) { // Template:
code = "<noinclude>" + code + "</noinclude>";
code = "<noinclude>" + code + "</noinclude>";
}
}


// Remove tags that become superfluous with this action
// Remove tags that become superfluous with this action
text = text.replace(/\{\{\s*([Nn]ew unreviewed article|[Uu]nreviewed|[Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, "");
text = text.replace(/\{\{\s*([Nn]ew unreviewed article|[Uu]nreviewed|[Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, "");
if (mw.config.get('wgNamespaceNumber') === 6) {
if (mw.config.get('wgNamespaceNumber') === 6) {
// remove "move to Commons" tag - deletion-tagged files cannot be moved to Commons
// remove "move to Commons" tag - deletion-tagged files cannot be moved to Commons
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, "");
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, "");
}
}


// Generate edit summary for edit
// Generate edit summary for edit
var editsummary;
var editsummary;
if (params.normalizeds.length > 1) {
if (params.normalizeds.length > 1) {
editsummary = '请求快速删除(';
editsummary = '请求快速删除(';
$.each(params.normalizeds, function(index, norm) {
$.each(params.normalizeds, function(index, norm) {
editsummary += '[[WP:CSD#' + norm.toUpperCase() + '|CSD ' + norm.toUpperCase() + ']]、';
editsummary += '[[WP:CSD#' + norm.toUpperCase() + '|CSD ' + norm.toUpperCase() + ']]、';
});
});
editsummary = editsummary.substr(0, editsummary.length - 1); // remove trailing comma
editsummary = editsummary.substr(0, editsummary.length - 1); // remove trailing comma
editsummary += ')。';
editsummary += ')。';
} else if (params.normalizeds[0] === "db") {
} else if (params.normalizeds[0] === "db") {
editsummary = '请求[[WP:CSD|快速删除]]:' + params.templateParams[0]["1"];
editsummary = '请求[[WP:CSD|快速删除]]:' + params.templateParams[0]["1"];
} else {
} else {
editsummary = "请求快速删除([[WP:CSD#" + params.normalizeds[0].toUpperCase() + "|CSD " + params.normalizeds[0].toUpperCase() + "]])";
editsummary = "请求快速删除([[WP:CSD#" + params.normalizeds[0].toUpperCase() + "|CSD " + params.normalizeds[0].toUpperCase() + "]])";
}
}


pageobj.setPageText(code + "\n" + text);
pageobj.setPageText(code + "\n" + text);
pageobj.setEditSummary(editsummary + Twinkle.getPref('summaryAd'));
pageobj.setEditSummary(editsummary + Twinkle.getPref('summaryAd'));
pageobj.setWatchlist(params.watch);
pageobj.setWatchlist(params.watch);
pageobj.setCreateOption('nocreate');
pageobj.setCreateOption('nocreate');
pageobj.save(Twinkle.speedy.callbacks.user.tagComplete);
pageobj.save(Twinkle.speedy.callbacks.user.tagComplete);
},
},


tagComplete: function(pageobj) {
tagComplete: function(pageobj) {
var params = pageobj.getCallbackParameters();
var params = pageobj.getCallbackParameters();


// Notification to first contributor
// Notification to first contributor
if (params.usertalk) {
if (params.usertalk) {
var callback = function(pageobj) {
var callback = function(pageobj) {
var initialContrib = pageobj.getCreator();
var initialContrib = pageobj.getCreator();


// disallow warning yourself
// disallow warning yourself
if (initialContrib === mw.config.get('wgUserName')) {
if (initialContrib === mw.config.get('wgUserName')) {
Morebits.status.warn("您(" + initialContrib + ")创建了该页,跳过通知");
Morebits.status.warn("您(" + initialContrib + ")创建了该页,跳过通知");


// don't notify users when their user talk page is nominated
// don't notify users when their user talk page is nominated
} else if (initialContrib === mw.config.get('wgTitle') && mw.config.get('wgNamespaceNumber') === 3) {
} else if (initialContrib === mw.config.get('wgTitle') && mw.config.get('wgNamespaceNumber') === 3) {
Morebits.status.warn("通知页面创建者:用户创建了自己的对话页");
Morebits.status.warn("通知页面创建者:用户创建了自己的对话页");


} else {
} else {
var talkPageName = 'User talk:' + initialContrib;
var talkPageName = 'User talk:' + initialContrib;
Morebits.wiki.flow.check(talkPageName, function () {
Morebits.wiki.flow.check(talkPageName, function () {
var flowpage = new Morebits.wiki.flow(talkPageName, "通知页面创建者(" + initialContrib + ")");
var flowpage = new Morebits.wiki.flow(talkPageName, "通知页面创建者(" + initialContrib + ")");
flowpage.setTopic('[[:' + Morebits.pageNameNorm + ']]的快速删除通知');
flowpage.setTopic('[[:' + Morebits.pageNameNorm + ']]的快速删除通知');
flowpage.setContent('{{subst:User:逆襲的天邪鬼/Twinkle/Template:Db-notice|target=' + Morebits.pageNameNorm + '|flow=yes}}');
flowpage.setContent('{{subst:User:逆襲的天邪鬼/Twinkle/Template:Db-notice|target=' + Morebits.pageNameNorm + '|flow=yes}}');
flowpage.newTopic();
flowpage.newTopic();
}, function() {
}, function() {
var usertalkpage = new Morebits.wiki.page(talkPageName, "通知页面创建者(" + initialContrib + ")"),
var usertalkpage = new Morebits.wiki.page(talkPageName, "通知页面创建者(" + initialContrib + ")"),
notifytext, i;
notifytext, i;


notifytext = "\n{{subst:User:逆襲的天邪鬼/Twinkle/Template:Db-notice|target=" + Morebits.pageNameNorm;
notifytext = "\n{{subst:User:逆襲的天邪鬼/Twinkle/Template:Db-notice|target=" + Morebits.pageNameNorm;
notifytext += (params.welcomeuser ? "" : "|nowelcome=yes") + "}}--~~~~";
notifytext += (params.welcomeuser ? "" : "|nowelcome=yes") + "}}--~~~~";


var editsummary = "通知:";
var editsummary = "通知:";
if (params.normalizeds.indexOf("g12") === -1) { // no article name in summary for G10 deletions
if (params.normalizeds.indexOf("g12") === -1) { // no article name in summary for G10 deletions
editsummary += "页面[[" + Morebits.pageNameNorm + "]]";
editsummary += "页面[[" + Morebits.pageNameNorm + "]]";
} else {
} else {
editsummary += "一攻击性页面";
editsummary += "一攻击性页面";
}
}
editsummary += "快速删除提名";
editsummary += "快速删除提名";


usertalkpage.setAppendText(notifytext);
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary(editsummary + Twinkle.getPref('summaryAd'));
usertalkpage.setEditSummary(editsummary + Twinkle.getPref('summaryAd'));
usertalkpage.setCreateOption('recreate');
usertalkpage.setCreateOption('recreate');
usertalkpage.setFollowRedirect(true);
usertalkpage.setFollowRedirect(true);
usertalkpage.append();
usertalkpage.append();
});
});
}
}


// add this nomination to the user's userspace log, if the user has enabled it
// add this nomination to the user's userspace log, if the user has enabled it
if (params.lognomination) {
if (params.lognomination) {
Twinkle.speedy.callbacks.user.addToLog(params, initialContrib);
Twinkle.speedy.callbacks.user.addToLog(params, initialContrib);
}
}
};
};
var thispage = new Morebits.wiki.page(Morebits.pageNameNorm);
var thispage = new Morebits.wiki.page(Morebits.pageNameNorm);
thispage.lookupCreator(callback);
thispage.lookupCreator(callback);
}
}
// or, if not notifying, add this nomination to the user's userspace log without the initial contributor's name
// or, if not notifying, add this nomination to the user's userspace log without the initial contributor's name
else if (params.lognomination) {
else if (params.lognomination) {
Twinkle.speedy.callbacks.user.addToLog(params, null);
Twinkle.speedy.callbacks.user.addToLog(params, null);
}
}
},
},


// note: this code is also invoked from twinkleimage
// note: this code is also invoked from twinkleimage
// the params used are:
// the params used are:
// for CSD: params.values, params.normalizeds (note: normalizeds is an array)
// 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)
// for DI: params.fromDI = true, params.templatename, params.normalized (note: normalized is a string)
addToLog: function(params, initialContrib) {
addToLog: function(params, initialContrib) {
var wikipedia_page = new Morebits.wiki.page("User:" + mw.config.get('wgUserName') + "/" + Twinkle.getPref('speedyLogPageName'), "添加项目到用户日志");
var wikipedia_page = new Morebits.wiki.page("User:" + mw.config.get('wgUserName') + "/" + Twinkle.getPref('speedyLogPageName'), "添加项目到用户日志");
params.logInitialContrib = initialContrib;
params.logInitialContrib = initialContrib;
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.speedy.callbacks.user.saveLog);
wikipedia_page.load(Twinkle.speedy.callbacks.user.saveLog);
},
},


saveLog: function(pageobj) {
saveLog: function(pageobj) {
var text = pageobj.getPageText();
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var params = pageobj.getCallbackParameters();


var appendText = "";
var appendText = "";


// add blurb if log page doesn't exist
// add blurb if log page doesn't exist
if (!pageobj.exists()) {
if (!pageobj.exists()) {
appendText +=
appendText +=
"这是该用户使用[[WP:TW|Twinkle]]的速删模块做出的[[WP:CSD|快速删除]]提名列表。\n\n" +
"这是该用户使用[[WP:TW|Twinkle]]的速删模块做出的[[WP:CSD|快速删除]]提名列表。\n\n" +
"如果您不再想保留此日志,请在[[Wikipedia:Twinkle/参数设置|参数设置]]中关掉,并" +
"如果您不再想保留此日志,请在[[Wikipedia:Twinkle/参数设置|参数设置]]中关掉,并" +
"使用[[WP:CSD#O1|CSD O1]]提交快速删除。\n";
"使用[[WP:CSD#O1|CSD O1]]提交快速删除。\n";
if (Morebits.userIsInGroup("sysop")) {
if (Morebits.userIsInGroup("sysop")) {
appendText += "\n此日志并不记录用Twinkle直接执行的删除。\n";
appendText += "\n此日志并不记录用Twinkle直接执行的删除。\n";
}
}
}
}


// create monthly header
// create monthly header
var date = new Date();
var date = new Date();
var headerRe = new RegExp("^==+\\s*" + date.getUTCFullYear() + "\\s*年\\s*" + (date.getUTCMonth() + 1) + "\\s*月\\s*==+", "m");
var headerRe = new RegExp("^==+\\s*" + date.getUTCFullYear() + "\\s*年\\s*" + (date.getUTCMonth() + 1) + "\\s*月\\s*==+", "m");
if (!headerRe.exec(text)) {
if (!headerRe.exec(text)) {
appendText += "\n\n=== " + date.getUTCFullYear() + "年" + (date.getUTCMonth() + 1) + "月 ===";
appendText += "\n\n=== " + date.getUTCFullYear() + "年" + (date.getUTCMonth() + 1) + "月 ===";
}
}


appendText += "\n# [[:" + Morebits.pageNameNorm + "]]: ";
appendText += "\n# [[:" + Morebits.pageNameNorm + "]]: ";
if (params.fromDI) {
if (params.fromDI) {
appendText += "图版[[WP:CSD#" + params.normalized.toUpperCase() + "|CSD " + params.normalized.toUpperCase() + "]]({{tl|" + params.templatename + "}})";
appendText += "图版[[WP:CSD#" + params.normalized.toUpperCase() + "|CSD " + params.normalized.toUpperCase() + "]]({{tl|" + params.templatename + "}})";
} else {
} else {
if (params.normalizeds.length > 1) {
if (params.normalizeds.length > 1) {
appendText += "多个理由(";
appendText += "多个理由(";
$.each(params.normalizeds, function(index, norm) {
$.each(params.normalizeds, function(index, norm) {
appendText += "[[WP:CSD#" + norm.toUpperCase() + "|" + norm.toUpperCase() + ']]、';
appendText += "[[WP:CSD#" + norm.toUpperCase() + "|" + norm.toUpperCase() + ']]、';
});
});
appendText = appendText.substr(0, appendText.length - 1); // remove trailing comma
appendText = appendText.substr(0, appendText.length - 1); // remove trailing comma
appendText += ')';
appendText += ')';
} else if (params.normalizeds[0] === "db") {
} else if (params.normalizeds[0] === "db") {
appendText += "自定义理由";
appendText += "自定义理由";
} else {
} else {
appendText += "[[WP:CSD#" + params.normalizeds[0].toUpperCase() + "|CSD " + params.normalizeds[0].toUpperCase() + "]]";
appendText += "[[WP:CSD#" + params.normalizeds[0].toUpperCase() + "|CSD " + params.normalizeds[0].toUpperCase() + "]]";
}
}
}
}


if (params.logInitialContrib) {
if (params.logInitialContrib) {
appendText += ";通知{{user|" + params.logInitialContrib + "}}";
appendText += ";通知{{user|" + params.logInitialContrib + "}}";
}
}
appendText += " ~~~~~\n";
appendText += " ~~~~~\n";


pageobj.setAppendText(appendText);
pageobj.setAppendText(appendText);
pageobj.setEditSummary("记录对[[" + Morebits.pageNameNorm + "]]的快速删除提名" + Twinkle.getPref('summaryAd'));
pageobj.setEditSummary("记录对[[" + Morebits.pageNameNorm + "]]的快速删除提名" + Twinkle.getPref('summaryAd'));
pageobj.setCreateOption("recreate");
pageobj.setCreateOption("recreate");
pageobj.append();
pageobj.append();
}
}
}
}
};
};


// validate subgroups in the form passed into the speedy deletion tag
// validate subgroups in the form passed into the speedy deletion tag
Twinkle.speedy.getParameters = function twinklespeedyGetParameters(form, values) {
Twinkle.speedy.getParameters = function twinklespeedyGetParameters(form, values) {
var parameters = [];
var parameters = [];


$.each(values, function(index, value) {
$.each(values, function(index, value) {
var currentParams = [];
var currentParams = [];
switch (value) {
switch (value) {
case 'reason':
case 'reason':
if (form["csd.reason_1"]) {
if (form["csd.reason_1"]) {
var dbrationale = form["csd.reason_1"].value;
var dbrationale = form["csd.reason_1"].value;
if (!dbrationale || !dbrationale.trim()) {
if (!dbrationale || !dbrationale.trim()) {
alert( '自定义理由:请指定理由。' );
alert( '自定义理由:请指定理由。' );
parameters = null;
parameters = null;
return false;
return false;
}
}
currentParams["1"] = dbrationale;
currentParams["1"] = dbrationale;
}
}
break;
break;


case 'a5':
case 'a5':
if (form["csd.a5_pagename"]) {
if (form["csd.a5_pagename"]) {
var otherpage = form["csd.a5_pagename"].value;
var otherpage = form["csd.a5_pagename"].value;
if (!otherpage || !otherpage.trim()) {
if (!otherpage || !otherpage.trim()) {
alert( 'CSD A5:请提供现有条目的名称。' );
alert( 'CSD A5:请提供现有条目的名称。' );
parameters = null;
parameters = null;
return false;
return false;
}
}
currentParams.pagename = otherpage;
currentParams.pagename = otherpage;
}
}
break;
break;


case 'g5':
case 'g5':
if (form["csd.g5_1"]) {
if (form["csd.g5_1"]) {
var deldisc = form["csd.g5_1"].value;
var deldisc = form["csd.g5_1"].value;
if (deldisc) {
if (deldisc) {
if (deldisc.substring(0, 9) !== "Wikipedia" &&
if (deldisc.substring(0, 9) !== "Wikipedia" &&
deldisc.substring(0, 3) !== "WP:" &&
deldisc.substring(0, 3) !== "WP:" &&
deldisc.substring(0, 5) !== "维基百科:" &&
deldisc.substring(0, 5) !== "维基百科:" &&
deldisc.substring(0, 5) !== "維基百科:") {
deldisc.substring(0, 5) !== "維基百科:") {
alert( 'CSD G5:您提供的讨论页名必须以“Wikipedia:”开头。' );
alert( 'CSD G5:您提供的讨论页名必须以“Wikipedia:”开头。' );
parameters = null;
parameters = null;
return false;
return false;
}
}
currentParams["1"] = deldisc;
currentParams["1"] = deldisc;
}
}
}
}
break;
break;


case 'g10':
case 'g10':
if (form["csd.g10_rationale"] && form["csd.g10_rationale"].value) {
if (form["csd.g10_rationale"] && form["csd.g10_rationale"].value) {
currentParams.rationale = form["csd.g10_rationale"].value;
currentParams.rationale = form["csd.g10_rationale"].value;
}
}
break;
break;


case 'f1':
case 'f1':
if (form["csd.f1_filename"]) {
if (form["csd.f1_filename"]) {
var redimage = form["csd.f1_filename"].value;
var redimage = form["csd.f1_filename"].value;
if (!redimage || !redimage.trim()) {
if (!redimage || !redimage.trim()) {
alert( 'CSD F1:请提供另一文件的名称。' );
alert( 'CSD F1:请提供另一文件的名称。' );
parameters = null;
parameters = null;
return false;
return false;
}
}
currentParams.filename = redimage.replace(/^\s*(Image|File|文件|檔案):/i, "");
currentParams.filename = redimage.replace(/^\s*(Image|File|文件|檔案):/i, "");
}
}
break;
break;


case 'f5':
case 'f5':
if (form["csd.f5_filename"]) {
if (form["csd.f5_filename"]) {
var redimage = form["csd.f5_filename"].value;
var redimage = form["csd.f5_filename"].value;
if (!redimage || !redimage.trim()) {
if (!redimage || !redimage.trim()) {
alert( 'CSD F5:请提供另一文件的名称。' );
alert( 'CSD F5:请提供另一文件的名称。' );
parameters = null;
parameters = null;
return false;
return false;
}
}
currentParams.filename = redimage.replace(/^\s*(Image|File|文件|檔案):/i, "");
currentParams.filename = redimage.replace(/^\s*(Image|File|文件|檔案):/i, "");
}
}
break;
break;


case 'f7':
case 'f7':
if (form["csd.f7_filename"]) {
if (form["csd.f7_filename"]) {
var filename = form["csd.f7_filename"].value;
var filename = form["csd.f7_filename"].value;
if (filename && filename !== Morebits.pageNameNorm) {
if (filename && filename !== Morebits.pageNameNorm) {
if (filename.indexOf("Image:") === 0 || filename.indexOf("File:") === 0 ||
if (filename.indexOf("Image:") === 0 || filename.indexOf("File:") === 0 ||
filename.indexOf("文件:") === 0 || filename.indexOf("檔案:") === 0) {
filename.indexOf("文件:") === 0 || filename.indexOf("檔案:") === 0) {
currentParams["1"] = filename;
currentParams["1"] = filename;
} else {
} else {
currentParams["1"] = "File:" + filename;
currentParams["1"] = "File:" + filename;
}
}
}
}
}
}
break;
break;


case 'r3':
case 'r3':
if (form["csd.r3_type"]) {
if (form["csd.r3_type"]) {
var redirtype = form["csd.r3_type"].value;
var redirtype = form["csd.r3_type"].value;
if (!redirtype) {
if (!redirtype) {
alert( 'CSD R3:请选择适用类别。' );
alert( 'CSD R3:请选择适用类别。' );
parameters = null;
parameters = null;
return false;
return false;
}
}
currentParams["1"] = redirtype;
currentParams["1"] = redirtype;
}
}
break;
break;


default:
default:
break;
break;
}
}
parameters.push(currentParams);
parameters.push(currentParams);
});
});
return parameters;
return parameters;
};
};


// function for processing talk page notification template parameters
// function for processing talk page notification template parameters
Twinkle.speedy.getUserTalkParameters = function twinklespeedyGetUserTalkParameters(normalized, parameters) {
Twinkle.speedy.getUserTalkParameters = function twinklespeedyGetUserTalkParameters(normalized, parameters) {
var utparams = [];
var utparams = [];
switch (normalized) {
switch (normalized) {
default:
default:
break;
break;
}
}
return utparams;
return utparams;
};
};




Twinkle.speedy.resolveCsdValues = function twinklespeedyResolveCsdValues(e) {
Twinkle.speedy.resolveCsdValues = function twinklespeedyResolveCsdValues(e) {
var values = (e.target.form ? e.target.form : e.target).getChecked('csd');
var values = (e.target.form ? e.target.form : e.target).getChecked('csd');
if (values.length === 0) {
if (values.length === 0) {
alert( "请选择一个理据!" );
alert( "请选择一个理据!" );
return null;
return null;
}
}
return values;
return values;
};
};


Twinkle.speedy.callback.evaluateSysop = function twinklespeedyCallbackEvaluateSysop(e) {
Twinkle.speedy.callback.evaluateSysop = function twinklespeedyCallbackEvaluateSysop(e) {
var form = (e.target.form ? e.target.form : e.target);
var form = (e.target.form ? e.target.form : e.target);


if (e.target.type === "checkbox" || e.target.type === "text" ||
if (e.target.type === "checkbox" || e.target.type === "text" ||
e.target.type === "select") {
e.target.type === "select") {
return;
return;
}
}


var tag_only = form.tag_only;
var tag_only = form.tag_only;
if( tag_only && tag_only.checked ) {
if( tag_only && tag_only.checked ) {
Twinkle.speedy.callback.evaluateUser(e);
Twinkle.speedy.callback.evaluateUser(e);
return;
return;
}
}


var values = Twinkle.speedy.resolveCsdValues(e);
var values = Twinkle.speedy.resolveCsdValues(e);
if (!values) {
if (!values) {
return;
return;
}
}


var normalizeds = values.map(function(value) {
var normalizeds = values.map(function(value) {
return Twinkle.speedy.normalizeHash[ value ];
return Twinkle.speedy.normalizeHash[ value ];
});
});


// analyse each criterion to determine whether to watch the page, prompt for summary, or open user talk page
// analyse each criterion to determine whether to watch the page, prompt for summary, or open user talk page
var watchPage, promptForSummary;
var watchPage, promptForSummary;
normalizeds.forEach(function(norm) {
normalizeds.forEach(function(norm) {
if (Twinkle.getPref("watchSpeedyPages").indexOf(norm) !== -1) {
if (Twinkle.getPref("watchSpeedyPages").indexOf(norm) !== -1) {
watchPage = true;
watchPage = true;
}
}
if (Twinkle.getPref("promptForSpeedyDeletionSummary").indexOf(norm) !== -1) {
if (Twinkle.getPref("promptForSpeedyDeletionSummary").indexOf(norm) !== -1) {
promptForSummary = true;
promptForSummary = true;
}
}
});
});


var params = {
var params = {
values: values,
values: values,
normalizeds: normalizeds,
normalizeds: normalizeds,
watch: watchPage,
watch: watchPage,
deleteTalkPage: form.talkpage && form.talkpage.checked,
deleteTalkPage: form.talkpage && form.talkpage.checked,
deleteRedirects: form.redirects.checked,
deleteRedirects: form.redirects.checked,
openUserTalk: form.openusertalk.checked,
openUserTalk: form.openusertalk.checked,
promptForSummary: promptForSummary,
promptForSummary: promptForSummary,
templateParams: Twinkle.speedy.getParameters( form, values )
templateParams: Twinkle.speedy.getParameters( form, values )
};
};
if(!params.templateParams) {
if(!params.templateParams) {
return;
return;
}
}


Morebits.simpleWindow.setButtonsEnabled( false );
Morebits.simpleWindow.setButtonsEnabled( false );
Morebits.status.init( form );
Morebits.status.init( form );


Twinkle.speedy.callbacks.sysop.main( params );
Twinkle.speedy.callbacks.sysop.main( params );
};
};


Twinkle.speedy.callback.evaluateUser = function twinklespeedyCallbackEvaluateUser(e) {
Twinkle.speedy.callback.evaluateUser = function twinklespeedyCallbackEvaluateUser(e) {
var form = (e.target.form ? e.target.form : e.target);
var form = (e.target.form ? e.target.form : e.target);


if (e.target.type === "checkbox" || e.target.type === "text" ||
if (e.target.type === "checkbox" || e.target.type === "text" ||
e.target.type === "select") {
e.target.type === "select") {
return;
return;
}
}


var values = Twinkle.speedy.resolveCsdValues(e);
var values = Twinkle.speedy.resolveCsdValues(e);
if (!values) {
if (!values) {
return;
return;
}
}
//var multiple = form.multiple.checked;
//var multiple = form.multiple.checked;
var normalizeds = [];
var normalizeds = [];
$.each(values, function(index, value) {
$.each(values, function(index, value) {
var norm = Twinkle.speedy.normalizeHash[ value ];
var norm = Twinkle.speedy.normalizeHash[ value ];


normalizeds.push(norm);
normalizeds.push(norm);
});
});


// analyse each criterion to determine whether to watch the page/notify the creator
// analyse each criterion to determine whether to watch the page/notify the creator
var watchPage = false;
var watchPage = false;
$.each(normalizeds, function(index, norm) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('watchSpeedyPages').indexOf(norm) !== -1) {
if (Twinkle.getPref('watchSpeedyPages').indexOf(norm) !== -1) {
watchPage = true;
watchPage = true;
return false; // break
return false; // break
}
}
});
});


var notifyuser = false;
var notifyuser = false;
if (form.notify.checked) {
if (form.notify.checked) {
$.each(normalizeds, function(index, norm) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('notifyUserOnSpeedyDeletionNomination').indexOf(norm) !== -1) {
if (Twinkle.getPref('notifyUserOnSpeedyDeletionNomination').indexOf(norm) !== -1) {
notifyuser = true;
notifyuser = true;
return false; // break
return false; // break
}
}
});
});
}
}


var welcomeuser = false;
var welcomeuser = false;
if (notifyuser) {
if (notifyuser) {
$.each(normalizeds, function(index, norm) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').indexOf(norm) !== -1) {
if (Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').indexOf(norm) !== -1) {
welcomeuser = true;
welcomeuser = true;
return false; // break
return false; // break
}
}
});
});
}
}


var csdlog = false;
var csdlog = false;
if (Twinkle.getPref('logSpeedyNominations')) {
if (Twinkle.getPref('logSpeedyNominations')) {
$.each(normalizeds, function(index, norm) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('noLogOnSpeedyNomination').indexOf(norm) === -1) {
if (Twinkle.getPref('noLogOnSpeedyNomination').indexOf(norm) === -1) {
csdlog = true;
csdlog = true;
return false; // break
return false; // break
}
}
});
});
}
}


var params = {
var params = {
values: values,
values: values,
normalizeds: normalizeds,
normalizeds: normalizeds,
watch: watchPage,
watch: watchPage,
usertalk: notifyuser,
// usertalk: notifyuser,
welcomeuser: welcomeuser,
welcomeuser: welcomeuser,
lognomination: csdlog,
lognomination: csdlog,
templateParams: Twinkle.speedy.getParameters( form, values )
templateParams: Twinkle.speedy.getParameters( form, values )
};
};
if (!params.templateParams) {
if (!params.templateParams) {
return;
return;
}
}


Morebits.simpleWindow.setButtonsEnabled( false );
Morebits.simpleWindow.setButtonsEnabled( false );
Morebits.status.init( form );
Morebits.status.init( form );


Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = "标记完成";
Morebits.wiki.actionCompleted.notice = "标记完成";


var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "标记页面");
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "标记页面");
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.speedy.callbacks.user.main);
wikipedia_page.load(Twinkle.speedy.callbacks.user.main);
};
};
})(jQuery);
})(jQuery);

Revision as of 14:48, 24 May 2017

//<nowiki>
// vim: set noet sts=0 sw=8:


(function($){


/*
 ****************************************
 *** twinklespeedy.js: CSD module
 ****************************************
 * Mode of invocation:     Tab ("CSD")
 * Active on:              Non-special, existing pages
 * Config directives in:   TwinkleConfig
 *
 * NOTE FOR DEVELOPERS:
 *   If adding a new criterion, add it to the appropriate places at the top of
 *   twinkleconfig.js.  Also check out the default values of the CSD preferences
 *   in twinkle.js, and add your new criterion to those if you think it would be
 *   good.
 */

Twinkle.speedy = function twinklespeedy() {
    // Disable on:
    // * special pages
    // * Flow pages
    // * non-existent pages
    if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgPageContentModel') === 'flow-board' || !mw.config.get('wgArticleId')) {
        return;
    }

    Twinkle.addPortletLink( Twinkle.speedy.callback, "速刪", "tw-csd", "速刪" );
};

// This function is run when the CSD tab/header link is clicked
Twinkle.speedy.callback = function twinklespeedyCallback() {
    Twinkle.speedy.initDialog(Morebits.userIsInGroup( 'sysop' ) ? Twinkle.speedy.callback.evaluateSysop : Twinkle.speedy.callback.evaluateUser, true);
};

// Used by unlink feature
Twinkle.speedy.dialog = null;

// The speedy criteria list can be in one of several modes
Twinkle.speedy.mode = {
    sysopSingleSubmit: 1,  // radio buttons, no subgroups, submit when "Submit" button is clicked
    sysopRadioClick: 2,  // radio buttons, no subgroups, submit when a radio button is clicked
    sysopMultipleSubmit: 3, // check boxes, subgroups, "Submit" button already present
    sysopMultipleRadioClick: 4, // check boxes, subgroups, need to add a "Submit" button
    userMultipleSubmit: 5,  // check boxes, subgroups, "Submit" button already pressent
    userMultipleRadioClick: 6,  // check boxes, subgroups, need to add a "Submit" button
    userSingleSubmit: 7,  // radio buttons, subgroups, submit when "Submit" button is clicked
    userSingleRadioClick: 8,  // 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.sysopSingleSubmit ||
            mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
            mode === Twinkle.speedy.mode.sysopRadioClick ||
            mode === Twinkle.speedy.mode.sysopMultipleRadioClick;
    },
    // do we have a "Submit" button once the form is created?
    hasSubmitButton: function twinklespeedyModeHasSubmitButton(mode) {
        return mode === Twinkle.speedy.mode.sysopSingleSubmit ||
            mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
            mode === Twinkle.speedy.mode.sysopMultipleRadioClick ||
            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.sysopMultipleSubmit ||
            mode === Twinkle.speedy.mode.userMultipleRadioClick ||
            mode === Twinkle.speedy.mode.sysopMultipleRadioClick;
    },
};

// 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( "選擇速刪理由" );
    dialog.setScriptName( "Twinkle" );
    // dialog.addFooterLink( "快速删除方针", "WP:CSD" );
    // dialog.addFooterLink( "Twinkle帮助", "WP:TW/DOC#speedy" );

    var form = new Morebits.quickForm( callbackfunc, (Twinkle.getPref('speedySelectionStyle') === 'radioClick' ? 'change' : null) );
    if( Morebits.userIsInGroup( 'sysop' ) ) {
        form.append( {
                type: 'checkbox',
                list: [
                    {
                        label: '只標記,不刪除',
                        value: 'tag_only',
                        name: 'tag_only',
                        tooltip: '如果您只想標記此頁面而不是刪除',
                        checked : Twinkle.getPref('deleteSysopDefaultToTag'),
                        event: function( event ) {
                            var cForm = event.target.form;
                            var cChecked = event.target.checked;
                            // enable/disable talk page checkbox
                            if (cForm.talkpage) {
                                cForm.talkpage.disabled = cChecked;
                                cForm.talkpage.checked = !cChecked && Twinkle.getPref('deleteTalkPageOnDelete');
                            }
                            // enable/disable redirects checkbox
                            cForm.redirects.disabled = cChecked;
                            cForm.redirects.checked = !cChecked;
                            // enable/disable delete multiple
                            cForm.delmultiple.disabled = cChecked;
                            cForm.delmultiple.checked = false;
                            // enable/disable open talk page checkbox
                            cForm.openusertalk.disabled = cChecked;
                            cForm.openusertalk.checked = false;

                            // enable/disable notify checkbox
                            // cForm.notify.disabled = !cChecked;
                            // cForm.notify.checked = cChecked;
                            // enable/disable multiple
                            cForm.multiple.disabled = !cChecked;
                            cForm.multiple.checked = false;

                            Twinkle.speedy.callback.modeChanged(cForm);

                            event.stopPropagation();
                        }
                    }
                ]
            } );

        var deleteOptions = form.append( {
                type: 'div',
                name: 'delete_options'
            } );
        deleteOptions.append( {
                type: 'header',
                label: '刪除相關設定'
            } );
        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
            deleteOptions.append( {
                type: 'checkbox',
                list: [
                    {
                        label: '刪除討論頁',
                        value: 'talkpage',
                        name: 'talkpage',
                        tooltip: "刪除時附帶刪除此頁面的討論頁。",
                        checked: Twinkle.getPref('deleteTalkPageOnDelete'),
                        disabled: Twinkle.getPref('deleteSysopDefaultToTag'),
                        event: function( event ) {
                            event.stopPropagation();
                        }
                    }
                ]
            } );
        }
        deleteOptions.append( {
                type: 'checkbox',
                list: [
                    {
                        label: '刪除重定向',
                        value: 'redirects',
                        name: 'redirects',
                        tooltip: "刪除到此頁的重定向。",
                        checked: Twinkle.getPref('deleteRedirectsOnDelete'),
                        disabled: Twinkle.getPref('deleteSysopDefaultToTag'),
                        event: function( event ) {
                            event.stopPropagation();
                        }
                    }
                ]
            } );
        deleteOptions.append( {
            type: 'checkbox',
            list: [
                {
                    label: '應用多個理由刪除',
                    value: 'delmultiple',
                    name: 'delmultiple',
                    tooltip: "您可選擇應用於該頁的多个理由。",
                    event: function( event ) {
                        Twinkle.speedy.callback.modeChanged( event.target.form );
                        event.stopPropagation();
                    }
                }
            ]
        } );
        deleteOptions.append( {
                type: 'checkbox',
                list: [
                    {
                        label: '開啟用戶對話頁',
                        value: 'openusertalk',
                        name: 'openusertalk',
                        tooltip: '此項的預設值為開啟您的對話頁設定。在您選擇應用多條理由刪除時此項將保持不變。',
                        checked : false
                    }
                ]
            } );
    }

    var tagOptions = form.append( {
            type: 'div',
            name: 'tag_options'
        } );

    if( Morebits.userIsInGroup( 'sysop' ) ) {
        tagOptions.append( {
                type: 'header',
                label: '標記相關設定'
            } );
    }

/*
    tagOptions.append( {
            type: 'checkbox',
            list: [
                {
                    label: '如可能,通知建立者',
                    value: 'notify',
                    name: 'notify',
                    tooltip: "如果開啟,提請刪除時將會在建立者的對話頁加入一个通知模板。",
                    checked: !Morebits.userIsInGroup( 'sysop' ) || Twinkle.getPref('deleteSysopDefaultToTag'),
                    disabled: Morebits.userIsInGroup( 'sysop' ) && !Twinkle.getPref('deleteSysopDefaultToTag'),
                    event: function( event ) {
                        event.stopPropagation();
                    }
                }
            ]
        } );
*/
    tagOptions.append( {
            type: 'checkbox',
            list: [
                {
                    label: '應用多个理由',
                    value: 'multiple',
                    name: 'multiple',
                    tooltip: "您可選擇應用於該頁的多個理由。",
                    disabled: Morebits.userIsInGroup( 'sysop' ) && !Twinkle.getPref('deleteSysopDefaultToTag'),
                    event: function( event ) {
                        Twinkle.speedy.callback.modeChanged( event.target.form );
                        event.stopPropagation();
                    }
                }
            ]
        } );

    form.append( {
            type: 'div',
            name: 'work_area',
            label: '初始化CSD模块失败,请重试,或将这报告给Twinkle开发者。'
        } );

    if( Twinkle.getPref( 'speedySelectionStyle' ) !== 'radioClick' ) {
        form.append( { type: 'submit' } );
    }

    var result = form.render();
    dialog.setContent( result );
    dialog.display();

    Twinkle.speedy.callback.modeChanged( result );

    // if sysop, check if CSD is already on the page and fill in custom rationale
    if (Morebits.userIsInGroup('sysop') && $("#delete-reason").length) {
        var customOption = $("input[name=csd][value=reason]")[0];

        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.getMode = function twinklespeedyCallbackGetMode(form) {
    var mode = Twinkle.speedy.mode.userSingleSubmit;
    if (form.tag_only && !form.tag_only.checked) {
        if (form.delmultiple.checked) {
            mode = Twinkle.speedy.mode.sysopMultipleSubmit;
        } else {
            mode = Twinkle.speedy.mode.sysopSingleSubmit;
        }
    } else {
        if (form.multiple.checked) {
            mode = Twinkle.speedy.mode.userMultipleSubmit;
        } else {
            mode = Twinkle.speedy.mode.userSingleSubmit;
        }
    }
    if (Twinkle.getPref('speedySelectionStyle') === 'radioClick') {
        mode++;
    }

    return mode;
};

Twinkle.speedy.callback.modeChanged = function twinklespeedyCallbackModeChanged(form) {
    var namespace = mw.config.get('wgNamespaceNumber');

    // first figure out what mode we're in
    var mode = Twinkle.speedy.callback.getMode(form);

    if (Twinkle.speedy.mode.isSysop(mode)) {
        $("[name=delete_options]").show();
        $("[name=tag_options]").hide();
    } else {
        $("[name=delete_options]").hide();
        $("[name=tag_options]").show();
    }

    var work_area = new Morebits.quickForm.element( {
            type: 'div',
            name: 'work_area'
        } );

    if (mode === Twinkle.speedy.mode.userMultipleRadioClick || mode === Twinkle.speedy.mode.sysopMultipleRadioClick) {
        var evaluateType = Twinkle.speedy.mode.isSysop(mode) ? 'evaluateSysop' : 'evaluateUser';

        work_area.append( {
                type: 'div',
                label: '當選擇完成後,點選:'
            } );
        work_area.append( {
                type: 'button',
                name: 'submit-multiple',
                label: '提交',
                event: function( event ) {
                    Twinkle.speedy.callback[evaluateType]( event );
                    event.stopPropagation();
                }
            } );
    }

    var radioOrCheckbox = (Twinkle.speedy.mode.isMultiple(mode) ? 'checkbox' : 'radio');

    if (Twinkle.speedy.mode.isSysop(mode) && !Twinkle.speedy.mode.isMultiple(mode)) {
        work_area.append( { type: 'header', label: '自訂理由' } );
        work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.customRationale, mode) } );
    }

    switch (namespace) {
        case 0:  // article
            work_area.append( { type: 'header', label: '條目' } );
            work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.articleList, mode) } );
            break;

        case 14:  // category
            work_area.append( { type: 'header', label: '分類' } );
            work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.categoryList, mode) } );
            break;

        default:
            break;
    }

    // custom rationale lives under general criteria when tagging
    var generalCriteria = Twinkle.speedy.generalList;
    if(!Twinkle.speedy.mode.isSysop(mode)) {
        generalCriteria = Twinkle.speedy.customRationale.concat(generalCriteria);
    }
    work_area.append( { type: 'header', label: '常規' } );
    work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(generalCriteria, mode) });

    if (mw.config.get('wgIsRedirect') || Morebits.userIsInGroup('sysop')) {
        work_area.append( { type: 'header', label: '重定向' } );
        if (namespace === 0 || namespace === 118) {
            work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.redirectArticleList, mode) } );
        }
        work_area.append( { type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.redirectList, mode) } );
    }

    var old_area = Morebits.quickForm.getElements(form, "work_area")[0];
    form.replaceChild(work_area.render(), old_area);
};

Twinkle.speedy.generateCsdList = function twinklespeedyGenerateCsdList(list, mode) {
    // mode switches
    var isSysop = Twinkle.speedy.mode.isSysop(mode);
    var multiple = Twinkle.speedy.mode.isMultiple(mode);
    var hasSubmitButton = Twinkle.speedy.mode.hasSubmitButton(mode);

    var openSubgroupHandler = function(e) {
        $(e.target.form).find('input').prop('disabled', true);
        $(e.target.form).children().css('color', 'gray');
        $(e.target).parent().css('color', 'black').find('input').prop('disabled', false);
        $(e.target).parent().find('input:text')[0].focus();
        e.stopPropagation();
    };
    var submitSubgroupHandler = function(e) {
        var evaluateType = Twinkle.speedy.mode.isSysop(mode) ? 'evaluateSysop' : 'evaluateUser';
        Twinkle.speedy.callback[evaluateType](e);
        e.stopPropagation();
    };

    return $.map(list, function(critElement) {
        var criterion = $.extend({}, critElement);

        if (multiple) {
            if (criterion.hideWhenMultiple) {
                return null;
            }
            if (criterion.hideSubgroupWhenMultiple) {
                criterion.subgroup = null;
            }
        } else {
            if (criterion.hideWhenSingle) {
                return null;
            }
            if (criterion.hideSubgroupWhenSingle) {
                criterion.subgroup = null;
            }
        }

        if (isSysop) {
            if (criterion.hideWhenSysop) {
                return null;
            }
            if (criterion.hideSubgroupWhenSysop) {
                criterion.subgroup = null;
            }
        } else {
            if (criterion.hideWhenUser) {
                return null;
            }
            if (criterion.hideSubgroupWhenUser) {
                criterion.subgroup = null;
            }
        }

        if (mw.config.get('wgIsRedirect') && criterion.hideWhenRedirect) {
            return null;
        }

        if (criterion.subgroup && !hasSubmitButton) {
            if ($.isArray(criterion.subgroup)) {
                criterion.subgroup.push({
                    type: 'button',
                    name: 'submit',
                    label: '提交',
                    event: submitSubgroupHandler
                });
            } else {
                criterion.subgroup = [
                    criterion.subgroup,
                    {
                        type: 'button',
                        name: 'submit',  // ends up being called "csd.submit" so this is OK
                        label: '提交',
                        event: submitSubgroupHandler
                    }
                ];
            }
            // FIXME: does this do anything?
            criterion.event = openSubgroupHandler;
        }

        if ( isSysop ) {
            var originalEvent = criterion.event;
            criterion.event = function(e) {
                if (multiple) return originalEvent(e);

                var normalizedCriterion = Twinkle.speedy.normalizeHash[e.target.value];
                $('[name=openusertalk]').prop('checked',
                        Twinkle.getPref('openUserTalkPageOnSpeedyDelete').indexOf(normalizedCriterion) !== -1
                    );
                if ( originalEvent ) {
                    return originalEvent(e);
                }
            };
        }

        return criterion;
    });
};

Twinkle.speedy.customRationale = [
    {
        label: '自訂理由' + (Morebits.userIsInGroup('sysop') ? '(自訂刪除理由)' : ''),
        value: 'reason',
        tooltip: '該頁應明顯不適合維基大典。如有疑問,請使用「議刪」而非「速刪」。',
        subgroup: {
            name: 'reason_1',
            type: 'input',
            label: '理由:',
            size: 60
        },
        hideWhenMultiple: true
    }
];

Twinkle.speedy.articleList = [
    {
        label: '極短且不知所云',
        value: '極短且不知所云',
    },
    {
        label: '生不立傳',
        value: '生不立傳',
    },
    {
        label: '非文言',
        value: '非文言'
    },
];

Twinkle.speedy.categoryList = [
    {
        label: '空類',
        value: '空類',
        tooltip: '不適用於維護性質的類別。'
    }
];

Twinkle.speedy.generalList = [
    {
        label: '作者請求',
        value: '作者請求',
        tooltip: '僅在頁面沒有其他作者(或者只有提刪者本人有實質編輯)的情況下適用。'
    },
    {
        label: '毀我大典',
        value: '毀我大典',
    },
    {
        label: '廣告宣傳',
        value: '廣告宣傳',
    },
    {
        label: 'G8: 管理员因技术原因删除页面',
        value: 'g8',
        tooltip: '包括解封用户后删除用户页、因用户夺取而删除、删除MediaWiki页面、因移动请求而删除页面。',
        hideWhenUser: true
    },
    {
        label: 'G10: 原作者清空页面或提出删除,且贡献者只有一人',
        value: 'g10',
        tooltip: '对条目内容无实际修改的除外;提请须出于善意,及附有合理原因。',
        subgroup: {
            name: 'g10_rationale',
            type: 'input',
            label: '可选的解释:',
            tooltip: '比如作者在哪里请求了删除。',
            size: 60
        },
        hideSubgroupWhenSysop: true
    },
    {
        label: 'G11: 明显的广告宣传页面,或只有相关人物或团体的联系方法的页面',
        value: 'g11',
        tooltip: '页面只收宣传之用,并须完全重写才能贴合百科全书要求。须注意,仅仅以某公司或产品为主题的条目,并不直接导致其自然满足此速删标准。'
    },
    {
        label: 'G12: 未列明来源且语调负面的生者传记',
        value: 'g12',
        tooltip: '注意是未列明来源且语调负面,必须2项均符合。'
    },
    {
        label: 'G13: 明显、拙劣的机器翻译',
        value: 'g13'
    },
    {
        label: 'G14: 超过两周没有进行任何翻译的非现代标准汉语页面',
        value: 'g14',
        tooltip: '包括所有未翻译的外语、汉语方言以及文言文。',
        hideWhenUser: true
    },
    {
        label: 'G15: 孤立页面,比如没有主页面的讨论页、指向空页面的重定向等',
        value: 'g15',
        tooltip: '包括以下几种类型:1. 没有对应文件的文件页面;2. 没有对应母页面的子页面,用户页子页面除外;3. 指向不存在页面的重定向;4. 没有对应内容页面的讨论页,讨论页存档和用户讨论页除外;5. 不存在注册用户的用户页及用户页子页面,随用户更名产生的用户页重定向除外。请在删除时注意有无将内容移至他处的必要。不包括在主页面挂有{{CSD Placeholder}}模板的讨论页。'
    },
    {
        label: 'G16: 因为主页面侵权而创建的临时页面仍然侵权',
        value: 'g16',
        hideWhenUser: true
    }
];

Twinkle.speedy.redirectArticleList = [
    {
        label: 'R2: 跨名字空间重定向。',
        value: 'r2',
        tooltip: '由条目的名字空间重定向至非条目名字空间,或将用户页移出条目名字空间时遗留的重定向。'
    }
];

Twinkle.speedy.redirectList = [
    {
        label: 'R3: 格式错误,或明显笔误的重定向。',
        value: 'r3',
        tooltip: '非一眼能看出的拼写错误和翻译或标题用字的争议应交由存废讨论处理。',
        subgroup: {
            name: 'r3_type',
            type: 'select',
            label: '适用类别:',
            list: [
                { label: '请选择', value: '' },
                { label: '标题繁简混用', value: '标题繁简混用。' },
                { label: '消歧义使用的括号或空格错误', value: '消歧义使用的括号或空格错误。' },
                { label: '间隔号使用错误', value: '间隔号使用错误。' },
                { label: '标题中使用非常见的错别字', value: '标题中使用非常见的错别字。' },
                { label: '移动侵权页面的临时页后所产生的重定向', value: '移动侵权页面的临时页后所产生的重定向。' }
            ]
        },
        hideSubgroupWhenSysop: true
    },
    {
        label: 'R5: 指向本身的重定向或循环的重定向。',
        value: 'r5',
        tooltip: '如A→B→C→……→A。'
    }
];

Twinkle.speedy.normalizeHash = {
    'reason': 'db',
    'multiple': 'multiple',
    'multiple-finish': 'multiple-finish',
    'g1': 'g1',
    'g2': 'g2',
    'g3': 'g3',
    'g5': 'g5',
    'g8': 'g8',
    'g10': 'g10',
    'g11': 'g11',
    'g12': 'g12',
    'g13': 'g13',
    'g14': 'g14',
    'g15': 'g15',
    'g16': 'g16',
    'a1': 'a1',
    'a2': 'a2',
    'a3': 'a3',
    'a5': 'a5',
    'a6': 'a6',
    'r2': 'r2',
    'r3': 'r3',
    'r5': 'r5',
    'f1': 'f1',
    'f3': 'f3',
    'f4': 'f4',
    'f5': 'f5',
    'f6': 'f6',
    'f7': 'f7',
    'o1': 'o1',
    'o3': 'o3',
    'o4': 'o4'
};

// keep this synched with [[MediaWiki:Deletereason-dropdown]]
Twinkle.speedy.reasonHash = {
    'reason': '',
// General
    'g1': '无实际内容',
    'g2': '测试页',
    'g3': '破坏',
    'g5': '曾经依存废讨论被删除的重建内容',
    'g8': '技术原因',
    'g10': '作者请求',
    'g11': '广告或宣传',
    'g12': '未列明来源或违反生者传记的负面内容',
    'g13': '明显且拙劣的机器翻译',
    'g14': '超过两周没有翻译的非现代标准汉语页面',
    'g15': '孤立页面',
    'g16': '临时页面依然侵权',
// Articles
    'a1': '非常短而无定义或内容',
    'a2': '内容只包含参考、链接、模板或/及分类',
    'a3': '与其他中文维基计划内容相同的文章',
    'a5': '条目建立时之内容即与其他现有条目内容相同',
    'a6': '复制自其他维基百科语言版本',
// Redirects
    'r2': '跨名字空间重定向',
    'r3': '标题错误的重定向',
    'r5': '指向本身的重定向或循环的重定向',
// Images and media
    'f1': '重复的图片',
    'f3': '[[:Category:未知版权的档案]]',
    'f4': '[[:Category:來源不明檔案]]',
    'f5': '已有高分辨率的图片取代',
    'f6': '孤立而没有被条目使用的非自由版权图片',
    'f7': '[[:Category:与维基共享资源重复的档案]]',
// User pages
    'o1': '用户请求删除自己的用户页或其子页面',
    'o3': '匿名用户的讨论页',
// Categories
    'o4': '空的类别'
// Templates
// Portals
};

Twinkle.speedy.callbacks = {
    getTemplateCodeAndParams: function(params) {
        var code, parameters, i;
        if (params.normalizeds.length > 1) {
            code = "{{delete";
            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') {
                        code += "|" + parameters[i];
                    }
                }
                $.extend(params.utparams, Twinkle.speedy.getUserTalkParameters(norm, parameters));
            });
            code += "}}";
        } else {
            parameters = params.templateParams[0] || [];
            code = "{{delete";
            if (params.values[0] !== 'reason') {
                code += '|' + params.values[0];
            }
            for (i in parameters) {
                if (typeof parameters[i] === 'string') {
                    code += "|" + parameters[i];
                }
            }
            code += "}}";
            params.utparams = Twinkle.speedy.getUserTalkParameters(params.normalizeds[0], parameters);
        }

        return [code, params.utparams];
    },

    parseWikitext: function(wikitext, callback) {
        var query = {
            action: "parse",
            prop: "text",
            pst: "true",
            text: wikitext,
            contentmodel: "wikitext",
            title: mw.config.get("wgPageName")
        };

        var statusIndicator = new Morebits.status( '构造删除理由' );
        var api = new Morebits.wiki.api( '解析删除模板', query, function(apiObj) {
                var reason = decodeURIComponent($(apiObj.getXML().querySelector('text').childNodes[0].nodeValue).find('#delete-reason').text()).replace(/\+/g, ' ');
                if (!reason) {
                    statusIndicator.warn( '未能从删除模板生成删除理由' );
                } else {
                    statusIndicator.info( '完成' );
                }
                callback(reason);
            }, statusIndicator);
        api.post();
    },

    sysop: {
        main: function( params ) {
            var reason;

            if (!params.normalizeds.length && params.normalizeds[0] === 'db') {
                reason = prompt("输入删除理由:", "");
                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("输入删除理由,或点击确定以接受自动生成的:", presetReason);
                    }
                    Twinkle.speedy.callbacks.sysop.deletePage( reason, params );
                });
            }
        },
        deletePage: function( reason, params ) {
            var thispage = new Morebits.wiki.page( mw.config.get('wgPageName'), "删除页面" );

            if (reason === null) {
                return Morebits.status.error("询问理由", "用户取消操作。");
            } else if (!reason || !reason.replace(/^\s*/, "").replace(/\s*$/, "")) {
                return Morebits.status.error("询问理由", "你不给我理由…我就…不管了…");
            }
            thispage.setEditSummary( reason + Twinkle.getPref('deletionSummaryAd') );
            thispage.deletePage(function() {
                thispage.getStatusElement().info("完成");
                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.openUserTalk ) {
                thispage.setCallbackParameters( params );
                thispage.lookupCreator( Twinkle.speedy.callbacks.sysop.openUserTalkPage );
            }
        },
        deleteTalk: function( params ) {
            // delete talk page
            if (params.deleteTalkPage &&
                    params.normalized !== 'f7' &&
                    params.normalized !== 'o1' &&
                    document.getElementById( 'ca-talk' ).className !== 'new') {
                var talkpage = new Morebits.wiki.page( Morebits.wikipedia.namespaces[ mw.config.get('wgNamespaceNumber') + 1 ] + ':' + mw.config.get('wgTitle'), "删除讨论页" );
                talkpage.setEditSummary('[[WP:CSD#G15|G15]]: 孤立页面: 已删除页面“' + Morebits.pageNameNorm + "”的讨论页" + Twinkle.getPref('deletionSummaryAd'));
                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);
            } 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  // 500 is max for normal users, 5000 for bots and sysops
                };
                var wikipedia_api = new Morebits.wiki.api( '取得重定向列表…', query, Twinkle.speedy.callbacks.sysop.deleteRedirectsMain,
                    new Morebits.status( '删除重定向' ) );
                wikipedia_api.params = params;
                wikipedia_api.post();
            }

            // prompt for protect on G11
            var $link, $bigtext;
            if (params.normalized === 'g11') {
                $link = $('<a/>', {
                    'href': '#',
                    'text': '点击这里施行保护',
                    'css': { 'fontSize': '130%', 'fontWeight': 'bold' },
                    'click': function(){
                        Morebits.wiki.actionCompleted.redirect = null;
                        Twinkle.speedy.dialog.close();
                        mw.config.set('wgArticleId', 0);
                        Twinkle.protect.callback();
                    }
                });
                $bigtext = $('<span/>', {
                    'text': '白纸保护该页',
                    'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
                });
                Morebits.status.info($bigtext[0], $link[0]);
            }

            // promote Unlink tool
            var $link, $bigtext;
            if( mw.config.get('wgNamespaceNumber') === 6 && params.normalized !== 'f7' ) {
                $link = $('<a/>', {
                    'href': '#',
                    'text': '点击这里前往反链工具',
                    'css': { 'fontWeight': 'bold' },
                    'click': function(){
                        Morebits.wiki.actionCompleted.redirect = null;
                        Twinkle.speedy.dialog.close();
                        Twinkle.unlink.callback("取消对已删除文件 " + Morebits.pageNameNorm + " 的使用");
                    }
                });
                $bigtext = $('<span/>', {
                    'text': '取消对已删除文件的使用',
                    'css': { 'fontWeight': 'bold' }
                });
                Morebits.status.info($bigtext[0], $link[0]);
            } else if (params.normalized !== 'f7') {
                $link = $('<a/>', {
                    'href': '#',
                    'text': '点击这里前往反链工具',
                    'css': { 'fontWeight': 'bold' },
                    'click': function(){
                        Morebits.wiki.actionCompleted.redirect = null;
                        Twinkle.speedy.dialog.close();
                        Twinkle.unlink.callback("取消对已删除页面 " + Morebits.pageNameNorm + " 的链接");
                    }
                });
                $bigtext = $('<span/>', {
                    'text': '取消对已删除页面的链接',
                    'css': { 'fontWeight': 'bold' }
                });
                Morebits.status.info($bigtext[0], $link[0]);
            }
        },
        openUserTalkPage: function( pageobj ) {
            pageobj.getStatusElement().unlink();  // don't need it anymore
            var user = pageobj.getCreator();
            var params = pageobj.getCallbackParameters();

            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': '点此打开User talk:' + user,
                    'target': '_blank',
                    'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
                });
                $bigtext = $('<span/>', {
                    'text': '通知页面创建者',
                    '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('打开用户' + user + '对话页编辑表单', '打开中…');

                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( '完成' );
            }
        },
        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("未发现重定向");
                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 + '(完成)' );
                    Morebits.wiki.removeCheckpoint();
                }
            };

            Morebits.wiki.addCheckpoint();

            $snapshot.each(function(key, value) {
                var title = $(value).attr('title');
                var page = new Morebits.wiki.page(title, '删除重定向 "' + title + '"');
                page.setEditSummary('[[WP:CSD#G15|G15]]: 孤立页面: 重定向到已删除页面“' + Morebits.pageNameNorm + "”" + Twinkle.getPref('deletionSummaryAd'));
                page.deletePage(onsuccess);
            });
        }
    },

    user: {
        main: function(pageobj) {
            var statelem = pageobj.getStatusElement();

            if (!pageobj.exists()) {
                statelem.error( "页面不存在,可能已被删除" );
                return;
            }

            var text = pageobj.getPageText();
            var params = pageobj.getCallbackParameters();

            statelem.status( '检查页面已有标记…' );

            // check for existing deletion tags
            var tag = /(?:\{\{\s*(db|d|delete|db-.*?)(?:\s*\||\s*\}\}))/i.exec( text );
            if ( tag ) {
                statelem.error( [ Morebits.htmlNode( 'strong', tag[1] ) , " 已被置于页面中。" ] );
                return;
            }

            var copyvio = /(?:\{\{\s*(copyvio)[^{}]*?\}\})/i.exec( text );
            if ( copyvio ) {
                statelem.error( '页面中已有版权验证模板。' );
                return;
            }

            var xfd = /(?:\{\{([rsaiftcmv]fd|md1|proposed deletion)[^{}]*?\}\})/i.exec( text );
            if ( xfd && !confirm( "删除相关模板{{" + xfd[1] + "}}已被置于页面中,您是否仍想添加一个快速删除模板?" ) ) {
                statelem.error( '页面已被提交至存废讨论。' );
                return;
            }

            // given the params, builds the template and also adds the user talk page parameters to the params that were passed in
            // returns => [<string> wikitext, <object> utparams]
            var buildData = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params),
                code = buildData[0];
            params.utparams = buildData[1];

            var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'));
            // patrol the page, if reached from Special:NewPages
            if( Twinkle.getPref('markSpeedyPagesAsPatrolled') ) {
                thispage.patrol();
            }

            // 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>";
            }

            // Remove tags that become superfluous with this action
            text = text.replace(/\{\{\s*([Nn]ew unreviewed article|[Uu]nreviewed|[Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, "");
            if (mw.config.get('wgNamespaceNumber') === 6) {
                // remove "move to Commons" tag - deletion-tagged files cannot be moved to Commons
                text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, "");
            }

            // Generate edit summary for edit
            var editsummary;
            if (params.normalizeds.length > 1) {
                editsummary = '请求快速删除(';
                $.each(params.normalizeds, function(index, norm) {
                    editsummary += '[[WP:CSD#' + norm.toUpperCase() + '|CSD ' + norm.toUpperCase() + ']]、';
                });
                editsummary = editsummary.substr(0, editsummary.length - 1); // remove trailing comma
                editsummary += ')。';
            } else if (params.normalizeds[0] === "db") {
                editsummary = '请求[[WP:CSD|快速删除]]:' + params.templateParams[0]["1"];
            } else {
                editsummary = "请求快速删除([[WP:CSD#" + params.normalizeds[0].toUpperCase() + "|CSD " + params.normalizeds[0].toUpperCase() + "]])";
            }

            pageobj.setPageText(code + "\n" + text);
            pageobj.setEditSummary(editsummary + Twinkle.getPref('summaryAd'));
            pageobj.setWatchlist(params.watch);
            pageobj.setCreateOption('nocreate');
            pageobj.save(Twinkle.speedy.callbacks.user.tagComplete);
        },

        tagComplete: function(pageobj) {
            var params = pageobj.getCallbackParameters();

            // Notification to first contributor
            if (params.usertalk) {
                var callback = function(pageobj) {
                    var initialContrib = pageobj.getCreator();

                    // disallow warning yourself
                    if (initialContrib === mw.config.get('wgUserName')) {
                        Morebits.status.warn("您(" + initialContrib + ")创建了该页,跳过通知");

                    // 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("通知页面创建者:用户创建了自己的对话页");

                    } else {
                        var talkPageName = 'User talk:' + initialContrib;
                        Morebits.wiki.flow.check(talkPageName, function () {
                            var flowpage = new Morebits.wiki.flow(talkPageName, "通知页面创建者(" + initialContrib + ")");
                            flowpage.setTopic('[[:' + Morebits.pageNameNorm + ']]的快速删除通知');
                            flowpage.setContent('{{subst:User:逆襲的天邪鬼/Twinkle/Template:Db-notice|target=' + Morebits.pageNameNorm + '|flow=yes}}');
                            flowpage.newTopic();
                        }, function() {
                            var usertalkpage = new Morebits.wiki.page(talkPageName, "通知页面创建者(" + initialContrib + ")"),
                                notifytext, i;

                            notifytext = "\n{{subst:User:逆襲的天邪鬼/Twinkle/Template:Db-notice|target=" + Morebits.pageNameNorm;
                            notifytext += (params.welcomeuser ? "" : "|nowelcome=yes") + "}}--~~~~";

                            var editsummary = "通知:";
                            if (params.normalizeds.indexOf("g12") === -1) {  // no article name in summary for G10 deletions
                                editsummary += "页面[[" + Morebits.pageNameNorm + "]]";
                            } else {
                                editsummary += "一攻击性页面";
                            }
                            editsummary += "快速删除提名";

                            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.lookupCreator(callback);
            }
            // 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_page = new Morebits.wiki.page("User:" + mw.config.get('wgUserName') + "/" + Twinkle.getPref('speedyLogPageName'), "添加项目到用户日志");
            params.logInitialContrib = initialContrib;
            wikipedia_page.setCallbackParameters(params);
            wikipedia_page.load(Twinkle.speedy.callbacks.user.saveLog);
        },

        saveLog: function(pageobj) {
            var text = pageobj.getPageText();
            var params = pageobj.getCallbackParameters();

            var appendText = "";

            // add blurb if log page doesn't exist
            if (!pageobj.exists()) {
                appendText +=
                    "这是该用户使用[[WP:TW|Twinkle]]的速删模块做出的[[WP:CSD|快速删除]]提名列表。\n\n" +
                    "如果您不再想保留此日志,请在[[Wikipedia:Twinkle/参数设置|参数设置]]中关掉,并" +
                    "使用[[WP:CSD#O1|CSD O1]]提交快速删除。\n";
                if (Morebits.userIsInGroup("sysop")) {
                    appendText += "\n此日志并不记录用Twinkle直接执行的删除。\n";
                }
            }

            // create monthly header
            var date = new Date();
            var headerRe = new RegExp("^==+\\s*" + date.getUTCFullYear() + "\\s*年\\s*" + (date.getUTCMonth() + 1) + "\\s*月\\s*==+", "m");
            if (!headerRe.exec(text)) {
                appendText += "\n\n=== " + date.getUTCFullYear() + "年" + (date.getUTCMonth() + 1) + "月 ===";
            }

            appendText += "\n# [[:" + Morebits.pageNameNorm + "]]: ";
            if (params.fromDI) {
                appendText += "图版[[WP:CSD#" + params.normalized.toUpperCase() + "|CSD " + params.normalized.toUpperCase() + "]]({{tl|" + params.templatename + "}})";
            } else {
                if (params.normalizeds.length > 1) {
                    appendText += "多个理由(";
                    $.each(params.normalizeds, function(index, norm) {
                        appendText += "[[WP:CSD#" + norm.toUpperCase() + "|" + norm.toUpperCase() + ']]、';
                    });
                    appendText = appendText.substr(0, appendText.length - 1);  // remove trailing comma
                    appendText += ')';
                } else if (params.normalizeds[0] === "db") {
                    appendText += "自定义理由";
                } else {
                    appendText += "[[WP:CSD#" + params.normalizeds[0].toUpperCase() + "|CSD " + params.normalizeds[0].toUpperCase() + "]]";
                }
            }

            if (params.logInitialContrib) {
                appendText += ";通知{{user|" + params.logInitialContrib + "}}";
            }
            appendText += " ~~~~~\n";

            pageobj.setAppendText(appendText);
            pageobj.setEditSummary("记录对[[" + Morebits.pageNameNorm + "]]的快速删除提名" + Twinkle.getPref('summaryAd'));
            pageobj.setCreateOption("recreate");
            pageobj.append();
        }
    }
};

// validate subgroups in the form passed into the speedy deletion tag
Twinkle.speedy.getParameters = function twinklespeedyGetParameters(form, values) {
    var parameters = [];

    $.each(values, function(index, value) {
        var currentParams = [];
        switch (value) {
            case 'reason':
                if (form["csd.reason_1"]) {
                    var dbrationale = form["csd.reason_1"].value;
                    if (!dbrationale || !dbrationale.trim()) {
                        alert( '自定义理由:请指定理由。' );
                        parameters = null;
                        return false;
                    }
                    currentParams["1"] = dbrationale;
                }
                break;

            case 'a5':
                if (form["csd.a5_pagename"]) {
                    var otherpage = form["csd.a5_pagename"].value;
                    if (!otherpage || !otherpage.trim()) {
                        alert( 'CSD A5:请提供现有条目的名称。' );
                        parameters = null;
                        return false;
                    }
                    currentParams.pagename = otherpage;
                }
                break;

            case 'g5':
                if (form["csd.g5_1"]) {
                    var deldisc = form["csd.g5_1"].value;
                    if (deldisc) {
                        if (deldisc.substring(0, 9) !== "Wikipedia" &&
                            deldisc.substring(0, 3) !== "WP:" &&
                            deldisc.substring(0, 5) !== "维基百科:" &&
                            deldisc.substring(0, 5) !== "維基百科:") {
                            alert( 'CSD G5:您提供的讨论页名必须以“Wikipedia:”开头。' );
                            parameters = null;
                            return false;
                        }
                        currentParams["1"] = deldisc;
                    }
                }
                break;

            case 'g10':
                if (form["csd.g10_rationale"] && form["csd.g10_rationale"].value) {
                    currentParams.rationale = form["csd.g10_rationale"].value;
                }
                break;

            case 'f1':
                if (form["csd.f1_filename"]) {
                    var redimage = form["csd.f1_filename"].value;
                    if (!redimage || !redimage.trim()) {
                        alert( 'CSD F1:请提供另一文件的名称。' );
                        parameters = null;
                        return false;
                    }
                    currentParams.filename = redimage.replace(/^\s*(Image|File|文件|檔案):/i, "");
                }
                break;

            case 'f5':
                if (form["csd.f5_filename"]) {
                    var redimage = form["csd.f5_filename"].value;
                    if (!redimage || !redimage.trim()) {
                        alert( 'CSD F5:请提供另一文件的名称。' );
                        parameters = null;
                        return false;
                    }
                    currentParams.filename = redimage.replace(/^\s*(Image|File|文件|檔案):/i, "");
                }
                break;

            case 'f7':
                if (form["csd.f7_filename"]) {
                    var filename = form["csd.f7_filename"].value;
                    if (filename && filename !== Morebits.pageNameNorm) {
                        if (filename.indexOf("Image:") === 0 || filename.indexOf("File:") === 0 ||
                            filename.indexOf("文件:") === 0 || filename.indexOf("檔案:") === 0) {
                            currentParams["1"] = filename;
                        } else {
                            currentParams["1"] = "File:" + filename;
                        }
                    }
                }
                break;

            case 'r3':
                if (form["csd.r3_type"]) {
                    var redirtype = form["csd.r3_type"].value;
                    if (!redirtype) {
                        alert( 'CSD R3:请选择适用类别。' );
                        parameters = null;
                        return false;
                    }
                    currentParams["1"] = redirtype;
                }
                break;

            default:
                break;
        }
        parameters.push(currentParams);
    });
    return parameters;
};

// function for processing talk page notification template parameters
Twinkle.speedy.getUserTalkParameters = function twinklespeedyGetUserTalkParameters(normalized, parameters) {
    var utparams = [];
    switch (normalized) {
        default:
            break;
    }
    return utparams;
};


Twinkle.speedy.resolveCsdValues = function twinklespeedyResolveCsdValues(e) {
    var values = (e.target.form ? e.target.form : e.target).getChecked('csd');
    if (values.length === 0) {
        alert( "请选择一个理据!" );
        return null;
    }
    return values;
};

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 values = Twinkle.speedy.resolveCsdValues(e);
    if (!values) {
        return;
    }

    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 open user talk page
    var watchPage, promptForSummary;
    normalizeds.forEach(function(norm) {
        if (Twinkle.getPref("watchSpeedyPages").indexOf(norm) !== -1) {
            watchPage = true;
        }
        if (Twinkle.getPref("promptForSpeedyDeletionSummary").indexOf(norm) !== -1) {
            promptForSummary = true;
        }
    });

    var params = {
        values: values,
        normalizeds: normalizeds,
        watch: watchPage,
        deleteTalkPage: form.talkpage && form.talkpage.checked,
        deleteRedirects: form.redirects.checked,
        openUserTalk: form.openusertalk.checked,
        promptForSummary: promptForSummary,
        templateParams: Twinkle.speedy.getParameters( form, values )
    };
    if(!params.templateParams) {
        return;
    }

    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;
    }

    var values = Twinkle.speedy.resolveCsdValues(e);
    if (!values) {
        return;
    }
    //var multiple = form.multiple.checked;
    var normalizeds = [];
    $.each(values, function(index, value) {
        var norm = Twinkle.speedy.normalizeHash[ value ];

        normalizeds.push(norm);
    });

    // analyse each criterion to determine whether to watch the page/notify the creator
    var watchPage = false;
    $.each(normalizeds, function(index, norm) {
        if (Twinkle.getPref('watchSpeedyPages').indexOf(norm) !== -1) {
            watchPage = true;
            return false;  // break
        }
    });

    var notifyuser = false;
    if (form.notify.checked) {
        $.each(normalizeds, function(index, norm) {
            if (Twinkle.getPref('notifyUserOnSpeedyDeletionNomination').indexOf(norm) !== -1) {
                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 = {
        values: values,
        normalizeds: normalizeds,
        watch: watchPage,
        // usertalk: notifyuser,
        welcomeuser: welcomeuser,
        lognomination: csdlog,
        templateParams: Twinkle.speedy.getParameters( form, values )
    };
    if (!params.templateParams) {
        return;
    }

    Morebits.simpleWindow.setButtonsEnabled( false );
    Morebits.status.init( form );

    Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
    Morebits.wiki.actionCompleted.notice = "标记完成";

    var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "标记页面");
    wikipedia_page.setCallbackParameters(params);
    wikipedia_page.load(Twinkle.speedy.callbacks.user.main);
};
})(jQuery);


//</nowiki>