vis-rails 0.0.6 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/lib/vis/rails/version.rb +1 -1
  3. data/vendor/assets/javascripts/vis.js +2 -9
  4. data/vendor/assets/vis/DataSet.js +17 -9
  5. data/vendor/assets/vis/graph/Edge.js +49 -24
  6. data/vendor/assets/vis/graph/Graph.js +268 -64
  7. data/vendor/assets/vis/graph/Groups.js +1 -1
  8. data/vendor/assets/vis/graph/Node.js +18 -67
  9. data/vendor/assets/vis/graph/Popup.js +40 -13
  10. data/vendor/assets/vis/graph/css/graph-navigation.css +18 -14
  11. data/vendor/assets/vis/graph/graphMixins/ClusterMixin.js +7 -5
  12. data/vendor/assets/vis/graph/graphMixins/HierarchicalLayoutMixin.js +20 -5
  13. data/vendor/assets/vis/graph/graphMixins/ManipulationMixin.js +33 -33
  14. data/vendor/assets/vis/graph/graphMixins/MixinLoader.js +30 -32
  15. data/vendor/assets/vis/graph/graphMixins/NavigationMixin.js +33 -1
  16. data/vendor/assets/vis/graph/graphMixins/SectorsMixin.js +2 -2
  17. data/vendor/assets/vis/graph/graphMixins/SelectionMixin.js +72 -60
  18. data/vendor/assets/vis/graph/graphMixins/physics/BarnesHut.js +43 -18
  19. data/vendor/assets/vis/graph/graphMixins/physics/HierarchialRepulsion.js +8 -8
  20. data/vendor/assets/vis/graph/graphMixins/physics/PhysicsMixin.js +309 -129
  21. data/vendor/assets/vis/graph/graphMixins/physics/Repulsion.js +10 -10
  22. data/vendor/assets/vis/module/exports.js +1 -2
  23. data/vendor/assets/vis/module/header.js +2 -2
  24. data/vendor/assets/vis/timeline/Range.js +53 -93
  25. data/vendor/assets/vis/timeline/Timeline.js +328 -224
  26. data/vendor/assets/vis/timeline/component/Component.js +17 -95
  27. data/vendor/assets/vis/timeline/component/CurrentTime.js +54 -59
  28. data/vendor/assets/vis/timeline/component/CustomTime.js +55 -83
  29. data/vendor/assets/vis/timeline/component/Group.js +398 -75
  30. data/vendor/assets/vis/timeline/component/ItemSet.js +662 -403
  31. data/vendor/assets/vis/timeline/component/Panel.js +118 -60
  32. data/vendor/assets/vis/timeline/component/RootPanel.js +80 -132
  33. data/vendor/assets/vis/timeline/component/TimeAxis.js +191 -277
  34. data/vendor/assets/vis/timeline/component/css/item.css +16 -23
  35. data/vendor/assets/vis/timeline/component/css/itemset.css +25 -4
  36. data/vendor/assets/vis/timeline/component/css/labelset.css +34 -0
  37. data/vendor/assets/vis/timeline/component/css/panel.css +15 -1
  38. data/vendor/assets/vis/timeline/component/css/timeaxis.css +8 -8
  39. data/vendor/assets/vis/timeline/component/item/Item.js +48 -26
  40. data/vendor/assets/vis/timeline/component/item/ItemBox.js +156 -230
  41. data/vendor/assets/vis/timeline/component/item/ItemPoint.js +118 -166
  42. data/vendor/assets/vis/timeline/component/item/ItemRange.js +135 -187
  43. data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +29 -92
  44. data/vendor/assets/vis/timeline/stack.js +112 -0
  45. data/vendor/assets/vis/util.js +136 -38
  46. metadata +4 -18
  47. data/vendor/assets/vis/.gitignore +0 -1
  48. data/vendor/assets/vis/EventBus.js +0 -89
  49. data/vendor/assets/vis/events.js +0 -116
  50. data/vendor/assets/vis/graph/ClusterMixin.js +0 -1019
  51. data/vendor/assets/vis/graph/NavigationMixin.js +0 -245
  52. data/vendor/assets/vis/graph/SectorsMixin.js +0 -547
  53. data/vendor/assets/vis/graph/SelectionMixin.js +0 -515
  54. data/vendor/assets/vis/graph/img/downarrow.png +0 -0
  55. data/vendor/assets/vis/graph/img/leftarrow.png +0 -0
  56. data/vendor/assets/vis/graph/img/rightarrow.png +0 -0
  57. data/vendor/assets/vis/graph/img/uparrow.png +0 -0
  58. data/vendor/assets/vis/timeline/Controller.js +0 -183
  59. data/vendor/assets/vis/timeline/Stack.js +0 -190
  60. data/vendor/assets/vis/timeline/component/ContentPanel.js +0 -113
  61. data/vendor/assets/vis/timeline/component/GroupSet.js +0 -580
  62. data/vendor/assets/vis/timeline/component/css/groupset.css +0 -59
