|
|
- var Node = require('../Node');
-
- /**
- *
- * @param object
- * @param overlappingNodes
- * @private
- */
- exports._getNodesOverlappingWith = function(object, overlappingNodes) {
- var nodes = this.body.nodes;
- for (var nodeId in nodes) {
- if (nodes.hasOwnProperty(nodeId)) {
- if (nodes[nodeId].isOverlappingWith(object)) {
- overlappingNodes.push(nodeId);
- }
- }
- }
- };
-
- /**
- * retrieve all nodes overlapping with given object
- * @param {Object} object An object with parameters left, top, right, bottom
- * @return {Number[]} An array with id's of the overlapping nodes
- * @private
- */
- exports._getAllNodesOverlappingWith = function (object) {
- var overlappingNodes = [];
- this._getNodesOverlappingWith(object,overlappingNodes);
- return overlappingNodes;
- };
-
-
- /**
- * Return a position object in canvasspace from a single point in screenspace
- *
- * @param pointer
- * @returns {{left: number, top: number, right: number, bottom: number}}
- * @private
- */
- exports._pointerToPositionObject = function(pointer) {
- var x = this._XconvertDOMtoCanvas(pointer.x);
- var y = this._YconvertDOMtoCanvas(pointer.y);
-
- return {
- left: x,
- top: y,
- right: x,
- bottom: y
- };
- };
-
-
- /**
- * Get the top node at the a specific point (like a click)
- *
- * @param {{x: Number, y: Number}} pointer
- * @return {Node | null} node
- * @private
- */
- exports._getNodeAt = function (pointer) {
- // we first check if this is an navigation controls element
- var positionObject = this._pointerToPositionObject(pointer);
- var overlappingNodes = this._getAllNodesOverlappingWith(positionObject);
-
- // if there are overlapping nodes, select the last one, this is the
- // one which is drawn on top of the others
- if (overlappingNodes.length > 0) {
- return this.body.nodes[overlappingNodes[overlappingNodes.length - 1]];
- }
- else {
- return null;
- }
- };
-
-
- /**
- * retrieve all edges overlapping with given object, selector is around center
- * @param {Object} object An object with parameters left, top, right, bottom
- * @return {Number[]} An array with id's of the overlapping nodes
- * @private
- */
- exports._getEdgesOverlappingWith = function (object, overlappingEdges) {
- var edges = this.body.edges;
- for (var edgeId in edges) {
- if (edges.hasOwnProperty(edgeId)) {
- if (edges[edgeId].isOverlappingWith(object)) {
- overlappingEdges.push(edgeId);
- }
- }
- }
- };
-
-
- /**
- * retrieve all nodes overlapping with given object
- * @param {Object} object An object with parameters left, top, right, bottom
- * @return {Number[]} An array with id's of the overlapping nodes
- * @private
- */
- exports._getAllEdgesOverlappingWith = function (object) {
- var overlappingEdges = [];
- this._getEdgesOverlappingWith(object,overlappingEdges);
- return overlappingEdges;
- };
-
- /**
- * Place holder. To implement change the getNodeAt to a _getObjectAt. Have the _getObjectAt call
- * getNodeAt and _getEdgesAt, then priortize the selection to user preferences.
- *
- * @param pointer
- * @returns {null}
- * @private
- */
- exports._getEdgeAt = function(pointer) {
- var positionObject = this._pointerToPositionObject(pointer);
- var overlappingEdges = this._getAllEdgesOverlappingWith(positionObject);
-
- if (overlappingEdges.length > 0) {
- return this.body.edges[overlappingEdges[overlappingEdges.length - 1]];
- }
- else {
- return null;
- }
- };
-
-
- /**
- * Add object to the selection array.
- *
- * @param obj
- * @private
- */
- exports._addToSelection = function(obj) {
- if (obj instanceof Node) {
- this.selectionObj.nodes[obj.id] = obj;
- }
- else {
- this.selectionObj.edges[obj.id] = obj;
- }
- };
-
- /**
- * Add object to the selection array.
- *
- * @param obj
- * @private
- */
- exports._addToHover = function(obj) {
- if (obj instanceof Node) {
- this.hoverObj.nodes[obj.id] = obj;
- }
- else {
- this.hoverObj.edges[obj.id] = obj;
- }
- };
-
-
- /**
- * Remove a single option from selection.
- *
- * @param {Object} obj
- * @private
- */
- exports._removeFromSelection = function(obj) {
- if (obj instanceof Node) {
- delete this.selectionObj.nodes[obj.id];
- }
- else {
- delete this.selectionObj.edges[obj.id];
- }
- };
-
- /**
- * Unselect all. The selectionObj is useful for this.
- *
- * @param {Boolean} [doNotTrigger] | ignore trigger
- * @private
- */
- exports._unselectAll = function(doNotTrigger) {
- if (doNotTrigger === undefined) {
- doNotTrigger = false;
- }
- for(var nodeId in this.selectionObj.nodes) {
- if(this.selectionObj.nodes.hasOwnProperty(nodeId)) {
- this.selectionObj.nodes[nodeId].unselect();
- }
- }
- for(var edgeId in this.selectionObj.edges) {
- if(this.selectionObj.edges.hasOwnProperty(edgeId)) {
- this.selectionObj.edges[edgeId].unselect();
- }
- }
-
- this.selectionObj = {nodes:{},edges:{}};
-
- if (doNotTrigger == false) {
- this.emit('select', this.getSelection());
- }
- };
-
- /**
- * Unselect all clusters. The selectionObj is useful for this.
- *
- * @param {Boolean} [doNotTrigger] | ignore trigger
- * @private
- */
- exports._unselectClusters = function(doNotTrigger) {
- if (doNotTrigger === undefined) {
- doNotTrigger = false;
- }
-
- for (var nodeId in this.selectionObj.nodes) {
- if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
- if (this.selectionObj.nodes[nodeId].clusterSize > 1) {
- this.selectionObj.nodes[nodeId].unselect();
- this._removeFromSelection(this.selectionObj.nodes[nodeId]);
- }
- }
- }
-
- if (doNotTrigger == false) {
- this.emit('select', this.getSelection());
- }
- };
-
-
- /**
- * return the number of selected nodes
- *
- * @returns {number}
- * @private
- */
- exports._getSelectedNodeCount = function() {
- var count = 0;
- for (var nodeId in this.selectionObj.nodes) {
- if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
- count += 1;
- }
- }
- return count;
- };
-
- /**
- * return the selected node
- *
- * @returns {number}
- * @private
- */
- exports._getSelectedNode = function() {
- for (var nodeId in this.selectionObj.nodes) {
- if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
- return this.selectionObj.nodes[nodeId];
- }
- }
- return null;
- };
-
- /**
- * return the selected edge
- *
- * @returns {number}
- * @private
- */
- exports._getSelectedEdge = function() {
- for (var edgeId in this.selectionObj.edges) {
- if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
- return this.selectionObj.edges[edgeId];
- }
- }
- return null;
- };
-
-
- /**
- * return the number of selected edges
- *
- * @returns {number}
- * @private
- */
- exports._getSelectedEdgeCount = function() {
- var count = 0;
- for (var edgeId in this.selectionObj.edges) {
- if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
- count += 1;
- }
- }
- return count;
- };
-
-
- /**
- * return the number of selected objects.
- *
- * @returns {number}
- * @private
- */
- exports._getSelectedObjectCount = function() {
- var count = 0;
- for(var nodeId in this.selectionObj.nodes) {
- if(this.selectionObj.nodes.hasOwnProperty(nodeId)) {
- count += 1;
- }
- }
- for(var edgeId in this.selectionObj.edges) {
- if(this.selectionObj.edges.hasOwnProperty(edgeId)) {
- count += 1;
- }
- }
- return count;
- };
-
- /**
- * Check if anything is selected
- *
- * @returns {boolean}
- * @private
- */
- exports._selectionIsEmpty = function() {
- for(var nodeId in this.selectionObj.nodes) {
- if(this.selectionObj.nodes.hasOwnProperty(nodeId)) {
- return false;
- }
- }
- for(var edgeId in this.selectionObj.edges) {
- if(this.selectionObj.edges.hasOwnProperty(edgeId)) {
- return false;
- }
- }
- return true;
- };
-
-
- /**
- * check if one of the selected nodes is a cluster.
- *
- * @returns {boolean}
- * @private
- */
- exports._clusterInSelection = function() {
- for(var nodeId in this.selectionObj.nodes) {
- if(this.selectionObj.nodes.hasOwnProperty(nodeId)) {
- if (this.selectionObj.nodes[nodeId].clusterSize > 1) {
- return true;
- }
- }
- }
- return false;
- };
-
- /**
- * select the edges connected to the node that is being selected
- *
- * @param {Node} node
- * @private
- */
- exports._selectConnectedEdges = function(node) {
- for (var i = 0; i < node.edges.length; i++) {
- var edge = node.edges[i];
- edge.select();
- this._addToSelection(edge);
- }
- };
-
- /**
- * select the edges connected to the node that is being selected
- *
- * @param {Node} node
- * @private
- */
- exports._hoverConnectedEdges = function(node) {
- for (var i = 0; i < node.edges.length; i++) {
- var edge = node.edges[i];
- edge.hover = true;
- this._addToHover(edge);
- }
- };
-
-
- /**
- * unselect the edges connected to the node that is being selected
- *
- * @param {Node} node
- * @private
- */
- exports._unselectConnectedEdges = function(node) {
- for (var i = 0; i < node.edges.length; i++) {
- var edge = node.edges[i];
- edge.unselect();
- this._removeFromSelection(edge);
- }
- };
-
-
-
-
- /**
- * 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
- *
- * @param {Node || Edge} object
- * @param {Boolean} append
- * @param {Boolean} [doNotTrigger] | ignore trigger
- * @private
- */
- exports._selectObject = function(object, append, doNotTrigger, highlightEdges, overrideSelectable) {
- if (doNotTrigger === undefined) {
- doNotTrigger = false;
- }
- if (highlightEdges === undefined) {
- highlightEdges = true;
- }
-
- if (this._selectionIsEmpty() == false && append == false && this.forceAppendSelection == false) {
- this._unselectAll(true);
- }
-
- // selectable allows the object to be selected. Override can be used if needed to bypass this.
- if (object.selected == false && (this.constants.selectable == true || overrideSelectable)) {
- object.select();
- this._addToSelection(object);
- if (object instanceof Node && this.blockConnectingEdgeSelection == false && highlightEdges == true) {
- this._selectConnectedEdges(object);
- }
- }
- // do not select the object if selectable is false, only add it to selection to allow drag to work
- else if (object.selected == false) {
- this._addToSelection(object);
- doNotTrigger = true;
- }
- else {
- object.unselect();
- this._removeFromSelection(object);
- }
-
- if (doNotTrigger == false) {
- this.emit('select', this.getSelection());
- }
- };
-
-
- /**
- * 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
- *
- * @param {Node || Edge} object
- * @private
- */
- exports._blurObject = function(object) {
- if (object.hover == true) {
- object.hover = false;
- this.emit("blurNode",{node:object.id});
- }
- };
-
- /**
- * 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
- *
- * @param {Node || Edge} object
- * @private
- */
- exports._hoverObject = function(object) {
- if (object.hover == false) {
- object.hover = true;
- this._addToHover(object);
- if (object instanceof Node) {
- this.emit("hoverNode",{node:object.id});
- }
- }
- if (object instanceof Node) {
- this._hoverConnectedEdges(object);
- }
- };
-
-
- /**
- * handles the selection part of the touch, only for navigation controls elements;
- * Touch is triggered before tap, also before hold. Hold triggers after a while.
- * This is the most responsive solution
- *
- * @param {Object} pointer
- * @private
- */
- exports._handleTouch = function(pointer) {
- };
-
-
- /**
- * handles the selection part of the tap;
- *
- * @param {Object} pointer
- * @private
- */
- exports._handleTap = function(pointer) {
- var node = this._getNodeAt(pointer);
- if (node != null) {
- this._selectObject(node, false);
- }
- else {
- var edge = this._getEdgeAt(pointer);
- if (edge != null) {
- this._selectObject(edge, false);
- }
- else {
- this._unselectAll();
- }
- }
- var properties = this.getSelection();
- properties['pointer'] = {
- DOM: {x: pointer.x, y: pointer.y},
- canvas: {x: this._XconvertDOMtoCanvas(pointer.x), y: this._YconvertDOMtoCanvas(pointer.y)}
- }
- this.emit("click", properties);
- this._requestRedraw();
- };
-
-
- /**
- * handles the selection part of the double tap and opens a cluster if needed
- *
- * @param {Object} pointer
- * @private
- */
- exports._handleDoubleTap = function(pointer) {
- var node = this._getNodeAt(pointer);
- if (node != null && node !== undefined) {
- // we reset the areaCenter here so the opening of the node will occur
- this.areaCenter = {"x" : this._XconvertDOMtoCanvas(pointer.x),
- "y" : this._YconvertDOMtoCanvas(pointer.y)};
- this.openCluster(node);
- }
- var properties = this.getSelection();
- properties['pointer'] = {
- DOM: {x: pointer.x, y: pointer.y},
- canvas: {x: this._XconvertDOMtoCanvas(pointer.x), y: this._YconvertDOMtoCanvas(pointer.y)}
- }
- this.emit("doubleClick", properties);
- };
-
-
- /**
- * Handle the onHold selection part
- *
- * @param pointer
- * @private
- */
- exports._handleOnHold = function(pointer) {
- var node = this._getNodeAt(pointer);
- if (node != null) {
- this._selectObject(node,true);
- }
- else {
- var edge = this._getEdgeAt(pointer);
- if (edge != null) {
- this._selectObject(edge,true);
- }
- }
- this._requestRedraw();
- };
-
-
- /**
- * handle the onRelease event. These functions are here for the navigation controls module
- * and data manipulation module.
- *
- * @private
- */
- exports._handleOnRelease = function(pointer) {
- this._manipulationReleaseOverload(pointer);
- this._navigationReleaseOverload(pointer);
- };
-
- exports._manipulationReleaseOverload = function (pointer) {};
- exports._navigationReleaseOverload = function (pointer) {};
-
- /**
- *
- * retrieve the currently selected objects
- * @return {{nodes: Array.<String>, edges: Array.<String>}} selection
- */
- exports.getSelection = function() {
- var nodeIds = this.getSelectedNodes();
- var edgeIds = this.getSelectedEdges();
- return {nodes:nodeIds, edges:edgeIds};
- };
-
- /**
- *
- * retrieve the currently selected nodes
- * @return {String[]} selection An array with the ids of the
- * selected nodes.
- */
- exports.getSelectedNodes = function() {
- var idArray = [];
- if (this.constants.selectable == true) {
- for (var nodeId in this.selectionObj.nodes) {
- if (this.selectionObj.nodes.hasOwnProperty(nodeId)) {
- idArray.push(nodeId);
- }
- }
- }
- return idArray
- };
-
- /**
- *
- * retrieve the currently selected edges
- * @return {Array} selection An array with the ids of the
- * selected nodes.
- */
- exports.getSelectedEdges = function() {
- var idArray = [];
- if (this.constants.selectable == true) {
- for (var edgeId in this.selectionObj.edges) {
- if (this.selectionObj.edges.hasOwnProperty(edgeId)) {
- idArray.push(edgeId);
- }
- }
- }
- return idArray;
- };
-
-
- /**
- * select zero or more nodes DEPRICATED
- * @param {Number[] | String[]} selection An array with the ids of the
- * selected nodes.
- */
- exports.setSelection = function() {
- console.log("setSelection is deprecated. Please use selectNodes instead.")
- };
-
-
- /**
- * select zero or more nodes with the option to highlight edges
- * @param {Number[] | String[]} selection An array with the ids of the
- * selected nodes.
- * @param {boolean} [highlightEdges]
- */
- exports.selectNodes = function(selection, highlightEdges) {
- var i, iMax, id;
-
- if (!selection || (selection.length == undefined))
- throw 'Selection must be an array with ids';
-
- // first unselect any selected node
- this._unselectAll(true);
-
- for (i = 0, iMax = selection.length; i < iMax; i++) {
- id = selection[i];
-
- var node = this.body.nodes[id];
- if (!node) {
- throw new RangeError('Node with id "' + id + '" not found');
- }
- this._selectObject(node,true,true,highlightEdges,true);
- }
- this.redraw();
- };
-
-
- /**
- * select zero or more edges
- * @param {Number[] | String[]} selection An array with the ids of the
- * selected nodes.
- */
- exports.selectEdges = function(selection) {
- var i, iMax, id;
-
- if (!selection || (selection.length == undefined))
- throw 'Selection must be an array with ids';
-
- // first unselect any selected node
- this._unselectAll(true);
-
- for (i = 0, iMax = selection.length; i < iMax; i++) {
- id = selection[i];
-
- var edge = this.body.edges[id];
- if (!edge) {
- throw new RangeError('Edge with id "' + id + '" not found');
- }
- this._selectObject(edge,true,true,false,true);
- }
- this.redraw();
- };
-
- /**
- * Validate the selection: remove ids of nodes which no longer exist
- * @private
- */
- exports._updateSelection = function () {
- for(var nodeId in this.selectionObj.nodes) {
- if(this.selectionObj.nodes.hasOwnProperty(nodeId)) {
- if (!this.body.nodes.hasOwnProperty(nodeId)) {
- delete this.selectionObj.nodes[nodeId];
- }
- }
- }
- for(var edgeId in this.selectionObj.edges) {
- if(this.selectionObj.edges.hasOwnProperty(edgeId)) {
- if (!this.body.edges.hasOwnProperty(edgeId)) {
- delete this.selectionObj.edges[edgeId];
- }
- }
- }
- };
|