blob: cca644b57bfec0ac6c9da9513ff8926362a5f69f [file] [log] [blame]
Masayoshi Kobayashi274c07d2013-02-20 21:38:16 +00001function gui(data_source){
2 var width = 960,
3 height = 500;
4 var color = d3.scale.category20();
5
6 var svg = d3.select("body").append("svg:svg")
7 .attr("width", width)
8 .attr("height", height);
9
10 var force = d3.layout.force()
11 .charge(-500)
12 .linkDistance(100)
13 .size([width, height]);
14
15 var path = svg.selectAll("path");
16 var circle = svg.selectAll("circle");
17 var text = svg.selectAll("g");
18 var pathlen = 0;
19 var from;
20 var to;
21 var path_set = 0;
22
23
24 d3.json(data_source,init);
25
26 function init(json){
27 nodes = force.nodes();
28 links = force.links();
29
30 json.nodes.forEach(function(item) {
31 nodes.push(item);
32 });
33/*
34 nodes.sort(function(a,b) {
35 if (a.name > b.name) {return 1;}
36 else if (a.name < b.name) {return -1;}
37 else {return 0;}
38 });
39*/
40 json.links.forEach(function(item) {
41 links.push(item);
42 });
43 draw(nodes, links);
44 }
45
Masayoshi Kobayashidd4ad8f2013-02-27 20:20:13 +000046 var node_drag = d3.behavior.drag()
47 .on("dragstart", dragstart)
48 .on("drag", dragmove)
49 .on("dragend", dragend);
50
51 function dragstart(d, i) {
52 force.stop() // stops the force auto positioning before you start dragging
53 }
54
55 function dragmove(d, i) {
56 d.px += d3.event.dx;
57 d.py += d3.event.dy;
58 d.x += d3.event.dx;
59 d.y += d3.event.dy;
60 tick(); // this is the key to make it work together with updating both px,py,x,y on d !
61 }
62
63 function dragend(d, i) {
64 d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
65 tick();
66 force.resume();
67 }
68
Masayoshi Kobayashi274c07d2013-02-20 21:38:16 +000069 function update(json) {
70 Array.prototype.diff2 = function(arr) {
71 return this.filter(function(i) {
72 for (var j = 0; j < arr.length ; j++) {
73 if (arr[j].source === i.source.index &&
74 arr[j].target === i.target.index)
75 return false;
76 }
77 return true;
78 });
79 };
80
81 Array.prototype.diff = function(arr) {
82 return this.filter(function(i) {
83 for (var j = 0; j < arr.length ; j++) {
84 if (arr[j].source.index === i.source &&
85 arr[j].target.index === i.target)
86 return false;
87 }
88 return true;
89 });
90 };
91
92 Array.prototype.node_diff = function(arr) {
93 return this.filter(function(i) {
94 for (var j = 0; j < arr.length ; j++) {
95 if (arr[j].name === i.name)
96 return false;
97 }
98 return true;
99 });
100 };
101
102
103 links.sort(function(a,b) {
104 if (a.source > b.source) {return 1;}
105 else if (a.source < b.source) {return -1;}
106 else {
107 if (a.target > b.target) {return 1;}
108 if (a.target < b.target) {return -1;}
109 else {return 0;}
110 }
111 });
112
113// for (var i=0; i<links.length; i++) {
114// if (i != 0 &&
115// links[i].source == links[i-1].source &&
116// links[i].target == links[i-1].target) {
117// links[i].linknum = links[i-1].linknum + 1;
118// }
119// else {links[i].linknum = 1;};
120// };
121
122
123 function cdiff(topo) {
124 var changed = false;
125
126 var n_adds = topo.nodes.node_diff(nodes);
127 var n_rems = nodes.node_diff(topo.nodes);
128 for (var i = 0; i < n_adds.length; i++) {
129 nodes.push(n_adds[i]);
130 changed = true;
131 }
132 for (var i = 0; i < n_rems.length; i++) {
133 for (var j = 0; j < nodes.length; j++) {
134 if ( nodes[j].name == n_rems[i].name ){
135 nodes.splice(j,1);
136 changed = true;
137 break;
138 }
139 }
140 }
141
142 var l_adds = [];
143 var l_rems = [];
144 l_adds = added_links(topo, links, l_adds);
145 l_rems = gone_links(topo, links, l_rems);
146
147 for (var i = 0; i < l_rems.length ; i++) {
148 for (var j = 0; j < links.length; j++) {
149 if (links[j].source.name == l_rems[i].source.name &&
150 links[j].target.name == l_rems[i].target.name) {
151 links.splice(j,1);
152 changed = true;
153 break;
154 }
155 }
156 }
157 for (var i = 0; i < l_adds.length; i++) {
158 var s;
159 var t;
160 for (var j = 0; j < nodes.length; j++) {
161 if ( json.nodes[l_adds[i].source].name == nodes[j].name ){
162 s = j;
163 break;
164 }
165 }
166 for (var j = 0; j < nodes.length; j++) {
167 if ( json.nodes[l_adds[i].target].name == nodes[j].name ){
168 t = j;
169 break;
170 }
171 }
172 l_adds[i].source = s;
173 l_adds[i].target = t;
174 links.push(l_adds[i]);
175 changed = true;
176 }
177 return changed
178 }
179
180
181 var changed = cdiff(json);
182
183 for (var i = 0; i < json.nodes.length; i++) {
184 nodes[i].group = json.nodes[i].group
185 }
186 var rewrite = 0;
187 for (var i = 0; i < links.length; i++) {
188 for (var j = 0; j < json.links.length; j++) {
189 /*
190 console.log("link" + i);
191 console.log(links[i].source.name + "->" + links[i].target.name);
192 console.log("type " + links[i].type);
193 console.log("json link" + j);
194 console.log(json.nodes[json.links[j].source].name + "->" + json.nodes[json.links[j].target].name);
195 */
196 if (links[i].target.name == json.nodes[json.links[j].target].name &&
197 links[i].source.name == json.nodes[json.links[j].source].name ){
198 links[i].type = json.links[j].type;
199 rewrite ++;
200 }
201 }
202 }
203 console.log("changed?" + changed);
204 if (changed){
205 console.log(nodes);
206 console.log(links);
207 path = svg.selectAll("path").data(links)
208 circle = svg.selectAll("circle").data(nodes);
209 text = svg.selectAll("text").data(nodes);
210
211 force.stop();
212
213 path.enter().append("svg:path")
214 .attr("class", function(d) { return "link"; })
215 .attr("marker-end", function(d) {
216 if(d.type == 1){
217 return "url(#TriangleRed)";
218 } else {
219 return "url(#Triangle)";
220 }
221 });
222
223 circle.enter().append("svg:circle")
224 .attr("r", 8)
225/* .on("click", function(d,i) {
226 if ( path_set == 0 || path_set == 2 ){
227 fm = d.name;
228 path_set = 1;
229 alert("from set to " + d.name);
230 }else if ( path_set == 1 ){
231 to = d.name;
232 path_set = 2;
233 alert("to set to " + d.name);
234 }
235 }) */
Masayoshi Kobayashidd4ad8f2013-02-27 20:20:13 +0000236 .call(node_drag);
237// .call(force.drag);
Masayoshi Kobayashi274c07d2013-02-20 21:38:16 +0000238
239/* text.enter().append("svg:text")
240 .attr("x", 8)
241 .attr("y", ".31em")
242 .attr("class", "shadow")
243 .text(function(d) { return d.name.split(":")[7]; }); */
244
245 text.enter().append("svg:text")
246 .attr("x", 8)
247 .attr("y", ".31em")
248 .text(function(d) { return d.name.split(":")[7]; });
249
250 circle.append("title")
251 .text(function(d) { return d.name; });
252
253 path.attr("stroke", function(d) {
254 if(d.type == 1){
255 return "red"
256 } else {
257 return "black"
258 }
259 })
260 .attr("stroke-width", function(d) {
261 if(d.type == 1){
262 return "4px";
263 } else {
264 return "1.5px";
265 }
266 });
267
268
269 path.exit().remove();
270 circle.exit().remove();
271 text.exit().remove();
272 force.on("tick", tick);
273 force.start();
274 }
275 }
276 function draw(nodes, links){
277 path = svg.append("svg:g").selectAll("path").data(links)
278 circle = svg.append("svg:g").selectAll("circle").data(nodes);
279 text = svg.append("svg:g").selectAll("text").data(nodes);
280
281 path.enter().append("svg:path")
282 .attr("class", function(d) { return "link"; })
283 .attr("marker-end", function(d) {
284 if(d.type == 1){
285 return "url(#TriangleRed)";
286 } else {
287 return "url(#Triangle)";
288 }
289 });
290
291 path.attr("stroke", function(d) {
292 if(d.type == 1){
293 return "red"
294 } else {
295 return "black"
296 }
297 }).attr("stroke-width", function(d) {
298 if(d.type == 1){
299 return "4px";
300 } else {
301 return "1.5px";
302 }
303 }).attr("marker-end", function(d) {
304 if(d.type == 1){
305 return "url(#TriangleRed)";
306 } else {
307 return "url(#Triangle)";
308 }
309 });
310
311
312 circle.enter().append("svg:circle")
313 .attr("r", 8)
314/* .on("click", function(d,i) {
315 if ( path_set == 0 || path_set == 2 ){
316 fm = d.name;
317 path_set = 1;
318 alert("from set to " + d.name);
319 }else if ( path_set == 1 ){
320 to = d.name;
321 path_set = 2;
322 alert("to set to " + d.name);
323 }
324 }) */
Masayoshi Kobayashidd4ad8f2013-02-27 20:20:13 +0000325 .call(node_drag);
326// .call(force.drag);
Masayoshi Kobayashi274c07d2013-02-20 21:38:16 +0000327
328/* text.enter().append("svg:text")
329 .attr("x", 8)
330 .attr("y", ".31em")
331 .attr("class", "shadow")
332 .text(function(d) { return d.name.split(":")[7]; }); */
333
334 text.enter().append("svg:text")
335 .attr("x", 8)
336 .attr("y", ".31em")
337 .text(function(d) { return d.name.split(":")[7]; });
338
339 circle.append("title")
340 .text(function(d) { return d.name; });
341
342 circle.attr("fill", function(d) {
343 if (d.group == 1){return "red";}
344 else if (d.group == 2){return "blue";}
345 else if (d.group == 3){return "green";}
346 else{ return "gray"; }
347 });
348
349
350 force.on("tick", tick);
351 path.exit().remove();
352 circle.exit().remove();
353// text.exit().remove();
354
355 force.start();
356
357 setInterval(function() {
358 $.ajax({
359// url: 'http://onosnat.onlab.us:8080/topology',
360 url: data_source,
361 success: function(json) {
362 update(json)
363 },
364 dataType: "json"
365 });
366 }, 3000);
367 }
368 function tick() {
369 path.attr("d", function(d) {
370 var dx = d.target.x - d.source.x,
371 dy = d.target.y - d.source.y,
Masayoshi Kobayashidd4ad8f2013-02-27 20:20:13 +0000372// dr = 1/d.linknum; //linknum is defined above
Masayoshi Kobayashi274c07d2013-02-20 21:38:16 +0000373 dr = 300;
374 return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
375 });
376
Ubuntu37ebda62013-03-01 00:35:31 +0000377 path.attr("stroke", function(d) {
Masayoshi Kobayashi274c07d2013-02-20 21:38:16 +0000378 if(d.type == 1){
379 return "red"
380 } else {
381 return "black"
382 }
383 }).attr("stroke-width", function(d) {
384 if(d.type == 1){
385 return "4px";
386 } else {
387 return "1.5px";
388 }
389 }).attr("marker-end", function(d) {
390 if(d.type == 1){
391 return "url(#TriangleRed)";
392 } else {
393 return "url(#Triangle)";
394 }
395 });
396
397
398// circle.attr("cx", function(d) { return d.x; }).attr("cy", function(d) { return d.y; });
399 circle.attr("transform", function(d) {
400 return "translate(" + d.x + "," + d.y + ")";
401 })
402 circle.attr("fill", function(d) {
403 if (d.group == 1){return "red";}
404 else if (d.group == 2){return "blue";}
405 else if (d.group == 3){return "green";}
406 else{ return "gray"; }
407 });
408// text.attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; });
409// text.attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; });
410 text.attr("transform", function(d) {
411 return "translate(" + d.x + "," + d.y + ")";
412 });
413 }
414}