vis-rails 0.0.4 → 0.0.5

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 (58) hide show
  1. checksums.yaml +5 -13
  2. data/lib/vis/rails/version.rb +1 -1
  3. data/vendor/assets/component/emitter.js +162 -0
  4. data/vendor/assets/javascripts/vis.js +1 -0
  5. data/vendor/assets/vis/DataSet.js +8 -2
  6. data/vendor/assets/vis/DataView.js +8 -4
  7. data/vendor/assets/vis/graph/Edge.js +210 -78
  8. data/vendor/assets/vis/graph/Graph.js +474 -652
  9. data/vendor/assets/vis/graph/Node.js +119 -82
  10. data/vendor/assets/vis/graph/css/graph-manipulation.css +128 -0
  11. data/vendor/assets/vis/graph/css/graph-navigation.css +62 -0
  12. data/vendor/assets/vis/graph/graphMixins/ClusterMixin.js +1141 -0
  13. data/vendor/assets/vis/graph/graphMixins/HierarchicalLayoutMixin.js +296 -0
  14. data/vendor/assets/vis/graph/graphMixins/ManipulationMixin.js +433 -0
  15. data/vendor/assets/vis/graph/graphMixins/MixinLoader.js +201 -0
  16. data/vendor/assets/vis/graph/graphMixins/NavigationMixin.js +173 -0
  17. data/vendor/assets/vis/graph/graphMixins/SectorsMixin.js +552 -0
  18. data/vendor/assets/vis/graph/graphMixins/SelectionMixin.js +558 -0
  19. data/vendor/assets/vis/graph/graphMixins/physics/BarnesHut.js +373 -0
  20. data/vendor/assets/vis/graph/graphMixins/physics/HierarchialRepulsion.js +64 -0
  21. data/vendor/assets/vis/graph/graphMixins/physics/PhysicsMixin.js +513 -0
  22. data/vendor/assets/vis/graph/graphMixins/physics/Repulsion.js +66 -0
  23. data/vendor/assets/vis/graph/img/acceptDeleteIcon.png +0 -0
  24. data/vendor/assets/vis/graph/img/addNodeIcon.png +0 -0
  25. data/vendor/assets/vis/graph/img/backIcon.png +0 -0
  26. data/vendor/assets/vis/graph/img/connectIcon.png +0 -0
  27. data/vendor/assets/vis/graph/img/cross.png +0 -0
  28. data/vendor/assets/vis/graph/img/cross2.png +0 -0
  29. data/vendor/assets/vis/graph/img/deleteIcon.png +0 -0
  30. data/vendor/assets/vis/graph/img/downArrow.png +0 -0
  31. data/vendor/assets/vis/graph/img/editIcon.png +0 -0
  32. data/vendor/assets/vis/graph/img/leftArrow.png +0 -0
  33. data/vendor/assets/vis/graph/img/rightArrow.png +0 -0
  34. data/vendor/assets/vis/graph/img/upArrow.png +0 -0
  35. data/vendor/assets/vis/module/exports.js +0 -2
  36. data/vendor/assets/vis/module/header.js +2 -2
  37. data/vendor/assets/vis/module/imports.js +1 -2
  38. data/vendor/assets/vis/timeline/Controller.js +56 -45
  39. data/vendor/assets/vis/timeline/Range.js +68 -62
  40. data/vendor/assets/vis/timeline/Stack.js +11 -13
  41. data/vendor/assets/vis/timeline/TimeStep.js +43 -38
  42. data/vendor/assets/vis/timeline/Timeline.js +215 -93
  43. data/vendor/assets/vis/timeline/component/Component.js +19 -3
  44. data/vendor/assets/vis/timeline/component/CurrentTime.js +1 -1
  45. data/vendor/assets/vis/timeline/component/CustomTime.js +39 -120
  46. data/vendor/assets/vis/timeline/component/GroupSet.js +35 -1
  47. data/vendor/assets/vis/timeline/component/ItemSet.js +272 -9
  48. data/vendor/assets/vis/timeline/component/RootPanel.js +59 -47
  49. data/vendor/assets/vis/timeline/component/TimeAxis.js +10 -0
  50. data/vendor/assets/vis/timeline/component/css/item.css +53 -22
  51. data/vendor/assets/vis/timeline/component/item/Item.js +40 -5
  52. data/vendor/assets/vis/timeline/component/item/ItemBox.js +3 -1
  53. data/vendor/assets/vis/timeline/component/item/ItemPoint.js +3 -1
  54. data/vendor/assets/vis/timeline/component/item/ItemRange.js +67 -3
  55. data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +37 -9
  56. data/vendor/assets/vis/timeline/img/delete.png +0 -0
  57. data/vendor/assets/vis/util.js +169 -30
  58. metadata +39 -12
