Skip to content

Commit 1a67c38

Browse files
committed
Link aliases in entity node details to their node
When viewing the details of an entity node, the listed aliases are now links that, when clicked, select the relevant alias node. If that alias node is not wholly visible, the view is updated to centre on that node. The highlighting of the selected node has been adjusted to make it more obvious. The event listener for node selection is now on the "select" event rather than the "tap" event so that it fires when a node is selected through code.
1 parent f13af26 commit 1a67c38

1 file changed

Lines changed: 43 additions & 4 deletions

File tree

templates/graph.html

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,30 @@ <h2 id="sidebar-title">No node selected</h2>
2727

2828
const BASE_NODE_SIZE = 10;
2929

30+
function isNodeInViewport(node) {
31+
const nodeBoundingBox = node.renderedBoundingBox();
32+
const container = node.cy().container();
33+
34+
const viewportWidth = container.clientWidth;
35+
const viewportHeight = container.clientHeight;
36+
37+
return !(
38+
nodeBoundingBox.x1 < 0 ||
39+
nodeBoundingBox.x2 > viewportWidth ||
40+
nodeBoundingBox.y1 < 0 ||
41+
nodeBoundingBox.y2 > viewportHeight
42+
);
43+
}
44+
45+
function ensureNodeInView(node) {
46+
if (!isNodeInViewport(node)) {
47+
node.cy().animate({
48+
center: { eles: node },
49+
duration: 500
50+
});
51+
}
52+
}
53+
3054
function renderEntityDetails(node) {
3155
const data = node.data();
3256

@@ -43,9 +67,24 @@ <h2 id="sidebar-title">No node selected</h2>
4367
} else {
4468
const aliasList = aliasNodes.map(aliasNode => {
4569
const aliasLabel = aliasNode.data('label');
46-
return `<li>${escapeHtml(aliasLabel)}</li>`;
70+
return `<li><a href="#" data-alias-id="${aliasNode.id()}">${aliasLabel}</a></li>`;
4771
}).join('');
4872
details.innerHTML = `<ul>${aliasList}</ul>`;
73+
74+
document.querySelectorAll('#node-details li a[data-alias-id]').forEach(item => {
75+
item.addEventListener('click', (e) => {
76+
const aliasId = e.target.getAttribute('data-alias-id');
77+
if (aliasId) {
78+
const cy = node.cy();
79+
const aliasNode = cy.getElementById(aliasId);
80+
if (aliasNode.length > 0) {
81+
cy.elements().unselect();
82+
aliasNode.select();
83+
ensureNodeInView(aliasNode);
84+
}
85+
}
86+
});
87+
});
4988
}
5089
}
5190

@@ -169,8 +208,8 @@ <h2 id="sidebar-title">No node selected</h2>
169208
{
170209
selector: ':selected',
171210
style: {
172-
'border-width': 0.5,
173-
'border-color': '#10b981'
211+
'border-width': 1.5,
212+
'border-color': '#ffdd00'
174213
}
175214
}
176215
],
@@ -184,7 +223,7 @@ <h2 id="sidebar-title">No node selected</h2>
184223
}
185224
});
186225

187-
cy.on('tap', 'node', (event) => {
226+
cy.on('select', 'node', (event) => {
188227
renderNodeDetails(event.target);
189228
});
190229

0 commit comments

Comments
 (0)