@@ -74,7 +74,7 @@ Groups.prototype.get = function (groupname) {
74
74
  Groups.prototype.add = function (groupname, style) {
75
75
  this.groups[groupname] = style;
76
76
  if (style.color) {
77
- style.color = Node.parseColor(style.color);
77
+ style.color = util.parseColor(style.color);
78
78
  }
79
79
  return style;
80
80
  };
@@ -42,8 +42,8 @@ function Node(properties, imagelist, grouplist, constants) {
42
42
  this.id = undefined;
43
43
  this.shape = constants.nodes.shape;
44
44
  this.image = constants.nodes.image;
45
- this.x = 0;
46
- this.y = 0;
45
+ this.x = null;
46
+ this.y = null;
47
47
  this.xFixed = false;
48
48
  this.yFixed = false;
49
49
  this.horizontalAlignLeft = true; // these are for the navigation controls
@@ -54,6 +54,8 @@ function Node(properties, imagelist, grouplist, constants) {
54
54
  this.radiusMin = constants.nodes.radiusMin;
55
55
  this.radiusMax = constants.nodes.radiusMax;
56
56
  this.level = -1;
57
+ this.preassignedLevel = false;
58
+
57
59
 
58
60
  this.imagelist = imagelist;
59
61
  this.grouplist = grouplist;
@@ -66,6 +68,7 @@ function Node(properties, imagelist, grouplist, constants) {
66
68
  this.minForce = constants.minForce;
67
69
  this.damping = constants.physics.damping;
68
70
  this.mass = 1; // kg
71
+ this.fixedData = {x:null,y:null};
69
72
 
70
73
  this.setProperties(properties, constants);
71
74
 
@@ -145,12 +148,10 @@ Node.prototype.setProperties = function(properties, constants) {
145
148
  if (properties.x !== undefined) {this.x = properties.x;}
146
149
  if (properties.y !== undefined) {this.y = properties.y;}
147
150
  if (properties.value !== undefined) {this.value = properties.value;}
148
- if (properties.level !== undefined) {this.level = properties.level;}
151
+ if (properties.level !== undefined) {this.level = properties.level; this.preassignedLevel = true;}
149
152
 
150
153
 
151
154
  // physics
152
- if (properties.internalMultiplier !== undefined) {this.internalMultiplier = properties.internalMultiplier;}
153
- if (properties.damping !== undefined) {this.dampingBase = properties.damping;}
154
155
  if (properties.mass !== undefined) {this.mass = properties.mass;}
155
156
 
156
157
  // navigation controls properties
@@ -176,13 +177,13 @@ Node.prototype.setProperties = function(properties, constants) {
176
177
  if (properties.shape !== undefined) {this.shape = properties.shape;}
177
178
  if (properties.image !== undefined) {this.image = properties.image;}
178
179
  if (properties.radius !== undefined) {this.radius = properties.radius;}
179
- if (properties.color !== undefined) {this.color = Node.parseColor(properties.color);}
180
+ if (properties.color !== undefined) {this.color = util.parseColor(properties.color);}
180
181
 
181
182
  if (properties.fontColor !== undefined) {this.fontColor = properties.fontColor;}
182
183
  if (properties.fontSize !== undefined) {this.fontSize = properties.fontSize;}
183
184
  if (properties.fontFace !== undefined) {this.fontFace = properties.fontFace;}
184
185
 
185
- if (this.image !== undefined) {
186
+ if (this.image !== undefined && this.image != "") {
186
187
  if (this.imagelist) {
187
188
  this.imageObj = this.imagelist.load(this.image);
188
189
  }
@@ -191,8 +192,8 @@ Node.prototype.setProperties = function(properties, constants) {
191
192
  }
192
193
  }
193
194
 
194
- this.xFixed = this.xFixed || (properties.x !== undefined && !properties.allowedToMove);
195
- this.yFixed = this.yFixed || (properties.y !== undefined && !properties.allowedToMove);
195
+ this.xFixed = this.xFixed || (properties.x !== undefined && !properties.allowedToMoveX);
196
+ this.yFixed = this.yFixed || (properties.y !== undefined && !properties.allowedToMoveY);
196
197
  this.radiusFixed = this.radiusFixed || (properties.radius !== undefined);
197
198
 
198
199
  if (this.shape == 'image') {
@@ -220,63 +221,6 @@ Node.prototype.setProperties = function(properties, constants) {
220
221
  this._reset();
221
222
  };
222
223
 
223
- /**
224
- * Parse a color property into an object with border, background, and
225
- * hightlight colors
226
- * @param {Object | String} color
227
- * @return {Object} colorObject
228
- */
229
- Node.parseColor = function(color) {
230
- var c;
231
- if (util.isString(color)) {
232
- if (util.isValidHex(color)) {
233
- var hsv = util.hexToHSV(color);
234
- var lighterColorHSV = {h:hsv.h,s:hsv.s * 0.45,v:Math.min(1,hsv.v * 1.05)};
235
- var darkerColorHSV = {h:hsv.h,s:Math.min(1,hsv.v * 1.25),v:hsv.v*0.6};
236
- var darkerColorHex = util.HSVToHex(darkerColorHSV.h ,darkerColorHSV.h ,darkerColorHSV.v);
237
- var lighterColorHex = util.HSVToHex(lighterColorHSV.h,lighterColorHSV.s,lighterColorHSV.v);
238
-
239
- c = {
240
- background: color,
241
- border:darkerColorHex,
242
- highlight: {
243
- background:lighterColorHex,
244
- border:darkerColorHex
245
- }
246
- };
247
- }
248
- else {
249
- c = {
250
- background:color,
251
- border:color,
252
- highlight: {
253
- background:color,
254
- border:color
255
- }
256
- };
257
- }
258
- }
259
- else {
260
- c = {};
261
- c.background = color.background || 'white';
262
- c.border = color.border || c.background;
263
-
264
- if (util.isString(color.highlight)) {
265
- c.highlight = {
266
- border: color.highlight,
267
- background: color.highlight
268
- }
269
- }
270
- else {
271
- c.highlight = {};
272
- c.highlight.background = color.highlight && color.highlight.background || c.background;
273
- c.highlight.border = color.highlight && color.highlight.border || c.border;
274
- }
275
- }
276
-
277
- return c;
278
- };
279
-
280
224
  /**
281
225
  * select this node
282
226
  */
@@ -316,7 +260,7 @@ Node.prototype._reset = function() {
316
260
  * has been set.
317
261
  */
318
262
  Node.prototype.getTitle = function() {
319
- return this.title;
263
+ return typeof this.title === "function" ? this.title() : this.title;
320
264
  };
321
265
 
322
266
  /**
@@ -412,6 +356,7 @@ Node.prototype.discreteStep = function(interval) {
412
356
  /**
413
357
  * Perform one discrete step for the node
414
358
  * @param {number} interval Time interval in seconds
359
+ * @param {number} maxVelocity The speed limit imposed on the velocity
415
360
  */
416
361
  Node.prototype.discreteStepLimited = function(interval, maxVelocity) {
417
362
  if (!this.xFixed) {
@@ -421,6 +366,9 @@ Node.prototype.discreteStepLimited = function(interval, maxVelocity) {
421
366
  this.vx = (Math.abs(this.vx) > maxVelocity) ? ((this.vx > 0) ? maxVelocity : -maxVelocity) : this.vx;
422
367
  this.x += this.vx * interval; // position
423
368
  }
369
+ else {
370
+ this.fx = 0;
371
+ }
424
372
 
425
373
  if (!this.yFixed) {
426
374
  var dy = this.damping * this.vy; // damping force
@@ -429,6 +377,9 @@ Node.prototype.discreteStepLimited = function(interval, maxVelocity) {
429
377
  this.vy = (Math.abs(this.vy) > maxVelocity) ? ((this.vy > 0) ? maxVelocity : -maxVelocity) : this.vy;
430
378
  this.y += this.vy * interval; // position
431
379
  }
380
+ else {
381
+ this.fy = 0;
382
+ }
432
383
  };
433
384
 
434
385
  /**
@@ -4,14 +4,39 @@
4
4
  * @param {Number} [x]
5
5
  * @param {Number} [y]
6
6
  * @param {String} [text]
7
+ * @param {Object} [style] An object containing borderColor,
8
+ * backgroundColor, etc.
7
9
  */
8
- function Popup(container, x, y, text) {
10
+ function Popup(container, x, y, text, style) {
9
11
  if (container) {
10
12
  this.container = container;
11
13
  }
12
14
  else {
13
15
  this.container = document.body;
14
16
  }
17
+
18
+ // x, y and text are optional, see if a style object was passed in their place
19
+ if (style === undefined) {
20
+ if (typeof x === "object") {
21
+ style = x;
22
+ x = undefined;
23
+ } else if (typeof text === "object") {
24
+ style = text;
25
+ text = undefined;
26
+ } else {
27
+ // for backwards compatibility, in case clients other than Graph are creating Popup directly
28
+ style = {
29
+ fontColor: 'black',
30
+ fontSize: 14, // px
31
+ fontFace: 'verdana',
32
+ color: {
33
+ border: '#666',
34
+ background: '#FFFFC6'
35
+ }
36
+ }
37
+ }
38
+ }
39
+
15
40
  this.x = 0;
16
41
  this.y = 0;
17
42
  this.padding = 5;
@@ -25,18 +50,20 @@ function Popup(container, x, y, text) {
25
50
 
26
51
  // create the frame
27
52
  this.frame = document.createElement("div");
28
- var style = this.frame.style;
29
- style.position = "absolute";
30
- style.visibility = "hidden";
31
- style.border = "1px solid #666";
32
- style.color = "black";
33
- style.padding = this.padding + "px";
34
- style.backgroundColor = "#FFFFC6";
35
- style.borderRadius = "3px";
36
- style.MozBorderRadius = "3px";
37
- style.WebkitBorderRadius = "3px";
38
- style.boxShadow = "3px 3px 10px rgba(128, 128, 128, 0.5)";
39
- style.whiteSpace = "nowrap";
53
+ var styleAttr = this.frame.style;
54
+ styleAttr.position = "absolute";
55
+ styleAttr.visibility = "hidden";
56
+ styleAttr.border = "1px solid " + style.color.border;
57
+ styleAttr.color = style.fontColor;
58
+ styleAttr.fontSize = style.fontSize + "px";
59
+ styleAttr.fontFamily = style.fontFace;
60
+ styleAttr.padding = this.padding + "px";
61
+ styleAttr.backgroundColor = style.color.background;
62
+ styleAttr.borderRadius = "3px";
63
+ styleAttr.MozBorderRadius = "3px";
64
+ styleAttr.WebkitBorderRadius = "3px";
65
+ styleAttr.boxShadow = "3px 3px 10px rgba(128, 128, 128, 0.5)";
66
+ styleAttr.whiteSpace = "nowrap";
40
67
  this.container.appendChild(this.frame);
41
68
  }
42
69
 
@@ -25,38 +25,42 @@ div.graph-navigation:active {
25
25
  box-shadow: 0px 0px 1px 3px rgba(56, 207, 21, 0.95);
26
26
  }
27
27
 
28
+ div.graph-navigation.active {
29
+ box-shadow: 0px 0px 1px 3px rgba(56, 207, 21, 0.95);
30
+ }
31
+
28
32
  div.graph-navigation.up {
29
33
  background-image: url("img/graph/upArrow.png");
30
- margin-top:520px;
31
- margin-left:55px;
34
+ bottom:50px;
35
+ left:55px;
32
36
  }
33
37
  div.graph-navigation.down {
34
38
  background-image: url("img/graph/downArrow.png");
35
- margin-top:560px;
36
- margin-left:55px;
39
+ bottom:10px;
40
+ left:55px;
37
41
  }
38
42
  div.graph-navigation.left {
39
43
  background-image: url("img/graph/leftArrow.png");
40
- margin-top:560px;
41
- margin-left:15px;
44
+ bottom:10px;
45
+ left:15px;
42
46
  }
43
47
  div.graph-navigation.right {
44
48
  background-image: url("img/graph/rightArrow.png");
45
- margin-top:560px;
46
- margin-left:95px;
49
+ bottom:10px;
50
+ left:95px;
47
51
  }
48
52
  div.graph-navigation.zoomIn {
49
53
  background-image: url("img/graph/plus.png");
50
- margin-top:560px;
51
- margin-left:555px;
54
+ bottom:10px;
55
+ right:15px;
52
56
  }
53
57
  div.graph-navigation.zoomOut {
54
58
  background-image: url("img/graph/minus.png");
55
- margin-top:560px;
56
- margin-left:515px;
59
+ bottom:10px;
60
+ right:55px;
57
61
  }
58
62
  div.graph-navigation.zoomExtends {
59
63
  background-image: url("img/graph/zoomExtends.png");
60
- margin-top:520px;
61
- margin-left:555px;
64
+ bottom:50px;
65
+ right:15px;
62
66
  }
@@ -22,7 +22,7 @@ var ClusterMixin = {
22
22
  // this is called here because if clusterin is disabled, the start and stabilize are called in
23
23
  // the setData function.
24
24
  if (this.stabilize) {
25
- this._doStabilize();
25
+ this._stabilize();
26
26
  }
27
27
  this.start();
28
28
  },
@@ -137,6 +137,7 @@ var ClusterMixin = {
137
137
  * @param {Number} zoomDirection | -1 / 0 / +1 for zoomOut / determineByZoom / zoomIn
138
138
  * @param {Boolean} recursive | enabled or disable recursive calling of the opening of clusters
139
139
  * @param {Boolean} force | enabled or disable forcing
140
+ * @param {Boolean} doNotStart | if true do not call start
140
141
  *
141
142
  */
142
143
  updateClusters : function(zoomDirection,recursive,force,doNotStart) {
@@ -987,9 +988,10 @@ var ClusterMixin = {
987
988
  var maxLevel = 0;
988
989
  var minLevel = 1e9;
989
990
  var clusterLevel = 0;
991
+ var nodeId;
990
992
 
991
993
  // we loop over all nodes in the list
992
- for (var nodeId in this.nodes) {
994
+ for (nodeId in this.nodes) {
993
995
  if (this.nodes.hasOwnProperty(nodeId)) {
994
996
  clusterLevel = this.nodes[nodeId].clusterSessions.length;
995
997
  if (maxLevel < clusterLevel) {maxLevel = clusterLevel;}
@@ -1001,7 +1003,7 @@ var ClusterMixin = {
1001
1003
  var amountOfNodes = this.nodeIndices.length;
1002
1004
  var targetLevel = maxLevel - this.constants.clustering.clusterLevelDifference;
1003
1005
  // we loop over all nodes in the list
1004
- for (var nodeId in this.nodes) {
1006
+ for (nodeId in this.nodes) {
1005
1007
  if (this.nodes.hasOwnProperty(nodeId)) {
1006
1008
  if (this.nodes[nodeId].clusterSessions.length < targetLevel) {
1007
1009
  this._clusterToSmallestNeighbour(this.nodes[nodeId]);
@@ -1044,8 +1046,8 @@ var ClusterMixin = {
1044
1046
  repositionNodes : function() {
1045
1047
  for (var i = 0; i < this.nodeIndices.length; i++) {
1046
1048
  var node = this.nodes[this.nodeIndices[i]];
1047
- if ((node.xFixed == false || node.yFixed == false) && this.createNodeOnClick != true) {
1048
- var radius = this.constants.physics.springLength * Math.min(100,node.mass);
1049
+ if ((node.xFixed == false || node.yFixed == false)) {
1050
+ var radius = 10 * 0.1*this.nodeIndices.length * Math.min(100,node.mass);
1049
1051
  var angle = 2 * Math.PI * Math.random();
1050
1052
  if (node.xFixed == false) {node.x = radius * Math.cos(angle);}
1051
1053
  if (node.yFixed == false) {node.y = radius * Math.sin(angle);}
@@ -1,6 +1,18 @@
1
1
  var HierarchicalLayoutMixin = {
2
2
 
3
3
 
4
+
5
+ _resetLevels : function() {
6
+ for (var nodeId in this.nodes) {
7
+ if (this.nodes.hasOwnProperty(nodeId)) {
8
+ var node = this.nodes[nodeId];
9
+ if (node.preassignedLevel == false) {
10
+ node.level = -1;
11
+ }
12
+ }
13
+ }
14
+ },
15
+
4
16
  /**
5
17
  * This is the main function to layout the nodes in a hierarchical way.
6
18
  * It checks if the node details are supplied correctly
@@ -12,6 +24,9 @@ var HierarchicalLayoutMixin = {
12
24
  if (this.constants.hierarchicalLayout.direction == "RL" || this.constants.hierarchicalLayout.direction == "DU") {
13
25
  this.constants.hierarchicalLayout.levelSeparation *= -1;
14
26
  }
27
+ else {
28
+ this.constants.hierarchicalLayout.levelSeparation = Math.abs(this.constants.hierarchicalLayout.levelSeparation);
29
+ }
15
30
  // get the size of the largest hubs and check if the user has defined a level for a node.
16
31
  var hubsize = 0;
17
32
  var node, nodeId;
@@ -35,7 +50,7 @@ var HierarchicalLayoutMixin = {
35
50
 
36
51
  // if the user defined some levels but not all, alert and run without hierarchical layout
37
52
  if (undefinedLevel == true && definedLevel == true) {
38
- alert("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes.")
53
+ alert("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes.");
39
54
  this.zoomExtent(true,this.constants.clustering.enabled);
40
55
  if (!this.constants.clustering.enabled) {
41
56
  this.start();
@@ -96,7 +111,7 @@ var HierarchicalLayoutMixin = {
96
111
  }
97
112
 
98
113
  // stabilize the system after positioning. This function calls zoomExtent.
99
- this._doStabilize();
114
+ this._stabilize();
100
115
  },
101
116
 
102
117
 
@@ -108,7 +123,7 @@ var HierarchicalLayoutMixin = {
108
123
  */
109
124
  _getDistribution : function() {
110
125
  var distribution = {};
111
- var nodeId, node;
126
+ var nodeId, node, level;
112
127
 
113
128
  // we fix Y because the hierarchy is vertical, we fix X so we do not give a node an x position for a second time.
114
129
  // the fix of X is removed after the x value has been set.
@@ -133,7 +148,7 @@ var HierarchicalLayoutMixin = {
133
148
 
134
149
  // determine the largest amount of nodes of all levels
135
150
  var maxCount = 0;
136
- for (var level in distribution) {
151
+ for (level in distribution) {
137
152
  if (distribution.hasOwnProperty(level)) {
138
153
  if (maxCount < distribution[level].amount) {
139
154
  maxCount = distribution[level].amount;
@@ -142,7 +157,7 @@ var HierarchicalLayoutMixin = {
142
157
  }
143
158
 
144
159
  // set the initial position and spacing of each nodes accordingly
145
- for (var level in distribution) {
160
+ for (level in distribution) {
146
161
  if (distribution.hasOwnProperty(level)) {
147
162
  distribution[level].nodeSpacing = (maxCount + 1) * this.constants.hierarchicalLayout.nodeSpacing;
148
163
  distribution[level].nodeSpacing /= (distribution[level].amount + 1);
@@ -62,7 +62,9 @@ var manipulationMixin = {
62
62
  */
63
63
  _createManipulatorBar : function() {
64
64
  // remove bound functions
65
- this.off('select', this.boundFunction);
65
+ if (this.boundFunction) {
66
+ this.off('select', this.boundFunction);
67
+ }
66
68
 
67
69
  // restore overloaded functions
68
70
  this._restoreOverloadedFunctions();
@@ -72,7 +74,7 @@ var manipulationMixin = {
72
74
 
73
75
  // reset global variables
74
76
  this.blockConnectingEdgeSelection = false;
75
- this.forceAppendSelection = false
77
+ this.forceAppendSelection = false;
76
78
 
77
79
  if (this.editMode == true) {
78
80
  while (this.manipulationDiv.hasChildNodes()) {
@@ -81,21 +83,21 @@ var manipulationMixin = {
81
83
  // add the icons to the manipulator div
82
84
  this.manipulationDiv.innerHTML = "" +
83
85
  "<span class='graph-manipulationUI add' id='graph-manipulate-addNode'>" +
84
- "<span class='graph-manipulationLabel'>Add Node</span></span>" +
86
+ "<span class='graph-manipulationLabel'>"+this.constants.labels['add'] +"</span></span>" +
85
87
  "<div class='graph-seperatorLine'></div>" +
86
88
  "<span class='graph-manipulationUI connect' id='graph-manipulate-connectNode'>" +
87
- "<span class='graph-manipulationLabel'>Add Link</span></span>";
89
+ "<span class='graph-manipulationLabel'>"+this.constants.labels['link'] +"</span></span>";
88
90
  if (this._getSelectedNodeCount() == 1 && this.triggerFunctions.edit) {
89
91
  this.manipulationDiv.innerHTML += "" +
90
92
  "<div class='graph-seperatorLine'></div>" +
91
93
  "<span class='graph-manipulationUI edit' id='graph-manipulate-editNode'>" +
92
- "<span class='graph-manipulationLabel'>Edit Node</span></span>";
94
+ "<span class='graph-manipulationLabel'>"+this.constants.labels['editNode'] +"</span></span>";
93
95
  }
94
96
  if (this._selectionIsEmpty() == false) {
95
97
  this.manipulationDiv.innerHTML += "" +
96
98
  "<div class='graph-seperatorLine'></div>" +
97
99
  "<span class='graph-manipulationUI delete' id='graph-manipulate-delete'>" +
98
- "<span class='graph-manipulationLabel'>Delete selected</span></span>";
100
+ "<span class='graph-manipulationLabel'>"+this.constants.labels['del'] +"</span></span>";
99
101
  }
100
102
 
101
103
 
@@ -121,7 +123,7 @@ var manipulationMixin = {
121
123
  else {
122
124
  this.editModeDiv.innerHTML = "" +
123
125
  "<span class='graph-manipulationUI edit editmode' id='graph-manipulate-editModeButton'>" +
124
- "<span class='graph-manipulationLabel'>Edit</span></span>"
126
+ "<span class='graph-manipulationLabel'>" + this.constants.labels['edit'] + "</span></span>";
125
127
  var editModeButton = document.getElementById("graph-manipulate-editModeButton");
126
128
  editModeButton.onclick = this._toggleEditMode.bind(this);
127
129
  }
@@ -137,15 +139,17 @@ var manipulationMixin = {
137
139
  _createAddNodeToolbar : function() {
138
140
  // clear the toolbar
139
141
  this._clearManipulatorBar();
140
- this.off('select', this.boundFunction);
142
+ if (this.boundFunction) {
143
+ this.off('select', this.boundFunction);
144
+ }
141
145
 
142
146
  // create the toolbar contents
143
147
  this.manipulationDiv.innerHTML = "" +
144
148
  "<span class='graph-manipulationUI back' id='graph-manipulate-back'>" +
145
- "<span class='graph-manipulationLabel'>Back</span></span>" +
149
+ "<span class='graph-manipulationLabel'>" + this.constants.labels['back'] + " </span></span>" +
146
150
  "<div class='graph-seperatorLine'></div>" +
147
151
  "<span class='graph-manipulationUI none' id='graph-manipulate-back'>" +
148
- "<span class='graph-manipulationLabel'>Click in an empty space to place a new node</span></span>";
152
+ "<span id='graph-manipulatorLabel' class='graph-manipulationLabel'>" + this.constants.labels['addDescription'] + "</span></span>";
149
153
 
150
154
  // bind the icon
151
155
  var backButton = document.getElementById("graph-manipulate-back");
@@ -168,7 +172,9 @@ var manipulationMixin = {
168
172
  this._unselectAll(true);
169
173
  this.freezeSimulation = true;
170
174
 
171
- this.off('select', this.boundFunction);
175
+ if (this.boundFunction) {
176
+ this.off('select', this.boundFunction);
177
+ }
172
178
 
173
179
  this._unselectAll();
174
180
  this.forceAppendSelection = false;
@@ -176,10 +182,10 @@ var manipulationMixin = {
176
182
 
177
183
  this.manipulationDiv.innerHTML = "" +
178
184
  "<span class='graph-manipulationUI back' id='graph-manipulate-back'>" +
179
- "<span class='graph-manipulationLabel'>Back</span></span>" +
185
+ "<span class='graph-manipulationLabel'>" + this.constants.labels['back'] + " </span></span>" +
180
186
  "<div class='graph-seperatorLine'></div>" +
181
187
  "<span class='graph-manipulationUI none' id='graph-manipulate-back'>" +
182
- "<span id='graph-manipulatorLabel' class='graph-manipulationLabel'>Click on a node and drag the edge to another node to connect them.</span></span>";
188
+ "<span id='graph-manipulatorLabel' class='graph-manipulationLabel'>" + this.constants.labels['linkDescription'] + "</span></span>";
183
189
 
184
190
  // bind the icon
185
191
  var backButton = document.getElementById("graph-manipulate-back");
@@ -261,7 +267,7 @@ var manipulationMixin = {
261
267
  var connectFromId = this.edges['connectionEdge'].fromId;
262
268
 
263
269
  // remove the temporary nodes and edge
264
- delete this.edges['connectionEdge']
270
+ delete this.edges['connectionEdge'];
265
271
  delete this.sectors['support']['nodes']['targetNode'];
266
272
  delete this.sectors['support']['nodes']['targetViaNode'];
267
273
 
@@ -282,36 +288,30 @@ var manipulationMixin = {
282
288
 
283
289
  /**
284
290
  * Adds a node on the specified location
285
- *
286
- * @param {Object} pointer
287
291
  */
288
292
  _addNode : function() {
289
293
  if (this._selectionIsEmpty() && this.editMode == true) {
290
294
  var positionObject = this._pointerToPositionObject(this.pointerPosition);
291
- var defaultData = {id:util.randomUUID(),x:positionObject.left,y:positionObject.top,label:"new",allowedToMove:true};
295
+ var defaultData = {id:util.randomUUID(),x:positionObject.left,y:positionObject.top,label:"new",allowedToMoveX:true,allowedToMoveY:true};
292
296
  if (this.triggerFunctions.add) {
293
297
  if (this.triggerFunctions.add.length == 2) {
294
298
  var me = this;
295
299
  this.triggerFunctions.add(defaultData, function(finalizedData) {
296
- me.createNodeOnClick = true;
297
300
  me.nodesData.add(finalizedData);
298
- me.createNodeOnClick = false;
299
301
  me._createManipulatorBar();
300
302
  me.moving = true;
301
303
  me.start();
302
304
  });
303
305
  }
304
306
  else {
305
- alert("The function for add does not support two arguments (data,callback).");
307
+ alert(this.constants.labels['addError']);
306
308
  this._createManipulatorBar();
307
309
  this.moving = true;
308
310
  this.start();
309
311
  }
310
312
  }
311
313
  else {
312
- this.createNodeOnClick = true;
313
314
  this.nodesData.add(defaultData);
314
- this.createNodeOnClick = false;
315
315
  this._createManipulatorBar();
316
316
  this.moving = true;
317
317
  this.start();
@@ -332,19 +332,19 @@ var manipulationMixin = {
332
332
  if (this.triggerFunctions.connect.length == 2) {
333
333
  var me = this;
334
334
  this.triggerFunctions.connect(defaultData, function(finalizedData) {
335
- me.edgesData.add(finalizedData)
335
+ me.edgesData.add(finalizedData);
336
336
  me.moving = true;
337
337
  me.start();
338
338
  });
339
339
  }
340
340
  else {
341
- alert("The function for connect does not support two arguments (data,callback).");
341
+ alert(this.constants.labels["linkError"]);
342
342
  this.moving = true;
343
343
  this.start();
344
344
  }
345
345
  }
346
346
  else {
347
- this.edgesData.add(defaultData)
347
+ this.edgesData.add(defaultData);
348
348
  this.moving = true;
349
349
  this.start();
350
350
  }
@@ -382,11 +382,11 @@ var manipulationMixin = {
382
382
  });
383
383
  }
384
384
  else {
385
- alert("The function for edit does not support two arguments (data, callback).")
385
+ alert(this.constants.labels["editError"]);
386
386
  }
387
387
  }
388
388
  else {
389
- alert("No edit function has been bound to this button.")
389
+ alert(this.constants.labels["editBoundError"]);
390
390
  }
391
391
  },
392
392
 
@@ -401,20 +401,20 @@ var manipulationMixin = {
401
401
  if (!this._clusterInSelection()) {
402
402
  var selectedNodes = this.getSelectedNodes();
403
403
  var selectedEdges = this.getSelectedEdges();
404
- if (this.triggerFunctions.delete) {
404
+ if (this.triggerFunctions.del) {
405
405
  var me = this;
406
406
  var data = {nodes: selectedNodes, edges: selectedEdges};
407
- if (this.triggerFunctions.delete.length = 2) {
408
- this.triggerFunctions.delete(data, function (finalizedData) {
407
+ if (this.triggerFunctions.del.length = 2) {
408
+ this.triggerFunctions.del(data, function (finalizedData) {
409
409
  me.edgesData.remove(finalizedData.edges);
410
410
  me.nodesData.remove(finalizedData.nodes);
411
- this._unselectAll();
411
+ me._unselectAll();
412
412
  me.moving = true;
413
413
  me.start();
414
414
  });
415
415
  }
416
416
  else {
417
- alert("The function for edit does not support two arguments (data, callback).")
417
+ alert(this.constants.labels["deleteError"])
418
418
  }
419
419
  }
420
420
  else {
@@ -426,7 +426,7 @@ var manipulationMixin = {
426
426
  }
427
427
  }
428
428
  else {
429
- alert("Clusters cannot be deleted.");
429
+ alert(this.constants.labels["deleteClusterError"]);
430
430
  }
431
431
  }
432
432
  }