Use more flexible wikidata music card
authorDan Scott <dscott@laurentian.ca>
Sun, 25 Mar 2018 14:32:02 +0000 (10:32 -0400)
committerDan Scott <dscott@laurentian.ca>
Sun, 25 Mar 2018 14:32:02 +0000 (10:32 -0400)
Base on the more generic example from
https://gitlab.com/denials/wikidata-music-infocard, which separates out the
record detail page elements into configurable CSS selector paths. This should
make it easier to keep up with any global refactoring or local customizations
of the catalogue record detail pages.

Signed-off-by: Dan Scott <dscott@laurentian.ca>
Open-ILS/web/js/ui/default/opac/wikidata_music_card.js

index a71a334..cf47304 100644 (file)
@@ -2,7 +2,7 @@
   /**
    * Display an infocard with data pulled from Wikidata
    *
-   * Copyright 2017 Dan Scott (dan@coffeecode.net), Laurentian University
+   * Copyright 2017,2018 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
    * * 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
+   * To use this in your catalogue, you will need to modify a few of the CSS
+   * queries to find the contributors, their names, and identify appropriate
    * locations for inserting the clickable note icon and the infocard.
    */
+
+  /* Path for the schema.org type declaration */
+  var type_path = 'div[typeof~="MusicAlbum"]';
+
+  /* List of elements describing contributors */
+  var contributors_path = 'span[resource^="#schemacontrib"]';
+
+  /* Path to find the name within each contributor element */
+  var contributor_name = 'span[property="name"]';
+
+  /* Within each contributor element, where we can append a Wikidata clickable icon */
+  var name_path = 'span[property="description"]';
+
+  /* Path for appending the requested infocards */
+  var infocard_location = '#rdetail_title+div';
+
   var icon_node;
   var note;
   var img;
   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) {
+  /* Ensure this is a musical recording, based on http://schema.org/MusicAlbum */
+  if (document.querySelector(type_path)) {
+    var contributor_nodes = document.querySelectorAll(contributors_path);
+    for (var node of contributor_nodes) {
       /* Insert clickable icon here */
-      icon_node = node.querySelector('span[property="description"]');
+      icon_node = node.querySelector(name_path);
       if (icon_node) {
         img = document.createElement('img');
         img.src = 'https://www.wikidata.org/static/favicon/wikidata.ico';
   }
 
   function getContribName(node) {
-    var entity_name = node.querySelector('span[property="name"]').textContent.trim();
-    var lastchar = entity_name[entity_name.length - 1];
+    var raw_name = node.querySelector(contributor_name).textContent.trim();
+    var lastchar = raw_name[raw_name.length - 1];
+    var entity_name = '';
     if (lastchar === '.' || lastchar === ',') {
-      entity_name = entity_name.slice(0, -1);
+      raw_name = raw_name.slice(0, -1);
     }
-    var inverse = entity_name.split(',');
-    if (inverse.length === 2) {
-      entity_name = inverse[1].trim() + " " + inverse[0].trim();
+    /* Change "Silver, Liberty" to "Liberty Silver" for the lookup */
+    var inverse = raw_name.split(',');
+    for (x in inverse.reverse()) {
+      entity_name += inverse[x].trim() + " ";
     }
-    return entity_name;
+    return entity_name.trim();
   }
 
   function perform(e) {
@@ -73,9 +90,7 @@
         '?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:P31 wd:Q5741069 . } ' + // rock band
+        '{ ?item wdt:P31/wdt:P279* wd:Q215380 . } ' + // instance of = any subclass of band
         'UNION ' +
         '{ ?item wdt:P106/wdt:P279* wd:Q639669 . } ' + // occupation = any subclass of musician
         'UNION ' +
   }
 
   function generateCard(icon_node, r) {
-    var auth_div = document.querySelector('div[class="rdetail_authors_div"]');
+    var auth_div = document.querySelector(infocard_location);
     var musician = document.createElement('div');
     var uri = r.item.value;
     var wdid = uri.substr(uri.lastIndexOf('/') + 1);
     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';
+    auth_div.appendChild(musician);
   }
 })()