Skip to content

Commit 02ae0c9

Browse files
committed
feat: Create "meta-node" to avoid unconnected nodes in graph
1 parent 16a15cf commit 02ae0c9

File tree

3 files changed

+43
-10
lines changed

3 files changed

+43
-10
lines changed

assets/cy-style.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@
2121
"edge-text-rotation": "autorotate"
2222
}
2323
},
24+
{
25+
"selector": ".meta",
26+
"style": {
27+
"background-color": "#fff",
28+
"font-style": "italic",
29+
"shape": "hexagon",
30+
"border-width": "3px"
31+
}
32+
},
2433
{
2534
"selector": ".standard",
2635
"style": {

graph.js

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ var elements = [];
22
var cy;
33
var cy_layout;
44
var removed = [];
5+
var meta_node;
6+
var meta_node_edges;
57

68
function selectionChanged() {
79
removed.toReversed().forEach(eles => eles.restore());
@@ -28,9 +30,6 @@ function selectionChanged() {
2830
}
2931

3032
function layoutNodes() {
31-
unconnected = cy.filter(function(element, i) {
32-
return element.isNode() && element.connectedEdges().length == 0
33-
}).remove();
3433
cy_layout = cy.layout({
3534
name: "cola",
3635
animate: "end",
@@ -39,7 +38,6 @@ function layoutNodes() {
3938
nodeDimensionsIncludeLabels: true,
4039
centerGraph: false,
4140
});
42-
unconnected.forEach((eles, i) => {eles.restore(); eles.position("x", 250); eles.position("y", 200 + i*50);});
4341
cy_layout.run();
4442
}
4543

@@ -91,6 +89,12 @@ function urlButton(type, url) {
9189
}
9290

9391
function highlightNode(node) {
92+
if (node.id() == "simulators") {
93+
return;
94+
}
95+
// Ignore the meta node
96+
meta_node.deselect();
97+
meta_node.remove();
9498
// change opacity if node or edge is not connected to the clicked node
9599
const nhood = node.closedNeighbourhood();
96100
const connectedEdges = node.connectedEdges();
@@ -123,9 +127,13 @@ function highlightNode(node) {
123127
}
124128

125129
function showNodeDetails(node) {
126-
showDetails(node.data(), node.outgoers("edge").map((edge) => {
127-
return {target: edge.target().id(), label: edge.data("label"), source: edge.source().id()};
128-
}));
130+
if (node.id() == "simulators") {
131+
showDetails(null, null);
132+
} else {
133+
showDetails(node.data(), node.outgoers("edge").map((edge) => {
134+
return {target: edge.target().id(), label: edge.data("label"), source: edge.source().id()};
135+
}));
136+
}
129137
}
130138

131139
function highlightEdge(edge) {
@@ -188,6 +196,10 @@ function highlightElement(event) {
188196
}
189197

190198
function unhighlightNode(event) {
199+
// Ignore the meta node
200+
meta_node.restore();
201+
meta_node_edges.restore();
202+
// Re-add the edges
191203
cy.elements().forEach(n => n.style("opacity", 1));
192204
showDetails(null, null);
193205
}
@@ -222,9 +234,14 @@ function newEdge(name, relation) {
222234
}
223235

224236
function create_cy_elements(data, style) {
225-
console.log("Creating", data);
237+
// Create a "meta-node" for all simulators
238+
elements.push(newNode("simulators", {full_name: "Simulators", features: "meta"}));
226239
for (const [name, description] of Object.entries(data)) {
227240
elements.push(newNode(name, description));
241+
// Connect all simulators to the meta node
242+
if (description["features"].includes("simulator")) {
243+
elements.push(newEdge("simulators", {name: name, description: "simulator"}));
244+
}
228245
if (description["relations"] !== undefined) {
229246
for (let relation of description["relations"]){
230247
if (relation["description"] === undefined)
@@ -239,7 +256,11 @@ function create_cy_elements(data, style) {
239256
layout: { name: 'random' },
240257
style: style
241258
});
259+
// store the meta_node, since we need to remove it when highlighting nodes
260+
meta_node = cy.$("#simulators");
261+
meta_node_edges = meta_node.connectedEdges();
242262
cy.on("select tap dbltap", "*", highlightElement);
243263
cy.on("unselect", "*", unhighlightNode);
264+
cy.$("#simulators").select();
244265
selectionChanged();
245266
}

index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ const selected = [];
44

55
// If params are null, show a default message
66
function showDetails(data, outgoers) {
7-
console.log("showDetails called")
87
// Show details about the simulator
98
const details = document.getElementById("details");
109
// Basic description
@@ -62,7 +61,11 @@ function showDetails(data, outgoers) {
6261

6362
const url = new URL(window.location.href);
6463
const params = new URLSearchParams(url.search);
65-
params.set('selected', data["full_name"]);
64+
if (data === null)
65+
params.delete('selected');
66+
else {
67+
params.set('selected', data["full_name"]);
68+
}
6669
url.search = params.toString();
6770
window.history.pushState({}, "", url);
6871
}

0 commit comments

Comments
 (0)