Skip to content

Commit 77e0704

Browse files
authored
Merge pull request #136 from neo4j/hover-nodes
Add hover effects for node IDs
2 parents 24e50b4 + 3df46ed commit 77e0704

File tree

7 files changed

+54
-5
lines changed

7 files changed

+54
-5
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ The package wraps the [Neo4j Visualization JavaScript library (NVL)](https://neo
3232
* Colors
3333
* Captions
3434
* Pinning
35+
* On hover tooltip
3536
* Relationship features:
3637
* Colors
3738
* Captions
39+
* On hover tooltip
3840
* Graph features:
3941
* Zooming
4042
* Panning

docs/source/rendering.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ It defaults to 10.000, because rendering a large number of nodes can be slow and
4545
However, you can increase this value if you are confident that your environment can handle the scale.
4646
In this case you might also want to pass ``Renderer.WEB_GL`` as the ``renderer`` to improve performance.
4747

48+
By default a tooltip will be shown when hovering over a node or relationship.
49+
But you can disable this by passing ``show_hover_tooltip=False``.
50+
4851

4952
Examples
5053
--------

js-applet/src/index.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { FreeLayoutType, NVL } from '@neo4j-nvl/base'
22
import type { Node, NvlOptions, Relationship } from '@neo4j-nvl/base'
3-
import { DragNodeInteraction, PanInteraction, ZoomInteraction } from '@neo4j-nvl/interaction-handlers'
3+
import { DragNodeInteraction, PanInteraction, ZoomInteraction, HoverInteraction } from '@neo4j-nvl/interaction-handlers'
44

55
class PyNVL {
66
nvl: NVL
@@ -11,8 +11,11 @@ class PyNVL {
1111

1212
dragNodeInteraction: DragNodeInteraction
1313

14+
hoverInteraction: HoverInteraction
15+
1416
constructor(
1517
frame: HTMLElement,
18+
tooltip: HTMLElement | null = null,
1619
nvlNodes: Node[] = [],
1720
nvlRels: Relationship[] = [],
1821
options: NvlOptions = {},
@@ -24,6 +27,30 @@ class PyNVL {
2427
this.panInteraction = new PanInteraction(this.nvl)
2528
this.dragNodeInteraction = new DragNodeInteraction(this.nvl)
2629

30+
if (tooltip !== null) {
31+
this.hoverInteraction = new HoverInteraction(this.nvl)
32+
33+
this.hoverInteraction.updateCallback('onHover', (element) => {
34+
if (element === undefined) {
35+
tooltip.textContent = "";
36+
if (tooltip.style.display === "block") {
37+
tooltip.style.display = "none";
38+
}
39+
} else if ("from" in element) {
40+
const rel = element as Relationship
41+
if (tooltip.style.display === "none") {
42+
tooltip.style.display = "block";
43+
}
44+
tooltip.setHTMLUnsafe(`<b>Source ID:</b> ${rel.from} </br><b>Target ID:</b> ${rel.to}`)
45+
} else if ("id" in element) {
46+
if (tooltip.style.display === "none") {
47+
tooltip.style.display = "block";
48+
}
49+
tooltip.setHTMLUnsafe(`<b>ID:</b> ${element.id}`)
50+
}
51+
})
52+
}
53+
2754
if (options.layout === FreeLayoutType) {
2855
this.nvl.setNodePositions(nvlNodes, false)
2956
}

python-wrapper/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ The package wraps the [Neo4j Visualization JavaScript library (NVL)](https://neo
3333
* Colors
3434
* Captions
3535
* Pinning
36+
* On hover tooltip
3637
* Relationship features:
3738
* Colors
3839
* Captions
40+
* On hover tooltip
3941
* Graph features:
4042
* Zooming
4143
* Panning

python-wrapper/src/neo4j_viz/nvl.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def render(
3535
render_options: RenderOptions,
3636
width: str,
3737
height: str,
38+
show_hover_tooltip: bool,
3839
) -> HTML:
3940
try:
4041
nodes_json = json.dumps([node.to_dict() for node in nodes])
@@ -46,19 +47,29 @@ def render(
4647
raise self.unsupported_field_type_error(e, "relationship")
4748

4849
render_options_json = json.dumps(render_options.to_dict())
49-
5050
container_id = str(uuid.uuid4())
51+
52+
if show_hover_tooltip:
53+
hover_element = f"document.getElementById('{container_id}-tooltip')"
54+
hover_div = f'<div id="{container_id}-tooltip" style="width: 20%; min-width: 100px; max-width: 600px; max-height: 80%; position: absolute; z-index: 2147483647; right: 0; bottom: 0; background: white; display: none; border: solid; border-color: #BBBEC3; border-width: 0.5px; padding: 0.8rem; border-radius: 8px; margin-bottom: 1rem; margin-right: 0.5rem; filter: drop-shadow(0 4px 8px rgba(26,27,29,0.12)); font-family: PublicSans; color: #4D5157; font-size: 14px"></div>'
55+
else:
56+
hover_element = "null"
57+
hover_div = ""
58+
5159
js_code = f"""
5260
var myNvl = new NVLBase.NVL(
5361
document.getElementById('{container_id}'),
62+
{hover_element},
5463
{nodes_json},
5564
{rels_json},
56-
{render_options_json}
65+
{render_options_json},
5766
);
5867
"""
5968
full_code = self.library_code + js_code
6069
html_output = f"""
61-
<div id="{container_id}" style="width: {width}; height: {height};"></div>
70+
<div id="{container_id}" style="width: {width}; height: {height}; position: relative;">
71+
{hover_div}
72+
</div>
6273
<script>
6374
{full_code}
6475
</script>

python-wrapper/src/neo4j_viz/resources/nvl_entrypoint/base.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

python-wrapper/src/neo4j_viz/visualization_graph.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def render(
5151
max_zoom: float = 10,
5252
allow_dynamic_min_zoom: bool = True,
5353
max_allowed_nodes: int = 10_000,
54+
show_hover_tooltip: bool = True,
5455
) -> HTML:
5556
"""
5657
Render the graph.
@@ -77,6 +78,8 @@ def render(
7778
Whether to allow dynamic minimum zoom level.
7879
max_allowed_nodes:
7980
The maximum allowed number of nodes to render.
81+
show_hover_tooltip:
82+
Whether to show an info tooltip when hovering over nodes and relationships.
8083
"""
8184

8285
num_nodes = len(self.nodes)
@@ -106,6 +109,7 @@ def render(
106109
render_options,
107110
width,
108111
height,
112+
show_hover_tooltip,
109113
)
110114

111115
def toggle_nodes_pinned(self, pinned: dict[NodeIdType, bool]) -> None:

0 commit comments

Comments
 (0)