User:Ch1902/infobox.js
Jump to navigation
Jump to search
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
$.expr.pseudos.template = $.expr.createPseudo(function (arg) {
return function (elem) {
return $.trim((elem.textContent || elem.innerText || jQuery(elem).text() || '')).toLowerCase() === arg.toLowerCase();
};
});
/**
* Widget to provide a toolbox link pull template data from wiki
* articles and display the parameter names and parsed values in a
* draggable table on wikidata
*/
$.widget('wd.infoboxview', {
defaults: {
page: '',
lang: 'en',
templates: [],
params: [],
showEmpty: false
},
api: '',
table: '',
templates: [],
loaded: false,
_create: function ()
{
var self = this;
if ($.type(this.options.templates) === 'string')
this.options.templates = [this.options.templates];
$.each(this.options.templates, function (i, v) {
self.options.templates[i] = v.replace(/_/g, ' ');
});
this.api = '//' + this.options.lang + '.wikipedia.org/w/api.php';
this.wiki = '//' + this.options.lang + '.wikipedia.org/wiki/';
this.table = $('<table/>').css({
position: 'absolute',
right: 15,
top: 80,
width: 400,
zIndex: 1000001
}).addClass('wikitable infoboxview-table').appendTo(document.body).hide();
if ($.fn.draggable)
this.table.draggable({handle: 'th > span'});
this.element.on('click', function (e) {
self._run(e);
return false;
});
this.table.on('click', 'tr:has(th)', function (e) {
self._toggle(e);
});
this.table.on('click', 'td', function (e) {
self._displayEntity(e);
});
mw.util.addCSS(
'table.infoboxview-table {font-size:small;border:1px solid #CCC;border-collapse:collapse}' +
'table.infoboxview-table p {margin:0;}' +
'table.infoboxview-table ul {list-style-type:none !important;list-style-image:none !important;margin:0;padding:0}' +
'table.infoboxview-table li {list-style-type:none !important;list-style-image:none !important;margin:0;padding:0}' +
'table.infoboxview-table .mw-redirected {color:darkgreen !important;font-weight:bold}' +
'table.infoboxview-table .mw-redirecterr {color:#C00 !important;font-weight:bold}' +
'table.infoboxview-table th {cursor:pointer}' +
'table.infoboxview-table th span {cursor:move}'
);
},
_toggle: function (e)
{
$('div.tipsy').hide();
if ($.nodeName(e.target, 'span'))
return true;
$(e.currentTarget).nextUntil('tr:has(th)').toggle();
},
_run: function (e)
{
var self = this;
$('div.tipsy').hide();
if (!e.shiftKey && this.loaded === true) {
this.table.toggle();
return;
}
if (!e.ctrlKey)
$('.infoboxview-table').hide(); // hide all others
this._loadTemplateCalls().done(function () {
if (self.templates.length < 1) // empty results
self._displayNotice();
else
self._displayData();
self.loaded = true;
});
},
_displayNotice: function () {
var table = this.table;
table.empty();
table.append('<tr><td colspan="2">' + this.options.page + ' contains no uses of ' + this.options.templates.join(', ') + '</td></tr>');
table.show();
table.css({top: $(window).scrollTop()});
},
_displayData: function () {
var self = this, params = this.options.params, empty = this.options.showEmpty, table = this.table,
lang = this.options.lang, data;
table.empty();
table.show();
table.css({top: $(window).scrollTop()});
$.each(this.templates, function (_, template) {
var data = params.length > 1 ? self._subsetValues(template, params, empty) : template, wikitable = self._objectToTable(data);
$.when(self._parseWikiText(wikitable)).done(function (data) {
var html = data && data.parse && data.parse.text && data.parse.text['*'] || '<table><tr><td colspan="2">Error</td></tr></table>';
html = html.replace(/href\=\"\//gi, 'href="//' + lang + '.wikipedia.org/');
var content = $(html);
table.append('<tr><th colspan="2"><span>' + template.__title__ + '</span></th></tr>');
table.append(content.find('tr'));
table.find('a.mw-redirect').each(function () {
var link = this, page = decodeURIComponent(link.href.split(/wiki\//)[1]);
link.className = '';
$.when(self._resolveRedirect(page)).done(function (data) {
if (data && data.query && data.query.redirects && data.query.redirects[0]) {
link.href = self.wiki + mw.util.wikiUrlencode(data.query.redirects[0].to);
link.className += ' mw-redirected';
} else {
link.className += ' mw-redirecterr';
}
});
});
});
});
},
_displayEntity: function (e) {
var self = this, td = $(e.currentTarget), next = td.next('td:has(a:not(.image, .new))'), links, requests, href, page, data;
if (next.length === 0)
return true;
data = td.data();
if (!data.tooltip) {
links = next.find('a:not(.image, .new)'), requests = [];
$.overlaySpinner(td, 'ib', 'small');
links.each(function () {
var href = this.href, page = decodeURIComponent(href.split(/\/wiki\//)[1].replace(/_/ig, ' '));
requests.push($.ajax({
url: '//www.wikidata.org/w/api.php',
type: 'GET',
dataType: 'json',
data: {action: 'wbgetentities', format: 'json', props: 'info|sitelinks', sites: self.options.lang + 'wiki', titles: page}
}));
});
$.when.apply($, requests).done(function () {
var results = [], html = [];
if (requests.length === 1) {
results.push(new Array(arguments[0], arguments[1], arguments[2]));
} else {
results = arguments;
}
$.each(results, function (_, res) {
var data = res[0], tooltip;
if (!data) {
tooltip = "Couldn't get data";
} else if (data.error) {
tooltip = data.error;
} else if (data.entities && data.entities['-1']) {
tooltip = '<a href="//www.wikidata.org/wiki/Special:ItemByTitle/' + self.options.lang + 'wiki/' + data.entities['-1'].title + '">No sitelinks found</a>';
} else {
$.each(data.entities, function (q, entity) {
var url = mw.util.getUrl(entity.title), desc = entity.sitelinks[self.options.lang + 'wiki'].title;
tooltip = entity.title + '/<a href="' + url + '">' + entity.title + '</a> – ' + desc;
return false;
});
}
html.push('<div>' + tooltip + '</div>');
});
html = html.join("\n");
self._displayTooltip(td, html);
td.data({tooltip: html});
$.removeOverlaySpinner('ib');
});
} else {
self._displayTooltip(td, data.entity);
}
},
_loadTemplateCalls: function () {
var self = this;
return $.ajax({
url: this.api,
type: 'GET',
dataType: 'jsonp',
data: {action: 'parse', format: 'json', redirects: 1, prop: '', generatexml: 1, page: this.options.page},
error: function () { },
success: function (data) {
if (data && data.parse && data.parse.parsetree) {
var xml = $.parseXML(data.parse.parsetree['*']), doc = $(xml), objects = [], selectors = [], templates;
$.each(self.options.templates, function (_, template) {
selectors.push('root > template:has(> title:template("' + template + '"))');
});
templates = doc.find(selectors.join(','));
templates.each(function () {
objects.push(self._constructTemplate($(this)));
});
self.templates = objects;
}
}
});
},
_constructTemplate: function (template) {
var self = this, tpl = {};
tpl.__title__ = $.trim(template.find('> title').text());
template.find('> part').each(function () {
var name = $(this).find('> name'), value = $(this).find('> value').contents(), key = name.is(':empty') ? name.attr('index') : $.trim(name.text());
if (value.length === 1 && value[0].nodeName === '#text') { // just text
tpl[key] = value.text();
} else {
tpl[key] = [];
value.each(function () {
if ($.nodeName(this, 'template')) {
tpl[key].push(self._constructTemplate($(this)));
} else {
tpl[key].push(this.nodeValue);
}
});
}
});
return tpl;
},
_objectToWikitext: function (obj) {
var self = this, str;
if ($.type(obj) === 'array')
{
str = "";
$.each(obj, function (_, value) {
if ($.type(value) === 'string') {
str += value;
} else {
str += self._objectToWikitext(value);
}
});
}
else if ($.type(obj) === 'object')
{
str = "{{" + obj.__title__ + "\n";
$.each(obj, function (key, value) {
if (key === '__title__')
return;
if ($.type(value) === 'string') {
str += "|" + key + "=" + value + "\n";
} else {
str += "|" + key + "=" + self._objectToWikitext(value) + "\n";
}
});
str += "}}";
}
else
{
str = obj;
}
return str;
},
_displayTooltip: function (el, content) {
var data = el.data();
if (data && data.tipsy) {
el.tipsy(el.tipsy('tip').is(':visible') ? 'hide' : 'show');
} else {
$(el).tipsy({
trigger: 'manual',
title: function () { return content; },
html: true,
gravity: 'e'
});
$(el).tipsy('show');
}
},
_subsetValues: function (template, keys, empty) {
var reduced = {};
$.each(keys, function (_, value) {
if ($.type(template[value]) !== 'undefined' && ((template[value] == '' && empty) || template[value] != ''))
reduced[value] = template[value];
});
return reduced;
},
_objectToTable: function (template) {
var self = this, str = "{|\n";
$.each(template, function (name, value) {
if (name === '__title__')
return;
str += "|-\n|class=\"" + name + "\"|" + name + " || " + self._objectToWikitext(value) + "\n";
});
str += "|}";
return str;
},
_parseWikiText: function (text) {
return $.ajax({
url: this.api,
type: 'GET',
dataType: 'jsonp',
data: {action: 'parse', format: 'json', prop: 'text', text: text, redirects: 1, disablepp: 1},
});
},
_resolveRedirect: function (page) {
return $.ajax({
url: this.api,
type: 'GET',
dataType: 'jsonp',
data: {action: 'query', format: 'json', titles: page, redirects: 1},
});
}
});