User:Irukaza/common.js
跳到导航
跳到搜索
注意:这类代码页面在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。
- 按住
CTRL+SHIFT+DEL 或 ⌘-Shift-R
来清除缓存! - 或尝试在地址栏的地址最后添加代码
?_=1
来访问最新页面。 - 你还可以在设置中勾选小工具在页面右上角添加清除缓存按钮!
//<nowiki>
// 由[[mediawiki:gadget-definitions.js]]调用,可以使用ES6语法
/**
* @Function: 使用表格界面显示和编辑小工具定义
* @Dependencies: mediawiki.api, jquery.tablesorter, oojs-ui-widgets
* @Author: [[User:Bhsd]]
* @Warning: 未添加繁体中文
*/
"use strict";
/* global OO */
$(() => {
// 1. 最基本的工具函数,用于text、HTML、data三种状态间转换
const Keys = ['name', 'type', 'default', 'peers', 'dependencies', 'rights', 'targets', 'hidden', 'pages'],
dictionary = { type: {general: '通常', styles: '纯CSS'},
targets: {desktop: '桌面版', mobile: '手机版', 'desktop,mobile': '通用'}
},
text2data = (text) => {
const parts = text.match( /^(.+)\[(.+)]\|(.+)$/ ),
params = $.extend({name: parts[1], pages: parts[3], type: 'general', targets: 'desktop'},
Object.fromEntries( parts[2].split( '|' ).map(s => s.includes( '=' ) ? s.split( '=' ) : [s, true]) ));
delete params.ResourceLoader;
['peers', 'dependencies', 'rights', 'pages'].forEach(key => {
params[key] = params[key] ? params[key].split(key == 'pages' ? '|' : ',').sort() : [];
});
return params;
},
data2html = (params, key) => {
const val = params[key];
switch(key) {
case 'name':
return $('<span>', {id: val, html: [ val,
$('<a>', {href: '#', title: '删除', html: $('<i>', {class: 'far fa-minus-square'})})
]});
case 'type':
case 'targets':
return dictionary[key][val];
case 'default':
case 'hidden':
return val ? '是' : '否';
case 'peers':
return val.map(ele => $('<div>', {html: $('<a>', {text: ele, href: `#${ele}`})}));
case 'dependencies':
case 'rights':
return val.map(ele => $('<div>', {text: ele}));
case 'pages':
return val.map(ele => $('<div>', {html: $('<a>', {text: ele,
href: mw.util.getUrl( `mediawiki:gadget-${ele}` )})}));
}
},
data2text = (params) => {
return `* ${ params.name }[${ params.type == 'general' ? 'ResourceLoader' : 'type=styles' }` +
['default', 'hidden'].map(key => params[key] ? `|${key}` : '').join( '' ) +
['peers', 'dependencies', 'rights'].map(key =>
params[key].length ? `|${key}=${ params[key].join(',') }` : '').join( '' ) +
(params.targets == 'desktop' ? '' : `|targets=${params.targets}`) +
`]|${ params.pages.join( '|' ) }`;
},
// 2. 使用表格显示小工具定义
insertRow = function() {
const params = text2data( this.textContent );
return $('<tr>', {class: 'defTr', html: Keys.map(key => $('<td>', {html: data2html(params, key)}))})
.data('params', params)[0];
},
// 3. 使用表格修改小工具定义
api = new mw.Api(),
btns = [ new OO.ui.ButtonWidget({label: '保存', flags: ['primary', 'progressive']}),
new OO.ui.ButtonWidget({label: '添加', flags: 'progressive'})
],
$tr = $('<tr>', {html: $('<td>', {colspan: 9, html: btns.map(ele => ele.$element)})}),
boolWidget = new OO.ui.DropdownInputWidget({options: [{data: 'true', label: '是'}, {data: '', label: '否'}]}),
freeWidget = new OO.ui.TagMultiselectWidget({allowArbitrary: true}),
getOptions = (key) => Object.entries( dictionary[key] ).map(ele => ({data: ele[0], label: ele[1]})),
widgets = [],
endEdit = (widget) => {
if (!document.body.contains( widget.$element[0] )) { return; }
const $oldTd = widget.$element.closest( 'td' ),
params = $oldTd.closest( '.defTr' ).data( 'params' ),
key = Keys[ $oldTd.index() ];
params[key] = widget.getValue();
widget.$element.detach();
$oldTd.html( data2html(params, key) );
},
save = () => {
btns[0].setDisabled( true );
widgets.forEach( endEdit );
const $table = $tr.closest( 'table' ),
revid = mw.config.get( 'wgCurRevisionId' ),
pageid = mw.config.get( 'wgArticleId' ),
section = $table.index( '.defTable' ) + 1,
// 注意可能标题自动编号
sectionName = $( '.mw-headline' ).eq( section - 1 ).contents().last().text().trim(),
text = `==${ sectionName }==\n` +
[...$table.find( '.defTr' )].map(ele => data2text( $(ele).data( 'params' ) )).join( '\n' );
mw.safeEdit(api, revid, {pageid, section, text, summary: `/*${sectionName}*/ 使用definitions小工具编辑`})
.then(() => { location.reload(); },
reason => { btns[0].setDisabled( reason == 'editConflict' ); });
},
edit = function(e) {
if (widgets.length === 0) {
widgets.push(...[ new OO.ui.TextInputWidget(),
new OO.ui.DropdownInputWidget({options: getOptions( 'type' )}),
boolWidget,
new OO.ui.MenuTagMultiselectWidget({allowArbitrary: true, options: [...$('.defTr')].map(ele =>
$(ele).data( 'params' )).filter(ele => ele.type == 'styles').map(ele => ({data: ele.name}))}),
freeWidget,
freeWidget,
new OO.ui.DropdownInputWidget({options: getOptions( 'targets' )}),
boolWidget,
freeWidget
]);
}
const $td = $(this),
i = $td.index(),
params = $td.closest( '.defTr' ).data( 'params' ),
widget = widgets[i],
table = e.delegateTarget;
if (!params) { return; }
if (!table.contains( $tr[0] )) { $tr.appendTo( table ); }
if ($td[0].contains( widget.$element[0] )) { return; }
endEdit( widget );
widget.setValue( params[ Keys[i] ] || '' );
$td.html( widget.$element );
},
deleteRow = function(e) {
e.preventDefault();
$(this).closest( '.defTr' ).detach();
};
$('h2:has( .mw-editsection )').next().children( 'ul' ).addBack( 'ul' ).replaceWith(function() {
return $('<table>', {class: 'wikitable sortable defTable', html: $('<tbody>', {html: $('<tr>', {html:
['名称', '类型', '默认', 'Peers', 'Dependencies', '权限', '范围', '隐藏', '链接']
.map(ele => $('<th>', {text: ele}))
}).add( $(this).children().map( insertRow ) )})}).tablesorter()
.on('dblclick', 'td', edit).on('click', 'i', deleteRow);
});
btns[0].on('click', save);
btns[1].$element.click(function() {
const params = {name: '', type: 'general', peers: [], dependencies: [], rights: [], targets: 'desktop',
pages: []};
$('<tr>', {class: 'defTr', html: Keys.map(key => $('<td>', {html: data2html(params, key)}))})
.data('params', params).insertBefore( $(this).closest( 'tr' ) );
});
});
//</nowiki>