Browse Source

Merge branch 'alex_new' into alex_dev

css_transitions
Alex de Mulder 10 years ago
parent
commit
45c54fd80c
9 changed files with 393 additions and 349 deletions
  1. +193
    -171
      dist/vis.js
  2. +1
    -1
      examples/graph/02_random_nodes.html
  3. +1
    -1
      examples/graph/18_fully_random_nodes_clustering.html
  4. +1
    -1
      examples/graph/19_scale_free_graph_clustering.html
  5. +1
    -1
      examples/graph/20_UI_example.html
  6. +7
    -0
      src/graph/ClusterMixin.js
  7. +12
    -2
      src/graph/Edge.js
  8. +21
    -21
      src/graph/Graph.js
  9. +156
    -151
      src/graph/SelectionMixin.js

+ 193
- 171
dist/vis.js View File

@ -9779,6 +9779,7 @@ function Edge (properties, graph, constants) {
this.width = constants.edges.width; this.width = constants.edges.width;
this.value = undefined; this.value = undefined;
this.length = constants.edges.length; this.length = constants.edges.length;
this.selected = false;
this.from = null; // a node this.from = null; // a node
this.to = null; // a node this.to = null; // a node
@ -10015,7 +10016,7 @@ Edge.prototype._drawLine = function(ctx) {
* @private * @private
*/ */
Edge.prototype._getLineWidth = function() { 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; return Math.min(this.width * 2, this.widthMax)*this.graphScaleInv;
} }
else { else {
@ -10365,6 +10366,15 @@ Edge._dist = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point
Edge.prototype.setScale = function(scale) { Edge.prototype.setScale = function(scale) {
this.graphScaleInv = 1.0/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 * Popup is a class to create a popup window with some text
* @param {Element} container The container object. * @param {Element} container The container object.
@ -11478,6 +11488,10 @@ var ClusterMixin = {
// if child node has been added on smaller scale than current, kick out // if child node has been added on smaller scale than current, kick out
if (childNode.formationScale < this.scale || force == true) { 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 // put the child node back in the global nodes object
this.nodes[containedNodeId] = childNode; this.nodes[containedNodeId] = childNode;
@ -11526,6 +11540,9 @@ var ClusterMixin = {
// recalculate the size of the node on the next time the node is rendered // recalculate the size of the node on the next time the node is rendered
parentNode.clearSizeCache(); parentNode.clearSizeCache();
// this unselects the rest of the edges
this._unselectConnectedEdges(parentNode);
} }
// check if a further expansion step is possible if recursivity is enabled // check if a further expansion step is possible if recursivity is enabled
@ -12271,7 +12288,7 @@ var SelectionMixin = {
_getNodeAt : function (pointer) { _getNodeAt : function (pointer) {
// we first check if this is an navigationUI element // we first check if this is an navigationUI element
var positionObject = this._pointerToPositionObject(pointer); 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 // if there are overlapping nodes, select the last one, this is the
// one which is drawn on top of the others // one which is drawn on top of the others
@ -12284,6 +12301,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 * Place holder. To implement change the _getNodeAt to a _getObjectAt. Have the _getObjectAt call
* _getNodeAt and _getEdgesAt, then priortize the selection to user preferences. * _getNodeAt and _getEdgesAt, then priortize the selection to user preferences.
@ -12293,18 +12340,25 @@ var SelectionMixin = {
* @private * @private
*/ */
_getEdgeAt : function(pointer) { _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 * @param obj
* @private * @private
*/ */
_addToSelection : function(obj) { _addToSelection : function(obj) {
this.selection.push(obj.id);
this.selectionObj[obj.id] = obj; this.selectionObj[obj.id] = obj;
}, },
@ -12316,12 +12370,6 @@ var SelectionMixin = {
* @private * @private
*/ */
_removeFromSelection : function(obj) { _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]; delete this.selectionObj[obj.id];
}, },
@ -12337,10 +12385,9 @@ var SelectionMixin = {
doNotTrigger = false; 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 = {}; this.selectionObj = {};
@ -12358,25 +12405,55 @@ var SelectionMixin = {
* @private * @private
*/ */
_selectionIsEmpty : function() { _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. * 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 * 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} append
* @param {Boolean} [doNotTrigger] | ignore trigger * @param {Boolean} [doNotTrigger] | ignore trigger
* @private * @private
*/ */
_selectNode : function(node, append, doNotTrigger) {
_selectObject : function(object, append, doNotTrigger) {
if (doNotTrigger === undefined) { if (doNotTrigger === undefined) {
doNotTrigger = false; doNotTrigger = false;
} }
@ -12385,14 +12462,16 @@ var SelectionMixin = {
this._unselectAll(true); 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 { else {
node.unselect();
this._removeFromSelection(node);
object.unselect();
this._removeFromSelection(object);
} }
if (doNotTrigger == false) { if (doNotTrigger == false) {
this._trigger('select'); this._trigger('select');
@ -12429,10 +12508,16 @@ var SelectionMixin = {
_handleTap : function(pointer) { _handleTap : function(pointer) {
var node = this._getNodeAt(pointer); var node = this._getNodeAt(pointer);
if (node != null) { if (node != null) {
this._selectNode(node,false);
this._selectObject(node,false);
} }
else { else {
this._unselectAll();
var edge = this._getEdgeAt(pointer);
if (edge != null) {
this._selectObject(edge,false);
}
else {
this._unselectAll();
}
} }
this._redraw(); this._redraw();
}, },
@ -12464,7 +12549,13 @@ var SelectionMixin = {
_handleOnHold : function(pointer) { _handleOnHold : function(pointer) {
var node = this._getNodeAt(pointer); var node = this._getNodeAt(pointer);
if (node != null) { 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(); this._redraw();
}, },
@ -12486,12 +12577,52 @@ var SelectionMixin = {
/** /**
* *
* retrieve the currently selected nodes
* retrieve the currently selected objects
* @return {Number[] | String[]} selection An array with the ids of the * @return {Number[] | String[]} selection An array with the ids of the
* selected nodes. * selected nodes.
*/ */
getSelection : function() { getSelection : function() {
return this.selection.concat([]);
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.
*/
getSelectedNodes : function() {
var idArray = [];
for(var objectId in this.selectionObj) {
if(this.selectionObj.hasOwnProperty(objectId)) {
if (this.selectionObj[objectId] instanceof Node) {
idArray.push(objectId);
}
}
}
return idArray
},
/**
*
* retrieve the currently selected edges
* @return {Array} selection An array with the ids of the
* selected nodes.
*/
getSelectedEdges : function() {
var idArray = [];
for(var objectId in this.selectionObj) {
if(this.selectionObj.hasOwnProperty(objectId)) {
if (this.selectionObj[objectId] instanceof Edge) {
idArray.push(objectId);
}
}
}
return idArray
}, },
/** /**
@ -12505,8 +12636,6 @@ var SelectionMixin = {
}, },
/** /**
* // TODO: rework this function, it is from the old system
*
* select zero or more nodes * select zero or more nodes
* @param {Number[] | String[]} selection An array with the ids of the * @param {Number[] | String[]} selection An array with the ids of the
* selected nodes. * selected nodes.
@ -12527,7 +12656,7 @@ var SelectionMixin = {
if (!node) { if (!node) {
throw new RangeError('Node with id "' + id + '" not found'); throw new RangeError('Node with id "' + id + '" not found');
} }
this._selectNode(node,true,true);
this._selectObject(node,true,true);
} }
this.redraw(); this.redraw();
@ -12535,135 +12664,28 @@ var SelectionMixin = {
/** /**
* TODO: rework this function, it is from the old system
*
* Validate the selection: remove ids of nodes which no longer exist * Validate the selection: remove ids of nodes which no longer exist
* @private * @private
*/ */
_updateSelection : function () { _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;
}
else {
j++;
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 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;
},
*/
}; };
@ -13562,27 +13584,28 @@ Graph.prototype._onDragStart = function () {
} }
// create an array with the selected nodes and their original location and status // 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);
}
} }
});
}
} }
}; };
@ -14925,7 +14948,6 @@ Graph.prototype._loadSectorSystem = function() {
* @private * @private
*/ */
Graph.prototype._loadSelectionSystem = function() { Graph.prototype._loadSelectionSystem = function() {
this.selection = [];
this.selectionObj = {}; this.selectionObj = {};
for (var mixinFunction in SelectionMixin) { for (var mixinFunction in SelectionMixin) {

+ 1
- 1
examples/graph/02_random_nodes.html View File

@ -96,7 +96,7 @@
// add event listeners // add event listeners
vis.events.addListener(graph, 'select', function(params) { vis.events.addListener(graph, 'select', function(params) {
document.getElementById('selection').innerHTML = document.getElementById('selection').innerHTML =
'Selection: ' + graph.getSelection();
'Selection: ' + JSON.stringify(graph.getSelection());
}); });
} }
</script> </script>

+ 1
- 1
examples/graph/18_fully_random_nodes_clustering.html View File

@ -65,7 +65,7 @@
// add event listeners // add event listeners
vis.events.addListener(graph, 'select', function(params) { vis.events.addListener(graph, 'select', function(params) {
document.getElementById('selection').innerHTML = document.getElementById('selection').innerHTML =
'Selection: ' + graph.getSelection();
'Selection: ' + JSON.stringify(graph.getSelection());
}); });
} }
</script> </script>

+ 1
- 1
examples/graph/19_scale_free_graph_clustering.html View File

@ -102,7 +102,7 @@
// add event listeners // add event listeners
vis.events.addListener(graph, 'select', function(params) { vis.events.addListener(graph, 'select', function(params) {
document.getElementById('selection').innerHTML = document.getElementById('selection').innerHTML =
'Selection: ' + graph.getSelection();
'Selection: ' + JSON.stringify(graph.getSelection());
}); });
} }
</script> </script>

+ 1
- 1
examples/graph/20_UI_example.html View File

@ -122,7 +122,7 @@
// add event listeners // add event listeners
vis.events.addListener(graph, 'select', function(params) { vis.events.addListener(graph, 'select', function(params) {
document.getElementById('selection').innerHTML = document.getElementById('selection').innerHTML =
'Selection: ' + graph.getSelection();
'Selection: ' + JSON.stringify(graph.getSelection());
}); });
} }
</script> </script>

+ 7
- 0
src/graph/ClusterMixin.js View File

@ -335,6 +335,10 @@ var ClusterMixin = {
// if child node has been added on smaller scale than current, kick out // if child node has been added on smaller scale than current, kick out
if (childNode.formationScale < this.scale || force == true) { 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 // put the child node back in the global nodes object
this.nodes[containedNodeId] = childNode; this.nodes[containedNodeId] = childNode;
@ -383,6 +387,9 @@ var ClusterMixin = {
// recalculate the size of the node on the next time the node is rendered // recalculate the size of the node on the next time the node is rendered
parentNode.clearSizeCache(); parentNode.clearSizeCache();
// this unselects the rest of the edges
this._unselectConnectedEdges(parentNode);
} }
// check if a further expansion step is possible if recursivity is enabled // check if a further expansion step is possible if recursivity is enabled

+ 12
- 2
src/graph/Edge.js View File

@ -32,6 +32,7 @@ function Edge (properties, graph, constants) {
this.width = constants.edges.width; this.width = constants.edges.width;
this.value = undefined; this.value = undefined;
this.length = constants.edges.length; this.length = constants.edges.length;
this.selected = false;
this.from = null; // a node this.from = null; // a node
this.to = null; // a node this.to = null; // a node
@ -268,7 +269,7 @@ Edge.prototype._drawLine = function(ctx) {
* @private * @private
*/ */
Edge.prototype._getLineWidth = function() { 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; return Math.min(this.width * 2, this.widthMax)*this.graphScaleInv;
} }
else { else {
@ -617,4 +618,13 @@ Edge._dist = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point
*/ */
Edge.prototype.setScale = function(scale) { Edge.prototype.setScale = function(scale) {
this.graphScaleInv = 1.0/scale; this.graphScaleInv = 1.0/scale;
};
};
Edge.prototype.select = function() {
this.selected = true;
}
Edge.prototype.unselect = function() {
this.selected = false;
}

+ 21
- 21
src/graph/Graph.js View File

@ -646,27 +646,28 @@ Graph.prototype._onDragStart = function () {
} }
// create an array with the selected nodes and their original location and status // 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
};
node.xFixed = true;
node.yFixed = true;
drag.selection.push(s);
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
};
object.xFixed = true;
object.yFixed = true;
drag.selection.push(s);
}
} }
});
}
} }
}; };
@ -2009,7 +2010,6 @@ Graph.prototype._loadSectorSystem = function() {
* @private * @private
*/ */
Graph.prototype._loadSelectionSystem = function() { Graph.prototype._loadSelectionSystem = function() {
this.selection = [];
this.selectionObj = {}; this.selectionObj = {};
for (var mixinFunction in SelectionMixin) { for (var mixinFunction in SelectionMixin) {

+ 156
- 151
src/graph/SelectionMixin.js View File

@ -108,7 +108,7 @@ var SelectionMixin = {
_getNodeAt : function (pointer) { _getNodeAt : function (pointer) {
// we first check if this is an navigationUI element // we first check if this is an navigationUI element
var positionObject = this._pointerToPositionObject(pointer); 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 // if there are overlapping nodes, select the last one, this is the
// one which is drawn on top of the others // one which is drawn on top of the others
@ -121,6 +121,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 * Place holder. To implement change the _getNodeAt to a _getObjectAt. Have the _getObjectAt call
* _getNodeAt and _getEdgesAt, then priortize the selection to user preferences. * _getNodeAt and _getEdgesAt, then priortize the selection to user preferences.
@ -130,18 +160,25 @@ var SelectionMixin = {
* @private * @private
*/ */
_getEdgeAt : function(pointer) { _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 * @param obj
* @private * @private
*/ */
_addToSelection : function(obj) { _addToSelection : function(obj) {
this.selection.push(obj.id);
this.selectionObj[obj.id] = obj; this.selectionObj[obj.id] = obj;
}, },
@ -153,12 +190,6 @@ var SelectionMixin = {
* @private * @private
*/ */
_removeFromSelection : function(obj) { _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]; delete this.selectionObj[obj.id];
}, },
@ -174,10 +205,9 @@ var SelectionMixin = {
doNotTrigger = false; 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 = {}; this.selectionObj = {};
@ -195,25 +225,55 @@ var SelectionMixin = {
* @private * @private
*/ */
_selectionIsEmpty : function() { _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. * 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 * 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} append
* @param {Boolean} [doNotTrigger] | ignore trigger * @param {Boolean} [doNotTrigger] | ignore trigger
* @private * @private
*/ */
_selectNode : function(node, append, doNotTrigger) {
_selectObject : function(object, append, doNotTrigger) {
if (doNotTrigger === undefined) { if (doNotTrigger === undefined) {
doNotTrigger = false; doNotTrigger = false;
} }
@ -222,14 +282,16 @@ var SelectionMixin = {
this._unselectAll(true); 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 { else {
node.unselect();
this._removeFromSelection(node);
object.unselect();
this._removeFromSelection(object);
} }
if (doNotTrigger == false) { if (doNotTrigger == false) {
this._trigger('select'); this._trigger('select');
@ -266,10 +328,16 @@ var SelectionMixin = {
_handleTap : function(pointer) { _handleTap : function(pointer) {
var node = this._getNodeAt(pointer); var node = this._getNodeAt(pointer);
if (node != null) { if (node != null) {
this._selectNode(node,false);
this._selectObject(node,false);
} }
else { else {
this._unselectAll();
var edge = this._getEdgeAt(pointer);
if (edge != null) {
this._selectObject(edge,false);
}
else {
this._unselectAll();
}
} }
this._redraw(); this._redraw();
}, },
@ -301,7 +369,13 @@ var SelectionMixin = {
_handleOnHold : function(pointer) { _handleOnHold : function(pointer) {
var node = this._getNodeAt(pointer); var node = this._getNodeAt(pointer);
if (node != null) { 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(); this._redraw();
}, },
@ -323,12 +397,52 @@ var SelectionMixin = {
/** /**
* *
* retrieve the currently selected nodes
* retrieve the currently selected objects
* @return {Number[] | String[]} selection An array with the ids of the * @return {Number[] | String[]} selection An array with the ids of the
* selected nodes. * selected nodes.
*/ */
getSelection : function() { getSelection : function() {
return this.selection.concat([]);
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.
*/
getSelectedNodes : function() {
var idArray = [];
for(var objectId in this.selectionObj) {
if(this.selectionObj.hasOwnProperty(objectId)) {
if (this.selectionObj[objectId] instanceof Node) {
idArray.push(objectId);
}
}
}
return idArray
},
/**
*
* retrieve the currently selected edges
* @return {Array} selection An array with the ids of the
* selected nodes.
*/
getSelectedEdges : function() {
var idArray = [];
for(var objectId in this.selectionObj) {
if(this.selectionObj.hasOwnProperty(objectId)) {
if (this.selectionObj[objectId] instanceof Edge) {
idArray.push(objectId);
}
}
}
return idArray
}, },
/** /**
@ -342,8 +456,6 @@ var SelectionMixin = {
}, },
/** /**
* // TODO: rework this function, it is from the old system
*
* select zero or more nodes * select zero or more nodes
* @param {Number[] | String[]} selection An array with the ids of the * @param {Number[] | String[]} selection An array with the ids of the
* selected nodes. * selected nodes.
@ -364,7 +476,7 @@ var SelectionMixin = {
if (!node) { if (!node) {
throw new RangeError('Node with id "' + id + '" not found'); throw new RangeError('Node with id "' + id + '" not found');
} }
this._selectNode(node,true,true);
this._selectObject(node,true,true);
} }
this.redraw(); this.redraw();
@ -372,135 +484,28 @@ var SelectionMixin = {
/** /**
* TODO: rework this function, it is from the old system
*
* Validate the selection: remove ids of nodes which no longer exist * Validate the selection: remove ids of nodes which no longer exist
* @private * @private
*/ */
_updateSelection : function () { _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;
}
else {
j++;
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 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;
},
*/
}; };

Loading…
Cancel
Save