vision/m4/sourcing/data_collection/visualization/assets/DOM_tree_viz.html (172 lines of code) (raw):

<!-- Adapted from https://gojs.net/latest/samples/DOMTree.html and https://gojs.net/latest/intro/tooltips.html--> <!DOCTYPE html> <body> <!-- * * * * * * * * * * * * * --> <!-- Start of GoJS sample code --> <script src="https://rawgit.com/NorthwoodsSoftware/GoJS/master/release/go.js"></script> <script id="code"> // Get the body tree of the html to display // Dirty trick from https://stackoverflow.com/questions/2522422/converting-a-javascript-string-to-a-html-object var body_html_string = `{{body_html}}`; var htmlObject = document.createElement('body'); htmlObject.innerHTML = body_html_string; var names = {}; // hash to keep track of what names have been used function init() { const $ = go.GraphObject.make; // for conciseness in defining templates myDiagram = $(go.Diagram, "myDiagramDiv", { initialAutoScale: go.Diagram.UniformToFill, // define the layout for the diagram layout: $(go.TreeLayout, { nodeSpacing: 5, layerSpacing: 30 }), "toolManager.hoverDelay": 10 }); // Define a simple node template consisting of text followed by an expand/collapse button myDiagram.nodeTemplate = $(go.Node, "Horizontal", { selectionChanged: nodeSelectionChanged }, // this event handler is defined below $(go.Panel, "Auto", $(go.Shape, { fill: "#1F4963", stroke: null }), $(go.TextBlock, { font: "bold 13px Helvetica, bold Arial, sans-serif", stroke: "white", margin: 3 }, new go.Binding("text", "key")), { toolTip: // define a tooltip for each node that displays the color as text $("ToolTip", $(go.TextBlock, { margin: 5, width: 250 }, new go.Binding("text", "", textInfo)) ) // end of Adornment } ), $("TreeExpanderButton") ); function formatString(string) { if (string == "") { return "∅" } else { if (string.length > 100) { return string.slice(0, 100-3) + "..." } else { return string } } } function textInfo(nodeData) { var text = formatString(nodeData.text) var textWithChildren = formatString(nodeData.textWithChildren) return "TAG: " + nodeData.tag + "\n\n-------------------------" + "\n\nTEXT:\n" + text + "\n\n-------------------------" + "\n\nTEXT (INCLUDING CHILDREN):\n" + textWithChildren + "\n\n-------------------------" + "\n\nNODE ATTRIBUTES:\n" + JSON.stringify(nodeData.attributes) } // Define a trivial link template with no arrowhead. myDiagram.linkTemplate = $(go.Link, { selectable: false }, $(go.Shape)); // the link shape // create the model for the DOM tree myDiagram.model = new go.TreeModel( { isReadOnly: true, // don't allow the user to delete or copy nodes // build up the tree in an Array of node data nodeDataArray: traverseDom(htmlObject) }); myDiagram.div.style.height = "450px"; } // Walk the DOM, starting at document, and return an Array of node data objects representing the DOM tree // Typical usage: traverseDom(document.activeElement) // The second and third arguments are internal, used when recursing through the DOM function traverseDom(node, parentName, dataArray) { if (parentName === undefined) parentName = null; if (dataArray === undefined) dataArray = []; // skip everything but HTML Elements if (!(node instanceof Element)) return; // Ignore the navigation menus if (node.id === "navSide" || node.id === "navTop") return; // add this node to the nodeDataArray var name = getName(node); var tag = node.nodeName; var text = getText(node); var textWithChildren = getTextWithChildren(node); var attributes = getAttributes(node); var data = { key: name, name: name, tag: tag, text: text, textWithChildren: textWithChildren, attributes: attributes, }; dataArray.push(data); // add a link to its parent if (parentName !== null) { data.parent = parentName; } // find all children var l = node.childNodes.length; for (var i = 0; i < l; i++) { traverseDom(node.childNodes[i], name, dataArray); } return dataArray; } // Give every node a unique name function getName(node) { var n = node.nodeName; if (node.id) n = n + " (id: " + node.id + ")"; var namenum = n; // make sure the name is unique var i = 1; while (names[namenum] !== undefined) { namenum = n + i; i++; } names[namenum] = node; return namenum; } // Extract text from every node function getTextWithChildren(node) { var textContent = node.textContent return textContent.trim() } function getText(node) { var text = ""; for (var i=0; i < node.childNodes.length; ++i) { if (node.childNodes[i].nodeType == Node.TEXT_NODE) { text += node.childNodes[i].textContent; } } return text.trim() } // Extract dictionary of attributes function getAttributes(node) { var dict = {}; var attrs = node.attributes; for (var i=0; i<attrs.length; i++) { dict[attrs[i].name] = attrs[i].value; } return dict } // When a Node is selected, highlight the corresponding HTML element. function nodeSelectionChanged(node) { if (node.isSelected) { names[node.data.name].style.backgroundColor = "lightblue"; } else { names[node.data.name].style.backgroundColor = ""; } } window.addEventListener('DOMContentLoaded', init); </script> <div id="sample"> <!-- The DIV needs an explicit size or else we won't see anything. --> <div id="myDiagramDiv" style="border: 1px solid black; width: 100%; height: 300px; position: relative; -webkit-tap-highlight-color: rgba(255, 255, 255, 0);"> <canvas tabindex="0" width="2108" height="574" style="position: absolute; top: 0px; left: 0px; z-index: 2; user-select: none; touch-action: none; width: 1054px; height: 287px;">This text is displayed if your browser does not support the Canvas HTML element.</canvas> <div style="position: absolute; overflow: auto; width: 1054px; height: 298px; z-index: 1;"> <div style="position: absolute; width: 1220.02px; height: 1px;"> </div> </div> </div> </div> <!-- * * * * * * * * * * * * * --> <!-- End of GoJS sample code --> </body> </html>