Skip to content

Instantly share code, notes, and snippets.

@magjac
Last active July 29, 2021 00:55
Show Gist options
  • Save magjac/18da096e75304b81871adc1d594039c8 to your computer and use it in GitHub Desktop.
Save magjac/18da096e75304b81871adc1d594039c8 to your computer and use it in GitHub Desktop.
d3-graphviz demo application showing association of SVG elements with DOT source HTML-like node label table cell elements

Open the console to see what's going on

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/viz.js@1.8.0/viz.js"></script>
<script src="https://unpkg.com/d3-graphviz@0.1.2/build/d3-graphviz.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>
var dotSrc = `
digraph DB {
graph [label="Click on a cell to convert to upper/lower case" labelloc="t", fontsize="20.0" tooltip=" "]
rankdir=LR
node [shape=plain]
person [
// NOTE: The use of HREF is a workaround for '[Dot] ID="value" fails to produce id string in svg:svg output for html nodes'
// See https://gitlab.com/graphviz/graphviz/issues/207
// For the workaorund and more info, see http://ftp.graphviz.org/mantisbt/view.php?id=2197
label=< <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR><TD>Person table</TD></TR>
<TR><TD ID="p.id" PORT="id" HREF=" ">Person ID</TD></TR>
<TR><TD ID="p.fn" PORT="fn" HREF=" ">First Name</TD></TR>
<TR><TD ID="p.mn" PORT="mn" HREF=" ">Middle Name</TD></TR>
<TR><TD ID="p.ln" PORT="ln" HREF=" ">Last Name</TD></TR>
</TABLE> >
]
address [
label=< <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR><TD>Addresses table</TD></TR>
<TR><TD ID="a.id" PORT="id" HREF=" ">Address ID</TD></TR>
<TR><TD ID="a.pid" PORT="pid" HREF=" ">Person ID</TD></TR>
<TR><TD ID="a.index" PORT="index" HREF=" ">ZIP Code</TD></TR>
<TR><TD ID="a.street" PORT="street" HREF=" ">Street Name</TD></TR>
<TR><TD ID="a.house" PORT="house" HREF=" ">House Number</TD></TR>
<TR><TD ID="a.town" PORT="town" HREF=" ">City/Town/Village Name</TD></TR>
<TR><TD ID="a.state" PORT="state" HREF=" ">State Name</TD></TR>
<TR><TD ID="a.district" PORT="district" HREF=" ">County/District Name</TD></TR>
<TR><TD ID="a.country" PORT="country" HREF=" ">Country Name</TD></TR>
</TABLE> >
]
phone [
label=< <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR><TD>Phone Number table</TD></TR>
<TR><TD ID="n.pid" PORT="pid" HREF=" ">Person ID</TD></TR>
<TR><TD ID="n.cc" PORT="cc" HREF=" ">Country Code</TD></TR>
<TR><TD ID="n.ac" PORT="ac" HREF=" ">Area Code</TD></TR>
<TR><TD ID="n.n" PORT="n" HREF=" ">Phone Number</TD></TR>
</TABLE> >
]
{phone:pid address:pid} -> person:id
}
`;
var graphviz = d3.select("#graph").graphviz();
var dotSrcLines;
function render(dotSrc) {
// console.log('DOT source =', dotSrc);
dotSrcLines = dotSrc.split('\n');
transition1 = d3.transition()
.delay(100)
.duration(1000);
graphviz
.transition(transition1)
.renderDot(dotSrc);
transition1
.transition()
.duration(0)
.on("end", function () {
nodes = d3.selectAll('.node,.edge');
nodes
.selectAll("g")
.on("click", fieldClickHandler)
.selectAll("a")
// Remove the workaround attributes to avoid consuming the click events
.attr("href", null)
.attr("title", null);
});
}
function fieldClickHandler () {
var node = d3.select(this);
var text = node.selectAll('text').text();
var id = node.attr('id');
var class1 = node.attr('class');
dotElement = id.replace(/^a_/, '');
console.log('Element id="%s" class="%s" text="%s" dotElement="%s"', id, class1, text, dotElement);
console.log('Finding and deleting references to %s "%s" from the DOT source', class1, dotElement);
for (i = 0; i < dotSrcLines.length; i++) {
if (dotSrcLines[i].indexOf(dotElement) >= 0) {
ucText = text.toUpperCase();
lcText = text.toLowerCase();
if (text != ucText) {
newText = ucText;
} else {
newText = lcText;
}
console.log('Converting "%s" to "%s" on line %d: %s', text, newText, i, dotSrcLines[i]);
dotSrcLines[i] = dotSrcLines[i].replace(text, newText);
}
}
dotSrc = dotSrcLines.join('\n');
render(dotSrc);
}
render(dotSrc);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment