-
Notifications
You must be signed in to change notification settings - Fork 4
[RFC] Add a search box #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,6 +96,11 @@ | |
| Node sizes indicate the number of declarations in the file.</p> | ||
|
|
||
| <label><input type="checkbox" id="pause" checked/> Pause graph layout</label> | ||
| <div id="search"> | ||
| <input type="search" id="search-input" list="suggestions" placeholder="Try searching for a node..."> | ||
| <datalist id="suggestions"><option value="Myriel"></option> | ||
| </datalist> | ||
| </div> | ||
| </div> | ||
| <div class="key-wrapper"> | ||
| <ul id="key"></ul> | ||
|
|
@@ -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=>"<option value=\"".concat(graph.getNodeAttribute(node, "label"), "\"></option>")).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) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic doesn't work for |
||
| state.selectedNode = suggestions[0].id; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you merge |
||
| 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) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should sort these alphabetically