blob: 080cff012ab585d80c0bf3f224b234893a8ad2f3 [file] [log] [blame]
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +01001// *********** HERE STARTS circle-mode.js *************
2
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +01003circleMode = false;
4
5function initCircleMode() {
avm99963027b5b02018-12-28 02:31:46 +01006 document.querySelector("#circle-mode").addEventListener('click', function() {
7 if(circleMode) {
8 circleMode = false;
9 document.querySelector("#circle-mode i").innerText = "trip_origin";
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +010010
avm99963027b5b02018-12-28 02:31:46 +010011 s.graph.nodes().forEach(function(n) {
12 n.x = n.originalX;
13 n.y = n.originalY;
14 n.size = 10;
15 });
16
17 s.refresh();
18 } else {
19 circleMode = true;
20 document.querySelector("#circle-mode i").innerText = "scatter_plot";
21
22 s.graph.nodes().forEach(function(n) {
23 n.x = n.circleX;
24 n.y = n.circleY;
25 });
26
27 s.refresh();
28 }
29 });
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +010030}
31
avm99963027b5b02018-12-28 02:31:46 +010032function isInRect(x, y, rect) {
33 if (x < -10000 || x > 10000) return true;
34 if (y < -10000 || y > 10000) return true;
35
36 var ans = true;
37 var c = crossProd (rect[0], rect[1], x, y);
38
39 for(var i = 1; i < 4; i++) {
40 var temp = crossProd (rect[i], rect[(i+1)%4], x, y);
41 if (c*temp < 0) ans = false;
42 }
43 return ans;
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +010044}
45
46function crossProd(r1, r2, x, y) {
avm99963027b5b02018-12-28 02:31:46 +010047 return r1[0]*r2[1] + r2[0]*y + x*r1[1] - r1[0]*y - r2[0]*r1[1] - x*r2[1];
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +010048}
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +010049// *********** HERE STARTS graf.js *************
50
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +010051// s is the sigma graph
52// graf is the JSON graph
53var s, graf;
54
55// query dario JSON for the graph information
56function xhr(method, url, params, callback) {
avm99963027b5b02018-12-28 02:31:46 +010057 var http = new XMLHttpRequest();
58 if (method == "POST") {
59 http.open(method, url, true);
60 } else {
61 if (params != "") {
62 http.open(method, url+"?"+params, true);
63 } else {
64 http.open(method, url, true);
65 }
66 }
67 http.onload = function() {
68 if(this.status != 200) {
69 console.warn("Attention, status code "+this.status+" when loading via xhr url "+url);
70 }
71 callback(this.responseText, this.status);
72 };
73 if (method == "POST") {
74 http.setRequestHeader("Content-type","application/x-www-form-urlencoded");
75 http.send(params);
76 } else {
77 http.send();
78 }
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +010079}
80
81
82function initGraf() {
avm99963027b5b02018-12-28 02:31:46 +010083 // create new methods for sigma library
84 updateSigma();
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +010085
avm99963027b5b02018-12-28 02:31:46 +010086 // create graf, s is the sigma graf
87 s = new sigma({
88 renderers: [{
89 container: "graf",
90 type: "webgl"
91 }],
92 settings: {
93 defaultEdgeColor: "#fff",
94 edgeColor: "default",
95 defaultLabelColor: "#fff",
96 autoRescale: false,
97 zoomMax: 30,
98 // enableEdgeHovering: true,
99 font: "Roboto",
100 labelThreshold: 5
101 }
102 });
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100103
104
avm99963027b5b02018-12-28 02:31:46 +0100105 // query for JSON for graph data
106 xhr("GET", "api.php", "action=getgraf", function(responseText, status) {
107 // graf is the JSON data
108 graf = JSON.parse(responseText);
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100109
avm99963027b5b02018-12-28 02:31:46 +0100110 // does graf.nodes have a size attribute?
111 var rectBorrar = [[0,0], [0,0], [0,0], [0,0]];
112 for (var i in graf.nodes) {
113 if (graf.nodes[i].name == "Erase") rectBorrar[0] = [ graf.nodes[i].x , graf.nodes[i].y ];
114 if (graf.nodes[i].name == "Borrar") rectBorrar[1] = [ graf.nodes[i].x , graf.nodes[i].y ];
115 if (graf.nodes[i].name == "Esborrar") rectBorrar[2] = [ graf.nodes[i].x , graf.nodes[i].y ];
116 if (graf.nodes[i].name == "Delete") rectBorrar[3] = [ graf.nodes[i].x , graf.nodes[i].y ];
117 }
118
119 var sizegraf = 0;
120 for (var i in graf.nodes) {
121 if ( isInRect(graf.nodes[i].x, graf.nodes[i].y, rectBorrar) ) continue;
122 sizegraf++;
123 }
124 var nnode = 0;
125 for (var i in graf.nodes) {
126 var ncolor = null;
127
128 if(graf.nodes[i].sex =="F") ncolor = "#d61c08";
129 else if(graf.nodes[i].sex == "M") ncolor = "#0159aa";
130 else ncolor = "#0ca80a";
131
132 // post-processing for year corrections
133 if(1970 < graf.nodes[i].year && graf.nodes[i].year < 2004) graf.nodes[i].year += 18;
134
135 var newX = 5000*Math.cos( 2*Math.PI*nnode/sizegraf );
136 var newY = 5000*Math.sin( 2*Math.PI*nnode/sizegraf );
137
138 if (isInRect(graf.nodes[i].x, graf.nodes[i].y, rectBorrar) ) continue;
139
140 s.graph.addNode({
141 // we add color, originalColor, size, originalX..Y, circleX..Y atributes
142 id: graf.nodes[i].id,
143 year: graf.nodes[i].year,
144 sex: graf.nodes[i].sex,
145 label: graf.nodes[i].name,
146 x: graf.nodes[i].x,
147 y: graf.nodes[i].y,
148 circleX: newX,
149 circleY: newY,
150 originalX: graf.nodes[i].x,
151 originalY: graf.nodes[i].y,
152 size: 10,
153 color: ncolor,
154 originalColor: ncolor
155 });
156 nnode++;
157
158 }
159
160 for (var i in graf.edges) {
161 if (isInRect(graf.nodes[graf.edges[i].a].x, graf.nodes[graf.edges[i].a].y, rectBorrar)) continue;
162 if (isInRect(graf.nodes[graf.edges[i].b].x, graf.nodes[graf.edges[i].b].y, rectBorrar)) continue;
163
164 s.graph.addEdge({
165 id: i,
166 source: graf.edges[i].a,
167 target: graf.edges[i].b,
168 size: Math.min(4, Math.max((7/(2*Math.pow(20, 2)))*Math.pow(graf.edges[i].votes, 2) + 1/2, 0.5))
169 });
170
171 }
172
173 s.bind('clickNode', function(e) {
174 var nodeId = e.data.node.id,
175 toKeep = s.graph.neighbors(nodeId);
176 // toKeep[nodeId] = e.data.node;
177
178
179 s.graph.nodes().forEach(function(n) {
180 if (toKeep[n.id] || n.id == nodeId) {
181 n.color = n.originalColor;
182 } else {
183 n.color = '#333';
184 }
185 });
186
187 s.graph.edges().forEach(function(e) {
188 if ((e.source == nodeId || e.target == nodeId) && (toKeep[e.source] || toKeep[e.target])) {
189 e.color = '#fff';
190 } else {
191 e.color = '#333';
192 }
193 });
194
195 if (circleMode) {
196 s.graph.nodes().forEach(function (n) {
197 n.x = n.circleX;
198 n.y = n.circleY;
199 n.size = 10;
200 });
201
202 e.data.node.x = 0;
203 e.data.node.y = 0;
204 e.data.node.size = 30;
205 }
206
207 s.refresh();
208
209 dialog.show(nodeId, toKeep);
210 });
211
212 initDialog();
213 initCamera();
214 initSearchBar();
215
216 s.refresh();
217 autocomplete(document.querySelector("#search-input"), graf.nodes, "search");
218 });
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100219}
220
221function updateSigma() {
avm99963027b5b02018-12-28 02:31:46 +0100222 // returns set of neighouts
223 sigma.classes.graph.addMethod("neighbors", function(nodeId) {
224 var k,
225 neighbors = {},
226 index = this.allNeighborsIndex[nodeId] || [];
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100227
avm99963027b5b02018-12-28 02:31:46 +0100228 for (k in index) {
229 neighbors[k] = this.nodesIndex[k];
230 }
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100231
avm99963027b5b02018-12-28 02:31:46 +0100232 return neighbors;
233 });
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100234
avm99963027b5b02018-12-28 02:31:46 +0100235 // returns number of neighbours from a set of years
236 sigma.classes.graph.addMethod("numNeighborsFromYears", function(nodeId, showYearsCopy) {
237 var k,
238 neighbors = 0,
239 index = this.allNeighborsIndex[nodeId] || [];
240
241 for (k in index) {
242 if(this.nodesIndex){
243 if (showYearsCopy.has("" + this.nodesIndex[k].year)) neighbors++;
244 else if (this.nodesIndex[k].year == 0) neighbors++;
245 }
246 }
247
248 return neighbors;
249 });
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100250}
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100251// *********** HERE STARTS limit-years.js *************
252
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100253var limitYears = false;
254var showYears = new Set();
255
256function repaint() {
257 //targetYear: graf.nodes[e.source].year,
258 if(limitYears) {
259 var added = new Set();
avm99963027b5b02018-12-28 02:31:46 +0100260
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100261 s.graph.nodes().forEach(function(n) {
262 var numNeig = s.graph.numNeighborsFromYears(n.id, showYears);
avm99963027b5b02018-12-28 02:31:46 +0100263
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100264 if ((n.year == 0 && (n.sex == 'F' || n.sex == 'M') )
265 || numNeig == 0
266 || (!showYears.has("" + n.year) && (n.year != 0) )) {
267 n.hidden = true;
268 }
269 else {
270 n.hidden = false;
271 added.add(n.id);
272 }
273 });
avm99963027b5b02018-12-28 02:31:46 +0100274
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100275 s.graph.edges().forEach(function(e) {
276 if(!added.has(e.source) && !added.has(e.target)){
277 e.hidden = true;
278 }
279 else e.hidden = false;
avm99963027b5b02018-12-28 02:31:46 +0100280 });
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100281 }
282 else {
283 s.graph.nodes().forEach(function(n) {
284 n.hidden = false;
285 });
avm99963027b5b02018-12-28 02:31:46 +0100286
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100287 s.graph.edges().forEach(function(e) {
288 e.hidden = false;
289 });
290 }
291}
292
293function altYearList() {
294 var yearlist = document.querySelector("#year-list");
avm99963027b5b02018-12-28 02:31:46 +0100295
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100296 if(yearlist.style.display == "none"){
297 yearlist.style.display = "block";
298 document.querySelector("#settings i").innerText = "close";
299 yearLimits = true;
300 }
301 else{
302 yearlist.style.display = "none";
303 document.querySelector("#settings i").innerText = "settings";
304 yearLimits = true;
305 }
306}
307
avm99963027b5b02018-12-28 02:31:46 +0100308function addYearList() {
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100309 var ylistspan = document.querySelector("#year-list-span")
avm99963027b5b02018-12-28 02:31:46 +0100310 for(var year = 2006; year < 2019; year++) {
311 var lab = document.createElement("label");
312 lab.setAttribute("class", "mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect custom-checkbox");
313 lab.setAttribute("for", "checkbox-"+year);
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100314 var yin = document.createElement("input");
315 yin.type = "checkbox";
avm99963027b5b02018-12-28 02:31:46 +0100316 yin.setAttribute("class", "mdl-checkbox__input");
317 yin.name = year;
318 yin.id = "checkbox-"+year;
319 yin.addEventListener("change", function() {
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100320 limitYears = true;
avm99963027b5b02018-12-28 02:31:46 +0100321
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100322 if(this.checked) {
323 showYears.add(this.name);
avm99963027b5b02018-12-28 02:31:46 +0100324 } else {
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100325 showYears.delete(this.name);
326 }
avm99963027b5b02018-12-28 02:31:46 +0100327
328 if (showYears.size == 0) limitYears = false;
329
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100330 repaint();
avm99963027b5b02018-12-28 02:31:46 +0100331
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100332 s.refresh();
333 });
avm99963027b5b02018-12-28 02:31:46 +0100334
335 var span = document.createElement("span");
336 span.innerText = year;
337 span.setAttribute("class", "mdl-checkbox__label");
338
339 lab.appendChild(yin);
340 lab.appendChild(span);
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100341 ylistspan.appendChild(lab);
avm99963027b5b02018-12-28 02:31:46 +0100342 ylistspan.insertAdjacentHTML("beforeend", "<br>");
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100343 }
avm99963027b5b02018-12-28 02:31:46 +0100344
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100345 document.querySelector("#settings").addEventListener("click", altYearList);
346}
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100347// *********** HERE STARTS search-bar.js *************
348
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100349function altSearchBar() {
350 if (document.querySelector(".md-google-search__metacontainer").style.display == "none") {
351 document.querySelector(".md-google-search__metacontainer").style.display = "block";
352 document.querySelector("#search i").innerText = "fullscreen";
avm99963865b8ca2018-12-28 02:52:50 +0100353 document.querySelector("#search-input").focus();
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100354 } else {
355 document.querySelector(".md-google-search__metacontainer").style.display = "none";
356 document.querySelector(".autocomplete-container").style.display = "none";
357 document.querySelector("#search i").innerText = "search";
358 }
359}
360
361function initSearchBar() {
362 document.querySelector("#search").addEventListener("click", altSearchBar);
363 if (window.innerWidth > 700) altSearchBar();
364}
365// *********** HERE STARTS dialog.js *************
366
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100367var dialog = {
368 fill: function(data, text, html=false) {
369 var el = document.querySelectorAll("*[data-fill=\""+data+"\"]");
370 for (var i in el) {
371 if (html === true) {
372 el[i].innerHTML = text;
373 } else {
374 el[i].innerText = text;
375 }
376 }
377 },
378 show: function(id, neighbors) {
379 var neighbors = Object.values(neighbors);
380
381 this.fill("name", graf.nodes[id].name);
382 this.fill("year", graf.nodes[id].year);
383 this.fill("sex", graf.nodes[id].sex);
384 this.fill("id", "#"+id);
385 this.fill("n-edges", neighbors.length);
386
387 var list = "";
388 neighbors.forEach(function (a) {
389 list += "<li><b>"+graf.nodes[id].name+" - "+a.label+":</b> "+(graf.edges[id+"_"+a.id] ? graf.edges[id+"_"+a.id].votes : graf.edges[a.id+"_"+id].votes)+" vots</li>";
390 });
391 this.fill("edges", list, true);
392
393 if (window.innerWidth > 700) {
394 document.querySelector("#dialog").style.display = "block";
395 document.querySelector("#backdrop-container").style.display = "block";
396 } else {
397 document.querySelector("#summary-dialog").style.display = "block";
398 }
399 },
400 close: function() {
401 document.querySelector("#dialog").style.display = "none";
402 document.querySelector("#summary-dialog").style.display = "none";
403 document.querySelector("#backdrop-container").style.display = "none";
404
405 s.graph.nodes().forEach(function(n) {
406 n.color = n.originalColor;
407 });
408
409 s.graph.edges().forEach(function(e) {
410 e.color = e.originalColor;
411 });
412
413 if(circleMode) {
414 s.graph.nodes().forEach(function (n) {
415 n.x = n.circleX;
416 n.y = n.circleY;
417 n.size = 10;
418 });
419 }
420 else {
421 s.graph.nodes().forEach(function (n) {
422 n.x = n.originalX;
423 n.y = n.originalY;
424 n.size = 10;
425 });
426 }
427 s.refresh();
428
429 },
430 max: function() {
431 document.querySelector("#summary-dialog").style.display = "none";
432 document.querySelector("#dialog").style.display = "block";
433 },
434 min: function() {
435 document.querySelector("#dialog").style.display = "none";
436 document.querySelector("#summary-dialog").style.display = "block";
437 }
438};
439
440
441function initDialog() {
442 document.querySelector("#quit-dialog").addEventListener("click", dialog.close);
443 document.querySelector("#quit2-dialog").addEventListener("click", dialog.close);
444 document.querySelector("#max-dialog").addEventListener("click", dialog.max);
445 document.querySelector("#min-dialog").addEventListener("click", dialog.min);
446}
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100447// *********** HERE STARTS camera.js *************
448
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100449function cameraGoto(nodeX, nodeY) {
450 sigma.misc.animation.camera( s.camera,
451 { x: nodeX, y: nodeY, ratio: 1 },
452 { duration: s.settings('animationsTime') || 300 }
453 );
454}
455
456function is_touch_device() {
avm99963027b5b02018-12-28 02:31:46 +0100457 var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
458 var mq = function(query) {
459 return window.matchMedia(query).matches;
460 }
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100461
avm99963027b5b02018-12-28 02:31:46 +0100462 if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
463 return true;
464 }
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100465
avm99963027b5b02018-12-28 02:31:46 +0100466 // include the 'heartz' as a way to have a non matching MQ to help terminate the join
467 // https://git.io/vznFH
468 var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
469 return mq(query);
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100470}
471
472function initCamera() {
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100473 if(!is_touch_device()) {
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100474 document.querySelector("#zoomin").addEventListener("click", function() {
475 s.camera.goTo({
476 ratio: Math.max(s.camera.settings("zoomMin"), s.camera.ratio / Math.sqrt(2))
477 });
478 });
avm99963027b5b02018-12-28 02:31:46 +0100479
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100480 document.querySelector("#zoomout").addEventListener("click", function() {
481 s.camera.goTo({
482 ratio: Math.min(s.camera.settings("zoomMax"), s.camera.ratio * Math.sqrt(2))
483 });
484 });
avm99963027b5b02018-12-28 02:31:46 +0100485 } else {
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100486 document.querySelector("#zoomin").style.display = "none";
487 document.querySelector("#zoomout").style.display = "none";
avm99963027b5b02018-12-28 02:31:46 +0100488
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100489 document.querySelector("#circle-mode").style.bottom = "110px";
490 document.querySelector("#settings").style.bottom = "60px";
491 document.querySelector("#search").style.bottom = "10px";
492 }
493}
avm99963027b5b02018-12-28 02:31:46 +0100494// *********** HERE STARTS just-do-it.js *************
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100495
496var seq = [38, 38, 40, 40, 37, 39, 37, 39, 65, 66, 13];
497var cur = 0;
498
499function justdoit() {
500 s.graph.nodes().forEach(function(n) {
501 switch(n.color) {
502 case "#d61c08":
503 n.color = "#0159aa";
504 break;
505
506 case "#0159aa":
507 n.color = "#0ca80a";
508 break;
509
510 case "#0ca80a":
511 n.color = "#d61c08";
512 break;
513 }
514 });
515
516 s.refresh();
517 setTimeout(justdoit, 333);
518}
519
520
avm99963027b5b02018-12-28 02:31:46 +0100521function initJustDoIt() {
Javier López-Contreras6d1d72d2018-12-27 23:17:18 +0100522 document.addEventListener("keydown", function() {
523 if (event.key == "f" && event.target.getAttribute("id") != "search-input") altSearchBar();
524 if (event.which == seq[cur]) {
525 if (cur < seq.length) {
526 ++cur;
527 if (cur == seq.length) {
528 justdoit();
529 }
530 }
531 } else cur = 0;
532 });
533}
avm99963027b5b02018-12-28 02:31:46 +0100534// *********** HERE STARTS init.js *************
535
536function init() {
537 initGraf();
538 addYearList();
539 initCircleMode();
540 initJustDoIt();
541}
542
543window.addEventListener("load", init);