/** * QUERY SECTION * * */ // SPARQL Query text -- 'prefixes' and 'thisUrlParams' defined in people.js; let queryNetwork = prefixes + " SELECT COUNT(?event1) AS ?count1 COUNT(?event2) AS ?count2 ?uri2 SAMPLE(?label2) AS ?text \ WHERE { \ {?event1 rdf:type crm:EL1_Exchange_Letters . \ ?event_to rdfs:subClassOf ?event1; \ 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 ?event1; \ 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 { \ ?event2 rdf:type crm:EL1_Exchange_Letters . \ ?event_to rdfs:subClassOf ?event2; \ 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 ?event2; \ 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 + ">) \ } \ }" // '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) }); // queryLetters defined in people.js console.log(queryLetters); /** * 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 words = processQuery(json); // Create page elements doListPersonNetwork(words); doWordCloud(words); } // Return structured object from raw query data for further processing function processQuery(json) { const tempArray = []; $.each( json['results']['bindings'], (index, value) => { let text = value['text']['value']; let link = value['uri2']['value']; let sent = parseInt(value['count1']['value']); let received = parseInt(value['count2']['value']); let count = sent + received; tempArray.push({'text': text, 'sent': sent, 'received': received, 'count': count, 'hlink': link}); } ); tempArray.sort((a, b) => b.count - a.count); return tempArray; } // Create formatted list of people in the network function doListPersonNetwork(words){ let ArrayNames = ""; words.forEach(element => { filteredText = element['text'].replace('"', '').replace("'", ''); ArrayNames += "
"+ "
" + element['text'] + "
[Lettere inviate: " + element['sent'] + "]" + "
[Lettere ricevute: " + element['received'] + "]" + "
[Totale corrispondenza: " + element['count'] + "]" + "
" + "
" + "
" + "" + "
" + "
" + "
"; }); document.getElementById("list_person_network").innerHTML = ArrayNames; addEventsToNameList(words); } function addEventsToNameList(words){ let counter = 0 for(let word of words){ if(counter>0) break; let listElem = document.getElementById('tot-' + word.text.replace('"', '').replace("'", '')); if(listElem!=null){ listElem.addEventListener("click", filterLetters); listElem.addEventListener("mouseover", highlightWord); listElem.addEventListener("mouseout", unHighlightWord); } counter++; } } function filterLetters(e){ try{ let preText = e.target.parentNode.textContent; console.log('text content', preText); let name = preText.split("[")[0]; console.log('name', name); // responseLet defined in people.js responseLet.then(data => { let lettersJson = data.results.bindings; lettersJson = lettersJson.filter(letter => letter.otherPerson.value==name); console.log(lettersJson); }); } catch{ console.log("Couldn't get the name"); } } // Create the word cloud function doWordCloud(words){ // Clear word cloud div $('#myWordCloud').empty(); // OVERALL GRAPHIC SETTINGS for the cloud container -- id, dimensions, position let width = 0.5*window.outerWidth; let height = 0.6*width; // append the svg object to the body of the page let svg = d3.select("#myWordCloud") .append("svg") .attr("id", "wordcloudNetwork") .attr("preserveAspectRatio", "xMinYMin meet") .attr("viewBox", "0 0 " + width + " " + height) .classed("svg-content", true) .attr("width", width) .attr("height", height) .attr("style", "border:1px solid black") // In case of empty cloud, draw special page and exit if (words.length == 0){ drawEmptyWordCloud(); return; } // THE ACTUAL CLOUD svg = document.getElementById('wordcloudNetwork'); console.log(svg); let zoom = window.devicePixelRatio; console.log('zoom', zoom); wcParameters = { svgWidth: svg.getBoundingClientRect().width, svgHeight: svg.getBoundingClientRect().height, maxFontSize: 30/((1+zoom)/2), minFontSize: 10/((1+zoom)/2) } let svgWords = hackWords(words, wcParameters); svg.innerHTML = svgWords; let wordCloudText = createWordCloud(words, wcParameters); svg.innerHTML = wordCloudText; addEventsToWordCloud(words); } // Helper function -- draw special empty word cloud if there are no occurrences function drawEmptyWordCloud(){ let wordIcon = "
\ \ \ \

Nessuna persona trovata

\
"; $("#wordcloudNetwork").css("display", "none"); $("#references_network").css("display", "none"); document.getElementById("myWordCloud").innerHTML = wordIcon; } /***************************** * Customized word cloud code * *****************************/ function hackWords(words, parameters){ let weights = words.map(word => word.count); let minWeight = Math.min(...weights); let maxFontSize = parameters.maxFontSize; let minFontSize = parameters.minFontSize; console.log('weights', weights); console.log('maxFontSize', maxFontSize); console.log('minFontSize',minFontSize); let stringOfWords = ""; for(let ind=0; ind'+words[ind].text+'\n'; } return stringOfWords; } // Takes a list of words, returns the innerHTML for a Word Cloud as a string containing multiple svg elements function createWordCloud(words, parameters){ let actualUsefulWidth = parameters.svgWidth; let actualUsefulHeight = parameters.svgHeight; console.log('Actual SVG dimensions', actualUsefulWidth, actualUsefulHeight); maxFontSize = parameters.maxFontSize; minFontSize = parameters.minFontSize; const rectObjs = [] let allBooms = 0 let attempts = 0; let outOfBorder = 0; for(let ind=0;ind=20*(ind+1)) break; attempts++; let boom = false; // word + bounding box parameters definition let word = words[ind]; let id0 = "word"+ind; let wordBB = document.getElementById(id0).getBoundingClientRect(); let fontSize = word.fontSize; let width = wordBB.width; let height = wordBB.height; let multiplier = 0.1 + 0.4*Math.max((maxFontSize-fontSize)/(maxFontSize-minFontSize), allBooms/(20*(ind+1))); let xR = Math.floor(actualUsefulWidth/2-width/2 + randomRange(-multiplier*actualUsefulWidth, multiplier*actualUsefulWidth)); let yR = Math.floor(actualUsefulHeight/2 + randomRange(-multiplier*actualUsefulHeight, multiplier*actualUsefulHeight)); //console.log('x', 'y', xR, yR) let angle; if(word.received/word.sent>3) angle = -3; else if(word.received/word.sent<0.3) angle = 3; let text = word.text; //console.log('Rect:', width, height, xR, yR, angle, text); // let newRect = new Rect(width, height, xR, yR, angle, text, fontSize); boom = checkBorder(newRect, 0, actualUsefulWidth, 0, actualUsefulHeight) if(boom){ outOfBorder++; if(outOfBorder<30){ ind--; continue; } else{ boom = false; } } for(let rect of rectObjs){ boom = checkColl(newRect, rect); if(boom) break; } if(boom){ allBooms++; ind--; continue; } allBooms = 0; rectObjs.push(newRect); } console.log('Attempted:', attempts); console.log('Placed:', rectObjs.length); console.log('booms!', allBooms); const rectTexts = []; rectObjs.forEach(rect => rectTexts.push(rect.printCoords(false, maxFontSize, minFontSize))); let rects = rectTexts.join('\n'); return rects; } function getFontSize(weight, minWeight, maxFontSize, minFontSize){ let r1 = weight/10*minWeight - 1/10; // between 0 and a big num let res = minFontSize + (maxFontSize-minFontSize)*r1/Math.sqrt(1+r1**2); return res; } function randomRange(a, b=0){ return (a-b)*Math.random()+b; } function randomInt(a){ return Math.floor(a*Math.random()); } function randomRangeInt(a, b=0){ let ap = Math.floor(a); let bp = Math.floor(b); return Math.floor((ap-bp)*Math.random())+bp; } // Check border collision function checkBorder(rect, minX, maxX, minY, maxY){ if(rect.minXmaxX) return true; if(rect.minYmaxY) return true; return false; } function addEventsToWordCloud(words){ for(let word of words){ let wcElem = document.getElementById('word-' + word.text.replace('"', '').replace("'", '')); if(wcElem!=null){ wcElem.addEventListener("click", focusPersonInList); wcElem.addEventListener("mouseover", highlightWord); wcElem.addEventListener("mouseout", unHighlightWord); } } } function focusPersonInList(e){ let targetId = e.target.id; console.log(targetId); let listElem = document.getElementById(targetId.replace('word-', 'list-')); listElem.scrollIntoView({behavior: "smooth", block: "center"}); } function highlightWord(e){ e.target.style['text-decoration'] = "underline"; } function unHighlightWord(e){ e.target.style['text-decoration'] = ""; }