From 90adc2f9690863325bd1df0f6caf1683450ff59f Mon Sep 17 00:00:00 2001 From: wimrijnders Date: Thu, 20 Jul 2017 23:07:47 +0200 Subject: [PATCH] Network: Add pointer data to hover events (#3128) Fix for #1222. This makes the passed data of events `hoverNode`, `hoverEdge`, `blurNode` and `blurEdge` more conformant to the passed data of the click events. In particular, the following fields are added to the event data: ``` event: [Object] original hover event, pointer: { DOM: {x:pointer_x, y:pointer_y}, canvas: {x:canvas_x, y:canvas_y} } ``` The changes can be tested with example `network/events/InteractionEvents`. --- lib/network/modules/InteractionHandler.js | 11 +- lib/network/modules/SelectionHandler.js | 122 ++++++++++++++++------ 2 files changed, 94 insertions(+), 39 deletions(-) diff --git a/lib/network/modules/InteractionHandler.js b/lib/network/modules/InteractionHandler.js index 663608cd..e3b66490 100644 --- a/lib/network/modules/InteractionHandler.js +++ b/lib/network/modules/InteractionHandler.js @@ -552,16 +552,9 @@ class InteractionHandler { } } - /** - * Adding hover highlights - */ + // adding hover highlights if (this.options.hover === true) { - // adding hover highlights - let obj = this.selectionHandler.getNodeAt(pointer); - if (obj === undefined) { - obj = this.selectionHandler.getEdgeAt(pointer); - } - this.selectionHandler.hoverObject(obj); + this.selectionHandler.hoverObject(event, pointer); } } diff --git a/lib/network/modules/SelectionHandler.js b/lib/network/modules/SelectionHandler.js index 56768e29..cabf101f 100644 --- a/lib/network/modules/SelectionHandler.js +++ b/lib/network/modules/SelectionHandler.js @@ -75,20 +75,52 @@ class SelectionHandler { return selectionChanged; } - _generateClickEvent(eventType, event, pointer, oldSelection, emptySelection = false) { - let properties; - if (emptySelection === true) { - properties = {nodes:[], edges:[]}; - } - else { - properties = this.getSelection(); - } + + /** + * Create an object containing the standard fields for an event. + * + * @param {Event} event + * @param {Object} pointer | object with the x and y screen coordinates of the mouse + * @private + */ + _initBaseEvent(event, pointer) { + let properties = {}; + properties['pointer'] = { DOM: {x: pointer.x, y: pointer.y}, canvas: this.canvas.DOMtoCanvas(pointer) }; properties['event'] = event; + return properties; + } + + + /** + * Generate an event which the user can catch. + * + * This adds some extra data to the event with respect to cursor position and + * selected nodes and edges. + * + * @param {String} eventType | Name of event to send + * @param {Event} event + * @param {Object} pointer | object with the x and y screen coordinates of the mouse + * @param {Object|undefined} object | If present, selection state before event occured + * @param {boolean|undefined} | Indicate if selection data should be passed + */ + _generateClickEvent(eventType, event, pointer, oldSelection, emptySelection = false) { + let properties = this._initBaseEvent(event, pointer); + + if (emptySelection === true) { + properties.nodes = []; + properties.edges = []; + } + else { + let tmp = this.getSelection(); + properties.nodes = tmp.nodes; + properties.edges = tmp.edges; + } + if (oldSelection !== undefined) { properties['previousSelection'] = oldSelection; } @@ -486,38 +518,78 @@ class SelectionHandler { /** - * This is called when someone clicks on a node. either select or deselect it. - * If there is an existing selection and we don't want to append to it, clear the existing selection + * Remove the highlight from a node or edge, in response to mouse movement * + * @param {Event} event + * @param {Object} pointer | object with the x and y screen coordinates of the mouse * @param {Node || Edge} object * @private */ - blurObject(object) { + emitBlurEvent(event, pointer, object) { + let properties = this._initBaseEvent(event, pointer); + if (object.hover === true) { object.hover = false; if (object instanceof Node) { - this.body.emitter.emit("blurNode", {node: object.id}); + properties.node = object.id; + this.body.emitter.emit("blurNode", properties); } else { - this.body.emitter.emit("blurEdge", {edge: object.id}); + properties.edge = object.id; + this.body.emitter.emit("blurEdge", properties); } } } + /** - * This is called when someone clicks on a node. either select or deselect it. - * If there is an existing selection and we don't want to append to it, clear the existing selection + * Create the highlight for a node or edge, in response to mouse movement * + * @param {Event} event + * @param {Object} pointer | object with the x and y screen coordinates of the mouse * @param {Node || Edge} object * @private */ - hoverObject(object) { + emitHoverEvent(event, pointer, object) { + let properties = this._initBaseEvent(event, pointer); + let hoverChanged = false; + + if (object.hover === false) { + object.hover = true; + this._addToHover(object); + hoverChanged = true; + if (object instanceof Node) { + properties.node = object.id; + this.body.emitter.emit("hoverNode", properties); + } + else { + properties.edge = object.id; + this.body.emitter.emit("hoverEdge", properties); + } + } + + return hoverChanged; + } + + + /** + * Perform actions in response to a mouse movement. + * + * @param {Event} event + * @param {Object} pointer | object with the x and y screen coordinates of the mouse + */ + hoverObject(event, pointer) { + let object = this.getNodeAt(pointer); + if (object === undefined) { + object = this.getEdgeAt(pointer); + } + let hoverChanged = false; // remove all node hover highlights for (let nodeId in this.hoverObj.nodes) { if (this.hoverObj.nodes.hasOwnProperty(nodeId)) { if (object === undefined || (object instanceof Node && object.id != nodeId) || object instanceof Edge) { - this.blurObject(this.hoverObj.nodes[nodeId]); + this.emitBlurEvent(event, pointer, this.hoverObj.nodes[nodeId]); delete this.hoverObj.nodes[nodeId]; hoverChanged = true; } @@ -528,7 +600,7 @@ class SelectionHandler { for (let edgeId in this.hoverObj.edges) { if (this.hoverObj.edges.hasOwnProperty(edgeId)) { // if the hover has been changed here it means that the node has been hovered over or off - // we then do not use the blurObject method here. + // we then do not use the emitBlurEvent method here. if (hoverChanged === true) { this.hoverObj.edges[edgeId].hover = false; delete this.hoverObj.edges[edgeId]; @@ -536,7 +608,7 @@ class SelectionHandler { // if the blur remains the same and the object is undefined (mouse off) or another // edge has been hovered, or another node has been hovered we blur the edge. else if (object === undefined || (object instanceof Edge && object.id != edgeId) || (object instanceof Node && !object.hover)) { - this.blurObject(this.hoverObj.edges[edgeId]); + this.emitBlurEvent(event, pointer, this.hoverObj.edges[edgeId]); delete this.hoverObj.edges[edgeId]; hoverChanged = true; } @@ -544,17 +616,7 @@ class SelectionHandler { } if (object !== undefined) { - if (object.hover === false) { - object.hover = true; - this._addToHover(object); - hoverChanged = true; - if (object instanceof Node) { - this.body.emitter.emit("hoverNode", {node: object.id}); - } - else { - this.body.emitter.emit("hoverEdge", {edge: object.id}); - } - } + hoverChanged = hoverChanged || this.emitHoverEvent(event, pointer, object); if (object instanceof Node && this.options.hoverConnectedEdges === true) { this._hoverConnectedEdges(object); }