User:Jean-Frédéric/ExLudo.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)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
* This adds links expansions and mods on item pages for video games
*
* To use it, add the following line to your common.js:
* mw.loader.load("//www.wikidata.org/w/index.php?title=User:Jean-Frédéric/ExLudo.js&action=raw&ctype=text/javascript");
*
*
* @license CC0-1.0
* @version 0.0.10
*/
/* jshint esversion: 6 */
(function () {
let translations = {
en: {
/* Headings */
"expansions": "Expansions",
"mods": "Mods",
"on-compilations": "On the compilations",
"based-on": "Are based on this game",
"using-this-engine": "Using this engine",
"in-series": "In this series",
"in-franchise": "Part of this franchise",
"award-winners": "Winners",
"sub-genres": "Sub-genres",
"demos": "Demos",
"in-universe": "Takes place in this universe",
/* Formatting */
"brackets-format": " ($1)",
"comma-format": ", ",
"year-format": "$1",
},
fr: {
"expansions": "Extensions",
"mods": "Mods",
"on-compilations": "Présent sur les compilations",
"based-on": "Basés sur ce jeu",
"using-this-engine": "Utilisant ce moteur de jeu",
"in-series": "Dans cette série",
"in-franchise": "Dans cette franchise",
"in-universe": "Dans cet univers",
"award-winners": "Lauréats",
"sub-genres": "Sous-genres",
"demos": "Démos",
},
};
let langs = [
// 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_games = [
"Q7889",
];
let p31values_franchise = [
"Q196600",
];
let p31values_engines = [
"Q193564",
"Q62505",
"Q63533016",
"Q355134",
"Q17083583"
];
let p31values_on_compilations = [
"Q7889",
"Q209163",
];
let p31values_based_on = [
"Q7889",
];
let p31values_series = [
"Q7058673",
];
let p31values_award = [
"Q18328126",
];
let p31values_genres = [
"Q659563",
"Q42907216"
];
let p31values_universe = [
"Q559618",
];
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_games)) {
function game_query (prop, heading) {
let query = "\
select ?item ?itemLabel (min(year(?date)) as ?year) ?dlc ?expansion {\
?item wdt:" + prop+ " wd:" + e.id + ".\
optional { ?item wdt:P577 ?date }\
optional { ?item wdt:P31 ?dlc filter (?dlc = wd:Q1066707) }\
optional { ?item wdt:P31 ?expansion filter (?expansion = wd:Q209163) }\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} group by ?item ?itemLabel ?dlc ?expansion order by ?year";
runquery(query, $.i18n(heading), function (i, v) {
let qid = v.item.value.replace(/.*\//, "");
let attr = [];
/* let format = [];
if (obj.rows[0].hasOwnProperty("dlc"))
format.push("[DLC]");
*/ if (v.year)
attr.push($.i18n("year-format", v.year.value));
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>");
});
}
game_query("P8646", "expansions");
game_query("P7075", "mods");
game_query("P12050", "demos");
}
if (hasp31(e.claims, p31values_on_compilations)) {
let query = "\
select ?item ?itemLabel (min(year(?date)) as ?year) {\
?item wdt:P527 wd:" + e.id + ".\
?item wdt:P31 wd:Q16070115.\
optional { ?item wdt:P577 ?date }\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} group by ?item ?itemLabel order by ?year";
runquery(query, $.i18n("on-compilations"), 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>");
});
}
if (hasp31(e.claims, p31values_engines)) {
let query = "\
select ?item ?itemLabel (min(year(?date)) as ?year) {\
?item wdt:P408 wd:" + e.id + ".\
optional { ?item wdt:P577 ?date }\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} group by ?item ?itemLabel order by ?year";
runquery(query, $.i18n("using-this-engine"), 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>");
});
}
if (hasp31(e.claims, p31values_based_on)) {
let query = "\
select ?item ?itemLabel ?subject ?subjectLabel (min(year(?date)) as ?year) {\
?item p:P144 ?based_on_statement.\
?based_on_statement ps:P144 wd:" + e.id + ".\
optional { ?based_on_statement pq:P2868 ?subject }\
optional { ?item wdt:P577 ?date }\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} group by ?item ?itemLabel ?subject ?subjectLabel order by ?year";
runquery(query, $.i18n("based-on"), function (i, v) {
let qid = v.item.value.replace(/.*\//, "");
let attr = [];
let year = "";
if (v.year)
attr.push($.i18n("year-format", v.year.value));
if (v.subject) {
let fqid = v.subject.value.replace(/.*\//, "");
let flink = "<a href=\"/wiki/" + fqid + "\">" + mw.html.escape(v.subjectLabel.value) + "</a>";
attr.push(flink);
}
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>");
});
}
if (hasp31(e.claims, p31values_series)) {
let query = `
select ?item ?itemLabel ?subitem ?subitemLabel (min(year(?date)) as ?year) ?subitemyear
with {
select ?subitem ?subitemLabel ?item (min(year(?date)) as ?subitemyear) {
?subitem wdt:P8646 ?item.
optional { ?subitem wdt:P577 ?date }
?item wdt:P179 wd:${e.id}.
} group by ?subitem ?subitemLabel ?item
} as %subitems
{
?item wdt:P179 wd:${e.id}.
values ?type { wd:Q7889 wd:Q16070115 wd:Q4393107 wd:Q65963104 }
?item wdt:P31 ?type.
optional { ?item wdt:P577 ?date }
optional { include %subitems }
service wikibase:label { bd:serviceParam wikibase:language "${langs},en" }
} group by ?item ?itemLabel ?subitem ?subitemLabel ?subitemyear order by ?year ?itemLabel ?subitemLabel
`;
runquery(query, $.i18n("in-series"), function (qid, obj) {
// The "true" parameter passed to runquery (after this callback
// function) causes it to group rows by ?item. The individual
// rows are in obj.rows.
// Here it creates a variable for the first row, for convenience
// when using the data which is the same for each row.
let v = obj.rows[0];
let subitems = [];
for (let row of obj.rows) {
if (row.hasOwnProperty("subitem")) {
let attr = [];
if (v.subitemyear)
attr.push($.i18n("year-format", v.subitemyear.value));
let attrtext = "";
if (attr.length > 0)
attrtext = $.i18n("brackets-format", attr.join($.i18n("comma-format")));
let subid = row.subitem.value.replace(/.*\//, "");
let subitem = `<li><a href="/wiki/${ subid }">${ mw.html.escape(row.subitemLabel.value) }</a> ${attrtext} </li>`;
subitems.push(subitem);
}
}
let attr = [];
let year = "";
if (v.year)
attr.push($.i18n("year-format", v.year.value));
if (v.subject) {
let fqid = v.subject.value.replace(/.*\//, "");
let flink = "<a href=\"/wiki/" + fqid + "\">" + mw.html.escape(v.subjectLabel.value) + "</a>";
attr.push(flink);
}
let attrtext = "";
if (attr.length > 0)
attrtext = $.i18n("brackets-format", attr.join($.i18n("comma-format")));
let sublist = "";
if (subitems.length) {
sublist = "<ul>" + subitems.join("") + "</ul>";
}
list.push("<li><a href=\"/wiki/" + qid + "\">" + mw.html.escape(v.itemLabel.value) + "</a>" + attrtext + sublist + "</li>");
}, true);
}
if (hasp31(e.claims, p31values_franchise)) {
let query = "\
select ?item ?itemLabel (min(?dates) as ?date) (min(year(?dates)) as ?year) ?print ?tv ?movie ?theatre ?game ?board ?card ?album ?audio ?amusement ?show{\
?item wdt:P8345 wd:" + e.id + ".\
MINUS {?item wdt:P31/wdt:P279* wd:Q14897293.}. \
MINUS {?item wdt:P31 wd:Q15831596.}\
optional { ?item wdt:P577 ?publication_date }.\
optional { ?item wdt:P580 ?start_date }.\
bind(COALESCE(?publication_date, ?start_date) as ?dates) .\
optional { ?item wdt:P31 ?print filter (?print IN (wd:Q2831984, wd:Q3297186, wd:Q14406742, wd:Q103076, wd:Q8274, wd:Q1760610, wd:Q21198342, wd:Q7725634, wd:Q47461344, wd:Q104213567)) }\
optional { ?item wdt:P31 ?tv filter (?tv IN (wd:Q5398426, wd:Q63952888, wd:Q104775758, wd:Q220898, wd:Q1259759, wd:Q581714, wd:Q117467246)) }\
optional { ?item wdt:P31 ?movie filter (?movie IN (wd:Q29168811, wd:Q24869, wd:Q202866, wd:Q24862, wd:Q11424, wd:Q20650540)) }\
optional { ?item wdt:P31 ?theatre filter (?theatre IN (wd:Q58483083)) }\
optional { ?item wdt:P31 ?game filter (?game IN (wd:Q7889, wd:Q16070115)) }\
optional { ?item wdt:P31 ?board filter (?board IN (wd:Q131436, wd:Q1643932)) }\
optional { ?item wdt:P31 ?card filter (?card IN (wd:Q734698)) }\
optional { ?item wdt:P31 ?album filter (?album IN (wd:Q482994)) }\
optional { ?item wdt:P31 ?audio filter (?audio IN (wd:Q105543609)) }\
optional { ?item wdt:P31 ?amusement filter (?amusement IN (wd:Q1144661, wd:Q512504, wd:Q1934961)) }\
optional { ?item wdt:P31 ?show filter (?show IN (wd:Q15116915, wd:Q85475422)) }\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} group by ?item ?itemLabel ?print ?tv ?movie ?theatre ?game ?board ?card ?album ?audio ?amusement ?show order by ?date" ;
runquery(query, $.i18n("in-franchise"), function (qid) {
let obj = newlist[qid];
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("print"))
format.push("📚");
if (obj.rows[0].hasOwnProperty("tv"))
format.push("📺");
if (obj.rows[0].hasOwnProperty("movie"))
format.push("🎬");
if (obj.rows[0].hasOwnProperty("theatre"))
format.push("🎭");
if (obj.rows[0].hasOwnProperty("game"))
format.push("🎮");
if (obj.rows[0].hasOwnProperty("board"))
format.push("🎲");
if (obj.rows[0].hasOwnProperty("card"))
format.push("🎴");
if (obj.rows[0].hasOwnProperty("album"))
format.push("💿");
if (obj.rows[0].hasOwnProperty("audio"))
format.push("🎵");
if (obj.rows[0].hasOwnProperty("amusement"))
format.push("🎢");
if (obj.rows[0].hasOwnProperty("show"))
format.push("🎪");
list.push(
"<li>"
+ "<span class=\"format\">" + format.join("") + "</span> "
+ "<a href=\"/wiki/" + qid + "\">"
+ mw.html.escape(obj.rows[0].itemLabel.value)
+ "</a>"
+ date
+ "</li>"
);
}, true);
}
if (hasp31(e.claims, p31values_universe)) {
let query = "\
select ?item ?itemLabel (min(?dates) as ?date) (min(year(?dates)) as ?year) ?print ?tv ?movie ?theatre ?game ?board ?card ?album ?audio ?amusement ?show{\
?item wdt:P1434 wd:" + e.id + ".\
optional { ?item wdt:P577 ?publication_date }.\
optional { ?item wdt:P580 ?start_date }.\
bind(COALESCE(?publication_date, ?start_date) as ?dates) .\
optional { ?item wdt:P31 ?print filter (?print IN (wd:Q2831984, wd:Q3297186, wd:Q14406742, wd:Q103076, wd:Q8274, wd:Q1760610, wd:Q21198342, wd:Q7725634, wd:Q47461344, wd:Q104213567)) }\
optional { ?item wdt:P31 ?tv filter (?tv IN (wd:Q5398426, wd:Q63952888, wd:Q104775758, wd:Q220898, wd:Q1259759, wd:Q581714, wd:Q117467246)) }\
optional { ?item wdt:P31 ?movie filter (?movie IN (wd:Q29168811, wd:Q24869, wd:Q202866, wd:Q24862, wd:Q11424, wd:Q20650540)) }\
optional { ?item wdt:P31 ?theatre filter (?theatre IN (wd:Q58483083)) }\
optional { ?item wdt:P31 ?game filter (?game IN (wd:Q7889, wd:Q16070115)) }\
optional { ?item wdt:P31 ?board filter (?board IN (wd:Q131436, wd:Q1643932)) }\
optional { ?item wdt:P31 ?card filter (?card IN (wd:Q734698)) }\
optional { ?item wdt:P31 ?album filter (?album IN (wd:Q482994)) }\
optional { ?item wdt:P31 ?audio filter (?audio IN (wd:Q105543609)) }\
optional { ?item wdt:P31 ?amusement filter (?amusement IN (wd:Q1144661, wd:Q512504, wd:Q1934961)) }\
optional { ?item wdt:P31 ?show filter (?show IN (wd:Q15116915, wd:Q85475422)) }\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} group by ?item ?itemLabel ?print ?tv ?movie ?theatre ?game ?board ?card ?album ?audio ?amusement ?show order by ?date" ;
runquery(query, $.i18n("in-universe"), function (qid) {
let obj = newlist[qid];
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("print"))
format.push("📚");
if (obj.rows[0].hasOwnProperty("tv"))
format.push("📺");
if (obj.rows[0].hasOwnProperty("movie"))
format.push("🎬");
if (obj.rows[0].hasOwnProperty("theatre"))
format.push("🎭");
if (obj.rows[0].hasOwnProperty("game"))
format.push("🎮");
if (obj.rows[0].hasOwnProperty("board"))
format.push("🎲");
if (obj.rows[0].hasOwnProperty("card"))
format.push("🎴");
if (obj.rows[0].hasOwnProperty("album"))
format.push("💿");
if (obj.rows[0].hasOwnProperty("audio"))
format.push("🎵");
if (obj.rows[0].hasOwnProperty("amusement"))
format.push("🎢");
if (obj.rows[0].hasOwnProperty("show"))
format.push("🎪");
list.push(
"<li>"
+ "<span class=\"format\">" + format.join("") + "</span> "
+ "<a href=\"/wiki/" + qid + "\">"
+ mw.html.escape(obj.rows[0].itemLabel.value)
+ "</a>"
+ date
+ "</li>"
);
}, true);
}
if (hasp31(e.claims, p31values_award)) {
let query = "\
select ?item ?itemLabel (year(?time) as ?year) {\
?item p:P166 ?statement.\
?statement ps:P166 wd:" + e.id + ".\
optional { ?statement pq:P585 ?time }\
service wikibase:label { bd:serviceParam wikibase:language \"" + langs + ",en\". }\
} order by ?year";
runquery(query, $.i18n("award-winners"), function (i, v) {
let qid = v.item.value.replace(/.*\//, "");
let attr = [];
let year = "";
if (v.year)
attr.push($.i18n("year-format", v.year.value));
if (v.subject) {
let fqid = v.subject.value.replace(/.*\//, "");
let flink = "<a href=\"/wiki/" + fqid + "\">" + mw.html.escape(v.subjectLabel.value) + "</a>";
attr.push(flink);
}
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>");
});
}
if (hasp31(e.claims, p31values_genres)) {
let query = `
select ?item ?itemLabel ?subitem ?subitemLabel
with {
select ?subitem ?subitemLabel ?item {
?subitem wdt:P279 ?item.
?item wdt:P279 wd:${e.id}.
} group by ?subitem ?subitemLabel ?item
} as %subitems
{
?item wdt:P279 wd:${e.id}.
optional { include %subitems }
service wikibase:label { bd:serviceParam wikibase:language "${langs},en" }
}
group by ?item ?itemLabel ?subitem ?subitemLabel
order by ?itemLabel ?subitemLabel
`;
runquery(query, $.i18n("sub-genres"), function (qid, obj) {
// The "true" parameter passed to runquery (after this callback
// function) causes it to group rows by ?item. The individual
// rows are in obj.rows.
// Here it creates a variable for the first row, for convenience
// when using the data which is the same for each row.
let v = obj.rows[0];
let subitems = [];
for (let row of obj.rows) {
if (row.hasOwnProperty("subitem")) {
let attr = [];
let attrtext = "";
if (attr.length > 0)
attrtext = $.i18n("brackets-format", attr.join($.i18n("comma-format")));
let subid = row.subitem.value.replace(/.*\//, "");
let subitem = `<li><a href="/wiki/${ subid }">${ mw.html.escape(row.subitemLabel.value) }</a> ${attrtext} </li>`;
subitems.push(subitem);
}
}
let attr = [];
let year = "";
if (v.year)
attr.push($.i18n("year-format", v.year.value));
if (v.subject) {
let fqid = v.subject.value.replace(/.*\//, "");
let flink = "<a href=\"/wiki/" + fqid + "\">" + mw.html.escape(v.subjectLabel.value) + "</a>";
attr.push(flink);
}
let attrtext = "";
if (attr.length > 0)
attrtext = $.i18n("brackets-format", attr.join($.i18n("comma-format")));
let sublist = "";
if (subitems.length) {
sublist = "<ul>" + subitems.join("") + "</ul>";
}
list.push("<li><a href=\"/wiki/" + qid + "\">" + mw.html.escape(v.itemLabel.value) + "</a>" + attrtext + sublist + "</li>");
}, true);
}
});
});
})();