diff --git a/index.html b/index.html index a3cc64d..963d43e 100644 --- a/index.html +++ b/index.html @@ -96,6 +96,11 @@ Node sizes indicate the number of declarations in the file.

+
@@ -161,9 +166,12 @@ let pause = document.getElementById('pause'); let graph = graphologyLibrary.gexf.parse(graphology.Graph, gexf); let rev_graph = graphologyLibrary.operators.reverse(graph); + let searchInput = document.getElementById("search-input"); + let searchSuggestions = document.getElementById("suggestions"); // interaction state var state = { + searchQuery: "", hoveredNode: undefined, hoveredDescendants: undefined, hoveredPath: undefined, @@ -289,14 +297,15 @@ node_data.y = 0.1*r * Math.sin(theta * 2 * Math.PI); } - var force_atlas_settings = { - barnesHutOptimize: false, - strongGravityMode: false, - gravity: 0.05, - scalingRatio: 10, - slowDown: 10, - edgeWeightInfluence: 1, - }; + var force_atlas_settings =graphologyLibrary.layoutForceAtlas2.inferSettings(graph); + +// barnesHutOptimize: false, +// strongGravityMode: false, +// gravity: 0.05, +// scalingRatio: 10, +// slowDown: 10, +// edgeWeightInfluence: 1, +// }; // run the optimizer a little graphologyLibrary.layoutForceAtlas2.assign(graph, { @@ -395,6 +404,60 @@ }, }); + // Feed the datalist autocomplete values: + + searchSuggestions.innerHTML = graph.nodes().map(node=>"")).join("\n"); + // Actions: + + function setSearchQuery(query) { + state.searchQuery = query; + if (searchInput.value !== query) + searchInput.value = query; + + if (query) { + const lcQuery = query.toLowerCase(); + const suggestions = graph.nodes().map(n=>({ + id: n, + label: graph.getNodeAttribute(n, "label") + })).filter(({label})=>label.toLowerCase().includes(lcQuery)); + // If we have a single perfect match, them we remove the suggestions, and + // we consider the user has selected a node through the datalist + // autocomplete: + + if (suggestions.length === 1 && suggestions[0].label === query) { + state.selectedNode = suggestions[0].id; + state.suggestions = undefined; + // Move the camera to center it on the selected node: + + const nodePosition = renderer.getNodeDisplayData(state.selectedNode); + renderer.getCamera().animate(nodePosition, { + duration: 500 + }); + }// Else, we display the suggestions list: + else { + state.selectedNode = undefined; + state.suggestions = new Set(suggestions.map(({id})=>id)); + } + }// If the query is empty, then we reset the selectedNode / suggestions state: + else { + state.selectedNode = undefined; + state.suggestions = undefined; + } + // Refresh rendering: + + renderer.refresh(); + } + + searchInput.addEventListener("input", ()=>{ + setSearchQuery(searchInput.value || ""); + } + ); + searchInput.addEventListener("blur", ()=>{ + setSearchQuery(""); + } + ); + + let statusElem = document.getElementById('statusWrapper'); let statusMsgElem = document.getElementById('statusMessage'); let setStatus = function(html) {