var dotSourceList = {{ dot_source_list|tojson }}; var state = { transitionDelay: 0, index: 0, playing: false, } var controls = { index: null, buttons: { next: null, prev: null, toggle: null, }, slider: null, } var graph = null; ///////////// // Helpers // ///////////// // From https://stackoverflow.com/a/37623959/1931274 function onRangeChange(r, f) { var n, c, m; r.addEventListener("input", function (e) { n = 1; c = e.target.value; if (c != m) { f(e); }; m = c; }); r.addEventListener("change", function (e) { if (!n) { f(e); }}); } ////////////// // UI Logic // ////////////// function setupControls() { controls.index = document.getElementById("index"); controls.buttons.next = document.getElementById("next"); controls.buttons.next.onclick = showNext; controls.buttons.prev = document.getElementById("prev"); controls.buttons.prev.onclick = showPrevious; controls.buttons.toggle = document.getElementById("toggle"); controls.buttons.toggle.onclick = toggle; controls.slider = document.getElementById("slider"); controls.slider.setAttribute("max", dotSourceList.length - 1); onRangeChange(controls.slider, showSliderState); } function updateControls() { controls.slider.value = state.index; controls.index.innerHTML = state.index; if (state.playing) { controls.buttons.toggle.innerHTML = "Pause"; } else { controls.buttons.toggle.innerHTML = "Play"; } } ////////////////// // UI callbacks // ////////////////// function toggle() { console.log("toggle"); state.playing = !state.playing; showThisGraph(); } function showNext() { console.log("next"); state.playing = false; if (state.index < dotSourceList.length - 1) { state.index = state.index + 1; } showThisGraph(); } function showPrevious() { console.log("previous"); state.playing = false; if (state.index != 0) { state.index = state.index - 1; } showThisGraph(); } function showSliderState() { console.log("slider"); var value = Number(controls.slider.value); state.index = value; state.playing = false; showThisGraph(); } /////////////// // Rendering // /////////////// function prepareGraph() { graph = d3.select("#graph").graphviz(); graph .zoom(false) .transition(function () { return d3.transition("main") .ease(d3.easeExpOut) .duration(500) // .delay(state.transitionDelay); }) .on("initEnd", showThisGraph); } function showThisGraph() { updateControls(); var dotSource = dotSourceList[state.index]; return graph .renderDot(dotSource) // The following sets up the "play" mode. .on("end", continueIfPlaying); } function continueIfPlaying() { if (!state.playing) { return } state.index = (state.index + 1) % dotSourceList.length; showThisGraph(); } ///////////////// // Entry Point // ///////////////// function main() { setupControls(); prepareGraph(); } document.addEventListener("DOMContentLoaded", main);