vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

458 lines
13 KiB

  1. function selectCompany(event) {
  2. var nodeId = event.value;
  3. network.selectNodes([nodeId]);
  4. highlightConnections({nodes:[nodeId]})
  5. network.focusOnNode(nodeId,{animation:false, scale:0.2})
  6. }
  7. function selectYear(year) {
  8. selectedYear = year
  9. console.log(year)
  10. populateYearDiv();
  11. recursiveClearDOM(document.getElementById("projectsDropdown"));
  12. populateProjectsDropdown();
  13. recursiveClearDOM(document.getElementById("companyDropdown"));
  14. }
  15. function selectProject(event) {
  16. if (event.value != "none") {
  17. selectedProject = event.value;
  18. }
  19. if (selectedType != "") {
  20. if (network) {
  21. network.destroy()
  22. network = null;
  23. }
  24. loadJSON('./data/combined/' + selectedYear + "_" + selectedProject + ".json", drawAll);
  25. document.getElementById("FILENAME").innerHTML = selectedYear + "_" + selectedProject + ".json";
  26. }
  27. }
  28. function selectType(type) {
  29. if (selectedType != type) {
  30. selectedType = type;
  31. totalValue = 0;
  32. populateTypeDiv();
  33. var allNodes = nodes.get();
  34. if (allNodes.length > 0) {
  35. if (selectedType == "connections") {
  36. for (var i = 0; i < allNodes.length; i++) {
  37. var node = allNodes[i];
  38. node.title = node.id + ": " + node.euData[selectedType];
  39. node.value = Math.max(1,Math.pow(Number(node.euData[selectedType]),1.05));
  40. totalValue += node.value;
  41. }
  42. network.setOptions({nodes:{radiusMax: nodeRadius, customScalingFunction:function (min,max,total,value) {
  43. if (max == min) {
  44. return 0.5;
  45. }
  46. else {
  47. var scale = 1 / (max - min);
  48. return Math.max(0,(value - min)*scale);
  49. }
  50. }}});
  51. }
  52. else { // by funding
  53. for (var i = 0; i < allNodes.length; i++) {
  54. var node = allNodes[i];
  55. node.title = node.id + ": " + Math.round(Number(node.euData[selectedType])) + " Euro";
  56. node.value = Number(node.euData[selectedType]);
  57. totalValue += node.value;
  58. }
  59. network.setOptions({nodes:{radiusMax: 80*nodeRadius, customScalingFunction:function (min,max,total,value) {
  60. var scale = value / total;
  61. return scale;
  62. }}});
  63. }
  64. nodes.update(allNodes);
  65. }
  66. }
  67. }
  68. function recursiveClearDOM(DOMobject) {
  69. while (DOMobject.hasChildNodes() == true) {
  70. recursiveClearDOM(DOMobject.firstChild);
  71. DOMobject.removeChild(DOMobject.firstChild);
  72. }
  73. }
  74. function viewAllNeighbours() {
  75. network.zoomExtent({nodes:connectedNodes, duration:0})
  76. }
  77. function doSteps(amount) {
  78. network.setFreezeSimulation(false);
  79. network.setOptions({stabilizationIterations:amount})
  80. network._stabilize()
  81. network.setFreezeSimulation(true);
  82. }
  83. var network;
  84. var nodes;
  85. var edges;
  86. var edgeOpacity = 0.15;
  87. var totalValue = 0;
  88. function drawAll(dataJSON, file) {
  89. // create an array with nodes
  90. nodes = new vis.DataSet(dataJSON.nodes);
  91. // create an array with edges
  92. edges = new vis.DataSet(dataJSON.edges);
  93. var totalMass = 0;
  94. totalValue = 0;
  95. for (var i = 0; i < dataJSON.nodes.length; i++) {
  96. totalMass += dataJSON.nodes[i].mass;
  97. totalValue += dataJSON.nodes[i].value;
  98. }
  99. var gravityConstant = -20000;
  100. if (totalMass < 2000) {
  101. gravityConstant = -2000;
  102. }
  103. var edgeNodeRatio = Math.max(1,dataJSON.edges.length) / Math.max(1,dataJSON.nodes.length);
  104. var nodeEdgeRatio = Math.max(1,dataJSON.nodes.length) / Math.max(1,dataJSON.edges.length);
  105. var centralGravity = Math.min(5,Math.max(0.1,edgeNodeRatio));
  106. var amountOfNodes = dataJSON.nodes.length;
  107. edgeOpacity = Math.min(1.0,Math.max(0.15,nodeEdgeRatio*2));
  108. nodeRadius = amountOfNodes * 0.8;
  109. var container = document.getElementById('mynetwork');
  110. var data = {
  111. nodes: nodes,
  112. edges: edges
  113. };
  114. var options = {
  115. stabilize: false,
  116. stabilizationIterations: 15000,
  117. smoothCurves: {
  118. enabled: true,
  119. dynamic: false
  120. },
  121. configurePhysics: false,
  122. physics: {barnesHut: {gravitationalConstant: gravityConstant, centralGravity: centralGravity, springLength: 100, springConstant: 0.001}},
  123. //physics: {barnesHut: {gravitationalConstant: 0, centralGravity: 0.0, springConstant: 0}},
  124. nodes: {
  125. shape: 'dot',
  126. radiusMax: nodeRadius,
  127. fontColor: '#ffffff',
  128. fontDrawThreshold: 8,
  129. scaleFontWithValue: true,
  130. fontSizeMin: 8,
  131. fontSizeMax: amountOfNodes * 0.25,
  132. fontSizeMaxVisible: 20,
  133. fontStrokeWidth: 1, // px
  134. fontStrokeColor: '#222222'
  135. },
  136. edges: {
  137. opacity: edgeOpacity
  138. },
  139. hideEdgesOnDrag: true,
  140. maxVelocity: 100,
  141. tooltip: {
  142. delay: 200,
  143. fontSize: 12,
  144. color: {
  145. background: "#fff"
  146. }
  147. }
  148. };
  149. network = new vis.Network(container, data, options);
  150. network.setFreezeSimulation(true);
  151. network.on("click",highlightConnections);
  152. populateCompanyDropdown();
  153. window.onresize = function () {network.redraw();};
  154. }
  155. // marked is used so we don't do heavy stuff on each click
  156. var marked = false;
  157. var connectedNodes = [];
  158. function highlightConnections(selectedItems) {
  159. if (selectedItems.nodes[0] == 'none') {
  160. return;
  161. }
  162. var nodeId;
  163. var requireUpdate = false;
  164. // we get all data from the dataset once to avoid updating multiple times.
  165. if (selectedItems.nodes.length == 0 && marked === true) {
  166. connectedNodes = [];
  167. requireUpdate = true;
  168. var allNodes = nodes.get({returnType:"Object"});
  169. // restore on unselect
  170. for (nodeId in allNodes) {
  171. allNodes[nodeId].color = undefined;
  172. if (allNodes[nodeId].oldLabel !== undefined) {
  173. allNodes[nodeId].label = allNodes[nodeId].oldLabel;
  174. allNodes[nodeId].oldLabel = undefined;
  175. }
  176. }
  177. marked = false;
  178. network.setOptions({nodes:{fontSizeMin:14},edges:{opacity:edgeOpacity}})
  179. }
  180. else if (selectedItems.nodes.length > 0) {
  181. var allNodes = nodes.get({returnType:"Object"});
  182. marked = true;
  183. requireUpdate = true;
  184. var mainNode = selectedItems.nodes[0]; // this is an ID
  185. connectedNodes = network.getConnectedNodes(mainNode);
  186. connectedNodes.push(mainNode);
  187. for (nodeId in allNodes) {
  188. allNodes[nodeId].color = 'rgba(150,150,150,0.1)';
  189. if (allNodes[nodeId].oldLabel === undefined) {
  190. allNodes[nodeId].oldLabel = allNodes[nodeId].label;
  191. allNodes[nodeId].label = "";
  192. }
  193. }
  194. for (var i = 0; i < connectedNodes.length; i++) {
  195. allNodes[connectedNodes[i]].color = undefined;
  196. if (allNodes[connectedNodes[i]].oldLabel !== undefined) {
  197. allNodes[connectedNodes[i]].label = allNodes[connectedNodes[i]].oldLabel;
  198. allNodes[connectedNodes[i]].oldLabel = undefined;
  199. }
  200. }
  201. // we want to set the fontSizeMin just so that the node we're looking at has a good fontsize at the zoomLevel
  202. console.log(totalValue, allNodes[mainNode].value)
  203. network.setOptions({nodes:{fontSizeMin:150},edges:{opacity:0.025}})
  204. }
  205. if (requireUpdate === true) {
  206. var updateArray = [];
  207. for (nodeId in allNodes) {
  208. updateArray.push(allNodes[nodeId]);
  209. }
  210. nodes.update(updateArray);
  211. }
  212. }
  213. function loadJSON(path, success, error) {
  214. selectedFile = path;
  215. var xhr = new XMLHttpRequest();
  216. xhr.onreadystatechange = function() {
  217. if (xhr.readyState === 4) {
  218. if (xhr.status === 200) {
  219. success(JSON.parse(xhr.responseText), path);
  220. }
  221. else {
  222. error();
  223. }
  224. }
  225. };
  226. xhr.open("GET", path, true);
  227. xhr.send();
  228. }
  229. function populateCompanyDropdown() {
  230. var nodesAr = nodes.get();
  231. var nodeIds = [];
  232. for (var i = 0; i < nodesAr.length;i++) {
  233. nodeIds.push(nodesAr[i].id);
  234. }
  235. nodeIds.sort()
  236. var dropdown = document.getElementById("companyDropdown");
  237. var option = document.createElement('option');
  238. option.text = '-- pick a company to focus on.';
  239. option.value = 'none';
  240. dropdown.add(option);
  241. for (i = 0; i < nodeIds.length; i++) {
  242. option = document.createElement('option');
  243. option.text = option.value = nodeIds[i];
  244. dropdown.add(option);
  245. }
  246. }
  247. function populateTypeDiv() {
  248. var container = document.getElementById("typeContainer");
  249. recursiveClearDOM(container);
  250. var types = ['funding', 'connections'];
  251. var typeLabels = ['size by funding', 'size by connections'];
  252. for (i = 0; i < types.length; i++) {
  253. var div = document.createElement('div');
  254. div.className = 'type';
  255. if (types[i] == selectedType) {
  256. div.className += ' selected'
  257. }
  258. div.innerHTML = typeLabels[i];
  259. div.onclick = selectType.bind(this,types[i])
  260. container.appendChild(div);
  261. }
  262. }
  263. function populateYearDiv() {
  264. var container = document.getElementById("yearContainer");
  265. recursiveClearDOM(container);
  266. for (i = 0; i < years.length; i++) {
  267. var div = document.createElement('div');
  268. div.className = 'year';
  269. if (years[i] == selectedYear) {
  270. div.className += ' selected'
  271. }
  272. div.innerHTML = years[i];
  273. div.onclick = selectYear.bind(this,years[i])
  274. container.appendChild(div);
  275. }
  276. }
  277. function populateProjectsDropdown() {
  278. var dropdown = document.getElementById("projectsDropdown");
  279. var option = document.createElement('option');
  280. option.text = '-- pick project to see the connections';
  281. option.value = 'none';
  282. dropdown.add(option);
  283. for (i = 0; i < yearlyProjects[selectedYear].length; i++) {
  284. option = document.createElement('option');
  285. option.text = option.value = yearlyProjects[selectedYear][i];
  286. dropdown.add(option);
  287. }
  288. }
  289. function download() {
  290. var file = selectedFile.replace("./data/combined/","");
  291. var nodesAr = nodes.get();
  292. var edgesAr = edges.get();
  293. var obj = {nodes: nodesAr, edges: edgesAr};
  294. var json = JSON.stringify(obj);
  295. var blob = new Blob([json], {type: "text/plain;charset=utf-8"});
  296. saveAs(blob, file);
  297. }
  298. var filesList = [
  299. '2010_FP7-ENERGY.json',
  300. '2010_FP7-ENVIRONMENT.json',
  301. '2010_FP7-EURATOM-FISSION.json',
  302. '2010_FP7-HEALTH.json',
  303. '2010_FP7-ICT.json',
  304. '2010_FP7-IDEAS-ERC.json',
  305. '2010_FP7-INCO.json',
  306. '2010_FP7-INFRASTRUCTURES.json',
  307. '2010_FP7-JTI.json',
  308. '2010_FP7-KBBE.json',
  309. '2010_FP7-NMP.json',
  310. '2010_FP7-PEOPLE.json',
  311. '2010_FP7-REGIONS.json',
  312. '2010_FP7-REGPOT.json',
  313. '2010_FP7-SIS.json',
  314. '2010_FP7-SME.json',
  315. '2010_FP7-SPACE.json',
  316. '2010_FP7-SSH.json',
  317. '2010_FP7-TRANSPORT.json',
  318. '2010_Other.json',
  319. '2011_FP7-COH.json',
  320. '2011_FP7-ENERGY.json',
  321. '2011_FP7-ENVIRONMENT.json',
  322. '2011_FP7-EURATOM-FISSION.json',
  323. '2011_FP7-GA.json',
  324. '2011_FP7-HEALTH.json',
  325. '2011_FP7-ICT,FP7-JTI.json',
  326. '2011_FP7-ICT.json',
  327. '2011_FP7-IDEAS-ERC.json',
  328. '2011_FP7-INCO.json',
  329. '2011_FP7-INFRASTRUCTURES.json',
  330. '2011_FP7-JTI.json',
  331. '2011_FP7-KBBE.json',
  332. '2011_FP7-NMP,FP7-INFRASTRUCTURES.json',
  333. '2011_FP7-NMP,FP7-TRANSPORT.json',
  334. '2011_FP7-NMP.json',
  335. '2011_FP7-PEOPLE.json',
  336. '2011_FP7-REGIONS.json',
  337. '2011_FP7-REGPOT.json',
  338. '2011_FP7-SECURITY.json',
  339. '2011_FP7-SIS.json',
  340. '2011_FP7-SME.json',
  341. '2011_FP7-SPACE.json',
  342. '2011_FP7-SSH.json',
  343. '2011_FP7-TRANSPORT.json',
  344. '2012_CIP.json',
  345. '2012_FP7-ENERGY.json',
  346. '2012_FP7-ENVIRONMENT.json',
  347. '2012_FP7-EURATOM-FISSION.json',
  348. '2012_FP7-HEALTH.json',
  349. '2012_FP7-ICT.json',
  350. '2012_FP7-IDEAS-ERC.json',
  351. '2012_FP7-INCO.json',
  352. '2012_FP7-INFRASTRUCTURES.json',
  353. '2012_FP7-JTI.json',
  354. '2012_FP7-KBBE.json',
  355. '2012_FP7-NMP.json',
  356. '2012_FP7-PEOPLE.json',
  357. '2012_FP7-REGIONS.json',
  358. '2012_FP7-REGPOT.json',
  359. '2012_FP7-SECURITY.json',
  360. '2012_FP7-SIS.json',
  361. '2012_FP7-SME.json',
  362. '2012_FP7-SPACE.json',
  363. '2012_FP7-SSH.json',
  364. '2012_FP7-TRANSPORT.json',
  365. '2012_Other.json',
  366. '2013_CIP.json',
  367. '2013_FP7-COH.json',
  368. '2013_FP7-ENERGY.json',
  369. '2013_FP7-ENVIRONMENT.json',
  370. '2013_FP7-EURATOM-FISSION.json',
  371. '2013_FP7-HEALTH.json',
  372. '2013_FP7-ICT.json',
  373. '2013_FP7-IDEAS-ERC.json',
  374. '2013_FP7-INCO.json',
  375. '2013_FP7-INFRASTRUCTURES,FP7-SME.json',
  376. '2013_FP7-INFRASTRUCTURES.json',
  377. '2013_FP7-JTI.json',
  378. '2013_FP7-KBBE.json',
  379. '2013_FP7-NMP.json',
  380. '2013_FP7-PEOPLE.json',
  381. '2013_FP7-REGIONS.json',
  382. '2013_FP7-REGPOT.json',
  383. '2013_FP7-SECURITY.json',
  384. '2013_FP7-SIS.json',
  385. '2013_FP7-SME.json',
  386. '2013_FP7-SPACE.json',
  387. '2013_FP7-SSH.json',
  388. '2013_FP7-TRANSPORT.json',
  389. ]
  390. filesList.sort();
  391. var fileIndex = -1;
  392. function next() {
  393. if (network) {
  394. network.destroy()
  395. network = null;
  396. }
  397. fileIndex++;
  398. document.getElementById("FILENAME").innerHTML = filesList[fileIndex];
  399. loadJSON('./data/combined/' + filesList[fileIndex], drawAll)
  400. }
  401. var years = [];
  402. var yearlyProjects = {};
  403. var selectedFile = "";
  404. for (var i = 0; i < filesList.length; i++) {
  405. var filename = filesList[i];
  406. var filenameArray = filename.split("_");
  407. var year = filenameArray[0];
  408. var project = filenameArray[1].replace(".json", "");
  409. if (years.indexOf(year) == -1) {
  410. years.push(year);
  411. yearlyProjects[year] = [];
  412. }
  413. yearlyProjects[year].push(project);
  414. }
  415. var selectedYear = years[years.length-1];
  416. var selectedType = "connections";
  417. var selectedProject = "";
  418. var nodeRadius = 1000;
  419. populateYearDiv();
  420. populateTypeDiv();
  421. populateProjectsDropdown();
  422. //next()