Przeglądaj źródła

Links on word cloud

Francesco 2 lat temu
rodzic
commit
40a532ad3e
3 zmienionych plików z 266 dodań i 208 usunięć
  1. 1 0
      Persona.html
  2. 14 208
      js/people.js
  3. 251 0
      js/word_cloud.js

+ 1 - 0
Persona.html

@@ -567,6 +567,7 @@
 	</footer>
 
 	<script src="js/people.js"></script>
+	<script src="js/word_cloud.js"></script>
 
 	<!-- Bootstrap core JavaScript -->
 	<script src="vendor/jquery/jquery.min.js"></script>

+ 14 - 208
js/people.js

@@ -3,7 +3,7 @@ thisUrlParams = {};
 window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
     thisUrlParams[key] = value;
 });
-console.log('URL get params: ', thisUrlParams);
+//console.log('URL get params: ', thisUrlParams);
 
 // Funzioni per eseguire le queries
 function prepareQueryURL(query){
@@ -261,36 +261,6 @@ OPTIONAL {?production crm:P4_has_time-span ?uri_time_span . \
 crm:P02_has_range <" + thisUrlParams.link + "> } \
 GROUP BY ?subject ?label ?nct "
 
-queryNetwork = prefixes + " SELECT DISTINCT COUNT(?event) AS ?count ?uri2 SAMPLE(?label2) AS ?text \
-WHERE { \
-{?event rdf:type crm:EL1_Exchange_Letters . \
-?event_to rdfs:subClassOf ?event; \
-rdf:type crm:EL2_Send_Letter ; \
-crm:P01_has_domain ?pc_to . \
-?pc_to crm:P02_has_range ?uri . \
-?uri rdfs:label ?label . \
-?event_from rdfs:subClassOf ?event; \
-rdf:type crm:EL3_Receive_Letter; \
-crm:P01_has_domain ?pc_from . \
-?pc_from crm:P02_has_range ?uri2 . \
-?uri2 rdfs:label ?label2 . \
-FILTER (?uri = <" + thisUrlParams.link + ">) \
-} UNION { \
-?event rdf:type crm:EL1_Exchange_Letters . \
-?event_to rdfs:subClassOf ?event; \
-rdf:type crm:EL3_Receive_Letter ; \
-crm:P01_has_domain ?pc_from . \
-?pc_from crm:P02_has_range ?uri . \
-?uri rdfs:label ?label . \
-?event_from rdfs:subClassOf ?event; \
-rdf:type crm:EL2_Send_Letter; \
-crm:P01_has_domain ?pc_to . \
-?pc_to crm:P02_has_range ?uri2 . \
-?uri2 rdfs:label ?label2 . \
-FILTER (?uri = <" + thisUrlParams.link + ">) \
-} \
-} ORDER BY DESC (?count)"
-
 queryGettatelliEv = prefixes + " SELECT DISTINCT ?event_type ?time_span \
 WHERE { \
 VALUES ?uri {<" + thisUrlParams.link + ">} \
@@ -317,8 +287,6 @@ OPTIONAL {?uri_sede owl:sameAs ?uri_place . \
 
 queryURL = prepareQueryURL(query);
 
-queryNet = prepareQueryURL(queryNetwork);
-
 queryDoc = prepareQueryURL(queryDocuments);
 
 queryOt = prepareQueryURL(queryOtherDoc);
@@ -359,16 +327,6 @@ response = $.ajax({
     error: function (e) {}
 });
 
-responseNet = $.ajax({
-
-    url: queryNet,
-    dataType: "json",
-    success: function (data){
-      handle_network(data);
-    },
-    error: function (e) {}
-});
-
 responseLet = $.ajax({
 
     url: queryEx,
@@ -464,7 +422,7 @@ var labelName = "";
 
 function handle_data(json) {
 
-  console.log(json['results']['bindings']);
+  //console.log(json['results']['bindings']);
 
   var graph = "";
   var label = "";
@@ -602,7 +560,7 @@ function handle_data(json) {
 
         labelName = first_name;
 
-        console.log(variants);
+        //console.log(variants);
 
         var id_snippet = "<div class='col-sm-4'><span class='label'>" + id_type + ":</span></div><div class='col' id='identificatore'>" + identifier + "</div>";
 
@@ -651,7 +609,7 @@ function get_dataset_name(graph) {
 
 function handle_InfoGettatelli(json) {
   
-  console.log(json);
+  //console.log(json);
 
   var card = "";
   var uri_card = "";
@@ -683,7 +641,7 @@ function handle_InfoGettatelli(json) {
 
 function handle_Gettatelli(json) {
   
-  console.log(json);
+  //console.log(json);
 
   var generic = "";
   var find = "";
@@ -724,7 +682,7 @@ function handle_Gettatelli(json) {
 
 function handle_Relazioni(json) {
   
-  console.log(json);
+  //console.log(json);
 
   var Relazioni = "";
   const myArray = []
@@ -817,7 +775,7 @@ function handle_Relazioni(json) {
 
 function handle_RelazioniInverse(json) {
   
-  console.log(json);
+  //console.log(json);
 
   var Relazioni = "";
   const myArray = []
@@ -944,7 +902,7 @@ function createColRelazione(text, link) {
 
 function handle_Compagnia(json) {
   
-  console.log(json);
+  //console.log(json);
 
   var denominazione = "";
   var sede = "";
@@ -991,7 +949,7 @@ function handle_Compagnia(json) {
 
 function handle_Letters(json) {
 
-  console.log(json);
+  //console.log(json);
 
   const send = [];
   const receive = [];
@@ -1104,7 +1062,7 @@ function handle_Letters(json) {
 
 function handle_Artwork(json) {
 
-  console.log(json);
+  //console.log(json);
 
   const oa = [];
 
@@ -1155,7 +1113,7 @@ function handle_Artwork(json) {
 
 function handle_Documents(json) {
 
-  console.log(json);
+  //console.log(json);
 
   const docs = [];
 
@@ -1209,7 +1167,7 @@ function handle_Documents(json) {
 
 function handle_Other_Documents(json) {
 
-  console.log(json);
+  //console.log(json);
 
   const doc = [];
 
@@ -1261,7 +1219,7 @@ function handle_Other_Documents(json) {
 }
 
 function handle_map(json) {
-  console.log(json);
+  //console.log(json);
 
   const locations = [];
   const place_names = [];
@@ -1319,7 +1277,7 @@ function handle_map(json) {
     luoghi.push(tempArray);
   }
     
-  console.log(luoghi);
+  //console.log(luoghi);
   var latitude = lat/i;
   var longitude = long/i;
 
@@ -1388,158 +1346,6 @@ function handle_map(json) {
 }
 
 
-
-function handle_network(json) {
-  console.log(json);
-
-  const words = [];
-  const tempArray = [];
-  var listwords = "";
-  var ArrayNames = "";
-
-  var temp = 0;
-  var sum = 0;
-  var i=0;
-  var j=0;
-
-  $.each(
-      json['results']['bindings'],
-      function (index, value) {
-        text = value['text']['value'];
-        link = value['uri2']['value'];
-        num = parseInt(value['count']['value']);
-        /*count = 0;
-        if ((num - temp) > 50) {
-          count = temp + 12;
-        } else {
-          count = num;
-        }
-        words.push([text, count]);
-        temp = count;
-        sum += temp;*/
-        tempArray.push([text, num]);
-        ArrayNames += "<div class='item-place-person'><div class='item-place-person-label'>" +
-        text + "<br /><span class='num_occ'>[Co-occorrenze: " + num + "]</span></div><div class='item-place-person-action'><div class='persona' id='" +
-        link + "'><i class='fa fa-user' style='cursor:pointer'></i></div></div></div></div>";
-      });
-
-  if (tempArray.length < 8) {
-    for (var k=0; k<tempArray.length; k++) {
-      text = tempArray[k][0];
-      count = tempArray[k][1] + 36;
-      words.push([text, count]);
-    }
-  } else {
-    for (var k=tempArray.length-1; k>=0; k--) {
-      text = tempArray[k][0]; 
-      num = tempArray[k][1];
-      count = 0;
-      if ((num - temp) > 50) {
-          count = temp + 12;
-        } else {
-          count = num;
-        }
-      words.push([text, count]);
-      temp = count;
-      sum += temp;
-      }
-    }
-  
-
-  document.getElementById("list_person_network").innerHTML = ArrayNames;
-
-  $('#myWordCloud').empty();
-  /*var tot = parseInt(words[0][1]);*/
-
-  for (var i in words) {
-    var text = words[i][0]
-    var count = words[i][1];
-    listwords += '{ "word": \"' + text + '\", "size": \"' + count + '\"},';
-  }
-
-  let listL = ('[' + listwords + ']').replace(',]', ']');
-
-  const links = JSON.parse(listL);
-
-  console.log(links);
-
-  // List of words
-  var myWords = links;
-  
-  // set the dimensions and margins of the graph
-  var margin = {top: 10, right: 10, bottom: 10, left: 10},
-      width = 850 - margin.left - margin.right,
-      height = 500 - margin.top - margin.bottom;
-
-  // append the svg object to the body of the page
-  var svg = d3.select("#myWordCloud").append("svg")
-      .attr("id", "wordcloudNetwork")
-      .attr("width", width + margin.left + margin.right)
-      .attr("height", height + margin.top + margin.bottom)
-      .append("g")
-        .attr("transform",
-              "translate(" + (width/2-50) + "," + (height/2+20) + ")");
-
-  // Constructs a new cloud layout instance. It run an algorithm to find the position of words that suits your requirements
-  // Wordcloud features that are different from one word to the other must be here
-  var layout = d3.layout.cloud()
-                        .size([width, height])
-                        .words(myWords.map(function(d) { return {text: d.word, size:d.size/2}; }))
-                        .padding(5)        //space between words
-                        .rotate(function() { return ~~(Math.random() * 2);})
-                        .fontSize(function(d) { return d.size + 6; })      // font size of words
-                        .on("end", draw);
-                        layout.start();
-
-
-  // This function takes the output of 'layout' above and draw the words
-  // Wordcloud features that are THE SAME from one word to the other can be here
-  function draw(words) {
-    var cloud = svg.selectAll("g text")
-                          .data(words, function(d) { return d.text; })
-
-          //Entering words
-          cloud.enter()
-              .append("text")
-              .style("font-family", "Impact")
-              .attr("text-anchor", "middle")
-              .attr('font-size', 1)
-              .text(function(d) { return d.text; });
-
-          //Entering and existing words
-          cloud
-              .transition()
-                  .duration(600)
-                  .style("font-size", function(d) { return d.size + "px"; })
-                  .attr("transform", function(d) {
-                      return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
-                  })
-                  .style("fill-opacity", 1);
-
-          //Exiting words
-          cloud.exit()
-              .transition()
-                  .duration(200)
-                  .style('fill-opacity', 1e-6)
-                  .attr('font-size', 1)
-                  .remove();
-    }
-
-    var wordIcon = "<div id='users_icon' class='no_info_icon'> \
-    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512'> \
-      <!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d='M319.9 320c57.41 0 103.1-46.56 103.1-104c0-57.44-46.54-104-103.1-104c-57.41 0-103.1 46.56-103.1 104C215.9 273.4 262.5 320 319.9 320zM369.9 352H270.1C191.6 352 128 411.7 128 485.3C128 500.1 140.7 512 156.4 512h327.2C499.3 512 512 500.1 512 485.3C512 411.7 448.4 352 369.9 352zM512 160c44.18 0 80-35.82 80-80S556.2 0 512 0c-44.18 0-80 35.82-80 80S467.8 160 512 160zM183.9 216c0-5.449 .9824-10.63 1.609-15.91C174.6 194.1 162.6 192 149.9 192H88.08C39.44 192 0 233.8 0 285.3C0 295.6 7.887 304 17.62 304h199.5C196.7 280.2 183.9 249.7 183.9 216zM128 160c44.18 0 80-35.82 80-80S172.2 0 128 0C83.82 0 48 35.82 48 80S83.82 160 128 160zM551.9 192h-61.84c-12.8 0-24.88 3.037-35.86 8.24C454.8 205.5 455.8 210.6 455.8 216c0 33.71-12.78 64.21-33.16 88h199.7C632.1 304 640 295.6 640 285.3C640 233.8 600.6 192 551.9 192z'/> \
-    </svg> \
-    <p>Nessuna persona trovata</p> \
-    </div>";
-
-    if (words.length == 0) {
-      $("#wordcloudNetwork").css("display", "none");
-      $("#references_network").css("display", "none");
-      document.getElementById("myWordCloud").innerHTML = wordIcon;
-    }
-
-}
-
 $(document).on("click", ".luogo", function (ev) {
 
     var link = this.id;

+ 251 - 0
js/word_cloud.js

@@ -0,0 +1,251 @@
+
+/**
+ * QUERY SECTION
+ * 
+ *               */
+
+// SPARQL Query text -- 'prefixes' and 'thisUrlParams' defined in people.js; 
+let queryNetwork = prefixes + " SELECT DISTINCT COUNT(?event) AS ?count ?uri2 SAMPLE(?label2) AS ?text \
+WHERE { \
+{?event rdf:type crm:EL1_Exchange_Letters . \
+?event_to rdfs:subClassOf ?event; \
+rdf:type crm:EL2_Send_Letter ; \
+crm:P01_has_domain ?pc_to . \
+?pc_to crm:P02_has_range ?uri . \
+?uri rdfs:label ?label . \
+?event_from rdfs:subClassOf ?event; \
+rdf:type crm:EL3_Receive_Letter; \
+crm:P01_has_domain ?pc_from . \
+?pc_from crm:P02_has_range ?uri2 . \
+?uri2 rdfs:label ?label2 . \
+FILTER (?uri = <" + thisUrlParams.link + ">) \
+} UNION { \
+?event rdf:type crm:EL1_Exchange_Letters . \
+?event_to rdfs:subClassOf ?event; \
+rdf:type crm:EL3_Receive_Letter ; \
+crm:P01_has_domain ?pc_from . \
+?pc_from crm:P02_has_range ?uri . \
+?uri rdfs:label ?label . \
+?event_from rdfs:subClassOf ?event; \
+rdf:type crm:EL2_Send_Letter; \
+crm:P01_has_domain ?pc_to . \
+?pc_to crm:P02_has_range ?uri2 . \
+?uri2 rdfs:label ?label2 . \
+FILTER (?uri = <" + thisUrlParams.link + ">) \
+} \
+} ORDER BY DESC (?count)"
+
+// 'prepareQueryURL' defined in people.js
+let queryNet = prepareQueryURL(queryNetwork);
+
+// do the query, call data processor on successful output
+$.ajax({
+    url: queryNet,
+    dataType: "json",
+    success: (data) => handle_word_network(data)
+});
+
+
+
+/**
+ * COMPONENT CREATION SECTION
+ * 
+ *               */
+
+// Master function, takes data output from the query and creates the HTML for the Word Cloud component of the page
+function handle_word_network(json){
+    // Pre-process data
+    let tempArray = processQuery(json);
+    let words = prepareWords(tempArray);
+    // Create page elements
+    doListPersonNetwork(tempArray);
+    doWordCloud(words);
+}
+
+
+// Return structured object from raw query data for further processing
+function processQuery(json) {
+  
+    const tempArray = [];
+    
+    $.each(
+        json['results']['bindings'],
+        function (index, value) {
+          let text = value['text']['value'];
+          let link = value['uri2']['value'];
+          let num = parseInt(value['count']['value']);
+          tempArray.push({'text': text, 'count': num, 'hlink': link});
+        }
+    );
+
+    return tempArray;
+
+}
+
+
+// Define font size, according to the number of words and limiting the impact of huge counts -- to refactor??
+function prepareWords(tempArray){
+
+    const words = [];
+
+    if (tempArray.length < 8) { // Less than 8 results -- font size is just = count/2 + constant
+      for (let entry in tempArray) {
+        let text = entry['text'];
+        let preSize = entry['count'] + 36;
+        let link = entry['hlink'];
+        words.push(
+            {
+                'text': text,
+                'size': preSize/2 + 6,
+                'hlink': link
+            }
+        );
+      }
+    } else { // More than 8 results -- font size = count except for especially "big" words
+      let temp = 0;
+      for (let k=tempArray.length-1; k>=0; k--) {
+        let text = tempArray[k]['text']; 
+        let count = tempArray[k]['count'];
+        let link = tempArray[k]['hlink'];
+        let preSize = 0;
+        if ((count - temp) > 50) {
+            preSize = temp + 12;
+          } else {
+            preSize = count;
+        }
+        words.push(
+            {
+                'text': text,
+                'size': preSize/2 + 6,
+                'hlink': link
+            }
+        );
+        temp = preSize;
+      }
+    }
+
+    console.log('tempArray', tempArray)
+    console.log('words', words)
+    
+    return words;
+
+}
+
+
+// Create formatted list of people in the network
+function doListPersonNetwork(tempArray){
+
+    let ArrayNames = "";
+
+    tempArray.forEach(element => {
+        ArrayNames += "<div class='item-place-person'><div class='item-place-person-label'>" +
+        element['text'] + "<br /><span class='num_occ'>[Co-occorrenze: " + element['num'] + "]</span></div><div class='item-place-person-action'><div class='persona' id='" +
+        element['hlink'] + "'><i class='fa fa-user' style='cursor:pointer'></i></div></div></div></div>";            
+    });
+
+    document.getElementById("list_person_network").innerHTML = ArrayNames;
+
+}
+
+
+// Create the word cloud
+function doWordCloud(myWords){
+    
+    // Clear word cloud div
+    $('#myWordCloud').empty();
+
+
+    // OVERALL GRAPHIC SETTINGS for the cloud container -- id, dimensions, position
+
+    // set the dimensions and margins of the graph
+    let margin = {top: 10, right: 10, bottom: 10, left: 10},
+        width = 850 - margin.left - margin.right,
+        height = 500 - margin.top - margin.bottom;
+  
+    // append the svg object to the body of the page
+    let svg = d3.select("#myWordCloud")
+        .append("svg")
+        .attr("id", "wordcloudNetwork")
+        .attr("width", width + margin.left + margin.right)
+        .attr("height", height + margin.top + margin.bottom)
+        .append("g")
+        .attr("transform", "translate(" + (width/2-50) + "," + (height/2+20) + ")");
+
+    // In case of empty cloud, draw special page and exit
+    if (myWords.length == 0){
+        drawEmptyWordCloud();
+        return;
+    }
+    
+
+    // THE ACTUAL CLOUD
+
+    // Constructs a new cloud layout instance. It runs an algorithm to find the position of words that suits your requirements
+    // Wordcloud features that are different from one word to the other must be here
+
+    let layout = d3.layout.cloud() // Constructs the cloud
+                          .size([width, height]) // Sets width and height
+                          .words(myWords) // put words in; expects an array of objects. Format is free, it all depends on the definition of the functions that are applied to define the cloud structure.
+                          //
+                          // A js curiosity: ~ is a bitwise not operator. On a number, the double bitwise not ~~ has the net effect of giving the integer part, that is: floor on positives and ceiling on negatives.
+                          .rotate( () => { return ~~(Math.random() * 2);} )
+                          .fontSize( word => { return word['size']; } ) // font size of words
+                          .on("end", word => draw(word, svg));
+    layout.start();
+  
+}
+
+
+// Helper function for the Word Cloud --
+// it draws the words
+// Wordcloud features that are THE SAME from one word to the other can be here ??
+function draw(words, svg) {
+    let cloud = svg.selectAll("g text")
+        .data(words, word => word.text) // What does this do?
+
+        //Entering words
+        cloud.enter()
+             .append("text")
+             .style("font-family", "Impact")
+             .attr("text-anchor", "middle")
+             .attr('font-size', 1)
+             .append("a")
+             .attr("href", word => word.hlink)
+             .text( word => { return word.text; });
+
+        //Entering and exiting words
+        cloud.transition()
+             .duration(600)
+             .style("font-size", function(d) { return d.size + "px"; })
+             .attr("transform", function(d) {
+                    return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
+             })
+             .style("fill-opacity", 1);
+
+        //Exiting words
+        cloud.exit()
+             .transition()
+              .duration(200)
+              .style('fill-opacity', 1e-6)
+              .attr('font-size', 1)
+              .remove();
+
+}
+
+
+// Helper function -- draw special empty word cloud if there are no occurrences
+function drawEmptyWordCloud(){
+
+    let wordIcon = "<div id='users_icon' class='no_info_icon'> \
+    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512'> \
+      <!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d='M319.9 320c57.41 0 103.1-46.56 103.1-104c0-57.44-46.54-104-103.1-104c-57.41 0-103.1 46.56-103.1 104C215.9 273.4 262.5 320 319.9 320zM369.9 352H270.1C191.6 352 128 411.7 128 485.3C128 500.1 140.7 512 156.4 512h327.2C499.3 512 512 500.1 512 485.3C512 411.7 448.4 352 369.9 352zM512 160c44.18 0 80-35.82 80-80S556.2 0 512 0c-44.18 0-80 35.82-80 80S467.8 160 512 160zM183.9 216c0-5.449 .9824-10.63 1.609-15.91C174.6 194.1 162.6 192 149.9 192H88.08C39.44 192 0 233.8 0 285.3C0 295.6 7.887 304 17.62 304h199.5C196.7 280.2 183.9 249.7 183.9 216zM128 160c44.18 0 80-35.82 80-80S172.2 0 128 0C83.82 0 48 35.82 48 80S83.82 160 128 160zM551.9 192h-61.84c-12.8 0-24.88 3.037-35.86 8.24C454.8 205.5 455.8 210.6 455.8 216c0 33.71-12.78 64.21-33.16 88h199.7C632.1 304 640 295.6 640 285.3C640 233.8 600.6 192 551.9 192z'/> \
+    </svg> \
+    <p>Nessuna persona trovata</p> \
+    </div>";
+
+    $("#wordcloudNetwork").css("display", "none");
+    $("#references_network").css("display", "none");
+
+    document.getElementById("myWordCloud").innerHTML = wordIcon;
+
+}