|  |  | @ -5,7 +5,7 @@ | 
			
		
	
		
			
				
					|  |  |  | * A dynamic, browser-based visualization library. | 
			
		
	
		
			
				
					|  |  |  | * | 
			
		
	
		
			
				
					|  |  |  | * @version 0.4.0-SNAPSHOT | 
			
		
	
		
			
				
					|  |  |  | * @date    2014-01-29 | 
			
		
	
		
			
				
					|  |  |  | * @date    2014-01-30 | 
			
		
	
		
			
				
					|  |  |  | * | 
			
		
	
		
			
				
					|  |  |  | * @license | 
			
		
	
		
			
				
					|  |  |  | * Copyright (C) 2011-2014 Almende B.V, http://almende.com | 
			
		
	
	
		
			
				
					|  |  | @ -9780,6 +9780,7 @@ function Edge (properties, graph, constants) { | 
			
		
	
		
			
				
					|  |  |  | this.width  = constants.edges.width; | 
			
		
	
		
			
				
					|  |  |  | this.value  = undefined; | 
			
		
	
		
			
				
					|  |  |  | this.length = constants.edges.length; | 
			
		
	
		
			
				
					|  |  |  | this.selected = false; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | this.from = null;   // a node | 
			
		
	
		
			
				
					|  |  |  | this.to = null;     // a node | 
			
		
	
	
		
			
				
					|  |  | @ -10016,7 +10017,7 @@ Edge.prototype._drawLine = function(ctx) { | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | Edge.prototype._getLineWidth = function() { | 
			
		
	
		
			
				
					|  |  |  | if (this.from.selected || this.to.selected) { | 
			
		
	
		
			
				
					|  |  |  | if (this.selected == true) { | 
			
		
	
		
			
				
					|  |  |  | return Math.min(this.width * 2, this.widthMax)*this.graphScaleInv; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | else { | 
			
		
	
	
		
			
				
					|  |  | @ -10366,6 +10367,15 @@ Edge._dist = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point | 
			
		
	
		
			
				
					|  |  |  | Edge.prototype.setScale = function(scale) { | 
			
		
	
		
			
				
					|  |  |  | this.graphScaleInv = 1.0/scale; | 
			
		
	
		
			
				
					|  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | Edge.prototype.select = function() { | 
			
		
	
		
			
				
					|  |  |  | this.selected = true; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | Edge.prototype.unselect = function() { | 
			
		
	
		
			
				
					|  |  |  | this.selected = false; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * Popup is a class to create a popup window with some text | 
			
		
	
		
			
				
					|  |  |  | * @param {Element}  container     The container object. | 
			
		
	
	
		
			
				
					|  |  | @ -11479,6 +11489,10 @@ var ClusterMixin = { | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | // if child node has been added on smaller scale than current, kick out | 
			
		
	
		
			
				
					|  |  |  | if (childNode.formationScale < this.scale || force == true) { | 
			
		
	
		
			
				
					|  |  |  | // remove the selection, first remove the selection from the connected edges | 
			
		
	
		
			
				
					|  |  |  | this._unselectConnectedEdges(parentNode); | 
			
		
	
		
			
				
					|  |  |  | parentNode.unselect(); | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | // put the child node back in the global nodes object | 
			
		
	
		
			
				
					|  |  |  | this.nodes[containedNodeId] = childNode; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
	
		
			
				
					|  |  | @ -11527,6 +11541,9 @@ var ClusterMixin = { | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | // recalculate the size of the node on the next time the node is rendered | 
			
		
	
		
			
				
					|  |  |  | parentNode.clearSizeCache(); | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | // this unselects the rest of the edges | 
			
		
	
		
			
				
					|  |  |  | this._unselectConnectedEdges(parentNode); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | // check if a further expansion step is possible if recursivity is enabled | 
			
		
	
	
		
			
				
					|  |  | @ -12272,7 +12289,7 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  | _getNodeAt : function (pointer) { | 
			
		
	
		
			
				
					|  |  |  | // we first check if this is an navigationUI element | 
			
		
	
		
			
				
					|  |  |  | var positionObject = this._pointerToPositionObject(pointer); | 
			
		
	
		
			
				
					|  |  |  | overlappingNodes = this._getAllNodesOverlappingWith(positionObject); | 
			
		
	
		
			
				
					|  |  |  | 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 | 
			
		
	
	
		
			
				
					|  |  | @ -12285,6 +12302,36 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * 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 | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | _getEdgesOverlappingWith : function (object, overlappingEdges) { | 
			
		
	
		
			
				
					|  |  |  | var edges = this.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 | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | _getAllEdgesOverlappingWith : function (object) { | 
			
		
	
		
			
				
					|  |  |  | var overlappingEdges = []; | 
			
		
	
		
			
				
					|  |  |  | this._doInAllActiveSectors("_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. | 
			
		
	
	
		
			
				
					|  |  | @ -12294,18 +12341,25 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | _getEdgeAt : function(pointer) { | 
			
		
	
		
			
				
					|  |  |  | return null; | 
			
		
	
		
			
				
					|  |  |  | var positionObject = this._pointerToPositionObject(pointer); | 
			
		
	
		
			
				
					|  |  |  | var overlappingEdges = this._getAllEdgesOverlappingWith(positionObject); | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | if (overlappingEdges.length > 0) { | 
			
		
	
		
			
				
					|  |  |  | return this.edges[overlappingEdges[overlappingEdges.length - 1]]; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | else { | 
			
		
	
		
			
				
					|  |  |  | return null; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * Add object to the selection array. The this.selection id array may not be needed. | 
			
		
	
		
			
				
					|  |  |  | * Add object to the selection array. | 
			
		
	
		
			
				
					|  |  |  | * | 
			
		
	
		
			
				
					|  |  |  | * @param obj | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | _addToSelection : function(obj) { | 
			
		
	
		
			
				
					|  |  |  | this.selection.push(obj.id); | 
			
		
	
		
			
				
					|  |  |  | this.selectionObj[obj.id] = obj; | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
	
		
			
				
					|  |  | @ -12317,12 +12371,6 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | _removeFromSelection : function(obj) { | 
			
		
	
		
			
				
					|  |  |  | for (var i = 0; i < this.selection.length; i++) { | 
			
		
	
		
			
				
					|  |  |  | if (obj.id == this.selection[i]) { | 
			
		
	
		
			
				
					|  |  |  | this.selection.splice(i,1); | 
			
		
	
		
			
				
					|  |  |  | break; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | delete this.selectionObj[obj.id]; | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
	
		
			
				
					|  |  | @ -12338,10 +12386,9 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  | doNotTrigger = false; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | this.selection = []; | 
			
		
	
		
			
				
					|  |  |  | for (var objId in this.selectionObj) { | 
			
		
	
		
			
				
					|  |  |  | if (this.selectionObj.hasOwnProperty(objId)) { | 
			
		
	
		
			
				
					|  |  |  | this.selectionObj[objId].unselect(); | 
			
		
	
		
			
				
					|  |  |  | for (var objectId in this.selectionObj) { | 
			
		
	
		
			
				
					|  |  |  | if (this.selectionObj.hasOwnProperty(objectId)) { | 
			
		
	
		
			
				
					|  |  |  | this.selectionObj[objectId].unselect(); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | this.selectionObj = {}; | 
			
		
	
	
		
			
				
					|  |  | @ -12359,25 +12406,55 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | _selectionIsEmpty : function() { | 
			
		
	
		
			
				
					|  |  |  | if (this.selection.length == 0) { | 
			
		
	
		
			
				
					|  |  |  | return true; | 
			
		
	
		
			
				
					|  |  |  | for(var objectId in this.selectionObj) { | 
			
		
	
		
			
				
					|  |  |  | if(this.selectionObj.hasOwnProperty(objectId)) { | 
			
		
	
		
			
				
					|  |  |  | return false; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | else { | 
			
		
	
		
			
				
					|  |  |  | return false; | 
			
		
	
		
			
				
					|  |  |  | return true; | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * select the edges connected to the node that is being selected | 
			
		
	
		
			
				
					|  |  |  | * | 
			
		
	
		
			
				
					|  |  |  | * @param {Node} node | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | _selectConnectedEdges : function(node) { | 
			
		
	
		
			
				
					|  |  |  | for (var i = 0; i < node.dynamicEdges.length; i++) { | 
			
		
	
		
			
				
					|  |  |  | var edge = node.dynamicEdges[i]; | 
			
		
	
		
			
				
					|  |  |  | edge.select(); | 
			
		
	
		
			
				
					|  |  |  | this._addToSelection(edge); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * unselect the edges connected to the node that is being selected | 
			
		
	
		
			
				
					|  |  |  | * | 
			
		
	
		
			
				
					|  |  |  | * @param {Node} node | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | _unselectConnectedEdges : function(node) { | 
			
		
	
		
			
				
					|  |  |  | for (var i = 0; i < node.dynamicEdges.length; i++) { | 
			
		
	
		
			
				
					|  |  |  | var edge = node.dynamicEdges[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} node | 
			
		
	
		
			
				
					|  |  |  | * @param {Node || Edge} object | 
			
		
	
		
			
				
					|  |  |  | * @param {Boolean} append | 
			
		
	
		
			
				
					|  |  |  | * @param {Boolean} [doNotTrigger] | ignore trigger | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | _selectNode : function(node, append, doNotTrigger) { | 
			
		
	
		
			
				
					|  |  |  | _selectObject : function(object, append, doNotTrigger) { | 
			
		
	
		
			
				
					|  |  |  | if (doNotTrigger === undefined) { | 
			
		
	
		
			
				
					|  |  |  | doNotTrigger = false; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
	
		
			
				
					|  |  | @ -12386,14 +12463,16 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  | this._unselectAll(true); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | if (node.selected == false) { | 
			
		
	
		
			
				
					|  |  |  | node.select(); | 
			
		
	
		
			
				
					|  |  |  | this._addToSelection(node); | 
			
		
	
		
			
				
					|  |  |  | if (object.selected == false) { | 
			
		
	
		
			
				
					|  |  |  | object.select(); | 
			
		
	
		
			
				
					|  |  |  | this._addToSelection(object); | 
			
		
	
		
			
				
					|  |  |  | if (object instanceof Node) { | 
			
		
	
		
			
				
					|  |  |  | this._selectConnectedEdges(object); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | else { | 
			
		
	
		
			
				
					|  |  |  | node.unselect(); | 
			
		
	
		
			
				
					|  |  |  | this._removeFromSelection(node); | 
			
		
	
		
			
				
					|  |  |  | object.unselect(); | 
			
		
	
		
			
				
					|  |  |  | this._removeFromSelection(object); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | if (doNotTrigger == false) { | 
			
		
	
		
			
				
					|  |  |  | this._trigger('select'); | 
			
		
	
	
		
			
				
					|  |  | @ -12428,10 +12507,16 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  | _handleTap : function(pointer) { | 
			
		
	
		
			
				
					|  |  |  | var node = this._getNodeAt(pointer); | 
			
		
	
		
			
				
					|  |  |  | if (node != null) { | 
			
		
	
		
			
				
					|  |  |  | this._selectNode(node,false); | 
			
		
	
		
			
				
					|  |  |  | this._selectObject(node,false); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | else { | 
			
		
	
		
			
				
					|  |  |  | this._unselectAll(); | 
			
		
	
		
			
				
					|  |  |  | var edge = this._getEdgeAt(pointer); | 
			
		
	
		
			
				
					|  |  |  | if (edge != null) { | 
			
		
	
		
			
				
					|  |  |  | this._selectObject(edge,false); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | else { | 
			
		
	
		
			
				
					|  |  |  | this._unselectAll(); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | this._redraw(); | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
	
		
			
				
					|  |  | @ -12463,7 +12548,13 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  | _handleOnHold : function(pointer) { | 
			
		
	
		
			
				
					|  |  |  | var node = this._getNodeAt(pointer); | 
			
		
	
		
			
				
					|  |  |  | if (node != null) { | 
			
		
	
		
			
				
					|  |  |  | this._selectNode(node,true); | 
			
		
	
		
			
				
					|  |  |  | this._selectObject(node,true); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | else { | 
			
		
	
		
			
				
					|  |  |  | var edge = this._getEdgeAt(pointer); | 
			
		
	
		
			
				
					|  |  |  | if (edge != null) { | 
			
		
	
		
			
				
					|  |  |  | this._selectObject(edge,true); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | this._redraw(); | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
	
		
			
				
					|  |  | @ -12485,12 +12576,72 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * | 
			
		
	
		
			
				
					|  |  |  | * retrieve the currently selected nodes | 
			
		
	
		
			
				
					|  |  |  | * retrieve the currently selected objects | 
			
		
	
		
			
				
					|  |  |  | * @return {Number[] | String[]} selection    An array with the ids of the | 
			
		
	
		
			
				
					|  |  |  | *                                            selected nodes. | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | getSelection : function() { | 
			
		
	
		
			
				
					|  |  |  | return this.selection.concat([]); | 
			
		
	
		
			
				
					|  |  |  | var nodeIdString = this.getSelectedNodes(); | 
			
		
	
		
			
				
					|  |  |  | /* | 
			
		
	
		
			
				
					|  |  |  | var edgeIdString = this.getSelectedEdges(); | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | var idString = ""; | 
			
		
	
		
			
				
					|  |  |  | if (nodeIdString != "") { | 
			
		
	
		
			
				
					|  |  |  | idString = idString.concat("Nodes: ",nodeIdString); | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | if (edgeIdString != "") { | 
			
		
	
		
			
				
					|  |  |  | idString = idString.concat("; "); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | if (edgeIdString != "") { | 
			
		
	
		
			
				
					|  |  |  | idString = idString.concat("Edges: ",edgeIdString); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | return nodeIdString | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * | 
			
		
	
		
			
				
					|  |  |  | * retrieve the currently selected nodes | 
			
		
	
		
			
				
					|  |  |  | * @return {String} selection    An array with the ids of the | 
			
		
	
		
			
				
					|  |  |  | *                                            selected nodes. | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | getSelectedNodes : function() { | 
			
		
	
		
			
				
					|  |  |  | var idString = "", i = 0; | 
			
		
	
		
			
				
					|  |  |  | for(var objectId in this.selectionObj) { | 
			
		
	
		
			
				
					|  |  |  | if(this.selectionObj.hasOwnProperty(objectId)) { | 
			
		
	
		
			
				
					|  |  |  | if (this.selectionObj[objectId] instanceof Node) { | 
			
		
	
		
			
				
					|  |  |  | if (i != 0) { | 
			
		
	
		
			
				
					|  |  |  | idString = idString.concat(", "); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | idString = idString.concat(String(objectId)); | 
			
		
	
		
			
				
					|  |  |  | i++; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | return idString | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * | 
			
		
	
		
			
				
					|  |  |  | * retrieve the currently selected edges | 
			
		
	
		
			
				
					|  |  |  | * @return {String} selection    An array with the ids of the | 
			
		
	
		
			
				
					|  |  |  | *                                            selected nodes. | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | getSelectedEdges : function() { | 
			
		
	
		
			
				
					|  |  |  | var idString = "", i = 0; | 
			
		
	
		
			
				
					|  |  |  | for(var objectId in this.selectionObj) { | 
			
		
	
		
			
				
					|  |  |  | if(this.selectionObj.hasOwnProperty(objectId)) { | 
			
		
	
		
			
				
					|  |  |  | if (this.selectionObj[objectId] instanceof Edge) { | 
			
		
	
		
			
				
					|  |  |  | if (i != 0) { | 
			
		
	
		
			
				
					|  |  |  | idString = idString.concat(", "); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | idString = idString.concat(String(objectId)); | 
			
		
	
		
			
				
					|  |  |  | i++; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | return idString | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
	
		
			
				
					|  |  | @ -12504,8 +12655,6 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * // TODO: rework this function, it is from the old system | 
			
		
	
		
			
				
					|  |  |  | * | 
			
		
	
		
			
				
					|  |  |  | * select zero or more nodes | 
			
		
	
		
			
				
					|  |  |  | * @param {Number[] | String[]} selection     An array with the ids of the | 
			
		
	
		
			
				
					|  |  |  | *                                            selected nodes. | 
			
		
	
	
		
			
				
					|  |  | @ -12526,7 +12675,7 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  | if (!node) { | 
			
		
	
		
			
				
					|  |  |  | throw new RangeError('Node with id "' + id + '" not found'); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | this._selectNode(node,true,true); | 
			
		
	
		
			
				
					|  |  |  | this._selectObject(node,true,true); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | this.redraw(); | 
			
		
	
	
		
			
				
					|  |  | @ -12534,135 +12683,28 @@ var SelectionMixin = { | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * TODO: rework this function, it is from the old system | 
			
		
	
		
			
				
					|  |  |  | * | 
			
		
	
		
			
				
					|  |  |  | * Validate the selection: remove ids of nodes which no longer exist | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | _updateSelection : function () { | 
			
		
	
		
			
				
					|  |  |  | var i = 0; | 
			
		
	
		
			
				
					|  |  |  | while (i < this.selection.length) { | 
			
		
	
		
			
				
					|  |  |  | var nodeId = this.selection[i]; | 
			
		
	
		
			
				
					|  |  |  | if (!this.nodes.hasOwnProperty(nodeId)) { | 
			
		
	
		
			
				
					|  |  |  | this.selection.splice(i, 1); | 
			
		
	
		
			
				
					|  |  |  | delete this.selectionObj[nodeId]; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | else { | 
			
		
	
		
			
				
					|  |  |  | i++; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * Unselect selected nodes. If no selection array is provided, all nodes | 
			
		
	
		
			
				
					|  |  |  | * are unselected | 
			
		
	
		
			
				
					|  |  |  | * @param {Object[]} selection     Array with selection objects, each selection | 
			
		
	
		
			
				
					|  |  |  | *                                 object has a parameter row. Optional | 
			
		
	
		
			
				
					|  |  |  | * @param {Boolean} triggerSelect  If true (default), the select event | 
			
		
	
		
			
				
					|  |  |  | *                                 is triggered when nodes are unselected | 
			
		
	
		
			
				
					|  |  |  | * @return {Boolean} changed       True if the selection is changed | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | /* _unselectNodes : function(selection, triggerSelect) { | 
			
		
	
		
			
				
					|  |  |  | var changed = false; | 
			
		
	
		
			
				
					|  |  |  | var i, iMax, id; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | if (selection) { | 
			
		
	
		
			
				
					|  |  |  | // remove provided selections | 
			
		
	
		
			
				
					|  |  |  | for (i = 0, iMax = selection.length; i < iMax; i++) { | 
			
		
	
		
			
				
					|  |  |  | id = selection[i]; | 
			
		
	
		
			
				
					|  |  |  | if (this.nodes.hasOwnProperty(id)) { | 
			
		
	
		
			
				
					|  |  |  | this.nodes[id].unselect(); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | var j = 0; | 
			
		
	
		
			
				
					|  |  |  | while (j < this.selection.length) { | 
			
		
	
		
			
				
					|  |  |  | if (this.selection[j] == id) { | 
			
		
	
		
			
				
					|  |  |  | this.selection.splice(j, 1); | 
			
		
	
		
			
				
					|  |  |  | changed = true; | 
			
		
	
		
			
				
					|  |  |  | for(var objectId in this.selectionObj) { | 
			
		
	
		
			
				
					|  |  |  | if(this.selectionObj.hasOwnProperty(objectId)) { | 
			
		
	
		
			
				
					|  |  |  | if (this.selectionObj[objectId] instanceof Node) { | 
			
		
	
		
			
				
					|  |  |  | if (!this.nodes.hasOwnProperty(objectId)) { | 
			
		
	
		
			
				
					|  |  |  | delete this.selectionObj[objectId]; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | else { | 
			
		
	
		
			
				
					|  |  |  | j++; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | else if (this.selection && this.selection.length) { | 
			
		
	
		
			
				
					|  |  |  | // remove all selections | 
			
		
	
		
			
				
					|  |  |  | for (i = 0, iMax = this.selection.length; i < iMax; i++) { | 
			
		
	
		
			
				
					|  |  |  | id = this.selection[i]; | 
			
		
	
		
			
				
					|  |  |  | if (this.nodes.hasOwnProperty(id)) { | 
			
		
	
		
			
				
					|  |  |  | this.nodes[id].unselect(); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | changed = true; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | this.selection = []; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | if (changed && (triggerSelect == true || triggerSelect == undefined)) { | 
			
		
	
		
			
				
					|  |  |  | // fire the select event | 
			
		
	
		
			
				
					|  |  |  | this._trigger('select'); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | return changed; | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  | * select all nodes on given location x, y | 
			
		
	
		
			
				
					|  |  |  | * @param {Array} selection   an array with node ids | 
			
		
	
		
			
				
					|  |  |  | * @param {boolean} append    If true, the new selection will be appended to the | 
			
		
	
		
			
				
					|  |  |  | *                            current selection (except for duplicate entries) | 
			
		
	
		
			
				
					|  |  |  | * @return {Boolean} changed  True if the selection is changed | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | /*  _selectNodes : function(selection, append) { | 
			
		
	
		
			
				
					|  |  |  | var changed = false; | 
			
		
	
		
			
				
					|  |  |  | var i, iMax; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | // TODO: the selectNodes method is a little messy, rework this | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | // check if the current selection equals the desired selection | 
			
		
	
		
			
				
					|  |  |  | var selectionAlreadyThere = true; | 
			
		
	
		
			
				
					|  |  |  | if (selection.length != this.selection.length) { | 
			
		
	
		
			
				
					|  |  |  | selectionAlreadyThere = false; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | else { | 
			
		
	
		
			
				
					|  |  |  | for (i = 0, iMax = Math.min(selection.length, this.selection.length); i < iMax; i++) { | 
			
		
	
		
			
				
					|  |  |  | if (selection[i] != this.selection[i]) { | 
			
		
	
		
			
				
					|  |  |  | selectionAlreadyThere = false; | 
			
		
	
		
			
				
					|  |  |  | break; | 
			
		
	
		
			
				
					|  |  |  | else { // assuming only edges and nodes are selected | 
			
		
	
		
			
				
					|  |  |  | if (!this.edges.hasOwnProperty(objectId)) { | 
			
		
	
		
			
				
					|  |  |  | delete this.selectionObj[objectId]; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | if (selectionAlreadyThere) { | 
			
		
	
		
			
				
					|  |  |  | return changed; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | if (append == undefined || append == false) { | 
			
		
	
		
			
				
					|  |  |  | // first deselect any selected node | 
			
		
	
		
			
				
					|  |  |  | var triggerSelect = false; | 
			
		
	
		
			
				
					|  |  |  | changed = this._unselectNodes(undefined, triggerSelect); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | for (i = 0, iMax = selection.length; i < iMax; i++) { | 
			
		
	
		
			
				
					|  |  |  | // add each of the new selections, but only when they are not duplicate | 
			
		
	
		
			
				
					|  |  |  | var id = selection[i]; | 
			
		
	
		
			
				
					|  |  |  | var isDuplicate = (this.selection.indexOf(id) != -1); | 
			
		
	
		
			
				
					|  |  |  | if (!isDuplicate) { | 
			
		
	
		
			
				
					|  |  |  | this.nodes[id].select(); | 
			
		
	
		
			
				
					|  |  |  | this.selection.push(id); | 
			
		
	
		
			
				
					|  |  |  | changed = true; | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | if (changed) { | 
			
		
	
		
			
				
					|  |  |  | // fire the select event | 
			
		
	
		
			
				
					|  |  |  | this._trigger('select'); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | return changed; | 
			
		
	
		
			
				
					|  |  |  | }, | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
	
		
			
				
					|  |  | @ -13569,27 +13611,28 @@ Graph.prototype._onDragStart = function () { | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | // create an array with the selected nodes and their original location and status | 
			
		
	
		
			
				
					|  |  |  | var me = this; | 
			
		
	
		
			
				
					|  |  |  | this.selection.forEach(function (id) { | 
			
		
	
		
			
				
					|  |  |  | var node = me.nodes[id]; | 
			
		
	
		
			
				
					|  |  |  | if (node) { | 
			
		
	
		
			
				
					|  |  |  | var s = { | 
			
		
	
		
			
				
					|  |  |  | id: id, | 
			
		
	
		
			
				
					|  |  |  | node: node, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | // store original x, y, xFixed and yFixed, make the node temporarily Fixed | 
			
		
	
		
			
				
					|  |  |  | x: node.x, | 
			
		
	
		
			
				
					|  |  |  | y: node.y, | 
			
		
	
		
			
				
					|  |  |  | xFixed: node.xFixed, | 
			
		
	
		
			
				
					|  |  |  | yFixed: node.yFixed | 
			
		
	
		
			
				
					|  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  | for (var objectId in this.selectionObj) { | 
			
		
	
		
			
				
					|  |  |  | if (this.selectionObj.hasOwnProperty(objectId)) { | 
			
		
	
		
			
				
					|  |  |  | var object = this.selectionObj[objectId]; | 
			
		
	
		
			
				
					|  |  |  | if (object instanceof Node) { | 
			
		
	
		
			
				
					|  |  |  | var s = { | 
			
		
	
		
			
				
					|  |  |  | id: object.id, | 
			
		
	
		
			
				
					|  |  |  | node: object, | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | // store original x, y, xFixed and yFixed, make the node temporarily Fixed | 
			
		
	
		
			
				
					|  |  |  | x: object.x, | 
			
		
	
		
			
				
					|  |  |  | y: object.y, | 
			
		
	
		
			
				
					|  |  |  | xFixed: object.xFixed, | 
			
		
	
		
			
				
					|  |  |  | yFixed: object.yFixed | 
			
		
	
		
			
				
					|  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | node.xFixed = true; | 
			
		
	
		
			
				
					|  |  |  | node.yFixed = true; | 
			
		
	
		
			
				
					|  |  |  | object.xFixed = true; | 
			
		
	
		
			
				
					|  |  |  | object.yFixed = true; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | drag.selection.push(s); | 
			
		
	
		
			
				
					|  |  |  | drag.selection.push(s); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | }); | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
	
		
			
				
					|  |  | @ -14932,7 +14975,6 @@ Graph.prototype._loadSectorSystem = function() { | 
			
		
	
		
			
				
					|  |  |  | * @private | 
			
		
	
		
			
				
					|  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  | Graph.prototype._loadSelectionSystem = function() { | 
			
		
	
		
			
				
					|  |  |  | this.selection = []; | 
			
		
	
		
			
				
					|  |  |  | this.selectionObj = {}; | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | for (var mixinFunction in SelectionMixin) { | 
			
		
	
	
		
			
				
					|  |  |  |