diff --git a/README.md b/README.md index 7ad77c8a..9958a2ee 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,11 @@ The package wraps the [Neo4j Visualization JavaScript library (NVL)](https://neo * Colors * Captions * Pinning + * On hover tooltip * Relationship features: * Colors * Captions + * On hover tooltip * Graph features: * Zooming * Panning diff --git a/docs/source/rendering.rst b/docs/source/rendering.rst index 1694d933..5ecb3ff5 100644 --- a/docs/source/rendering.rst +++ b/docs/source/rendering.rst @@ -45,6 +45,9 @@ It defaults to 10.000, because rendering a large number of nodes can be slow and However, you can increase this value if you are confident that your environment can handle the scale. In this case you might also want to pass ``Renderer.WEB_GL`` as the ``renderer`` to improve performance. +By default a tooltip will be shown when hovering over a node or relationship. +But you can disable this by passing ``show_hover_tooltip=False``. + Examples -------- diff --git a/js-applet/src/index.ts b/js-applet/src/index.ts index 7732635f..16546e57 100644 --- a/js-applet/src/index.ts +++ b/js-applet/src/index.ts @@ -1,6 +1,6 @@ import { FreeLayoutType, NVL } from '@neo4j-nvl/base' import type { Node, NvlOptions, Relationship } from '@neo4j-nvl/base' -import { DragNodeInteraction, PanInteraction, ZoomInteraction } from '@neo4j-nvl/interaction-handlers' +import { DragNodeInteraction, PanInteraction, ZoomInteraction, HoverInteraction } from '@neo4j-nvl/interaction-handlers' class PyNVL { nvl: NVL @@ -11,8 +11,11 @@ class PyNVL { dragNodeInteraction: DragNodeInteraction + hoverInteraction: HoverInteraction + constructor( frame: HTMLElement, + tooltip: HTMLElement | null = null, nvlNodes: Node[] = [], nvlRels: Relationship[] = [], options: NvlOptions = {}, @@ -24,6 +27,30 @@ class PyNVL { this.panInteraction = new PanInteraction(this.nvl) this.dragNodeInteraction = new DragNodeInteraction(this.nvl) + if (tooltip !== null) { + this.hoverInteraction = new HoverInteraction(this.nvl) + + this.hoverInteraction.updateCallback('onHover', (element) => { + if (element === undefined) { + tooltip.textContent = ""; + if (tooltip.style.display === "block") { + tooltip.style.display = "none"; + } + } else if ("from" in element) { + const rel = element as Relationship + if (tooltip.style.display === "none") { + tooltip.style.display = "block"; + } + tooltip.setHTMLUnsafe(`Source ID: ${rel.from} Target ID: ${rel.to}`) + } else if ("id" in element) { + if (tooltip.style.display === "none") { + tooltip.style.display = "block"; + } + tooltip.setHTMLUnsafe(`ID: ${element.id}`) + } + }) + } + if (options.layout === FreeLayoutType) { this.nvl.setNodePositions(nvlNodes, false) } diff --git a/python-wrapper/README.md b/python-wrapper/README.md index ee0bde70..1df0ad38 100644 --- a/python-wrapper/README.md +++ b/python-wrapper/README.md @@ -33,9 +33,11 @@ The package wraps the [Neo4j Visualization JavaScript library (NVL)](https://neo * Colors * Captions * Pinning + * On hover tooltip * Relationship features: * Colors * Captions + * On hover tooltip * Graph features: * Zooming * Panning diff --git a/python-wrapper/src/neo4j_viz/nvl.py b/python-wrapper/src/neo4j_viz/nvl.py index bde5340e..ca1a0f5f 100644 --- a/python-wrapper/src/neo4j_viz/nvl.py +++ b/python-wrapper/src/neo4j_viz/nvl.py @@ -35,6 +35,7 @@ def render( render_options: RenderOptions, width: str, height: str, + show_hover_tooltip: bool, ) -> HTML: try: nodes_json = json.dumps([node.to_dict() for node in nodes]) @@ -46,19 +47,29 @@ def render( raise self.unsupported_field_type_error(e, "relationship") render_options_json = json.dumps(render_options.to_dict()) - container_id = str(uuid.uuid4()) + + if show_hover_tooltip: + hover_element = f"document.getElementById('{container_id}-tooltip')" + hover_div = f'
' + else: + hover_element = "null" + hover_div = "" + js_code = f""" var myNvl = new NVLBase.NVL( document.getElementById('{container_id}'), + {hover_element}, {nodes_json}, {rels_json}, - {render_options_json} + {render_options_json}, ); """ full_code = self.library_code + js_code html_output = f""" - +0;)p--}0===a(n[o],h)?t(n,o,p):t(n,++p,i),p<=r&&(o=p+1),r<=p&&(i=p-1)}}(e,r,o||0,i||e.length-1,a||n)}function t(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function n(e,t){return e u?(e-o)*(e-o)+(t-i)*(t-i):l-f},cn=function(e,t,n){for(var r,o,i,a,s=0,u=0;u{e.exports=function(e,t,n){for(var r=n-1,o=e.length;++r0;){for(var T=t.pop(),P=0;P