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
Showing
11 changed files
with
177 additions
and
103 deletions
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 | { | 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 | ... | ... |
-
Please register or login to post a comment