| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <body> | |
| <script src="https://d3js.org/d3.v5.min.js"></script> | |
| <script src="https://unpkg.com/@hpcc-js/wasm@0.3.11/dist/index.min.js"></script> | |
| <script src="https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js"></script> | |
| <div id="graph" style="text-align: center;"></div> | |
| <script> | |
| var dotSrc = ` | |
| <INSERT_DOT> | |
| `; | |
| var dotSrcLines; | |
| // Label to assembly line mapping | |
| var labelAsm = {}; | |
| // regex to find node label line | |
| const re = /^"(?<node>[^"]+)" \[label="\1/; | |
| var graphviz = d3.select("#graph").graphviz(); | |
| function render() { | |
| var t = d3.transition().delay(100).duration(500); | |
| graphviz.transition(t).renderDot(dotSrc).on("end", interactive); | |
| } | |
| function setup() { | |
| dotSrcLines = dotSrc.split('\n'); | |
| console.log("Removing assembly lines from nodes"); | |
| // find the assembly line for each label and preserve it in labelAsm | |
| for (i = 0; i < dotSrcLines.length;) { | |
| console.log("checking line %d: %s", i, dotSrcLines[i]); | |
| match = dotSrcLines[i].match(re); | |
| if (match && dotSrcLines[i+2].startsWith(' ')) { | |
| console.log(match); | |
| node = match.groups['node']; | |
| console.log('Found node "%s" on line %d', node, i); | |
| labelAsm[node] = dotSrcLines[i+2]; | |
| console.log(labelAsm); | |
| console.log('Deleting line %d: %s', i+2, dotSrcLines[i+2]); | |
| dotSrcLines.splice(i+2, 1); | |
| i = i+3; | |
| } else { | |
| i++; | |
| } | |
| } | |
| dotSrc = dotSrcLines.join('\n'); | |
| render(); | |
| } | |
| function interactive() { | |
| nodes = d3.selectAll('.node'); | |
| nodes.on("click", function () { | |
| var title = d3.select(this).selectAll('title').text().trim(); | |
| var text = d3.select(this).selectAll('text').text(); | |
| var id = d3.select(this).attr('id'); | |
| var class1 = d3.select(this).attr('class'); | |
| dotElement = title.replace('->',' -> '); | |
| console.log('Element id="%s" class="%s" title="%s" text="%s" dotElement="%s"', id, class1, title, text, dotElement); | |
| console.log('Inserting assembly line for "%s"', dotElement); | |
| for (i = 0; i < dotSrcLines.length;) { | |
| var match = dotSrcLines[i].match(re); | |
| if (match) { | |
| var node = match.groups['node']; | |
| if (node === dotElement) { | |
| // check if we have an assembly line | |
| var asm = labelAsm[node]; | |
| if (asm) { | |
| // toggle the assembly line | |
| if (dotSrcLines[i+2].startsWith(' ')) { | |
| dotSrcLines.splice(i+2, 1); | |
| } else { | |
| dotSrcLines.splice(i+2, 0, asm); | |
| } | |
| break; | |
| } | |
| } | |
| } | |
| i++; | |
| } | |
| dotSrc = dotSrcLines.join('\n'); | |
| render(); | |
| }); | |
| } | |
| setup(); | |
| </script> |