--- /dev/null
+;(function () {
+ /**
+ * Display an infocard with data pulled from Wikidata
+ *
+ * Copyright 2017 Dan Scott (dan@coffeecode.net), Laurentian University
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Based on the primary contributor's name, search Wikidata via SPARQL for
+ * musicians or bands using an exact string match of the label or alias,
+ * and retrieve the data of interest.
+ *
+ * Current limitations:
+ * * Only activated for musical recordings, to avoid ambiguous results
+ * * Hard-coded for English
+ *
+ * To use this in your catalogue, you will need to modify a few of the
+ * CSS queries to find the performer's name and identify appropriate
+ * locations for inserting the clickable note icon and the infocard.
+ */
+ var icon_node;
+ var note;
+ var wd;
+
+ /* Ensure this is a musical recording */
+ if (document.getElementById('canvas_main').getAttribute('typeof').indexOf('MusicAlbum') > -1) {
+ /* Performer's name - used to find a matching item in wikidata */
+ var performer_nodes = document.querySelectorAll('span[resource^="#schemacontrib"]');
+ for (var node of performer_nodes) {
+ /* Insert clickable icon here */
+ icon_node = node.querySelector('span[property="description"]');
+ if (icon_node) {
+ note = document.createElement('span');
+ note.class = 'wikidata';
+ note.innerText = ' ♪';
+ note.addEventListener('click', perform, { once: true });
+ icon_node.insertBefore(note, null);
+ }
+ }
+ }
+
+ function getContribName(node) {
+ var entity_name = node.querySelector('span[property="name"]').textContent.trim();
+ var lastchar = entity_name[entity_name.length - 1];
+ if (lastchar === '.' || lastchar === ',') {
+ entity_name = entity_name.slice(0, -1);
+ }
+ var inverse = entity_name.split(',');
+ if (inverse.length === 2) {
+ entity_name = inverse[1].trim() + " " + inverse[0].trim();
+ }
+ return entity_name;
+ }
+
+ function perform(e) {
+ var entity_name = getContribName(this.parentNode.parentNode);
+ findPerformer(icon_node, entity_name);
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ function toggleMode(el) {
+ wd = document.getElementById('magic_musician');
+ wd.style.display = 'inherit';
+ el.addEventListener('click', toggle);
+ }
+
+ function toggle(e) {
+ wd = document.getElementById('magic_musician');
+
+ if (wd.style.display === 'inherit') {
+ wd.style.display = 'none';
+ } else {
+ wd.style.display = 'inherit';
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ function findPerformer(icon_node, entity_name) {
+ var url = 'https://query.wikidata.org/sparql';
+ var query = 'SELECT DISTINCT ?item ?itemLabel ?itemDescription ?image ?birthPlace ?birthPlaceLabel ' +
+ '?website ?musicbrainz ?songKick ?twitter ?facebook ?wplink ' +
+ 'WHERE { ' +
+ '?item rdfs:label|skos:altLabel|wdt:P1449 "' + entity_name + '"@en . ' +
+ '{ ?item wdt:P31/wdt:P279* wd:Q215380 . } ' + // band
+ 'UNION ' +
+ '{ ?item wdt:P106/wdt:P279* wd:Q639669 . } ' + // musician
+ 'OPTIONAL { ?item wdt:P3478 ?songKick } . ' +
+ 'OPTIONAL { ?item wdt:P19 ?birthPlace } . ' +
+ 'OPTIONAL { ?item wdt:P856 ?website } . ' +
+ 'OPTIONAL { ?item wdt:P434 ?musicbrainz } . ' +
+ 'OPTIONAL { ?item wdt:P2002 ?twitter } . ' +
+ 'OPTIONAL { ?item wdt:P2013 ?facebook } . ' +
+ 'OPTIONAL { ?item wdt:P18 ?image } . ' +
+ 'OPTIONAL { ' +
+ '?wplink schema:about ?item . ' +
+ '?wplink schema:inLanguage "en" . ' +
+ '?wplink schema:isPartOf <https://en.wikipedia.org/> . ' +
+ '} ' +
+ 'SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } ' +
+ '} ' +
+ 'LIMIT 10';
+ var q = '?query=' + encodeURIComponent(query);
+
+ var req = new window.XMLHttpRequest();
+ req.open('GET', url + q);
+ req.setRequestHeader('Accept', 'application/sparql-results+json');
+ if (req.responseType && (req.responseType = 'json')) {
+ req.onload = function (evt) {
+ var r = req.response.results.bindings[0];
+ if (r !== undefined) {
+ generateCard(icon_node, r);
+ toggleMode(note);
+ // console.log(r);
+ }
+ }
+ } else {
+ // IE 10/11
+ req.onload = function (evt) {
+ var r = JSON.parse(req.responseText).results.bindings[0];
+ if (r !== undefined) {
+ generateCard(icon_node, r);
+ toggleMode(note);
+ // console.log(r);
+ }
+ }
+ }
+ req.send();
+ }
+
+ function generateCard(icon_node, r) {
+ var auth_div = document.querySelector('div[class="rdetail_authors_div"]');
+ var musician = document.createElement('div');
+ musician.id = 'magic_musician';
+ musician.style.padding = '0.5em 1em 1em 1em';
+ musician.style.border = 'thin blue solid';
+ musician.style.overflow = 'hidden';
+
+ addWDValue('itemLabel', null, null, false);
+
+ if (r.hasOwnProperty('image')) {
+ var img = document.createElement('img');
+ img.src = r.image.value.replace('http:', 'https:');
+ img.style.float = 'left';
+ img.style.width = '150px';
+ img.style['margin-right'] = '1em';
+ musician.appendChild(img);
+ }
+
+ if (r.hasOwnProperty('itemDescription')) {
+ var description = r.itemDescription.value;
+ var wdd = document.createElement('div');
+ var wddl = document.createElement('label');
+ wddl.innerText = description;
+ wdd.appendChild(wddl);
+ musician.appendChild(wdd);
+ }
+
+ // Get the description from Wikipedia
+ if (r.hasOwnProperty('wplink')) {
+ wpapi = 'https://en.wikipedia.org/w/api.php?origin=*&format=json&action=query&prop=extracts&explaintext=true&exintro=true&titles=';
+ var wplink = r.wplink.value;
+ // Strip the WP title from the link
+ wptitle = wplink.substring(wplink.lastIndexOf('/') + 1);
+
+ var req = new window.XMLHttpRequest();
+ req.open('GET', wpapi + wptitle);
+ req.onload = function (evt) {
+ var r = JSON.parse(req.response);
+ var k = Object.getOwnPropertyNames(r.query.pages)[0];
+ var description = r.query.pages[k].extract;
+
+ // Just the first line will do
+ var linefeed = description.indexOf('\n');
+ var period = description.indexOf('. ');
+ if (linefeed > 0) {
+ description = description.substring(0, linefeed);
+ } else if (period > 0) {
+ description = description.substring(0, period + 1);
+ }
+ var wdd = document.createElement('p');
+ var wpa = document.createElement('a');
+ wpa.href = wplink;
+ wpa.innerText = '(Wikipedia)';
+ wdd.innerText = description + ' ';
+ wdd.appendChild(wpa);
+ musician.appendChild(wdd);
+ }
+ req.send();
+ }
+
+ function addWDValue(property, propertyLabel, label, isLink, linkFormatter) {
+ var value = '';
+ if (r.hasOwnProperty(property)) {
+ value = r[property].value;
+ var valueDiv = document.createElement('div');
+ var labelText = value;
+ if (!propertyLabel && !label && !isLink) {
+ var strong = document.createElement('strong');
+ valueDiv.appendChild(strong);
+ strong.innerText = labelText;
+ }
+ if (propertyLabel) {
+ var valueLabel = document.createElement('label');
+ valueLabel.innerText = propertyLabel;
+ valueDiv.appendChild(valueLabel);
+ }
+ if (label) {
+ if (r.hasOwnProperty(label)) {
+ labelText = r[label].value;
+ } else {
+ labelText = label;
+ }
+ }
+ if (isLink) {
+ var valueLink = document.createElement('a');
+ if (linkFormatter) {
+ valueLink.href = linkFormatter(value);
+ } else {
+ valueLink.href = value;
+ }
+ valueLink.innerText = labelText;
+ valueDiv.appendChild(valueLink);
+ }
+ musician.appendChild(valueDiv);
+ }
+ }
+
+ addWDValue('birthPlace', 'Birth place: ', 'birthPlaceLabel', true);
+ addWDValue('website', 'Web site: ', null, true);
+ addWDValue('musicbrainz', null, 'Discography (Musicbrainz)', true, function(value) { return 'https://musicbrainz.org/artist/' + value });
+ addWDValue('songKick', null, 'Tour dates (Songkick)', true, function(value) { return 'http://www.songkick.com/artists/' + value });
+ addWDValue('twitter', 'Twitter: ', null, true, function(value) { return 'https://twitter.com/' + value });
+ addWDValue('facebook', 'Facebook: ', null, true, function(value) { return 'https://www.facebook.com/' + value });
+
+ var uri = r.item.value;
+ var wd = document.createElement('div');
+ var wdl = document.createElement('label');
+ wdl.innerText = 'Edit on Wikidata: ';
+ var wdv = document.createElement('a');
+ wdv.href = uri;
+ wdv.innerText = uri.substr(uri.lastIndexOf('/') + 1);
+ wd.appendChild(wdl);
+ wd.appendChild(wdv);
+ musician.appendChild(wd);
+
+ auth_div.appendChild(musician);
+ /* Append the Wikidata infocard to the page */
+ document.getElementById('rdetail_image_div').style.clear = 'both';
+ }
+})()