PageRenderTime 62ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/static/models/graph.js

https://gitlab.com/comptrans/VisualGraphX
JavaScript | 312 lines | 173 code | 47 blank | 92 comment | 21 complexity | 68a8bdf5347fa02ad99737c57cd344de MD5 | raw file
  1. // dependencies
  2. define([], function() {
  3. // ############ SETUP MODEL ############
  4. var setup = Backbone.Model.extend({
  5. defaults: {
  6. graph: '',
  7. orientation: 0, // default is directed
  8. edge: 0,
  9. source: '',
  10. external: '',
  11. label_node: '',
  12. label_edge: '',
  13. rootnode: '',
  14. max_depth: '',
  15. set_depth: ''
  16. }
  17. });
  18. // ############ NODE MODEL ############
  19. var node = Backbone.Model.extend({
  20. defaults: {
  21. id: '',
  22. expanded: false
  23. }
  24. });
  25. var nodes = Backbone.Collection.extend({
  26. model: node
  27. });
  28. // ############ LINK MODEL ############
  29. var link = Backbone.Model.extend({
  30. defaults: {
  31. source: '',
  32. target: ''
  33. }
  34. });
  35. var links = Backbone.Collection.extend({
  36. mode: link
  37. });
  38. // ############ GRAPH MODEL ############
  39. var graph = Backbone.Model.extend({
  40. defaults: {
  41. directed: '',
  42. type: '',
  43. label: '',
  44. metadata: '',
  45. nodes: new nodes(),
  46. edges: new links()
  47. }
  48. });
  49. var graphs = Backbone.Collection.extend({
  50. model: graph
  51. });
  52. return Backbone.Model.extend({
  53. // defaults
  54. defaults : {
  55. id: null,
  56. title: '',
  57. type: 'd3js_generic', // d3js_generic as the default (predefined) graph type
  58. definition: '', // e.g. category
  59. date: null,
  60. state: '',
  61. state_info: '',
  62. modified: false,
  63. dataset_id: '',
  64. dataset_id_job : ''
  65. },
  66. // initialize
  67. initialize: function(app, options) {
  68. var _this = this; // make copy current Graph Model
  69. this.app = app; // link app
  70. // initialize models for nodes and links
  71. this.graphs = new graphs();
  72. this.nodes = new nodes();
  73. this.links = new links();
  74. // initialize model for the visualization setup (e.g. rootnode, depth)
  75. this.setup = new setup();
  76. // set definition of the graph as specified in
  77. this.set('definition', this.app.types.attributes['d3js_generic']);
  78. this.listenTo(this, 'sync', function() {
  79. this.labels = {};
  80. this.labels.nodes = [];
  81. this.labels.edges = [];
  82. // retrieve the data from the jgf file and write to model
  83. var single = this.get('graph'); //
  84. this.graphs.add((typeof single === 'undefined') ? this.get('graphs') : single);
  85. for(model in this.graphs.models) {
  86. this.graphs.add(this.graphs.models[model]);
  87. //
  88. var nodes = this.graphs.models[model].toJSON().nodes;
  89. var edges = this.graphs.models[model].toJSON().edges;
  90. this.labels.nodes.push(this._labels(nodes));
  91. this.labels.edges.push(this._labels(edges));
  92. }
  93. /* ################# SET initial graph.setup values ##################*/
  94. this.setup.set('graph', 0); // default graph (number of occurence)
  95. this.setup.set('edge', 1); // default edge type to undirected (=1)
  96. this.setup.set('source', 0); // internal or external source of the nodes
  97. // check for property with url corresponding to external source
  98. this.setup.set('external', this._urlPropertySearch(this.graphs.models[this.setup.get('graph')].toJSON().nodes));
  99. // set default (node, edge) label: label if present otherwise first attribute
  100. this.setup.set('label_node', this._defaults(this.labels.nodes, 'label', this.setup.get('graph')));
  101. //this.setup.set('label_edge', this._defaults(this.labels.edges, 'label', this.setup.get('graph')));
  102. this.setup.set('label_edge', 'none');
  103. // determine the rootnode of
  104. this.setup.set('rootnode', this._rootnode(this.graphs.models[this.setup.get('graph')].toJSON().nodes));
  105. //var depth = this._graphdepth(this.data, rootnode, []);
  106. var depth = 100; // default depth - as calculation takes too much time
  107. this.setup.set('max_depth', depth);
  108. this.setup.set('set_depth', (depth >= 2) ? 2 : depth );
  109. console.log(this);
  110. this.trigger('ready', this); // fire 'ready'-event - meaning that the data has been fetched
  111. });
  112. this.fetch();
  113. },
  114. url: function() {
  115. return this.app.options.durl;
  116. },
  117. // determine adjacency list
  118. _adj: function(data, adj) {
  119. for(key in data.nodes) {
  120. adj[data.nodes[key].id] = []; // intialize nodes
  121. }
  122. for(key in data.links) {
  123. adj[data.links[key].source].push(data.links[key].target);
  124. }
  125. },
  126. // determines the depth of a graph recursively
  127. _graphdepth: function(data, rootnode, path) {
  128. var childs = JSON.search(data, '//links[source="' + rootnode + '"]/target');
  129. if(childs.length == 0) {
  130. return 0;
  131. } else {
  132. path.push(rootnode); // remember active path
  133. var sub = [];
  134. for(j in childs) {
  135. // check if child is in active path: backedge
  136. if(path.indexOf(childs[j]) == -1) {
  137. sub.push(this._graphdepth(data, childs[j], path) +1);
  138. }
  139. }
  140. return Math.max(...sub);
  141. }
  142. },
  143. // create list with labels of edges and nodes
  144. _labels: function(collection){
  145. properties = [];
  146. if (collection.length > 0) {
  147. var keys = Object.keys(collection[0]);
  148. //console.log(keys);
  149. var i = 0;
  150. for (i; i < keys.length; i++) {
  151. properties[i] = {property: keys[i]};
  152. }
  153. }
  154. return properties;
  155. },
  156. // check if default(searchterm) value exists as label
  157. _defaults: function(labels, searchterm, graph){
  158. if(labels.length > 0) {
  159. // set default as
  160. var default_value = labels[graph][0].property;
  161. for(property in labels[graph]) {
  162. if(labels[graph][property].property.indexOf(searchterm) > -1) {
  163. default_value = searchterm;
  164. }
  165. }
  166. return default_value;
  167. }
  168. },
  169. // search for a property in the JSON nodes that consists of an URL otherwise return first
  170. _urlPropertySearch: function(nodes) {
  171. var found = [false, '']; // if and where (property name) url has been found
  172. var meta = nodes[0].metadata; // get the metadata from first node
  173. for(property in meta) {
  174. var validated = urlValidation(meta[property]);
  175. if(validated){
  176. found[0] = validated;
  177. found[1] = property;
  178. }
  179. }
  180. return found;
  181. // check if property is valid url
  182. function urlValidation(prop) {
  183. return /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(prop);
  184. }
  185. },
  186. // determine the rootnode - if there is root: true in metadata
  187. _rootnode: function(nodes) {
  188. if($.inArray('metadata', Object.getOwnPropertyNames(nodes[0])) > -1) {
  189. // retrieve node object with root == true
  190. var rootnode = $.grep(nodes, function(node) {
  191. return node.metadata.root == 'true'
  192. });
  193. }
  194. return nodes[0].id;
  195. if(rootnode == null) { // equivalent to if(variable === undefined || variable === null)
  196. return nodes[0].id;
  197. } else {
  198. return rootnode[0].id; // return the id of first found
  199. }
  200. }
  201. });
  202. });
  203. /*
  204. if(childs.length == 0) {
  205. return 0;
  206. } else {
  207. var sub = [];
  208. for(var j in childs) {
  209. console.log(childs[j]);
  210. if(visited.indexOf(childs[j]) > -1){
  211. console.log('already visited');
  212. }
  213. if(visited.indexOf(childs[j]) == -1) {
  214. sub.push(this._graphdepth(data, childs[j], visited) +1);
  215. visited.push(childs[j]);
  216. }
  217. }
  218. return Math.max(...sub);
  219. }*/
  220. // verify the para metrized depth of the graph
  221. /*_verifydepth : function(data, rootnode, depth) {
  222. var counter = 0; // counter for the depth
  223. var verification = false;
  224. console.log(data);
  225. // create toplogy of graph as list
  226. var top = [[rootnode]];
  227. // iterate through the levels
  228. while(counter <= depth) {
  229. for(tier in top) {
  230. for(node in tier) {
  231. }
  232. top[counter]
  233. }
  234. }
  235. },/*
  236. // test for
  237. _connectivity: function() {
  238. },
  239. /*
  240. //implementation of the iterative deepening depth first search
  241. _iddfs: function(root) {
  242. var depth = 1000;
  243. var found;
  244. for(var i=0; i <= depth; i++) {
  245. found = this_dls(root, depth);
  246. if(found) {
  247. return;
  248. }
  249. }
  250. var found = this._dls();
  251. },
  252. // implementation of the recursive depth-limited DFS
  253. _dls: function(node, depth) {
  254. if(depth == 0) {
  255. return;
  256. }
  257. },*/