@@ -0,0 +1,373 @@
1
+ /**
2
+ * Created by Alex on 2/10/14.
3
+ */
4
+
5
+ var barnesHutMixin = {
6
+
7
+ /**
8
+ * This function calculates the forces the nodes apply on eachother based on a gravitational model.
9
+ * The Barnes Hut method is used to speed up this N-body simulation.
10
+ *
11
+ * @private
12
+ */
13
+ _calculateNodeForces : function() {
14
+ var node;
15
+ var nodes = this.calculationNodes;
16
+ var nodeIndices = this.calculationNodeIndices;
17
+ var nodeCount = nodeIndices.length;
18
+
19
+ this._formBarnesHutTree(nodes,nodeIndices);
20
+
21
+ var barnesHutTree = this.barnesHutTree;
22
+
23
+ // place the nodes one by one recursively
24
+ for (var i = 0; i < nodeCount; i++) {
25
+ node = nodes[nodeIndices[i]];
26
+ // starting with root is irrelevant, it never passes the BarnesHut condition
27
+ this._getForceContribution(barnesHutTree.root.children.NW,node);
28
+ this._getForceContribution(barnesHutTree.root.children.NE,node);
29
+ this._getForceContribution(barnesHutTree.root.children.SW,node);
30
+ this._getForceContribution(barnesHutTree.root.children.SE,node);
31
+ }
32
+ },
33
+
34
+
35
+ /**
36
+ * This function traverses the barnesHutTree. It checks when it can approximate distant nodes with their center of mass.
37
+ * If a region contains a single node, we check if it is not itself, then we apply the force.
38
+ *
39
+ * @param parentBranch
40
+ * @param node
41
+ * @private
42
+ */
43
+ _getForceContribution : function(parentBranch,node) {
44
+ // we get no force contribution from an empty region
45
+ if (parentBranch.childrenCount > 0) {
46
+ var dx,dy,distance;
47
+
48
+ // get the distance from the center of mass to the node.
49
+ dx = parentBranch.centerOfMass.x - node.x;
50
+ dy = parentBranch.centerOfMass.y - node.y;
51
+ distance = Math.sqrt(dx * dx + dy * dy);
52
+
53
+ // BarnesHut condition
54
+ // original condition : s/d < theta = passed === d/s > 1/theta = passed
55
+ // calcSize = 1/s --> d * 1/s > 1/theta = passed
56
+ if (distance * parentBranch.calcSize > this.constants.physics.barnesHut.theta) {
57
+ // duplicate code to reduce function calls to speed up program
58
+ if (distance == 0) {
59
+ distance = 0.1*Math.random();
60
+ dx = distance;
61
+ }
62
+ var gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.mass / (distance * distance * distance);
63
+ var fx = dx * gravityForce;
64
+ var fy = dy * gravityForce;
65
+ node.fx += fx;
66
+ node.fy += fy;
67
+ }
68
+ else {
69
+ // Did not pass the condition, go into children if available
70
+ if (parentBranch.childrenCount == 4) {
71
+ this._getForceContribution(parentBranch.children.NW,node);
72
+ this._getForceContribution(parentBranch.children.NE,node);
73
+ this._getForceContribution(parentBranch.children.SW,node);
74
+ this._getForceContribution(parentBranch.children.SE,node);
75
+ }
76
+ else { // parentBranch must have only one node, if it was empty we wouldnt be here
77
+ if (parentBranch.children.data.id != node.id) { // if it is not self
78
+ // duplicate code to reduce function calls to speed up program
79
+ if (distance == 0) {
80
+ distance = 0.5*Math.random();
81
+ dx = distance;
82
+ }
83
+ var gravityForce = this.constants.physics.barnesHut.gravitationalConstant * parentBranch.mass * node.mass / (distance * distance * distance);
84
+ var fx = dx * gravityForce;
85
+ var fy = dy * gravityForce;
86
+ node.fx += fx;
87
+ node.fy += fy;
88
+ }
89
+ }
90
+ }
91
+ }
92
+ },
93
+
94
+ /**
95
+ * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes.
96
+ *
97
+ * @param nodes
98
+ * @param nodeIndices
99
+ * @private
100
+ */
101
+ _formBarnesHutTree : function(nodes,nodeIndices) {
102
+ var node;
103
+ var nodeCount = nodeIndices.length;
104
+
105
+ var minX = Number.MAX_VALUE,
106
+ minY = Number.MAX_VALUE,
107
+ maxX =-Number.MAX_VALUE,
108
+ maxY =-Number.MAX_VALUE;
109
+
110
+ // get the range of the nodes
111
+ for (var i = 0; i < nodeCount; i++) {
112
+ var x = nodes[nodeIndices[i]].x;
113
+ var y = nodes[nodeIndices[i]].y;
114
+ if (x < minX) { minX = x; }
115
+ if (x > maxX) { maxX = x; }
116
+ if (y < minY) { minY = y; }
117
+ if (y > maxY) { maxY = y; }
118
+ }
119
+ // make the range a square
120
+ var sizeDiff = Math.abs(maxX - minX) - Math.abs(maxY - minY); // difference between X and Y
121
+ if (sizeDiff > 0) {minY -= 0.5 * sizeDiff; maxY += 0.5 * sizeDiff;} // xSize > ySize
122
+ else {minX += 0.5 * sizeDiff; maxX -= 0.5 * sizeDiff;} // xSize < ySize
123
+
124
+
125
+ var minimumTreeSize = 1e-5;
126
+ var rootSize = Math.max(minimumTreeSize,Math.abs(maxX - minX));
127
+ var halfRootSize = 0.5 * rootSize;
128
+ var centerX = 0.5 * (minX + maxX), centerY = 0.5 * (minY + maxY);
129
+
130
+ // construct the barnesHutTree
131
+ var barnesHutTree = {root:{
132
+ centerOfMass:{x:0,y:0}, // Center of Mass
133
+ mass:0,
134
+ range: {minX:centerX-halfRootSize,maxX:centerX+halfRootSize,
135
+ minY:centerY-halfRootSize,maxY:centerY+halfRootSize},
136
+ size: rootSize,
137
+ calcSize: 1 / rootSize,
138
+ children: {data:null},
139
+ maxWidth: 0,
140
+ level: 0,
141
+ childrenCount: 4
142
+ }};
143
+ this._splitBranch(barnesHutTree.root);
144
+
145
+ // place the nodes one by one recursively
146
+ for (i = 0; i < nodeCount; i++) {
147
+ node = nodes[nodeIndices[i]];
148
+ this._placeInTree(barnesHutTree.root,node);
149
+ }
150
+
151
+ // make global
152
+ this.barnesHutTree = barnesHutTree
153
+ },
154
+
155
+
156
+ _updateBranchMass : function(parentBranch, node) {
157
+ var totalMass = parentBranch.mass + node.mass;
158
+ var totalMassInv = 1/totalMass;
159
+
160
+ parentBranch.centerOfMass.x = parentBranch.centerOfMass.x * parentBranch.mass + node.x * node.mass;
161
+ parentBranch.centerOfMass.x *= totalMassInv;
162
+
163
+ parentBranch.centerOfMass.y = parentBranch.centerOfMass.y * parentBranch.mass + node.y * node.mass;
164
+ parentBranch.centerOfMass.y *= totalMassInv;
165
+
166
+ parentBranch.mass = totalMass;
167
+ var biggestSize = Math.max(Math.max(node.height,node.radius),node.width);
168
+ parentBranch.maxWidth = (parentBranch.maxWidth < biggestSize) ? biggestSize : parentBranch.maxWidth;
169
+
170
+ },
171
+
172
+
173
+ _placeInTree : function(parentBranch,node,skipMassUpdate) {
174
+ if (skipMassUpdate != true || skipMassUpdate === undefined) {
175
+ // update the mass of the branch.
176
+ this._updateBranchMass(parentBranch,node);
177
+ }
178
+
179
+ if (parentBranch.children.NW.range.maxX > node.x) { // in NW or SW
180
+ if (parentBranch.children.NW.range.maxY > node.y) { // in NW
181
+ this._placeInRegion(parentBranch,node,"NW");
182
+ }
183
+ else { // in SW
184
+ this._placeInRegion(parentBranch,node,"SW");
185
+ }
186
+ }
187
+ else { // in NE or SE
188
+ if (parentBranch.children.NW.range.maxY > node.y) { // in NE
189
+ this._placeInRegion(parentBranch,node,"NE");
190
+ }
191
+ else { // in SE
192
+ this._placeInRegion(parentBranch,node,"SE");
193
+ }
194
+ }
195
+ },
196
+
197
+
198
+ _placeInRegion : function(parentBranch,node,region) {
199
+ switch (parentBranch.children[region].childrenCount) {
200
+ case 0: // place node here
201
+ parentBranch.children[region].children.data = node;
202
+ parentBranch.children[region].childrenCount = 1;
203
+ this._updateBranchMass(parentBranch.children[region],node);
204
+ break;
205
+ case 1: // convert into children
206
+ // if there are two nodes exactly overlapping (on init, on opening of cluster etc.)
207
+ // we move one node a pixel and we do not put it in the tree.
208
+ if (parentBranch.children[region].children.data.x == node.x &&
209
+ parentBranch.children[region].children.data.y == node.y) {
210
+ node.x += Math.random();
211
+ node.y += Math.random();
212
+ this._placeInTree(parentBranch,node, true);
213
+ }
214
+ else {
215
+ this._splitBranch(parentBranch.children[region]);
216
+ this._placeInTree(parentBranch.children[region],node);
217
+ }
218
+ break;
219
+ case 4: // place in branch
220
+ this._placeInTree(parentBranch.children[region],node);
221
+ break;
222
+ }
223
+ },
224
+
225
+
226
+ /**
227
+ * this function splits a branch into 4 sub branches. If the branch contained a node, we place it in the subbranch
228
+ * after the split is complete.
229
+ *
230
+ * @param parentBranch
231
+ * @private
232
+ */
233
+ _splitBranch : function(parentBranch) {
234
+ // if the branch is filled with a node, replace the node in the new subset.
235
+ var containedNode = null;
236
+ if (parentBranch.childrenCount == 1) {
237
+ containedNode = parentBranch.children.data;
238
+ parentBranch.mass = 0; parentBranch.centerOfMass.x = 0; parentBranch.centerOfMass.y = 0;
239
+ }
240
+ parentBranch.childrenCount = 4;
241
+ parentBranch.children.data = null;
242
+ this._insertRegion(parentBranch,"NW");
243
+ this._insertRegion(parentBranch,"NE");
244
+ this._insertRegion(parentBranch,"SW");
245
+ this._insertRegion(parentBranch,"SE");
246
+
247
+ if (containedNode != null) {
248
+ this._placeInTree(parentBranch,containedNode);
249
+ }
250
+ },
251
+
252
+
253
+ /**
254
+ * This function subdivides the region into four new segments.
255
+ * Specifically, this inserts a single new segment.
256
+ * It fills the children section of the parentBranch
257
+ *
258
+ * @param parentBranch
259
+ * @param region
260
+ * @param parentRange
261
+ * @private
262
+ */
263
+ _insertRegion : function(parentBranch, region) {
264
+ var minX,maxX,minY,maxY;
265
+ var childSize = 0.5 * parentBranch.size;
266
+ switch (region) {
267
+ case "NW":
268
+ minX = parentBranch.range.minX;
269
+ maxX = parentBranch.range.minX + childSize;
270
+ minY = parentBranch.range.minY;
271
+ maxY = parentBranch.range.minY + childSize;
272
+ break;
273
+ case "NE":
274
+ minX = parentBranch.range.minX + childSize;
275
+ maxX = parentBranch.range.maxX;
276
+ minY = parentBranch.range.minY;
277
+ maxY = parentBranch.range.minY + childSize;
278
+ break;
279
+ case "SW":
280
+ minX = parentBranch.range.minX;
281
+ maxX = parentBranch.range.minX + childSize;
282
+ minY = parentBranch.range.minY + childSize;
283
+ maxY = parentBranch.range.maxY;
284
+ break;
285
+ case "SE":
286
+ minX = parentBranch.range.minX + childSize;
287
+ maxX = parentBranch.range.maxX;
288
+ minY = parentBranch.range.minY + childSize;
289
+ maxY = parentBranch.range.maxY;
290
+ break;
291
+ }
292
+
293
+
294
+ parentBranch.children[region] = {
295
+ centerOfMass:{x:0,y:0},
296
+ mass:0,
297
+ range:{minX:minX,maxX:maxX,minY:minY,maxY:maxY},
298
+ size: 0.5 * parentBranch.size,
299
+ calcSize: 2 * parentBranch.calcSize,
300
+ children: {data:null},
301
+ maxWidth: 0,
302
+ level: parentBranch.level+1,
303
+ childrenCount: 0
304
+ };
305
+ },
306
+
307
+
308
+ /**
309
+ * This function is for debugging purposed, it draws the tree.
310
+ *
311
+ * @param ctx
312
+ * @param color
313
+ * @private
314
+ */
315
+ _drawTree : function(ctx,color) {
316
+ if (this.barnesHutTree !== undefined) {
317
+
318
+ ctx.lineWidth = 1;
319
+
320
+ this._drawBranch(this.barnesHutTree.root,ctx,color);
321
+ }
322
+ },
323
+
324
+
325
+ /**
326
+ * This function is for debugging purposes. It draws the branches recursively.
327
+ *
328
+ * @param branch
329
+ * @param ctx
330
+ * @param color
331
+ * @private
332
+ */
333
+ _drawBranch : function(branch,ctx,color) {
334
+ if (color === undefined) {
335
+ color = "#FF0000";
336
+ }
337
+
338
+ if (branch.childrenCount == 4) {
339
+ this._drawBranch(branch.children.NW,ctx);
340
+ this._drawBranch(branch.children.NE,ctx);
341
+ this._drawBranch(branch.children.SE,ctx);
342
+ this._drawBranch(branch.children.SW,ctx);
343
+ }
344
+ ctx.strokeStyle = color;
345
+ ctx.beginPath();
346
+ ctx.moveTo(branch.range.minX,branch.range.minY);
347
+ ctx.lineTo(branch.range.maxX,branch.range.minY);
348
+ ctx.stroke();
349
+
350
+ ctx.beginPath();
351
+ ctx.moveTo(branch.range.maxX,branch.range.minY);
352
+ ctx.lineTo(branch.range.maxX,branch.range.maxY);
353
+ ctx.stroke();
354
+
355
+ ctx.beginPath();
356
+ ctx.moveTo(branch.range.maxX,branch.range.maxY);
357
+ ctx.lineTo(branch.range.minX,branch.range.maxY);
358
+ ctx.stroke();
359
+
360
+ ctx.beginPath();
361
+ ctx.moveTo(branch.range.minX,branch.range.maxY);
362
+ ctx.lineTo(branch.range.minX,branch.range.minY);
363
+ ctx.stroke();
364
+
365
+ /*
366
+ if (branch.mass > 0) {
367
+ ctx.circle(branch.centerOfMass.x, branch.centerOfMass.y, 3*branch.mass);
368
+ ctx.stroke();
369
+ }
370
+ */
371
+ }
372
+
373
+ };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Created by Alex on 2/10/14.
3
+ */
4
+
5
+ var hierarchalRepulsionMixin = {
6
+
7
+
8
+ /**
9
+ * Calculate the forces the nodes apply on eachother based on a repulsion field.
10
+ * This field is linearly approximated.
11
+ *
12
+ * @private
13
+ */
14
+ _calculateNodeForces : function() {
15
+ var dx, dy, distance, fx, fy, combinedClusterSize,
16
+ repulsingForce, node1, node2, i, j;
17
+
18
+ var nodes = this.calculationNodes;
19
+ var nodeIndices = this.calculationNodeIndices;
20
+
21
+ // approximation constants
22
+ var b = 5;
23
+ var a_base = 0.5*-b;
24
+
25
+
26
+ // repulsing forces between nodes
27
+ var nodeDistance = this.constants.physics.hierarchicalRepulsion.nodeDistance;
28
+ var minimumDistance = nodeDistance;
29
+
30
+ // we loop from i over all but the last entree in the array
31
+ // j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j
32
+ for (i = 0; i < nodeIndices.length-1; i++) {
33
+
34
+ node1 = nodes[nodeIndices[i]];
35
+ for (j = i+1; j < nodeIndices.length; j++) {
36
+ node2 = nodes[nodeIndices[j]];
37
+
38
+ dx = node2.x - node1.x;
39
+ dy = node2.y - node1.y;
40
+ distance = Math.sqrt(dx * dx + dy * dy);
41
+
42
+ var a = a_base / minimumDistance;
43
+ if (distance < 2*minimumDistance) {
44
+ repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / minimumDistance - 1) * steepness))
45
+
46
+ // normalize force with
47
+ if (distance == 0) {
48
+ distance = 0.01;
49
+ }
50
+ else {
51
+ repulsingForce = repulsingForce/distance;
52
+ }
53
+ fx = dx * repulsingForce;
54
+ fy = dy * repulsingForce;
55
+
56
+ node1.fx -= fx;
57
+ node1.fy -= fy;
58
+ node2.fx += fx;
59
+ node2.fy += fy;
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,513 @@
1
+ /**
2
+ * Created by Alex on 2/6/14.
3
+ */
4
+
5
+
6
+ var physicsMixin = {
7
+
8
+ /**
9
+ * Toggling barnes Hut calculation on and off.
10
+ *
11
+ * @private
12
+ */
13
+ _toggleBarnesHut : function() {
14
+ this.constants.physics.barnesHut.enabled = !this.constants.physics.barnesHut.enabled;
15
+ this._loadSelectedForceSolver();
16
+ this.moving = true;
17
+ this.start();
18
+ },
19
+
20
+
21
+
22
+ /**
23
+ * This loads the node force solver based on the barnes hut or repulsion algorithm
24
+ *
25
+ * @private
26
+ */
27
+ _loadSelectedForceSolver : function() {
28
+ // this overloads the this._calculateNodeForces
29
+ if (this.constants.physics.barnesHut.enabled == true) {
30
+ this._clearMixin(repulsionMixin);
31
+ this._clearMixin(hierarchalRepulsionMixin);
32
+
33
+ this.constants.physics.centralGravity = this.constants.physics.barnesHut.centralGravity;
34
+ this.constants.physics.springLength = this.constants.physics.barnesHut.springLength;
35
+ this.constants.physics.springConstant = this.constants.physics.barnesHut.springConstant;
36
+ this.constants.physics.damping = this.constants.physics.barnesHut.damping;
37
+
38
+ this._loadMixin(barnesHutMixin);
39
+ }
40
+ else if (this.constants.physics.hierarchicalRepulsion.enabled == true) {
41
+ this._clearMixin(barnesHutMixin);
42
+ this._clearMixin(repulsionMixin);
43
+
44
+ this.constants.physics.centralGravity = this.constants.physics.hierarchicalRepulsion.centralGravity;
45
+ this.constants.physics.springLength = this.constants.physics.hierarchicalRepulsion.springLength;
46
+ this.constants.physics.springConstant = this.constants.physics.hierarchicalRepulsion.springConstant;
47
+ this.constants.physics.damping = this.constants.physics.hierarchicalRepulsion.damping;
48
+
49
+ this._loadMixin(hierarchalRepulsionMixin);
50
+ }
51
+ else {
52
+ this._clearMixin(barnesHutMixin);
53
+ this._clearMixin(hierarchalRepulsionMixin);
54
+ this.barnesHutTree = undefined;
55
+
56
+ this.constants.physics.centralGravity = this.constants.physics.repulsion.centralGravity;
57
+ this.constants.physics.springLength = this.constants.physics.repulsion.springLength;
58
+ this.constants.physics.springConstant = this.constants.physics.repulsion.springConstant;
59
+ this.constants.physics.damping = this.constants.physics.repulsion.damping;
60
+
61
+ this._loadMixin(repulsionMixin);
62
+ }
63
+ },
64
+
65
+ /**
66
+ * Before calculating the forces, we check if we need to cluster to keep up performance and we check
67
+ * if there is more than one node. If it is just one node, we dont calculate anything.
68
+ *
69
+ * @private
70
+ */
71
+ _initializeForceCalculation : function() {
72
+ // stop calculation if there is only one node
73
+ if (this.nodeIndices.length == 1) {
74
+ this.nodes[this.nodeIndices[0]]._setForce(0,0);
75
+ }
76
+ else {
77
+ // if there are too many nodes on screen, we cluster without repositioning
78
+ if (this.nodeIndices.length > this.constants.clustering.clusterThreshold && this.constants.clustering.enabled == true) {
79
+ this.clusterToFit(this.constants.clustering.reduceToNodes, false);
80
+ }
81
+
82
+ // we now start the force calculation
83
+ this._calculateForces();
84
+ }
85
+ },
86
+
87
+
88
+ /**
89
+ * Calculate the external forces acting on the nodes
90
+ * Forces are caused by: edges, repulsing forces between nodes, gravity
91
+ * @private
92
+ */
93
+ _calculateForces : function() {
94
+ // Gravity is required to keep separated groups from floating off
95
+ // the forces are reset to zero in this loop by using _setForce instead
96
+ // of _addForce
97
+
98
+ this._calculateGravitationalForces();
99
+ this._calculateNodeForces();
100
+
101
+
102
+ if (this.constants.smoothCurves == true) {
103
+ this._calculateSpringForcesWithSupport();
104
+ }
105
+ else {
106
+ this._calculateSpringForces();
107
+ }
108
+ },
109
+
110
+
111
+ /**
112
+ * Smooth curves are created by adding invisible nodes in the center of the edges. These nodes are also
113
+ * handled in the calculateForces function. We then use a quadratic curve with the center node as control.
114
+ * This function joins the datanodes and invisible (called support) nodes into one object.
115
+ * We do this so we do not contaminate this.nodes with the support nodes.
116
+ *
117
+ * @private
118
+ */
119
+ _updateCalculationNodes : function() {
120
+ if (this.constants.smoothCurves == true) {
121
+ this.calculationNodes = {};
122
+ this.calculationNodeIndices = [];
123
+
124
+ for (var nodeId in this.nodes) {
125
+ if (this.nodes.hasOwnProperty(nodeId)) {
126
+ this.calculationNodes[nodeId] = this.nodes[nodeId];
127
+ }
128
+ }
129
+ var supportNodes = this.sectors['support']['nodes'];
130
+ for (var supportNodeId in supportNodes) {
131
+ if (supportNodes.hasOwnProperty(supportNodeId)) {
132
+ if (this.edges.hasOwnProperty(supportNodes[supportNodeId].parentEdgeId)) {
133
+ this.calculationNodes[supportNodeId] = supportNodes[supportNodeId];
134
+ }
135
+ else {
136
+ supportNodes[supportNodeId]._setForce(0,0);
137
+ }
138
+ }
139
+ }
140
+
141
+ for (var idx in this.calculationNodes) {
142
+ if (this.calculationNodes.hasOwnProperty(idx)) {
143
+ this.calculationNodeIndices.push(idx);
144
+ }
145
+ }
146
+ }
147
+ else {
148
+ this.calculationNodes = this.nodes;
149
+ this.calculationNodeIndices = this.nodeIndices;
150
+ }
151
+ },
152
+
153
+
154
+ /**
155
+ * this function applies the central gravity effect to keep groups from floating off
156
+ *
157
+ * @private
158
+ */
159
+ _calculateGravitationalForces : function() {
160
+ var dx, dy, distance, node, i;
161
+ var nodes = this.calculationNodes;
162
+ var gravity = this.constants.physics.centralGravity;
163
+ var gravityForce = 0;
164
+
165
+ for (i = 0; i < this.calculationNodeIndices.length; i++) {
166
+ node = nodes[this.calculationNodeIndices[i]];
167
+ node.damping = this.constants.physics.damping; // possibly add function to alter damping properties of clusters.
168
+ // gravity does not apply when we are in a pocket sector
169
+ if (this._sector() == "default" && gravity != 0) {
170
+ dx = -node.x;
171
+ dy = -node.y;
172
+ distance = Math.sqrt(dx*dx + dy*dy);
173
+ gravityForce = gravity / distance;
174
+
175
+ node.fx = dx * gravityForce;
176
+ node.fy = dy * gravityForce;
177
+ }
178
+ else {
179
+ node.fx = 0;
180
+ node.fy = 0;
181
+ }
182
+ }
183
+ },
184
+
185
+
186
+ /**
187
+ * this function calculates the effects of the springs in the case of unsmooth curves.
188
+ *
189
+ * @private
190
+ */
191
+ _calculateSpringForces : function() {
192
+ var edgeLength, edge, edgeId;
193
+ var dx, dy, fx, fy, springForce, length;
194
+ var edges = this.edges;
195
+
196
+ // forces caused by the edges, modelled as springs
197
+ for (edgeId in edges) {
198
+ if (edges.hasOwnProperty(edgeId)) {
199
+ edge = edges[edgeId];
200
+ if (edge.connected) {
201
+ // only calculate forces if nodes are in the same sector
202
+ if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) {
203
+ edgeLength = edge.customLength ? edge.length : this.constants.physics.springLength;
204
+ // this implies that the edges between big clusters are longer
205
+ edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth;
206
+
207
+ dx = (edge.from.x - edge.to.x);
208
+ dy = (edge.from.y - edge.to.y);
209
+ length = Math.sqrt(dx * dx + dy * dy);
210
+
211
+ if (length == 0) {
212
+ length = 0.01;
213
+ }
214
+
215
+ springForce = this.constants.physics.springConstant * (edgeLength - length) / length;
216
+
217
+ fx = dx * springForce;
218
+ fy = dy * springForce;
219
+
220
+ edge.from.fx += fx;
221
+ edge.from.fy += fy;
222
+ edge.to.fx -= fx;
223
+ edge.to.fy -= fy;
224
+ }
225
+ }
226
+ }
227
+ }
228
+ },
229
+
230
+
231
+ /**
232
+ * This function calculates the springforces on the nodes, accounting for the support nodes.
233
+ *
234
+ * @private
235
+ */
236
+ _calculateSpringForcesWithSupport : function() {
237
+ var edgeLength, edge, edgeId, combinedClusterSize;
238
+ var edges = this.edges;
239
+
240
+ // forces caused by the edges, modelled as springs
241
+ for (edgeId in edges) {
242
+ if (edges.hasOwnProperty(edgeId)) {
243
+ edge = edges[edgeId];
244
+ if (edge.connected) {
245
+ // only calculate forces if nodes are in the same sector
246
+ if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) {
247
+ if (edge.via != null) {
248
+ var node1 = edge.to;
249
+ var node2 = edge.via;
250
+ var node3 = edge.from;
251
+
252
+ edgeLength = edge.customLength ? edge.length : this.constants.physics.springLength;
253
+
254
+ combinedClusterSize = node1.clusterSize + node3.clusterSize - 2;
255
+
256
+ // this implies that the edges between big clusters are longer
257
+ edgeLength += combinedClusterSize * this.constants.clustering.edgeGrowth;
258
+ this._calculateSpringForce(node1,node2,0.5*edgeLength);
259
+ this._calculateSpringForce(node2,node3,0.5*edgeLength);
260
+ }
261
+ }
262
+ }
263
+ }
264
+ }
265
+ },
266
+
267
+
268
+ /**
269
+ * This is the code actually performing the calculation for the function above. It is split out to avoid repetition.
270
+ *
271
+ * @param node1
272
+ * @param node2
273
+ * @param edgeLength
274
+ * @private
275
+ */
276
+ _calculateSpringForce : function(node1,node2,edgeLength) {
277
+ var dx, dy, fx, fy, springForce, length;
278
+
279
+ dx = (node1.x - node2.x);
280
+ dy = (node1.y - node2.y);
281
+ length = Math.sqrt(dx * dx + dy * dy);
282
+
283
+ springForce = this.constants.physics.springConstant * (edgeLength - length) / length;
284
+
285
+ if (length == 0) {
286
+ length = 0.01;
287
+ }
288
+
289
+ fx = dx * springForce;
290
+ fy = dy * springForce;
291
+
292
+ node1.fx += fx;
293
+ node1.fy += fy;
294
+ node2.fx -= fx;
295
+ node2.fy -= fy;
296
+ },
297
+
298
+
299
+ /**
300
+ * Load the HTML for the physics config and bind it
301
+ * @private
302
+ */
303
+ _loadPhysicsConfiguration : function() {
304
+ if (this.physicsConfiguration === undefined) {
305
+ var hierarchicalLayoutDirections = ["LR","RL","UD","DU"];
306
+ this.physicsConfiguration = document.createElement('div');
307
+ this.physicsConfiguration.className = "PhysicsConfiguration";
308
+ this.physicsConfiguration.innerHTML = '' +
309
+ '<table><tr><td><b>Simulation Mode:</b></td></tr>' +
310
+ '<tr>' +
311
+ '<td width="120px"><input type="radio" name="graph_physicsMethod" id="graph_physicsMethod1" value="BH" checked="checked">Barnes Hut</td>' +
312
+ '<td width="120px"><input type="radio" name="graph_physicsMethod" id="graph_physicsMethod2" value="R">Repulsion</td>'+
313
+ '<td width="120px"><input type="radio" name="graph_physicsMethod" id="graph_physicsMethod3" value="H">Hierarchical</td>' +
314
+ '</tr>'+
315
+ '</table>' +
316
+ '<table id="graph_BH_table" style="display:none">'+
317
+ '<tr><td><b>Barnes Hut</b></td></tr>'+
318
+ '<tr>'+
319
+ '<td width="150px">gravitationalConstant</td><td>0</td><td><input type="range" min="500" max="20000" value="' + (-1* this.constants.physics.barnesHut.gravitationalConstant) + '" step="25" style="width:300px" id="graph_BH_gc"></td><td width="50px">-20000</td><td><input value="' + (-1* this.constants.physics.barnesHut.gravitationalConstant) + '" id="graph_BH_gc_value" style="width:60px"></td>'+
320
+ '</tr>'+
321
+ '<tr>'+
322
+ '<td width="150px">centralGravity</td><td>0</td><td><input type="range" min="0" max="3" value="' + this.constants.physics.barnesHut.centralGravity + '" step="0.05" style="width:300px" id="graph_BH_cg"></td><td>3</td><td><input value="' + this.constants.physics.barnesHut.centralGravity + '" id="graph_BH_cg_value" style="width:60px"></td>'+
323
+ '</tr>'+
324
+ '<tr>'+
325
+ '<td width="150px">springLength</td><td>0</td><td><input type="range" min="0" max="500" value="' + this.constants.physics.barnesHut.springLength + '" step="1" style="width:300px" id="graph_BH_sl"></td><td>500</td><td><input value="' + this.constants.physics.barnesHut.springLength + '" id="graph_BH_sl_value" style="width:60px"></td>'+
326
+ '</tr>'+
327
+ '<tr>'+
328
+ '<td width="150px">springConstant</td><td>0</td><td><input type="range" min="0" max="0.5" value="' + this.constants.physics.barnesHut.springConstant + '" step="0.001" style="width:300px" id="graph_BH_sc"></td><td>0.5</td><td><input value="' + this.constants.physics.barnesHut.springConstant + '" id="graph_BH_sc_value" style="width:60px"></td>'+
329
+ '</tr>'+
330
+ '<tr>'+
331
+ '<td width="150px">damping</td><td>0</td><td><input type="range" min="0" max="0.3" value="' + this.constants.physics.barnesHut.damping + '" step="0.005" style="width:300px" id="graph_BH_damp"></td><td>0.3</td><td><input value="' + this.constants.physics.barnesHut.damping + '" id="graph_BH_damp_value" style="width:60px"></td>'+
332
+ '</tr>'+
333
+ '</table>'+
334
+ '<table id="graph_R_table" style="display:none">'+
335
+ '<tr><td><b>Repulsion</b></td></tr>'+
336
+ '<tr>'+
337
+ '<td width="150px">nodeDistance</td><td>0</td><td><input type="range" min="0" max="300" value="' + this.constants.physics.repulsion.nodeDistance + '" step="1" style="width:300px" id="graph_R_nd"></td><td width="50px">300</td><td><input value="' + this.constants.physics.repulsion.nodeDistance + '" id="graph_R_nd_value" style="width:60px"></td>'+
338
+ '</tr>'+
339
+ '<tr>'+
340
+ '<td width="150px">centralGravity</td><td>0</td><td><input type="range" min="0" max="3" value="' + this.constants.physics.repulsion.centralGravity + '" step="0.05" style="width:300px" id="graph_R_cg"></td><td>3</td><td><input value="' + this.constants.physics.repulsion.centralGravity + '" id="graph_R_cg_value" style="width:60px"></td>'+
341
+ '</tr>'+
342
+ '<tr>'+
343
+ '<td width="150px">springLength</td><td>0</td><td><input type="range" min="0" max="500" value="' + this.constants.physics.repulsion.springLength + '" step="1" style="width:300px" id="graph_R_sl"></td><td>500</td><td><input value="' + this.constants.physics.repulsion.springLength + '" id="graph_R_sl_value" style="width:60px"></td>'+
344
+ '</tr>'+
345
+ '<tr>'+
346
+ '<td width="150px">springConstant</td><td>0</td><td><input type="range" min="0" max="0.5" value="' + this.constants.physics.repulsion.springConstant + '" step="0.001" style="width:300px" id="graph_R_sc"></td><td>0.5</td><td><input value="' + this.constants.physics.repulsion.springConstant + '" id="graph_R_sc_value" style="width:60px"></td>'+
347
+ '</tr>'+
348
+ '<tr>'+
349
+ '<td width="150px">damping</td><td>0</td><td><input type="range" min="0" max="0.3" value="' + this.constants.physics.repulsion.damping + '" step="0.005" style="width:300px" id="graph_R_damp"></td><td>0.3</td><td><input value="' + this.constants.physics.repulsion.damping + '" id="graph_R_damp_value" style="width:60px"></td>'+
350
+ '</tr>'+
351
+ '</table>'+
352
+ '<table id="graph_H_table" style="display:none">'+
353
+ '<tr><td width="150"><b>Hierarchical</b></td></tr>'+
354
+ '<tr>'+
355
+ '<td width="150px">nodeDistance</td><td>0</td><td><input type="range" min="0" max="300" value="' + this.constants.physics.hierarchicalRepulsion.nodeDistance + '" step="1" style="width:300px" id="graph_H_nd"></td><td width="50px">300</td><td><input value="' + this.constants.physics.hierarchicalRepulsion.nodeDistance + '" id="graph_H_nd_value" style="width:60px"></td>'+
356
+ '</tr>'+
357
+ '<tr>'+
358
+ '<td width="150px">centralGravity</td><td>0</td><td><input type="range" min="0" max="3" value="' + this.constants.physics.hierarchicalRepulsion.centralGravity + '" step="0.05" style="width:300px" id="graph_H_cg"></td><td>3</td><td><input value="' + this.constants.physics.hierarchicalRepulsion.centralGravity + '" id="graph_H_cg_value" style="width:60px"></td>'+
359
+ '</tr>'+
360
+ '<tr>'+
361
+ '<td width="150px">springLength</td><td>0</td><td><input type="range" min="0" max="500" value="' + this.constants.physics.hierarchicalRepulsion.springLength + '" step="1" style="width:300px" id="graph_H_sl"></td><td>500</td><td><input value="' + this.constants.physics.hierarchicalRepulsion.springLength + '" id="graph_H_sl_value" style="width:60px"></td>'+
362
+ '</tr>'+
363
+ '<tr>'+
364
+ '<td width="150px">springConstant</td><td>0</td><td><input type="range" min="0" max="0.5" value="' + this.constants.physics.hierarchicalRepulsion.springConstant + '" step="0.001" style="width:300px" id="graph_H_sc"></td><td>0.5</td><td><input value="' + this.constants.physics.hierarchicalRepulsion.springConstant + '" id="graph_H_sc_value" style="width:60px"></td>'+
365
+ '</tr>'+
366
+ '<tr>'+
367
+ '<td width="150px">damping</td><td>0</td><td><input type="range" min="0" max="0.3" value="' + this.constants.physics.hierarchicalRepulsion.damping + '" step="0.005" style="width:300px" id="graph_H_damp"></td><td>0.3</td><td><input value="' + this.constants.physics.hierarchicalRepulsion.damping + '" id="graph_H_damp_value" style="width:60px"></td>'+
368
+ '</tr>'+
369
+ '<tr>'+
370
+ '<td width="150px">direction</td><td>1</td><td><input type="range" min="0" max="3" value="' + hierarchicalLayoutDirections.indexOf(this.constants.hierarchicalLayout.direction) + '" step="1" style="width:300px" id="graph_H_direction"></td><td>4</td><td><input value="' + this.constants.hierarchicalLayout.direction + '" id="graph_H_direction_value" style="width:60px"></td>'+
371
+ '</tr>'+
372
+ '<tr>'+
373
+ '<td width="150px">levelSeparation</td><td>1</td><td><input type="range" min="0" max="' + this.constants.hierarchicalLayout.levelSeparation + '" value="150" step="1" style="width:300px" id="graph_H_levsep"></td><td>500</td><td><input value="' + this.constants.hierarchicalLayout.levelSeparation + '" id="graph_H_levsep_value" style="width:60px"></td>'+
374
+ '</tr>'+
375
+ '<tr>'+
376
+ '<td width="150px">nodeSpacing</td><td>1</td><td><input type="range" min="0" max="' + this.constants.hierarchicalLayout.nodeSpacing + '" value="100" step="1" style="width:300px" id="graph_H_nspac"></td><td>500</td><td><input value="' + this.constants.hierarchicalLayout.nodeSpacing + '" id="graph_H_nspac_value" style="width:60px"></td>'+
377
+ '</tr>'+
378
+ '</table>'
379
+ this.containerElement.parentElement.insertBefore(this.physicsConfiguration,this.containerElement);
380
+
381
+
382
+
383
+ var rangeElement;
384
+ rangeElement = document.getElementById('graph_BH_gc');
385
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_BH_gc',-1,"physics_barnesHut_gravitationalConstant");
386
+ rangeElement = document.getElementById('graph_BH_cg');
387
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_BH_cg',1,"physics_centralGravity");
388
+ rangeElement = document.getElementById('graph_BH_sc');
389
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_BH_sc',1,"physics_springConstant");
390
+ rangeElement = document.getElementById('graph_BH_sl');
391
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_BH_sl',1,"physics_springLength");
392
+ rangeElement = document.getElementById('graph_BH_damp');
393
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_BH_damp',1,"physics_damping");
394
+
395
+
396
+ rangeElement = document.getElementById('graph_R_nd');
397
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_R_nd',1,"physics_repulsion_nodeDistance");
398
+ rangeElement = document.getElementById('graph_R_cg');
399
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_R_cg',1,"physics_centralGravity");
400
+ rangeElement = document.getElementById('graph_R_sc');
401
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_R_sc',1,"physics_springConstant");
402
+ rangeElement = document.getElementById('graph_R_sl');
403
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_R_sl',1,"physics_springLength");
404
+ rangeElement = document.getElementById('graph_R_damp');
405
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_R_damp',1,"physics_damping");
406
+
407
+ rangeElement = document.getElementById('graph_H_nd');
408
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_H_nd',1,"physics_hierarchicalRepulsion_nodeDistance");
409
+ rangeElement = document.getElementById('graph_H_cg');
410
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_H_cg',1,"physics_centralGravity");
411
+ rangeElement = document.getElementById('graph_H_sc');
412
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_H_sc',1,"physics_springConstant");
413
+ rangeElement = document.getElementById('graph_H_sl');
414
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_H_sl',1,"physics_springLength");
415
+ rangeElement = document.getElementById('graph_H_damp');
416
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_H_damp',1,"physics_damping");
417
+ rangeElement = document.getElementById('graph_H_direction');
418
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_H_direction',hierarchicalLayoutDirections,"hierarchicalLayout_direction");
419
+ rangeElement = document.getElementById('graph_H_levsep');
420
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_H_levsep',1,"hierarchicalLayout_levelSeparation");
421
+ rangeElement = document.getElementById('graph_H_nspac');
422
+ rangeElement.onchange = showValueOfRange.bind(this,'graph_H_nspac',1,"hierarchicalLayout_nodeSpacing");
423
+
424
+ var radioButton1 = document.getElementById("graph_physicsMethod1");
425
+ var radioButton2 = document.getElementById("graph_physicsMethod2");
426
+ var radioButton3 = document.getElementById("graph_physicsMethod3");
427
+
428
+ radioButton2.checked = true;
429
+ if (this.constants.physics.barnesHut.enabled) {
430
+ radioButton1.checked = true;
431
+ }
432
+ if (this.constants.hierarchicalLayout.enabled) {
433
+ radioButton3.checked = true;
434
+ }
435
+
436
+ switchConfigurations.apply(this);
437
+
438
+ radioButton1.onchange = switchConfigurations.bind(this);
439
+ radioButton2.onchange = switchConfigurations.bind(this);
440
+ radioButton3.onchange = switchConfigurations.bind(this);
441
+ }
442
+ },
443
+
444
+ _overWriteGraphConstants : function(constantsVariableName, value) {
445
+ var nameArray = constantsVariableName.split("_");
446
+ if (nameArray.length == 1) {
447
+ this.constants[nameArray[0]] = value;
448
+ }
449
+ else if (nameArray.length == 2) {
450
+ this.constants[nameArray[0]][nameArray[1]] = value;
451
+ }
452
+ else if (nameArray.length == 3) {
453
+ this.constants[nameArray[0]][nameArray[1]][nameArray[2]] = value;
454
+ }
455
+ }
456
+ }
457
+
458
+
459
+ function switchConfigurations () {
460
+ var ids = ["graph_BH_table","graph_R_table","graph_H_table"]
461
+ var radioButton = document.querySelector('input[name="graph_physicsMethod"]:checked').value;
462
+ var tableId = "graph_" + radioButton + "_table";
463
+ var table = document.getElementById(tableId);
464
+ table.style.display = "block";
465
+ for (var i = 0; i < ids.length; i++) {
466
+ if (ids[i] != tableId) {
467
+ table = document.getElementById(ids[i]);
468
+ table.style.display = "none";
469
+ }
470
+ }
471
+ this._restoreNodes();
472
+ if (radioButton == "R") {
473
+ this.constants.hierarchicalLayout.enabled = false;
474
+ this.constants.physics.hierarchicalRepulsion.enabeled = false;
475
+ this.constants.physics.barnesHut.enabled = false;
476
+ }
477
+ else if (radioButton == "H") {
478
+ this.constants.hierarchicalLayout.enabled = true;
479
+ this.constants.physics.hierarchicalRepulsion.enabeled = true;
480
+ this.constants.physics.barnesHut.enabled = false;
481
+ this._setupHierarchicalLayout();
482
+ }
483
+ else {
484
+ this.constants.hierarchicalLayout.enabled = false;
485
+ this.constants.physics.hierarchicalRepulsion.enabeled = false;
486
+ this.constants.physics.barnesHut.enabled = true;
487
+ }
488
+ this._loadSelectedForceSolver();
489
+ this.moving = true;
490
+ this.start();
491
+ }
492
+
493
+ function showValueOfRange (id,map,constantsVariableName) {
494
+ var valueId = id + "_value";
495
+ var rangeValue = document.getElementById(id).value;
496
+ if (constantsVariableName == "hierarchicalLayout_direction" ||
497
+ constantsVariableName == "hierarchicalLayout_levelSeparation" ||
498
+ constantsVariableName == "hierarchicalLayout_nodeSpacing") {
499
+ this._setupHierarchicalLayout();
500
+ }
501
+
502
+ if (map instanceof Array) {
503
+ document.getElementById(valueId).value = map[parseInt(rangeValue)];
504
+ this._overWriteGraphConstants(constantsVariableName,map[parseInt(rangeValue)]);
505
+ }
506
+ else {
507
+ document.getElementById(valueId).value = map * parseFloat(rangeValue);
508
+ this._overWriteGraphConstants(constantsVariableName,map * parseFloat(rangeValue));
509
+ }
510
+ this.moving = true;
511
+ this.start();
512
+ };
513
+