User:Irukaza/common.js:修订间差异
跳到导航
跳到搜索
imported>=海豚= 无编辑摘要 |
imported>=海豚= 无编辑摘要 |
||
(未显示同一用户的1个中间版本) | |||
第1行: | 第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> |
2021年7月28日 (三) 21:49的版本
//<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>