User:Quasiboost/rater/rater.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
//繁體中文使用者请使用 User:Chiefwei/rater/rater-t.js
//原始地址:en:User:Kephir/gadgets/rater.js 版本:2017-11-5
/*jshint shadow:true, latedef:true, boss:true, scripturl:true, loopfunc:true, undef:true */
/*global $, mw, importStylesheet, wgScript, wgNamespaceIds, wgFormattedNamespaces, wgNamespaceNumber, wgPageName, wgTitle, wgAction */
mw.loader.using(['mediawiki.api', 'mediawiki.Title', 'jquery.ui'], function () {
"use strict";
if (mw.config.get('wgNamespaceNumber') < 0)
return;
mw.loader.load('/wiki/User:Chiefwei/rater/rater.css?action=raw&ctype=text/css', 'text/css');
/*
== 代码 ==
*/
var api = new mw.Api();
/*
=== 模板数据 ===
*/
var raterData = {};
var dataurl ='';
function getRaterData(kind) {
if (kind === 'default') {
dataurl = mw.config.get('wgScript') + '?action=raw&ctype=application/json&maxage=86400&title=User:Chiefwei/rater/' + kind + '.js';
} else {
dataurl = mw.config.get('wgScript') + '?action=raw&ctype=application/json&maxage=86400&title=User:Sz-iwbot/rater/' + kind + '.json';
}
if (raterData[kind] === void(null)) {
try {
$.ajax({
'url': dataurl,
'dataType': 'json',
'async': false,
'success': function (data) {
raterData[kind] = data;
},
'error': function (xhr, message) {
mw.log.error(new Error(message));
}
});
} catch (e) {
alert('获取评级工具“' + kind + '”数据错误:' + e.message + '。评级工具可能无法正常工作。');
raterData[kind] = null;
}
}
return raterData[kind];
}
var projectKeywords = null;
function getKeywordsMapping() {
if (projectKeywords === null) {
var projects = getRaterData('projects');
projectKeywords = {};
for (var key in projects) {
for (var i = 0; i < projects[key].length; ++i) {
projectKeywords[projects[key][i].toLowerCase()] = key;
}
}
}
return projectKeywords;
}
function cloneInto(what, target) {
if (typeof what === 'object') {
if (what === null)
return what;
if ((target === null) || (typeof target !== 'object'))
target = {};
for (var key in what) {
target[key] = cloneInto(what[key], target[key]);
}
return target;
} else
return what;
}
function clone(what) {
return cloneInto(what, null);
}
var projectData = {};
function getTemplateInfo(name) {
if (projectData[name] === void(null)) {
try {
$.ajax({
'url': mw.config.get('wgScript') + '?action=raw&ctype=application/json&maxage=86400&title=Template:' + name + '/rater-data.js',
'dataType': 'json',
'async': false,
'success': function (data) {
projectData[name] = data;
},
'error': function (xhr, message) {
if (xhr.status === 404) { // just pretend nothing happened.
projectData[name] = null;
return;
}
mw.log.error(new Error(message));
}
});
} catch (e) {
alert('获取模板“' + name + '”数据错误:' + e.message + '。如果您力所能及请修复之。正在回滚至默认数据,可能未必准确。');
projectData[name] = null;
}
}
return projectData[name];
}
function wantedTemplate(name) {
var projects = getRaterData('projects');
return name in projects;
}
function normaliseTitle(name) {
var aliases = getRaterData('aliases');
name = (new mw.Title(name)).getMainText();
if (aliases[name])
name = aliases[name];
return name;
}
/*
=== 模板对象 ===
*/
function ProjectTemplate(name, params, postws) {
var sumtrack = {};
var isnew = (params === null);
var dropped = false;
var tpinfo = getTemplateInfo(name);
var defdata = getRaterData('default');
var fallback;
if (tpinfo === null || typeof(tpinfo) === 'undefined') {
tpinfo = {};
fallback = true;
}
tpinfo = cloneInto(tpinfo, clone(defdata));
// make data nice
if (tpinfo.taskforces) {
if (tpinfo.taskforces.items) {
var newtf = [];
for (var key in tpinfo.taskforces.items) {
var tfe = {
'name': tpinfo.taskforces.items[key],
'part': (typeof tpinfo.taskforces.partsuf === 'string') ? key + tpinfo.taskforces.partsuf : null,
'prio': (typeof tpinfo.taskforces.priosuf === 'string') ? key + tpinfo.taskforces.priosuf : null
};
newtf[newtf.length] = tfe;
}
tpinfo.taskforces = newtf;
}
} else
tpinfo.taskforces = [];
for (var key in tpinfo.params)
if (tpinfo.params[key] === null)
delete tpinfo.params[key];
for (var i = 0; i < tpinfo.taskforces.length; ++i) {
var tf = tpinfo.taskforces[i];
if (tf.part) {
tpinfo.params[tf.part] = cloneInto(tpinfo.params[tf.part] || {}, {
'group': 'task'
});
}
if (tf.prio) {
tpinfo.params[tf.prio] = cloneInto(tpinfo.params[tf.prio] || {}, {
'group': 'task'
});
}
if (tf.prio && tf.part) {
tpinfo.params[tf.prio].implies = tf.part;
}
}
params = params || {};
// process params
for (var key in params) {
if ((key in tpinfo.params) && (tpinfo.params[key].alias)) {
params[tpinfo.params[key].alias] = params[key];
delete params[key];
}
}
this.isFallback = function () {
return fallback;
};
this.getParam = function (key) {
return key in params ? params[key] : null;
};
this.setParam = function (key, value) {
if ((value === null) || (value === void(null)))
return this.delParam(key);
params[key] = String(value);
sumtrack[key] = String(value);
return value;
};
this.delParam = function (key) {
delete params[key];
sumtrack[key] = false;
return void(null);
};
this.serialise = function () {
if (dropped)
return '';
var result = '{{' + name;
for (var key in params) {
result += ' |' + key + '=' + params[key];
}
return result + '}}' + postws;
};
this.getChanges = function () {
if (dropped)
return isnew ? '' : '-' + this.getProjectName();
var result = [];
for (var key in sumtrack) {
if (sumtrack[key] !== false)
result[result.length] = key + '=' + sumtrack[key];
else
result[result.length] = '-' + key;
}
if (!result.length) {
if (isnew)
return '+' + this.getProjectName();
return void(null);
}
return (isnew ? '+' : '') + this.getProjectName() + ': ' + result.join(", ");
};
this.getProjectName = function () {
if (tpinfo.name)
return tpinfo.name;
return name.replace(/^WikiProject /, '');
};
this.getTemplateName = function () {
return name;
};
this.getParamData = function (key) {
var defParamData = {
'desc': key,
'group': (key in tpinfo.params) ? 'main' : 'unk',
'mandatory': false,
'obsolete': false,
'values': 'string',
'defvalue': (key in tpinfo.params) ?
( (tpinfo.params[key].values === 'flag-temp') ? 'y'
: (tpinfo.params[key].values === 'flag-perm') ? 'n'
: ''
) : ''
};
return cloneInto(tpinfo.params[key] || {}, defParamData);
};
this.drop = function () {
return dropped = !dropped;
};
this.forEachParam = function (walker) {
for (var key in tpinfo.params) {
if (tpinfo.params[key].alias)
continue;
if (walker(key, key in params ? params[key] : null, this.getParamData(key)))
return;
}
for (var key in params) {
if (!(key in tpinfo.params))
if (walker(key, params[key], this.getParamData(key)))
return;
}
};
this.forEachTaskForce = function (walker) {
for (var i = 0; i < tpinfo.taskforces.length; ++i) {
var tf = tpinfo.taskforces[i];
if (walker(tf.name, this.getParam(tf.part), this.getParam(tf.prio), tf.part, tf.prio))
return;
}
};
}
/*
=== 界面 ===
*/
function UserInterface() {
if (this === window)
return new UserInterface();
var self = this;
function el(tag, child, attr, events) {
var node = document.createElement(tag);
if (child) {
if (typeof child !== 'object')
child = [child];
for (var i = 0; i < child.length; ++i) {
var ch = child[i];
if ((ch === void(null)) || (ch === null))
continue;
else if (typeof ch !== 'object')
ch = document.createTextNode(String(ch));
node.appendChild(ch);
}
}
if (attr) for (var key in attr) {
node.setAttribute(key, String(attr[key]));
}
if (events) for (var key in events) {
if(node)node.addEventListener(key, events[key], false);
}
return node;
}
function link(child, href, attr, ev) {
attr = attr || {};
ev = ev || {};
if (typeof href === 'string')
attr.href = href;
else {
attr.href = 'javascript:void(null);';
ev.click = href;
}
return el('a', child, attr, ev);
}
function pform(child, handler, attr) {
attr = attr || {};
attr.action = 'javascript:void(null);';
return el('form', child, attr, { 'submit': handler });
}
var pluckedData = [];
var tab = [null, null, null];
var tabIsFresh = [false, false, false];
var uiSource, uiPreview, uiStatus, uiTemplates, uiSummary, uiAddTemplName;
var dirtySummary = false;
var curTab = 0;
function setTab(target) {
tab[curTab].style.display = 'none';
tab[curTab = target].style.display = '';
}
function switchTab(target) {
if (!tabIsFresh[target]) {
if (target === 2) { // preview
var source = tabIsFresh[1] ? uiSource.value : serialise();
api.post({
'action': 'parse',
'title': talkpage,
'text': source,
'pst': '1',
'prop': 'text'
}, {
success: function (result) {
uiPreview.innerHTML = result.parse.text['*']; // XXX
setTab(target);
tabIsFresh[2] = true;
},
error: function () {
self.setStatus('渲染错误。');
}
});
return;
} else if (target === 1) { // source
if (tabIsFresh[0]) {
uiSource.value = serialise();
}
} else if (target === 0) { // editor
try {
self.extract(uiSource.value);
} catch (e) {
self.setStatus(e.message + ' — 请编辑源代码并重试。');
return;
}
}
tabIsFresh[target] = true;
}
setTab(target);
}
function tabSwitcher(target) {
return function (ev) {
switchTab(target);
};
}
function serialise() {
var result = '';
for (var i = 0; i < pluckedData.length; ++i) {
if (typeof pluckedData[i] === 'string')
result += pluckedData[i];
else if (pluckedData[i].serialise)
result += pluckedData[i].serialise();
}
return result;
}
function gatherSummary() {
var sums = [];
for (var i = 0; i < pluckedData.length; ++i) {
if (pluckedData[i].getChanges) {
var ch = pluckedData[i].getChanges();
if (ch) sums[sums.length] = ch;
}
}
return '评级:' + sums.join('; ') + '([[User:Chiefwei/rater|工具协助]])';
}
var lastTemplate;
var contig;
var uiProjList = el('datalist');
(function () {
var projects = getRaterData('projects');
for (var key in projects) {
for (var k in projects[key]) {
var pname = projects[key][k] || key.replace(/^WikiProject /, '');
uiProjList.appendChild(el('option', [pname], { 'value': pname }));
}
}
})();
var uiBox = el('div', [
// header
el('h4', ['评级',
el('span', ['\u00a0[', link('关闭', function (ev) {
ev.preventDefault();
self.show(false);
}), ']'], { 'class': 'editsection' }),
el('span', ['\u00a0[',
'β (2012-11-11) | ',
link('关于', mw.util.getUrl('en:User:Kephir/gadgets/rater'), { 'title': '关于本小工具' }), ' | ',
link('汉化', mw.util.getUrl('User:Chiefwei/rater'), { 'title': '汉化者页面' }), ' | ',
link('反馈', mw.util.getUrl('en:User talk:Kephir/gadgets/rater'), { 'title': '向作者反馈' }),
']'], { 'class': 'editsection' })
]),
// tabs
el('ul', [
el('li', [link('编辑' , tabSwitcher(0))]),
el('li', [link('源码' , tabSwitcher(1))]),
el('li', [link('预览', tabSwitcher(2))])
], { 'class': 'tabs' }),
// body: main
tab[0] = el('div', [
uiTemplates = el('ul'),
el('div', [
'附注',
el('ul', [
el('li', [
'部分专题模板(标示', el('span', '如此', { 'class': 'fallback' }),
')缺少评级数据,故已使用默认数据,但可能无法正确映射模板所能识别的实际参数。例如,部分专题横幅未适用重要度或图片/信息框请求等字段,亦可能使用了特殊名称。请使用预览功能以检查参数是否受正确识别,并使用源代码编辑器修正,亦可点击[编辑]链接填写模板评级数据。添加其他非评级讨论页模板时,请将评级参数按照默认留空,并填写该模板所含字段。', link('请清除浏览器缓存', mw.util.getUrl('WP:BYPASS')), '以确保评级工具使用最新的模板数据。'
])
])
], { 'class': 'notes' }),
el('form', [
uiAddTemplName = el('input', null, {
'type': 'text',
'size': '30',
'placeholder': '专题名、模板名、关键词或缩写',
'class': 'name'
}),
el('input', null, {
'type': 'submit',
'value': '添加'
})
], { 'action': 'javascript:void(0);', 'class': 'new-template' }, {
'submit': function (ev) {
var name = uiAddTemplName.value;
if (!name)
return;
var keywords = getKeywordsMapping();
if (keywords[name.toLowerCase()])
name = keywords[name.toLowerCase()];
name = normaliseTitle(name);
if (!wantedTemplate(name))
name = 'WikiProject ' + name;
if (!wantedTemplate(name)) {
if (!confirm('“' + uiAddTemplName.value + '”无法与已知专题关联。是否依然添加?'))
return;
}
var ptpl = new ProjectTemplate(name, null, '\n');
pluckedData.splice(++lastTemplate, 0, ptpl);
uiTemplates.appendChild(createUIForProjectTemplate(ptpl, true));
tabIsFresh[1] = tabIsFresh[2] = false;
uiAddTemplName.value = '';
if (!dirtySummary) {
uiSummary.value = gatherSummary();
}
}
})
]),
// body: source
tab[1] = el('div', [
uiSource = el('textarea', null, {
'rows': 15,
'cols': 70
}, {
'keypress': function () {
tabIsFresh[0] = tabIsFresh[2] = false;
if (!dirtySummary) {
dirtySummary = true;
uiSummary.classList.add('dirty');
uiSummary.value = '修改讨论页顶部([[User:Chiefwei/rater|工具协助]])';
}
},
'change': function () {
tabIsFresh[0] = tabIsFresh[2] = false;
if (!dirtySummary) {
dirtySummary = true;
uiSummary.classList.add('dirty');
uiSummary.value = '修改讨论页顶部([[User:Chiefwei/rater|工具协助]])';
}
}
})
]),
// body: preview
tab[2] = el('div', [
uiPreview = el('div')
]),
el('br', null, { 'class': 'before-footer' }),
// footer
el('div', [
el('div', [
el('label', '编辑摘要:'),
uiSummary = el('input', null, {
'type': 'text',
'size': '60'
}, { 'keypress': function (ev) {
if (!dirtySummary) {
dirtySummary = true;
this.classList.add('dirty');
}
}})
]),
el('span', [uiStatus = document.createTextNode('')], { 'class': 'status-line' }),
el('input', null, {
'type': 'button',
'value': '保存',
'class': 'save-button'
}, { 'click': function (ev) {
var summary = uiSummary.value;
var markup = (curTab === 0) ? serialise() : uiSource.value;
self.setStatus('正在提交……');
self.save(markup, summary, {
success: function () {
self.setStatus('已更新');
setTimeout(function () {
self.show(false);
}, 1500);
},
error: function () {
console.error(arguments);
self.setStatus('错误');
}
});
} }),
el('br')
], { 'class': 'bottom' }),
// nothing
null
], { 'class': 'kephir-rater' });
$(uiBox).draggable().resizable(); // XXX: jQuery sucks
tab[0].style.display = tab[1].style.display = tab[2].style.display = 'none';
function createUIForProjectTemplate(tp, expanded) {
var paramWidget = {};
function normaliseBool(value) {
if (typeof value === 'boolean')
return value;
if ((value === '1') || (value === 'Y') || (value === 'y') || (value.toLowerCase() === 'yes'))
return true;
if ((value === '0') || (value === 'N') || (value === 'n') || (value.toLowerCase() === 'no'))
return false;
mw.log.error(new Error("无法正常化布尔值"));
}
function updateValue(param, value) {
tabIsFresh[1] = tabIsFresh[2] = false;
tp.setParam(param, value);
if (!dirtySummary) {
uiSummary.value = gatherSummary();
}
}
var grph = { };
function createWidget(name, value, data) {
var widget;
var dataTypes = {
'flag-temp': function () {
widget = el('input', null, { 'type': 'checkbox' });
widget.checked = normaliseBool(value);
widget.addEventListener('change', function () {
updateValue(name, this.checked ? 'yes' : null);
}, false);
},
'flag-perm': function () {
widget = el('input', null, { 'type': 'checkbox' });
widget.checked = normaliseBool(value);
widget.addEventListener('change', function () {
updateValue(name, this.checked ? 'yes' : 'no');
}, false);
},
'flag-inv': function () {
widget = el('input', null, { 'type': 'checkbox' });
widget.checked = !normaliseBool(value);
widget.addEventListener('change', function () {
updateValue(name, this.checked ? 'no' : 'yes');
}, false);
},
'string': function () {
widget = el('input', null, { 'type': 'text' });
widget.value = value;
widget.addEventListener('change', function () {
updateValue(name, this.value);
}, false);
widget.addEventListener('keypress', function () {
updateValue(name, this.value);
}, false);
},
'class-std': {
'list': ['', 'Stub', 'Start', 'C', 'B', 'GA', 'A', 'FA', 'List', 'FL', 'Disambig', 'NA'],
'normalise': 'mlc'
},
'class-ext': {
'list': ['', 'Stub', 'Start', 'C', 'B', 'GA', 'A', 'FA', 'List', 'FL', 'NA', 'Category', 'Disambig', 'File', 'Portal', 'Project', 'Template'],
'normalise': 'mlc'
},
'class-ext-list': {
'list': ['', 'Stub', 'Start', 'C', 'B', 'GA', 'A', 'FA', 'SL', 'List', 'CL', 'BL', 'AL', 'FL'],
'normalise': 'mlc'
},
'importance-std': {
'list': ['', 'Low', 'Mid', 'High', 'Top', 'NA', 'Bottom', 'Unknown'],
'normalise': 'mlc'
},
'importance-lit': {
'list': ['', 'Low', 'Mid', 'High', 'Top'],
'normalise': 'mlc'
},
'b-checklist': {
'list': ['', 'yes', 'no', 'n/a'],
'normalise': 'mlc'
}
};
var uiName = el('span', [data.desc]);
var uiHelp = null;
if (typeof data.values === 'string') {
try {
if (typeof dataTypes[data.values] === 'function')
dataTypes[data.values]();
else if (dataTypes[data.values])
data.values = dataTypes[data.values];
else
dataTypes.string();
} catch (e) {
dataTypes.string();
}
}
if (data.values.list) {
widget = el('select');
var vlist;
if (data.values.list instanceof Array) {
vlist = data.values.list;
for (var i = 0; i < vlist.length; ++i) {
widget.appendChild(el('option', [vlist[i]], { 'value': vlist[i] }));
}
} else {
vlist = Object.keys(data.values.list);
for (var key in data.values.list) {
widget.appendChild(el('option', [data.values.list[key]], { 'value': key }));
}
}
if (data.values.normalise) {
value = value || '';
switch (data.values.normalise) {
case 'lc':
value = value.toLowerCase();
break;
case 'mlc':
for (var i = 0; i < vlist.length; ++i) {
if (vlist[i].toLowerCase() === value.toLowerCase()) {
value = vlist[i];
break;
}
}
break;
}
}
if (data.values.aliases) {
if (value in data.values.aliases) {
value = data.values.aliases[value];
}
}
if (vlist.indexOf(value) === -1) {
dataTypes.string();
// TODO: datalist
} else {
widget.value = value;
widget.addEventListener('change', function () {
updateValue(name, this.value);
}, false);
}
}
// TODO: datalist
if (data.obsolete) {
uiName.classList.add('obsolete');
uiName.title = 'This parameter is obsolete.';
}
if (data.helplink) {
uiHelp = el('span', ['[', link('?', mw.util.getUrl(data.helplink)), ']']);
}
paramWidget[name] = widget;
return el('li', [uiName, uiHelp && ' ', uiHelp, ':', widget]);
}
function createPlaceholder(name, data) {
var pholder = el('li', [paramWidget[name] = link(data.desc, function (ev) {
tabIsFresh[1] = tabIsFresh[2] = false;
tp.setParam(name, data.defvalue);
if (grph[data.group])
grph[data.group].classList.remove('absent');
var widget = createWidget(name, data.defvalue, data);
pholder.parentNode.insertBefore(widget, pholder);
pholder.parentNode.removeChild(pholder);
if (!dirtySummary) {
uiSummary.value = gatherSummary();
}
})], { 'class': 'absent' });
return pholder;
}
function createWidgetTF(tfname, part, prio, partpname, priopname, prioscale) {
var uiCheck = null, uiCombo = null;
if (partpname !== null) {
uiCheck = el('input', null, { 'type': 'checkbox' });
try {
uiCheck.checked = normaliseBool(part);
} catch (e) {
uiCheck.checked = true;
}
uiCheck.addEventListener('change', function (w) {
updateValue(partpname, this.checked ? 'yes' : null);
}, false);
paramWidget[partpname] = uiCheck;
}
if (priopname !== null) {
var items = prioscale || ["", "Top", "High", "Mid", "Low", "Unknown"]; // XXX
uiCombo = el('select');
for (var i = 0; i < items.length; ++i) {
uiCombo.appendChild(el('option', [items[i]], { 'value': items[i] }));
}
uiCombo.value = prio;
uiCombo.addEventListener('change', function () {
updateValue(priopname, this.value);
}, false);
paramWidget[priopname] = uiCombo;
}
return el('li', [uiCheck, tfname, uiCombo && ': ', uiCombo]);
}
function createPlaceholderTF(tfname, partpname, priopname) {
var pholder = el('li', [ paramWidget[priopname] = paramWidget[partpname] = link(tfname, function (ev) {
if (partpname) tp.setParam(partpname, 'y');
if (priopname) tp.setParam(priopname, '');
var widget = createWidgetTF(tfname, true, '', partpname, priopname);
grph.task.classList.remove('absent');
pholder.parentNode.insertBefore(widget, pholder);
pholder.parentNode.removeChild(pholder);
if (!dirtySummary) {
uiSummary.value = gatherSummary();
}
})], { 'class': 'absent' });
return pholder;
}
var uiParams, uiGroups, uiDel;
var ui = el('li', [
uiDel = link('(delete)', function () {
if (tp.drop())
ui.classList.add('dropped');
else
ui.classList.remove('dropped');
tabIsFresh[1] = tabIsFresh[2] = false;
if (!dirtySummary)
uiSummary.value = gatherSummary();
}, { 'class': 'delete-template' }),
el('b', [link(tp.getProjectName(), mw.util.getUrl('Template:' + tp.getTemplateName()))]),
el('small', [' [', link('编辑', '/wiki/Template:' + tp.getTemplateName() + '/rater-data.js?action=edit&editintro=User:Chiefwei/rater/data-editnotice&preload=User:Chiefwei/rater/data-preload'), ']'], { 'class': 'absent', 'title': 'Edit data' }), ':',
uiParams = el('ul', [], { 'class': 'params' }),
uiGroups = el('dl', [], { 'class': 'p-groups' })
], { 'class': 'template-entry' });
var grpNames = {
'vis' : '外观',
'req' : '请求',
'task': '工作组',
'misc': '其他',
'unk' : '未识别'
};
var grps = {
'main': uiParams
};
var grpl = {
'main': null
};
function addGroup(tag) {
uiGroups.appendChild(grph[tag] = el('dt', grpNames[tag] || tag, { 'class': 'absent' }));
uiGroups.appendChild(el('dd', [grps[tag] = el('ul', null, { 'class': 'params' })]));
return grps[tag];
}
if (!expanded) {
ui.classList.add('hide-absent');
}
if (tp.isFallback()) {
ui.classList.add('fallback');
}
tp.forEachParam(function (name, value, data) {
if (data.group === 'task')
return;
if (!grps[data.group])
addGroup(data.group);
if ((value === null) && !data.mandatory)
if (!data.obsolete)
grps[data.group].appendChild(createPlaceholder(name, data));
else;
else {
grps[data.group].appendChild(createWidget(name, value, data));
if (grph[data.group])
grph[data.group].classList.remove('absent');
}
});
tp.forEachTaskForce(function (tfname, part, prio, partpname, priopname) {
var item;
if (!grps.task) addGroup('task');
if (partpname && (part === null))
item = createPlaceholderTF(tfname, partpname, priopname);
else {
item = createWidgetTF(tfname, part, prio, partpname, priopname);
grph.task.classList.remove('absent');
}
grps.task.appendChild(item);
});
var uiNewCustParmName;
ui.appendChild(el('div', [
el('form', [
uiNewCustParmName = el('input', null, { 'type': 'text', 'placeholder': '新自定义参数', 'size': 20 }),
el('input', null, { 'type': 'submit', 'value': '添加' })
], { 'action': 'javascript:void(0);', 'class': 'new-custom-param' }, {
'submit': function (ev) {
var nname = uiNewCustParmName.value;
tabIsFresh[1] = tabIsFresh[2] = false;
if (paramWidget[nname]) {
if (paramWidget[nname].tagName === 'A') { // XXX - placeholder
paramWidget[nname].click();
} else {
// reactivate if deleted (deleting not implemented yet)
paramWidget[nname].focus();
}
} else {
var pd = tp.getParamData(nname);
tp.setParam(nname, '');
(grps[pd.group] || addGroup(pd.group)).appendChild(createWidget(nname, '', pd));
if (!dirtySummary) {
uiSummary.value = gatherSummary();
}
}
uiNewCustParmName.value = '';
}
})
], { 'class': 'absent' }));
var hidelink, hltext;
uiParams.appendChild(hidelink = link([hltext = document.createTextNode('[+]')], function () {
if (!ui.classList.contains('hide-absent')) {
ui.classList.add('hide-absent');
hltext.data = '[+]';
} else {
ui.classList.remove('hide-absent');
hltext.data = '[–]';
}
}));
return ui;
}
this.clear = function () {
dirtySummary = false;
uiSummary.value = '';
uiSummary.classList.remove('dirty');
};
this.extract = function (markup) {
var m;
pluckedData = [];
lastTemplate = -1;
contig = true;
while (uiTemplates.hasChildNodes())
uiTemplates.removeChild(uiTemplates.firstChild);
uiSource.value = markup;
tabIsFresh[1] = true;
try {
// TODO: Parsoid?
while (markup !== '') {
if (!(m = /^([^]*?)\{\{\s*((?:\}[^\}\|]|[^\}\|])+?)\s*(?=\||}})/.exec(markup))) {
pluckedData[pluckedData.length] = markup;
break;
}
var name = normaliseTitle(m[2]);
if (!wantedTemplate(name)) {
pluckedData[pluckedData.length] = markup.substr(0, m[0].length);
markup = markup.substr(m[0].length);
continue;
}
pluckedData[pluckedData.length] = m[1];
var params = {};
var postws = '';
markup = markup.substr(m[0].length);
var ppid = 1;
for (;;) {
if (m = /^\s*}}(\s*)/.exec(markup)) {
postws = m[1];
markup = markup.substr(m[0].length);
break;
} else if (m = /^\s*\|\s*([^=\|]+?)\s*=\s*(.*?)\s*(?=\||}})/.exec(markup)) {
markup = markup.substr(m[0].length);
params[m[1]] = m[2];
} else if (m = /^\s*\|\s*(.*?)\s*(?=\||}})/.exec(markup)) {
markup = markup.substr(m[0].length);
params[ppid++] = m[1];
} else {
mw.log.error(new Error('“' + name + '”错误的模板调用'));
}
}
if (lastTemplate !== (pluckedData.length - 1))
contig = false;
var ptpl = new ProjectTemplate(name, params, postws);
pluckedData[lastTemplate = pluckedData.length] = ptpl;
uiTemplates.appendChild(createUIForProjectTemplate(ptpl));
}
tabIsFresh[0] = true;
setTab(0);
} catch (e) {
this.setStatus('解析' + e.message + '时出错,请修复源代码并重试。');
setTab(1);
}
};
this.save = function (markup, summary, handlers) {
alert('@!#?@!\n' + summary + '\n' + markup);
};
this.show = function (value) {
uiBox.style.display = value ? '' : 'none';
if (value) {
if (curTab === 0)
uiAddTemplName.focus();
else if (curTab === 1)
uiSource.focus();
}
};
this.install = function (where) {
function uniqid() {
var s = '', cs = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890.-';
for (var i = 0; i < 24; ++i) {
s += cs.charAt(Math.floor(Math.random() * cs.length));
}
return s;
}
where.appendChild(uiBox);
where.appendChild(uiProjList);
uiProjList.id = 'kephir-rater-' + uniqid();
uiAddTemplName.setAttribute('list', uiProjList.id);
};
this.setStatus = function (message, level) {
uiStatus.data = message;
};
return this;
}
/*
=== Glue ===
*/
var api = new mw.Api();
var ui = new UserInterface();
ui.show(false);
ui.install(document.body);
var talkpage = mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceNumber') - (mw.config.get('wgNamespaceNumber') % 2) + 1] + ':' + mw.config.get('wgTitle');
var link = mw.util.addPortletLink(mw.config.get('skin') === 'vector' ? 'p-views' : 'p-cactions',
'javascript:void(0);', '评级 (legacy)', 'p-kephir-rater', '使用工具为条目评级', '5'
);
if(link) {
link.addEventListener('click', function (ev) {
ev.preventDefault();
api.get({
action: 'query',
prop: 'info|revisions',
rvprop: 'timestamp|content',
rvsection: 0,
rvlimit: 1,
rvdir: 'older',
meta: 'tokens',
titles: talkpage
}, {
success: function (result) {
var tpgpid = Object.keys(result.query.pages)[0];
var tpg = result.query.pages[tpgpid];
var tpgstart = tpg.starttimestamp;
var tpgtoken = result.query.tokens.csrftoken;
var tpgbase = tpg.revisions ? tpg.revisions[0].timestamp : void(0);
var tpgrev = tpg.lastrevid;
ui.save = function (markup, summary, handlers) {
api.post({
action: 'edit',
section: 0,
title: talkpage,
basetimestamp: tpgbase,
starttimestamp: tpgstart,
token: tpgtoken,
notminor: true,
summary: summary,
watchlist: 'nochange',
text: markup,
tags: 'rater'
}, handlers);
};
ui.clear();
ui.extract(tpg.revisions ? tpg.revisions[0]['*'] : '');
ui.show(true);
},
error: function () {
console.error(arguments);
alert('错误,参见控制台。');
}
});
}, false);
}
if (/^Category:(Unassessed|Unknown-importance)_.*?_articles$/.test(mw.config.get('wgPageName'))) {
var links = document.getElementById('mw-pages').getElementsByTagName('a');
for (var i = 0; i < links.length; ++i)
links[i].href = links[i].href.replace(/\/wiki\/Talk:/, '/wiki/');
}
if ((mw.config.get('wgNamespaceNumber') === mw.config.get('wgNamespaceIds').template) && /\/rater-data\.js$/.test(mw.config.get('wgPageName'))) {
mw.config.set('wgCodeEditorCurrentLanguage', 'json');
mw.loader.load('ext.codeEditor');
if (Object.defineProperty)
Object.defineProperty(window, 'syntaxHighlighterConfig', {
'set': function () { }
});
else if (window.__defineSetter__)
window.__defineSetter__('syntaxHighlighterConfig', function () { });
}
});