User:Nikki/ExMusica.js
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.
/**
* This adds links to band members on item pages for musical groups
* and links to recordings/performances on item pages for musical works.
*
* To use it, add the following line to your common.js:
* mw.loader.load("//www.wikidata.org/w/index.php?title=User:Nikki/ExMusica.js&action=raw&ctype=text/javascript");
*
* @license CC0-1.0
* @version 0.6.1
*/
/* jshint esversion: 6 */
(function () {
let translations = {
en: {
/* Headings */
"members": "Members",
"on-tracklist-of": "On the tracklist of",
"parts": "Parts",
"recordings-performances": "Recordings and performances",
"reissues": "Reissues",
"releases": "Releases",
"remixes": "Remixes",
"soundtrack-to": "Soundtrack to",
"translations": "Translations",
"uses-melody": "Uses this melody",
"no-performers": "no performers",
/* Formatting */
"brackets-format": " ($1)",
"comma-format": ", ",
"year-format": "$1",
},
de: {
"members": "Mitglieder",
"on-tracklist-of": "Auf der Titelliste von",
"parts": "Teile",
"releases": "Veröffentlichungen",
"soundtrack-to": "Soundtrack zu",
"translations": "Übersetzungen",
},
ja: {
"members": "メンバー",
"reissues": "リイシュー",
"translations": "翻訳",
"brackets-format": "($1)",
"comma-format": "、",
"year-format": "$1年",
},
};
let langs = [...new Set([
// If the UI language is English, the chain is only ["en"] and
// using slice() to remove the last array element will result in
// an empty array. To avoid that, we use shift() to get the first
// element and slice() to get anything between the first and last
// elements separately.
mw.language.getFallbackLanguageChain().shift(),
mw.language.getFallbackLanguageChain().slice(1, -1),
mw.config.get("wgULSBabelLanguages") || [],
mw.config.get("wgULSAcceptLanguageList") || [],
"en"
].flat().map(function (x) { return x.toLowerCase(); }))].join(",");
// P31 values to run this script on
let p31values_members = [
"Q207338", "Q42998", "Q215380", "Q216337", "Q239582", "Q641066",
"Q762048", "Q1261230", "Q1426710", "Q5741069", "Q9212979", "Q10269077",
"Q11264216", "Q11446438", "Q19464263", "Q25391823", "Q56816954",
];
let p31values_works = [
"Q105543609",
"Q58483083",
];
let p31values_releases = [
"Q482994",
"Q134556",
"Q169930",
"Q106042566"
];
let p31values_melodies = [
"Q105543609",
];
let p31values_translations = [
"Q105543609",
];
let p31values_parts = [
"Q100775361",
];
let p31values_soundtracks = [
"Q482994", "Q134556", "Q169930",
"Q6128115", "Q20089094", "Q10590726",
"Q20135338", "Q394970", "Q1892995",
"Q841983", "Q368281", "Q2031291",
];
let p31values_tracks = [
"Q55850593",
"Q55850643",
"Q7302866",
];
let list = [];
let newlist = {};
function hasp31(claims, list) {
for (let i = 0; i < claims.P31.length; i++) {
if (list.includes( claims.P31[i].mainsnak.datavalue.value.id ))
return true;
}
return false;
}
function runquery(query, heading, callback, usenew) {
$.post("https://query.wikidata.org/sparql?format=json", { query: query }, function (data) {
if (!data.results.bindings.length)
return;
list = [];
newlist = {};
$.each(data.results.bindings, function (i, v) {
let qid = v.item.value.replace(/.*\//, "");
if (!newlist.hasOwnProperty(qid))
newlist[qid] = { "qid": qid, "rows": [] };
newlist[qid].rows.push(v);
});
let dobj = data.results.bindings;
if (usenew)
dobj = newlist;
$.each(dobj, callback);
$(".wikibase-sitelinkgrouplistview").append(
"<div style=\"clear: both\">"
+ "<h3 style=\"display: inline\">" + mw.html.escape(heading) + "</h3>"
+ "<ul>" + list.join("\n") + "</ul>"
+ "</div>"
);
});
}
mw.loader.using("jquery.i18n").then(function() {
mw.hook("wikibase.entityPage.entityLoaded").add(function (e) {
if (e.type !== "item")
return;
if (!e.claims.hasOwnProperty("P31"))
return;
$.i18n().load(translations);
if (hasp31(e.claims, p31values_members)) {
let query = "\
select ?item ?itemLabel ?date {\
?item p:P463 ?s.\
?s ps:P463 wd:" + e.id + ".\
optional { ?s pq:P580 ?start }\
optional { ?s pq:P582 ?end }\
bind(if(bound(?start) || bound(?end), concat(coalesce(str(year(?start)),\"\"),\"–\",coalesce(str(year(?end)),\"\")), \"\") as ?date).\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} order by bound(?end) ?end bound(?start) ?start ?itemLabel";
runquery(query, $.i18n("members"), function (i, v) {
let qid = v.item.value.replace(/.*\//, "");
let date = "";
if (v.date.value != "") {
date = $.i18n("brackets-format", $.i18n("year-format", v.date.value));
}
list.push("<li><a href=\"/wiki/" + qid + "\">" + mw.html.escape(v.itemLabel.value) + "</a>" + mw.html.escape(date) + "</li>");
});
} else if (hasp31(e.claims, p31values_works)) {
let query = "\
select ?item ?performer ?itemLabel ?performerLabel (min(year(?date)) as ?year) ?audio ?video ?tv ?contest ?inst ?live (sample(?p1476) as ?title) {\
?item wdt:P2550 wd:" + e.id + ".\
optional { ?item wdt:P175 ?performer }\
optional { ?item wdt:P10135 ?date }\
optional { ?item wdt:P31 ?audio filter (?audio = wd:Q55850593) }\
optional { ?item wdt:P31 ?inst filter (?inst = wd:Q55850643) }\
optional { ?item wdt:P31 ?video filter (?video = wd:Q193977) }\
optional { ?item wdt:P31 ?tv filter (?tv = wd:Q78331840) }\
optional { ?item wdt:P31 ?live filter (?live = wd:Q106805967) }\
optional { ?item wdt:P31 ?contest filter (?contest in (wd:Q63483382, wd:Q63481999, wd:Q106588852, wd:Q107080092)) }\
optional { ?item wdt:P1476 ?p1476 }\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} group by ?item ?performer ?itemLabel ?performerLabel ?audio ?video ?tv ?contest ?inst ?live";
runquery(query, $.i18n("recordings-performances"), function (qid) {
let obj = newlist[qid];
let performers = [];
for (let v of obj.rows) {
if (v.performer) {
let pqid = v.performer.value.replace(/.*\//, "");
let perf = "<a href=\"/wiki/" + pqid + "\">" + mw.html.escape(v.performerLabel.value) + "</a>";
performers.push(perf);
}
}
if (performers.length === 0)
performers.push("<em>" + $.i18n("no-performers") + "</em>");
let date = "";
if (obj.rows[0].year)
date = $.i18n("brackets-format", $.i18n("year-format", obj.rows[0].year.value));
let format = [];
if (obj.rows[0].hasOwnProperty("audio"))
format.push("🎵🎤");
if (obj.rows[0].hasOwnProperty("inst"))
format.push("🎵");
if (obj.rows[0].hasOwnProperty("live"))
format.push("🎵🎪");
if (obj.rows[0].hasOwnProperty("video"))
format.push("🎬");
if (obj.rows[0].hasOwnProperty("tv"))
format.push("📺");
if (obj.rows[0].hasOwnProperty("contest"))
format.push("🏆");
let title = obj.rows[0].title || obj.rows[0].itemLabel;
list.push(
"<li>"
+ "<span class=\"format\">" + format.join("") + "</span> "
+ "<a href=\"/wiki/" + qid + "\" lang=\"" + title["xml:lang"] + "\">"
+ mw.html.escape(title.value)
+ "</a> - "
+ performers.join(", ")
+ date
+ "</li>"
);
}, true);
} else if (hasp31(e.claims, p31values_releases)) {
function release_query (prop, heading) {
let query = "\
select ?item (min(?year_) as ?year) ?country ?format ?itemLabel ?countryLabel ?formatLabel {\
?item wdt:" + prop+ " wd:" + e.id + ".\
optional { ?item wdt:P577 ?date. bind(year(?date) as ?year_). }\
optional { ?item wdt:P437 ?format }\
optional { ?item wdt:P291 ?country. }\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} group by ?item ?country ?format ?itemLabel ?countryLabel ?formatLabel order by ?year";
runquery(query, $.i18n(heading), function (i, v) {
let qid = v.item.value.replace(/.*\//, "");
let attr = [];
if (v.year)
attr.push($.i18n("year-format", v.year.value));
if (v.format) {
let fqid = v.format.value.replace(/.*\//, "");
let flink = "<a href=\"/wiki/" + fqid + "\">" + mw.html.escape(v.formatLabel.value) + "</a>";
attr.push(flink);
}
if (v.country) {
let cqid = v.country.value.replace(/.*\//, "");
let clink = "<a href=\"/wiki/" + cqid + "\">" + mw.html.escape(v.countryLabel.value) + "</a>";
attr.push(clink);
}
let attrtext = "";
if (attr.length > 0)
attrtext = $.i18n("brackets-format", attr.join($.i18n("comma-format")));
list.push("<li><a href=\"/wiki/" + qid + "\">" + mw.html.escape(v.itemLabel.value) + "</a>" + attrtext + "</li>");
});
}
release_query("P9237", "reissues");
release_query("P9831", "releases");
} else if (hasp31(e.claims, p31values_parts)) {
let query = "\
select ?item ?itemLabel ?code {\
?item p:P361 ?st.\
?st ps:P361 wd:" + e.id + ".\
optional { ?st pq:P528 ?code }\
bind(replace(?code, \"^([^0-9]*[0-9]+)([^0-9].*)?\", \"$1\") as ?ncode).\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} order by (!bound(?code)) strlen(?ncode) ?code ?itemLabel";
runquery(query, $.i18n("parts"), function (i, v) {
let qid = v.item.value.replace(/.*\//, "");
let code = "";
if (v.code)
code = $.i18n("brackets-format", v.code.value);
list.push("<li><a href=\"/wiki/" + qid + "\">" + mw.html.escape(v.itemLabel.value) + "</a>" + mw.html.escape(code) + "</li>");
});
} else if (hasp31(e.claims, p31values_tracks)) {
function track_query (prop, heading) {
let query = "\
select ?item (coalesce(?title, ?label) as ?itemLabel) (year(?date) as ?year) {\
?item wdt:" + prop + " wd:" + e.id + ".\
optional { ?item wdt:P577 ?date; }\
optional { ?item wdt:P1476 ?title }\
service wikibase:label {\
bd:serviceParam wikibase:language \"" + langs + ",en\".\
?item rdfs:label ?label\
}\
} order by (!bound(?date)) ?date";
runquery(query, $.i18n(heading), function (i, v) {
let qid = v.item.value.replace(/.*\//, "");
let date = "";
if (v.year)
date = $.i18n("brackets-format", $.i18n("year-format", v.year.value));
list.push("<li><a href=\"/wiki/" + qid + "\">" + mw.html.escape(v.itemLabel.value) + "</a>" + date + "</li>");
});
}
track_query("P658", "on-tracklist-of");
track_query("P9810", "remixes");
}
if (hasp31(e.claims, p31values_melodies)) {
let query = "\
select ?item ?itemLabel (group_concat(?langLabel_; separator=\", \") as ?langLabel) {\
?item wdt:P1625 wd:" + e.id + ".\
optional { ?item wdt:P407 ?lang }\
service wikibase:label {\
bd:serviceParam wikibase:language \"" + langs + ",en\".\
?item rdfs:label ?itemLabel.\
?lang rdfs:label ?langLabel_.\
}\
} group by ?item ?itemLabel order by ?itemLabel ?langLabel ?item";
runquery(query, $.i18n("uses-melody"), function (i, v) {
let qid = v.item.value.replace(/.*\//, "");
let lang = "";
if (v.langLabel) {
lang = $.i18n("brackets-format", v.langLabel.value);
}
list.push("<li><a href=\"/wiki/" + qid + "\">" + mw.html.escape(v.itemLabel.value) + "</a>" + mw.html.escape(lang) + "</li>");
});
}
if (hasp31(e.claims, p31values_translations)) {
let query = "\
select ?item ?itemLabel (group_concat(?langLabel_; separator=\", \") as ?langLabel) {\
?item wdt:P9745 wd:" + e.id + ".\
optional { ?item wdt:P407 ?lang }\
service wikibase:label {\
bd:serviceParam wikibase:language \"" + langs + ",en\".\
?item rdfs:label ?itemLabel.\
?lang rdfs:label ?langLabel_.\
}\
} group by ?item ?itemLabel order by ?itemLabel ?langs ?item";
runquery(query, $.i18n("translations"), function (i, v) {
let qid = v.item.value.replace(/.*\//, "");
let lang = "";
if (v.langLabel) {
lang = $.i18n("brackets-format", v.langLabel.value);
}
list.push("<li><a href=\"/wiki/" + qid + "\">" + mw.html.escape(v.itemLabel.value) + "</a>" + mw.html.escape(lang) + "</li>");
});
}
if (hasp31(e.claims, p31values_soundtracks)) {
let query = "\
select ?item ?itemLabel (min(year(?date)) as ?year) {\
?item wdt:P406 wd:" + e.id + ".\
optional { ?item wdt:P577 ?date }\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} group by ?item ?itemLabel order by ?year ?itemLabel";
runquery(query, $.i18n("soundtrack-to"), function (i, v) {
let qid = v.item.value.replace(/.*\//, "");
let attr = [];
let year = "";
if (v.year)
year = $.i18n("brackets-format", $.i18n("year-format", v.year.value));
list.push("<li><a href=\"/wiki/" + qid + "\">" + mw.html.escape(v.itemLabel.value) + "</a>" + year + "</li>");
});
}
});
});
})();