Skip to content

Instantly share code, notes, and snippets.

@basnijholt
Created September 16, 2024 17:59
Show Gist options
  • Save basnijholt/1f1268bb172e0612595fa022979dcf0a to your computer and use it in GitHub Desktop.
Save basnijholt/1f1268bb172e0612595fa022979dcf0a to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PipeFunc Graph</title>
<script src="https://unpkg.com/[email protected]/dist/jquery.min.js"></script>
<script src="https://unpkg.com/[email protected]/jquery.mousewheel.js"></script>
<script src="https://unpkg.com/[email protected]/dist/jquery.color.js"></script>
<script src="https://unpkg.com/[email protected]/dist/d3.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/mountainstorm/jquery.graphviz.svg@master/js/jquery.graphviz.svg.js"></script>
<script src="https://unpkg.com/@hpcc-js/[email protected]/dist/index.min.js"></script>
<script src="https://unpkg.com/[email protected]/build/d3-graphviz.min.js"></script>
</head>
<body>
<div id="graph" style="text-align: center;"></div>
<script>
// Initialize a d3-graphviz renderer instance
var graphviz = d3.select("#graph").graphviz();
// Configuration for transitions in rendering the graph
var d3Config = {
transitionDelay: 0,
transitionDuration: 500
};
// Variable for storing the selected graph rendering engine
var selectedEngine = "dot";
// Object for saving the current GraphVizSVG
var graphVizObject;
// Variable for storing the selected direction for highlighting
var selectedDirection = "bidirectional";
// Array holding the current selections
var currentSelection = [];
// Function to highlight selected nodes and their connected nodes
function highlightSelection() {
let highlightedNodes = $();
currentSelection.forEach(selection => {
const nodes = getConnectedNodes(selection.set, selection.direction);
highlightedNodes = highlightedNodes.add(nodes);
});
graphVizObject.highlight(highlightedNodes, true);
}
// Function to retrieve nodes connected in the specified direction
function getConnectedNodes(nodeSet, mode = "bidirectional") {
let resultSet = $().add(nodeSet);
const nodes = graphVizObject.nodesByName();
nodeSet.each((i, el) => {
if (el.className.baseVal === "edge") {
const [startNode, endNode] = $(el).data("name").split("->");
if ((mode === "bidirectional" || mode === "upstream") && startNode) {
resultSet = resultSet.add(nodes[startNode]).add(graphVizObject.linkedTo(nodes[startNode], true));
}
if ((mode === "bidirectional" || mode === "downstream") && endNode) {
resultSet = resultSet.add(nodes[endNode]).add(graphVizObject.linkedFrom(nodes[endNode], true));
}
} else {
if (mode === "bidirectional" || mode === "upstream") {
resultSet = resultSet.add(graphVizObject.linkedTo(el, true));
}
if (mode === "bidirectional" || mode === "downstream") {
resultSet = resultSet.add(graphVizObject.linkedFrom(el, true));
}
}
});
return resultSet;
}
// Function to reset the graph zoom and selection highlights
function resetGraph() {
graphviz.resetZoom();
graphVizObject.highlight(); // Reset node selection on reset
currentSelection = [];
}
// Function to update the graph rendering engine
function updateEngine(newEngine) {
selectedEngine = newEngine;
}
// Main function to render the graph from DOT source
function render(dotSource) {
var transition = d3.transition("graphTransition")
.ease(d3.easeLinear)
.delay(d3Config.transitionDelay)
.duration(d3Config.transitionDuration);
graphviz
.engine(selectedEngine)
.fade(true)
.transition(transition)
.tweenPaths(true)
.tweenShapes(true)
.zoomScaleExtent([0, Infinity])
.zoom(true)
.renderDot(dotSource)
.on("end", function () {
// Calls the jquery.graphviz.svg setup directly
$('#graph').data('graphviz.svg').setup(); // Re-setup after rendering
});
}
// Document ready function
$(document).ready(function () {
// Initialize the GraphVizSVG object from jquery.graphviz.svg.js
$("#graph").graphviz({
shrink: null,
zoom: false,
ready: function () {
graphVizObject = this;
// Event listener for node clicks to handle selection
graphVizObject.nodes().click(function (event) {
const nodeSet = $().add(this);
const selectionObject = {
set: nodeSet,
direction: selectedDirection
};
// If CMD, CTRL, or SHIFT is pressed, add to the selection
if (event.ctrlKey || event.metaKey || event.shiftKey) {
currentSelection.push(selectionObject);
} else {
currentSelection = [selectionObject];
}
highlightSelection();
});
// Event listener for pressing the escape key to cancel highlights
$(document).keydown(function (event) {
if (event.keyCode === 27) {
graphVizObject.highlight();
}
});
}
});
});
// As an example, we load the graph from a DOT source file from a URL:
var dotSource;
var url = "https://gist.githubusercontent.com/basnijholt/02e2ed6675a752e55f969ca42cb81460/raw/8adadcef38456a4a3e8894b3e171a0da61f7ff16/pipefunc-example.dot";
$.get(url, function (data) {
dotSource = data;
render(dotSource);
});
</script>
</body>
</html>