LLWiki正在建设中,欢迎加入我们!
MediaWiki:Gadget-definitions-core.js
跳转到导航
跳转到搜索
注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的更改的影响。
- Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-R(Mac为⌘-R)
- Google Chrome:按Ctrl-Shift-R(Mac为⌘-Shift-R)
- Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5。
//<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', 'actions', 'rights', 'skins', 'hidden', 'pages'],
dictionary = { type: {general: '通常', styles: '纯CSS'},
skins: {vector: '桌面版', minerva: '手机版', 'vector,minerva': '通用'}
},
text2data = (text) => {
const parts = text.match( /^(.+)\[(.+)]\|(.+)$/ ),
params = $.extend({name: parts[1], pages: parts[3], type: 'general', skins: 'vector,minerva'},
Object.fromEntries( parts[2].split( '|' ).map(s => s.includes( '=' ) ? s.split( '=' ) : [s, true]) ));
delete params.ResourceLoader;
['peers', 'dependencies', 'rights', 'actions', '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 'skins':
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':
return val.map(ele => $('<div>', ele.startsWith('ext.gadget.') ? {html: $('<a>', {text: ele, href: `#${ele.slice(11)}`})} : {text: ele}));
case 'rights':
case 'actions':
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', 'actions'].map(key =>
params[key].length ? `|${key}=${ params[key].join(',') }` : '').join( '' ) +
(params.skins == 'vector,minerva' ? '' : `|skins=${params.skins}`) +
`]|${ 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' ),
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, {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,
freeWidget,
new OO.ui.DropdownInputWidget({options: getOptions( 'skins' )}),
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: [], actions: [], rights: [], skins: 'vector,minerva',
pages: []};
$('<tr>', {class: 'defTr', html: Keys.map(key => $('<td>', {html: data2html(params, key)}))})
.data('params', params).insertBefore( $(this).closest( 'tr' ) );
});
});
//</nowiki>