Simon Hunt

GUI -- store ref to node/link selection in backing data.

- tweaking force-layout parameters; now host-to-host intent path is highlighted.
- injectTestEvent() now uses recursion to look for appropriate json files.
- implemented updateHost() event.
- some refactoring cleanup in topo2.js

Change-Id: I888f05032d3c9df6470bd4d2f399f61efb9dbd46
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
7 "labels": [ 7 "labels": [
8 "0000ffffffff0008", 8 "0000ffffffff0008",
9 "FF:FF:FF:FF:00:08", 9 "FF:FF:FF:FF:00:08",
10 - "sw-8" 10 + "sw-8",
11 + ""
11 ], 12 ],
12 "metaUi": { 13 "metaUi": {
13 "x": 400, 14 "x": 400,
......
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
7 "labels": [ 7 "labels": [
8 "0000ffffffff0003", 8 "0000ffffffff0003",
9 "FF:FF:FF:FF:00:03", 9 "FF:FF:FF:FF:00:03",
10 - "sw-3" 10 + "sw-3",
11 + ""
11 ], 12 ],
12 "metaUi": { 13 "metaUi": {
13 "x": 800, 14 "x": 800,
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffff0003/21-of:0000ffffffff0008/20",
5 + "type": "direct",
6 + "linkWidth": 2,
4 "src": "of:0000ffffffff0003", 7 "src": "of:0000ffffffff0003",
5 "srcPort": "21", 8 "srcPort": "21",
6 "dst": "of:0000ffffffff0008", 9 "dst": "of:0000ffffffff0008",
7 "dstPort": "20", 10 "dstPort": "20",
8 - "type": "infra",
9 - "linkWidth": 2,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addHost", 2 "event": "addHost",
3 "payload": { 3 "payload": {
4 - "id": "00:00:00:00:00:03/-1", 4 + "id": "0E:2A:69:30:13:86/-1",
5 + "ingress": "0E:2A:69:30:13:86/-1/0-of:0000ffffffff0003/2",
6 + "egress": "of:0000ffffffff0003/2-0E:2A:69:30:13:86/-1/0",
5 "cp": { 7 "cp": {
6 "device": "of:0000ffffffff0003", 8 "device": "of:0000ffffffff0003",
7 - "port": 1 9 + "port": 2
8 }, 10 },
9 "labels": [ 11 "labels": [
10 - "10.0.0.3", 12 + "unknown",
11 - "00:00:00:00:00:03" 13 + "0E:2A:69:30:13:86"
12 ], 14 ],
13 - "metaUi": { 15 + "props": {}
14 - }
15 } 16 }
16 } 17 }
......
1 { 1 {
2 "event": "addHost", 2 "event": "addHost",
3 "payload": { 3 "payload": {
4 - "id": "00:00:00:00:00:08/-1", 4 + "id": "A6:96:E5:03:52:5F/-1",
5 + "ingress": "A6:96:E5:03:52:5F/-1/0-of:0000ffffffff0008/1",
6 + "egress": "of:0000ffffffff0008/1-A6:96:E5:03:52:5F/-1/0",
5 "cp": { 7 "cp": {
6 "device": "of:0000ffffffff0008", 8 "device": "of:0000ffffffff0008",
7 "port": 1 9 "port": 1
8 }, 10 },
9 "labels": [ 11 "labels": [
10 - "10.0.0.8", 12 + "unknown",
11 - "00:00:00:00:00:08" 13 + "A6:96:E5:03:52:5F"
12 ], 14 ],
13 - "metaUi": { 15 + "props": {}
14 - }
15 } 16 }
16 } 17 }
......
1 +{
2 + "event": "updateHost",
3 + "payload": {
4 + "id": "0E:2A:69:30:13:86/-1",
5 + "ingress": "0E:2A:69:30:13:86/-1/0-of:0000ffffffff0003/2",
6 + "egress": "of:0000ffffffff0003/2-0E:2A:69:30:13:86/-1/0",
7 + "cp": {
8 + "device": "of:0000ffffffff0003",
9 + "port": 2
10 + },
11 + "labels": [
12 + "10.0.0.13",
13 + "0E:2A:69:30:13:86"
14 + ],
15 + "props": {}
16 + }
17 +}
1 +{
2 + "event": "updateHost",
3 + "payload": {
4 + "id": "A6:96:E5:03:52:5F/-1",
5 + "ingress": "A6:96:E5:03:52:5F/-1/0-of:0000ffffffff0008/1",
6 + "egress": "of:0000ffffffff0008/1-A6:96:E5:03:52:5F/-1/0",
7 + "cp": {
8 + "device": "of:0000ffffffff0008",
9 + "port": 1
10 + },
11 + "labels": [
12 + "10.0.0.17",
13 + "A6:96:E5:03:52:5F"
14 + ],
15 + "props": {}
16 + }
17 +}
1 +{
2 + "event": "doUiThing",
3 + "payload": {
4 + "id": "xyyzy"
5 + }
6 +}
1 { 1 {
2 "comments": [ 2 "comments": [
3 - "Add two devices and one link (auto), and two hosts." 3 + "Add two devices and one link (auto), and two hosts.",
4 + "Then update the two hosts (with IP address labels)."
4 ], 5 ],
5 "title": "Simple Startup Scenario", 6 "title": "Simple Startup Scenario",
6 "params": { 7 "params": {
......
...@@ -53,13 +53,18 @@ ...@@ -53,13 +53,18 @@
53 fill: #846; 53 fill: #846;
54 } 54 }
55 55
56 -#topo svg .node text { 56 +#topo svg .node.device text {
57 - stroke: none;
58 fill: white; 57 fill: white;
59 font: 10pt sans-serif; 58 font: 10pt sans-serif;
60 pointer-events: none; 59 pointer-events: none;
61 } 60 }
62 61
62 +#topo svg .node.host text {
63 + fill: #846;
64 + font: 9pt sans-serif;
65 + pointer-events: none;
66 +}
67 +
63 #topo svg .node.selected rect, 68 #topo svg .node.selected rect,
64 #topo svg .node.selected circle { 69 #topo svg .node.selected circle {
65 filter: url(#blue-glow); 70 filter: url(#blue-glow);
...@@ -73,7 +78,7 @@ ...@@ -73,7 +78,7 @@
73 78
74 #topo svg .link.showPath { 79 #topo svg .link.showPath {
75 stroke: #f00; 80 stroke: #f00;
76 - stroke-width: 4px; 81 + stroke-width: 6px;
77 } 82 }
78 83
79 /* for debugging */ 84 /* for debugging */
......
...@@ -82,18 +82,21 @@ ...@@ -82,18 +82,21 @@
82 opt: 'img/opt.png' 82 opt: 'img/opt.png'
83 }, 83 },
84 force: { 84 force: {
85 - note: 'node.class or link.class is used to differentiate', 85 + note_for_links: 'link.type is used to differentiate',
86 linkDistance: { 86 linkDistance: {
87 - infra: 200, 87 + direct: 100,
88 - host: 40 88 + optical: 120,
89 + hostLink: 20
89 }, 90 },
90 linkStrength: { 91 linkStrength: {
91 - infra: 1.0, 92 + direct: 1.0,
92 - host: 1.0 93 + optical: 1.0,
94 + hostLink: 1.0
93 }, 95 },
96 + note_for_nodes: 'node.class is used to differentiate',
94 charge: { 97 charge: {
95 - device: -400, 98 + device: -8000,
96 - host: -100 99 + host: -300
97 }, 100 },
98 pad: 20, 101 pad: 20,
99 translate: function() { 102 translate: function() {
...@@ -204,39 +207,37 @@ ...@@ -204,39 +207,37 @@
204 evn = ++sc.evNumber, 207 evn = ++sc.evNumber,
205 pfx = sc.evDir + sc.ctx + sc.evPrefix + evn, 208 pfx = sc.evDir + sc.ctx + sc.evPrefix + evn,
206 onosUrl = pfx + sc.evOnos, 209 onosUrl = pfx + sc.evOnos,
207 - uiUrl = pfx + sc.evUi; 210 + uiUrl = pfx + sc.evUi,
211 + stack = [
212 + { url: onosUrl, cb: handleServerEvent },
213 + { url: uiUrl, cb: handleUiEvent }
214 + ];
215 + recurseFetchEvent(stack, evn);
216 + }
208 217
209 - tryOnosEvent(onosUrl, uiUrl); 218 + function recurseFetchEvent(stack, evn) {
219 + var v = scenario.view,
220 + frame;
221 + if (stack.length === 0) {
222 + v.alert('Error:\n\nNo event #' + evn + ' found.');
223 + return;
210 } 224 }
225 + frame = stack.shift();
211 226
212 - // TODO: tryOnosEvent/tryUiEvent folded into recursive function. 227 + d3.json(frame.url, function (err, data) {
213 - function tryOnosEvent(onosUrl, uiUrl) {
214 - var v = scenario.view;
215 - d3.json(onosUrl, function(err, data) {
216 if (err) { 228 if (err) {
217 if (err.status === 404) { 229 if (err.status === 404) {
218 - tryUiEvent(uiUrl); 230 + // if we didn't find the data, try the next stack frame
231 + recurseFetchEvent(stack, evn);
219 } else { 232 } else {
220 - v.alert('non-404 error:\n\n' + onosUrl + '\n\n' + err); 233 + v.alert('non-404 error:\n\n' + frame.url + '\n\n' + err);
221 } 234 }
222 } else { 235 } else {
223 - testDebug('loaded: ' + onosUrl); 236 + testDebug('loaded: ' + frame.url);
224 - handleServerEvent(data); 237 + frame.cb(data);
225 } 238 }
226 }); 239 });
227 - }
228 240
229 - function tryUiEvent(uiUrl) {
230 - var v = scenario.view;
231 - d3.json(uiUrl, function(err, data) {
232 - if (err) {
233 - v.alert('Error:\n\n' + uiUrl + '\n\n' +
234 - err.status + ': ' + err.statusText);
235 - } else {
236 - testDebug('loaded: ' + uiUrl);
237 - handleUiEvent(data);
238 - }
239 - });
240 } 241 }
241 242
242 function handleUiEvent(data) { 243 function handleUiEvent(data) {
...@@ -261,19 +262,15 @@ ...@@ -261,19 +262,15 @@
261 function cycleLabels() { 262 function cycleLabels() {
262 deviceLabelIndex = (deviceLabelIndex === network.deviceLabelCount - 1) ? 0 : deviceLabelIndex + 1; 263 deviceLabelIndex = (deviceLabelIndex === network.deviceLabelCount - 1) ? 0 : deviceLabelIndex + 1;
263 264
264 - function niceLabel(label) {
265 - return (label && label.trim()) ? label : '.';
266 - }
267 -
268 network.nodes.forEach(function (d) { 265 network.nodes.forEach(function (d) {
269 if (d.class !== 'device') { return; } 266 if (d.class !== 'device') { return; }
270 267
271 - var idx = (deviceLabelIndex < d.labels.length) ? deviceLabelIndex : 0, 268 + var label = niceLabel(deviceLabel(d)),
272 - node = d3.select('#' + safeId(d.id)), 269 + node = d.el,
273 box; 270 box;
274 271
275 node.select('text') 272 node.select('text')
276 - .text(niceLabel(d.labels[idx])) 273 + .text(label)
277 .style('opacity', 0) 274 .style('opacity', 0)
278 .transition() 275 .transition()
279 .style('opacity', 1); 276 .style('opacity', 1);
...@@ -359,18 +356,18 @@ ...@@ -359,18 +356,18 @@
359 updateLink: stillToImplement, 356 updateLink: stillToImplement,
360 removeLink: stillToImplement, 357 removeLink: stillToImplement,
361 addHost: addHost, 358 addHost: addHost,
362 - updateHost: stillToImplement, 359 + updateHost: updateHost,
363 removeHost: stillToImplement, 360 removeHost: stillToImplement,
364 showPath: showPath 361 showPath: showPath
365 }; 362 };
366 363
367 function addDevice(data) { 364 function addDevice(data) {
368 var device = data.payload, 365 var device = data.payload,
369 - node = createDeviceNode(device); 366 + nodeData = createDeviceNode(device);
370 note('addDevice', device.id); 367 note('addDevice', device.id);
371 368
372 - network.nodes.push(node); 369 + network.nodes.push(nodeData);
373 - network.lookup[node.id] = node; 370 + network.lookup[nodeData.id] = nodeData;
374 updateNodes(); 371 updateNodes();
375 network.force.start(); 372 network.force.start();
376 } 373 }
...@@ -380,7 +377,7 @@ ...@@ -380,7 +377,7 @@
380 lnk = createLink(link); 377 lnk = createLink(link);
381 378
382 if (lnk) { 379 if (lnk) {
383 - note('addLink', lnk.id); 380 + note('addLink', link.id);
384 381
385 network.links.push(lnk); 382 network.links.push(lnk);
386 network.lookup[lnk.id] = lnk; 383 network.lookup[lnk.id] = lnk;
...@@ -393,8 +390,8 @@ ...@@ -393,8 +390,8 @@
393 var host = data.payload, 390 var host = data.payload,
394 node = createHostNode(host), 391 node = createHostNode(host),
395 lnk; 392 lnk;
396 -
397 note('addHost', node.id); 393 note('addHost', node.id);
394 +
398 network.nodes.push(node); 395 network.nodes.push(node);
399 network.lookup[host.id] = node; 396 network.lookup[host.id] = node;
400 updateNodes(); 397 updateNodes();
...@@ -409,6 +406,15 @@ ...@@ -409,6 +406,15 @@
409 network.force.start(); 406 network.force.start();
410 } 407 }
411 408
409 + function updateHost(data) {
410 + var host = data.payload,
411 + hostData = network.lookup[host.id];
412 + note('updateHost', host.id);
413 +
414 + $.extend(hostData, host);
415 + updateNodes();
416 + }
417 +
412 function showPath(data) { 418 function showPath(data) {
413 var links = data.payload.links, 419 var links = data.payload.links,
414 s = [ data.event + "\n" + links.length ]; 420 s = [ data.event + "\n" + links.length ];
...@@ -420,7 +426,7 @@ ...@@ -420,7 +426,7 @@
420 links.forEach(function (d, i) { 426 links.forEach(function (d, i) {
421 var link = network.lookup[d]; 427 var link = network.lookup[d];
422 if (link) { 428 if (link) {
423 - d3.select('#' + link.svgId).classed('showPath', true); 429 + link.el.classed('showPath', true);
424 } 430 }
425 }); 431 });
426 432
...@@ -432,7 +438,7 @@ ...@@ -432,7 +438,7 @@
432 function stillToImplement(data) { 438 function stillToImplement(data) {
433 var p = data.payload; 439 var p = data.payload;
434 note(data.event, p.id); 440 note(data.event, p.id);
435 - //network.view.alert('Not yet implemented: "' + data.event + '"'); 441 + network.view.alert('Not yet implemented: "' + data.event + '"');
436 } 442 }
437 443
438 function unknownEvent(data) { 444 function unknownEvent(data) {
...@@ -454,7 +460,7 @@ ...@@ -454,7 +460,7 @@
454 function createHostLink(host) { 460 function createHostLink(host) {
455 var src = host.id, 461 var src = host.id,
456 dst = host.cp.device, 462 dst = host.cp.device,
457 - id = host.id, 463 + id = host.ingress,
458 srcNode = network.lookup[src], 464 srcNode = network.lookup[src],
459 dstNode = network.lookup[dst], 465 dstNode = network.lookup[dst],
460 lnk; 466 lnk;
...@@ -466,31 +472,32 @@ ...@@ -466,31 +472,32 @@
466 return null; 472 return null;
467 } 473 }
468 474
475 + // Compose link ...
469 lnk = { 476 lnk = {
470 - svgId: safeId(src) + '-' + safeId(dst),
471 id: id, 477 id: id,
472 source: srcNode, 478 source: srcNode,
473 target: dstNode, 479 target: dstNode,
474 class: 'link', 480 class: 'link',
481 + type: 'hostLink',
475 svgClass: 'link hostLink', 482 svgClass: 'link hostLink',
476 x1: srcNode.x, 483 x1: srcNode.x,
477 y1: srcNode.y, 484 y1: srcNode.y,
478 x2: dstNode.x, 485 x2: dstNode.x,
479 y2: dstNode.y, 486 y2: dstNode.y,
480 width: 1 487 width: 1
481 - }; 488 + }
482 return lnk; 489 return lnk;
483 } 490 }
484 491
485 function createLink(link) { 492 function createLink(link) {
486 - var type = link.type, 493 + // start with the link object as is
494 + var lnk = link,
495 + type = link.type,
487 src = link.src, 496 src = link.src,
488 dst = link.dst, 497 dst = link.dst,
489 - id = link.id,
490 w = link.linkWidth, 498 w = link.linkWidth,
491 srcNode = network.lookup[src], 499 srcNode = network.lookup[src],
492 - dstNode = network.lookup[dst], 500 + dstNode = network.lookup[dst];
493 - lnk;
494 501
495 if (!(srcNode && dstNode)) { 502 if (!(srcNode && dstNode)) {
496 // TODO: send warning message back to server on websocket 503 // TODO: send warning message back to server on websocket
...@@ -499,9 +506,8 @@ ...@@ -499,9 +506,8 @@
499 return null; 506 return null;
500 } 507 }
501 508
502 - lnk = { 509 + // Augment as needed...
503 - svgId: safeId(src) + '-' + safeId(dst), 510 + $.extend(lnk, {
504 - id: id,
505 source: srcNode, 511 source: srcNode,
506 target: dstNode, 512 target: dstNode,
507 class: 'link', 513 class: 'link',
...@@ -511,7 +517,7 @@ ...@@ -511,7 +517,7 @@
511 x2: dstNode.x, 517 x2: dstNode.x,
512 y2: dstNode.y, 518 y2: dstNode.y,
513 width: w 519 width: w
514 - }; 520 + });
515 return lnk; 521 return lnk;
516 } 522 }
517 523
...@@ -532,7 +538,6 @@ ...@@ -532,7 +538,6 @@
532 var entering = link.enter() 538 var entering = link.enter()
533 .append('line') 539 .append('line')
534 .attr({ 540 .attr({
535 - id: function (d) { return d.svgId; },
536 class: function (d) { return d.svgClass; }, 541 class: function (d) { return d.svgClass; },
537 x1: function (d) { return d.x1; }, 542 x1: function (d) { return d.x1; },
538 y1: function (d) { return d.y1; }, 543 y1: function (d) { return d.y1; },
...@@ -548,8 +553,13 @@ ...@@ -548,8 +553,13 @@
548 }); 553 });
549 554
550 // augment links 555 // augment links
551 - // TODO: add src/dst port labels etc. 556 + entering.each(function (d) {
557 + var link = d3.select(this);
558 + // provide ref to element selection from backing data....
559 + d.el = link;
552 560
561 + // TODO: add src/dst port labels etc.
562 + });
553 563
554 // operate on both existing and new links, if necessary 564 // operate on both existing and new links, if necessary
555 //link .foo() .bar() ... 565 //link .foo() .bar() ...
...@@ -577,7 +587,6 @@ ...@@ -577,7 +587,6 @@
577 587
578 // cache label array length 588 // cache label array length
579 network.deviceLabelCount = device.labels.length; 589 network.deviceLabelCount = device.labels.length;
580 -
581 return node; 590 return node;
582 } 591 }
583 592
...@@ -587,13 +596,16 @@ ...@@ -587,13 +596,16 @@
587 596
588 // Augment as needed... 597 // Augment as needed...
589 node.class = 'host'; 598 node.class = 'host';
599 + if (!node.type) {
600 + // TODO: perhaps type would be: {phone, tablet, laptop, endstation} ?
601 + node.type = 'endstation';
602 + }
590 node.svgClass = 'node host'; 603 node.svgClass = 'node host';
591 // TODO: consider placing near its switch, if [x,y] not defined 604 // TODO: consider placing near its switch, if [x,y] not defined
592 positionNode(node); 605 positionNode(node);
593 606
594 // cache label array length 607 // cache label array length
595 network.hostLabelCount = host.labels.length; 608 network.hostLabelCount = host.labels.length;
596 -
597 return node; 609 return node;
598 } 610 }
599 611
...@@ -645,11 +657,27 @@ ...@@ -645,11 +657,27 @@
645 return d.fixed ? d.svgClass + ' fixed' : d.svgClass; 657 return d.fixed ? d.svgClass + ' fixed' : d.svgClass;
646 } 658 }
647 659
660 + function hostLabel(d) {
661 + var idx = (hostLabelIndex < d.labels.length) ? hostLabelIndex : 0;
662 + return d.labels[idx];
663 + }
664 + function deviceLabel(d) {
665 + var idx = (deviceLabelIndex < d.labels.length) ? deviceLabelIndex : 0;
666 + return d.labels[idx];
667 + }
668 + function niceLabel(label) {
669 + return (label && label.trim()) ? label : '.';
670 + }
671 +
648 function updateNodes() { 672 function updateNodes() {
649 node = nodeG.selectAll('.node') 673 node = nodeG.selectAll('.node')
650 .data(network.nodes, function (d) { return d.id; }); 674 .data(network.nodes, function (d) { return d.id; });
651 675
652 // operate on existing nodes, if necessary 676 // operate on existing nodes, if necessary
677 + // update host labels
678 + node.filter('.host').select('text')
679 + .text(hostLabel);
680 +
653 //node .foo() .bar() ... 681 //node .foo() .bar() ...
654 682
655 // operate on entering nodes: 683 // operate on entering nodes:
...@@ -671,9 +699,12 @@ ...@@ -671,9 +699,12 @@
671 entering.filter('.device').each(function (d) { 699 entering.filter('.device').each(function (d) {
672 var node = d3.select(this), 700 var node = d3.select(this),
673 icon = iconUrl(d), 701 icon = iconUrl(d),
674 - idx = (deviceLabelIndex < d.labels.length) ? deviceLabelIndex : 0, 702 + label = niceLabel(deviceLabel(d)),
675 box; 703 box;
676 704
705 + // provide ref to element from backing data....
706 + d.el = node;
707 +
677 node.append('rect') 708 node.append('rect')
678 .attr({ 709 .attr({
679 'rx': 5, 710 'rx': 5,
...@@ -681,7 +712,7 @@ ...@@ -681,7 +712,7 @@
681 }); 712 });
682 713
683 node.append('text') 714 node.append('text')
684 - .text(d.labels[idx]) 715 + .text(label)
685 .attr('dy', '1.1em'); 716 .attr('dy', '1.1em');
686 717
687 box = adjustRectToFitText(node); 718 box = adjustRectToFitText(node);
...@@ -717,16 +748,19 @@ ...@@ -717,16 +748,19 @@
717 // augment host nodes... 748 // augment host nodes...
718 entering.filter('.host').each(function (d) { 749 entering.filter('.host').each(function (d) {
719 var node = d3.select(this), 750 var node = d3.select(this),
720 - idx = (hostLabelIndex < d.labels.length) ? hostLabelIndex : 0,
721 box; 751 box;
722 752
753 + // provide ref to element from backing data....
754 + d.el = node;
755 +
723 node.append('circle') 756 node.append('circle')
724 .attr('r', 8); // TODO: define host circle radius 757 .attr('r', 8); // TODO: define host circle radius
725 758
726 // TODO: are we attaching labels to hosts? 759 // TODO: are we attaching labels to hosts?
727 node.append('text') 760 node.append('text')
728 - .text(d.labels[idx]) 761 + .text(hostLabel)
729 - .attr('dy', '1.1em'); 762 + .attr('dy', '1.3em')
763 + .attr('text-anchor', 'middle');
730 764
731 // debug function to show the modelled x,y coordinates of nodes... 765 // debug function to show the modelled x,y coordinates of nodes...
732 if (debug('showNodeXY')) { 766 if (debug('showNodeXY')) {
...@@ -964,16 +998,15 @@ ...@@ -964,16 +998,15 @@
964 link = linkG.selectAll('.link'); 998 link = linkG.selectAll('.link');
965 node = nodeG.selectAll('.node'); 999 node = nodeG.selectAll('.node');
966 1000
1001 + function chrg(d) {
1002 + return fcfg.charge[d.class] || -12000;
1003 + }
967 function ldist(d) { 1004 function ldist(d) {
968 - return 2 * 30; 1005 + return fcfg.linkDistance[d.type] || 50;
969 - //return fcfg.linkDistance[d.class] || 150;
970 } 1006 }
971 function lstrg(d) { 1007 function lstrg(d) {
972 - return 2 * 0.6; 1008 + // 0.0 - 1.0
973 - //return fcfg.linkStrength[d.class] || 1; 1009 + return fcfg.linkStrength[d.type] || 1.0;
974 - }
975 - function lchrg(d) {
976 - return fcfg.charge[d.class] || -200;
977 } 1010 }
978 1011
979 function selectCb(d, self) { 1012 function selectCb(d, self) {
...@@ -1003,23 +1036,13 @@ ...@@ -1003,23 +1036,13 @@
1003 .size(forceDim) 1036 .size(forceDim)
1004 .nodes(network.nodes) 1037 .nodes(network.nodes)
1005 .links(network.links) 1038 .links(network.links)
1006 - .gravity(0.3) 1039 + .gravity(0.4)
1007 - .charge(-15000) 1040 + .friction(0.7)
1008 - .friction(0.1) 1041 + .charge(chrg)
1009 - //.charge(lchrg)
1010 .linkDistance(ldist) 1042 .linkDistance(ldist)
1011 .linkStrength(lstrg) 1043 .linkStrength(lstrg)
1012 .on('tick', tick); 1044 .on('tick', tick);
1013 1045
1014 - // TVUE
1015 - //.gravity(0.3)
1016 - //.charge(-15000)
1017 - //.friction(0.1)
1018 - //.linkDistance(function(d) { return d.value * 30; })
1019 - //.linkStrength(function(d) { return d.value * 0.6; })
1020 - //.size([w, h])
1021 - //.start();
1022 -
1023 network.drag = d3u.createDragBehavior(network.force, selectCb, atDragEnd); 1046 network.drag = d3u.createDragBehavior(network.force, selectCb, atDragEnd);
1024 } 1047 }
1025 1048
......