vis-rails 0.0.1

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 (71) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.gitmodules +3 -0
  4. data/.project +11 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +202 -0
  7. data/README.md +29 -0
  8. data/Rakefile +1 -0
  9. data/lib/vis/rails/engine.rb +6 -0
  10. data/lib/vis/rails/version.rb +5 -0
  11. data/lib/vis/rails.rb +7 -0
  12. data/vendor/assets/javascripts/vis.js +1 -0
  13. data/vendor/assets/stylesheets/vis.css +3 -0
  14. data/vendor/assets/vis/DataSet.js +936 -0
  15. data/vendor/assets/vis/DataView.js +281 -0
  16. data/vendor/assets/vis/EventBus.js +89 -0
  17. data/vendor/assets/vis/events.js +116 -0
  18. data/vendor/assets/vis/graph/ClusterMixin.js +1019 -0
  19. data/vendor/assets/vis/graph/Edge.js +620 -0
  20. data/vendor/assets/vis/graph/Graph.js +2111 -0
  21. data/vendor/assets/vis/graph/Groups.js +80 -0
  22. data/vendor/assets/vis/graph/Images.js +41 -0
  23. data/vendor/assets/vis/graph/NavigationMixin.js +245 -0
  24. data/vendor/assets/vis/graph/Node.js +978 -0
  25. data/vendor/assets/vis/graph/Popup.js +105 -0
  26. data/vendor/assets/vis/graph/SectorsMixin.js +547 -0
  27. data/vendor/assets/vis/graph/SelectionMixin.js +515 -0
  28. data/vendor/assets/vis/graph/dotparser.js +829 -0
  29. data/vendor/assets/vis/graph/img/downarrow.png +0 -0
  30. data/vendor/assets/vis/graph/img/leftarrow.png +0 -0
  31. data/vendor/assets/vis/graph/img/minus.png +0 -0
  32. data/vendor/assets/vis/graph/img/plus.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/graph/img/zoomExtends.png +0 -0
  36. data/vendor/assets/vis/graph/shapes.js +225 -0
  37. data/vendor/assets/vis/module/exports.js +68 -0
  38. data/vendor/assets/vis/module/header.js +24 -0
  39. data/vendor/assets/vis/module/imports.js +32 -0
  40. data/vendor/assets/vis/shim.js +252 -0
  41. data/vendor/assets/vis/timeline/Controller.js +172 -0
  42. data/vendor/assets/vis/timeline/Range.js +553 -0
  43. data/vendor/assets/vis/timeline/Stack.js +192 -0
  44. data/vendor/assets/vis/timeline/TimeStep.js +449 -0
  45. data/vendor/assets/vis/timeline/Timeline.js +476 -0
  46. data/vendor/assets/vis/timeline/component/Component.js +148 -0
  47. data/vendor/assets/vis/timeline/component/ContentPanel.js +113 -0
  48. data/vendor/assets/vis/timeline/component/CurrentTime.js +101 -0
  49. data/vendor/assets/vis/timeline/component/CustomTime.js +255 -0
  50. data/vendor/assets/vis/timeline/component/Group.js +129 -0
  51. data/vendor/assets/vis/timeline/component/GroupSet.js +546 -0
  52. data/vendor/assets/vis/timeline/component/ItemSet.js +612 -0
  53. data/vendor/assets/vis/timeline/component/Panel.js +112 -0
  54. data/vendor/assets/vis/timeline/component/RootPanel.js +215 -0
  55. data/vendor/assets/vis/timeline/component/TimeAxis.js +522 -0
  56. data/vendor/assets/vis/timeline/component/css/currenttime.css +5 -0
  57. data/vendor/assets/vis/timeline/component/css/customtime.css +6 -0
  58. data/vendor/assets/vis/timeline/component/css/groupset.css +59 -0
  59. data/vendor/assets/vis/timeline/component/css/item.css +93 -0
  60. data/vendor/assets/vis/timeline/component/css/itemset.css +17 -0
  61. data/vendor/assets/vis/timeline/component/css/panel.css +14 -0
  62. data/vendor/assets/vis/timeline/component/css/timeaxis.css +41 -0
  63. data/vendor/assets/vis/timeline/component/css/timeline.css +2 -0
  64. data/vendor/assets/vis/timeline/component/item/Item.js +81 -0
  65. data/vendor/assets/vis/timeline/component/item/ItemBox.js +302 -0
  66. data/vendor/assets/vis/timeline/component/item/ItemPoint.js +237 -0
  67. data/vendor/assets/vis/timeline/component/item/ItemRange.js +251 -0
  68. data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +91 -0
  69. data/vendor/assets/vis/util.js +673 -0
  70. data/vis-rails.gemspec +47 -0
  71. metadata +142 -0
@@ -0,0 +1,620 @@
1
+ /**
2
+ * @class Edge
3
+ *
4
+ * A edge connects two nodes
5
+ * @param {Object} properties Object with properties. Must contain
6
+ * At least properties from and to.
7
+ * Available properties: from (number),
8
+ * to (number), label (string, color (string),
9
+ * width (number), style (string),
10
+ * length (number), title (string)
11
+ * @param {Graph} graph A graph object, used to find and edge to
12
+ * nodes.
13
+ * @param {Object} constants An object with default values for
14
+ * example for the color
15
+ */
16
+ function Edge (properties, graph, constants) {
17
+ if (!graph) {
18
+ throw "No graph provided";
19
+ }
20
+ this.graph = graph;
21
+
22
+ // initialize constants
23
+ this.widthMin = constants.edges.widthMin;
24
+ this.widthMax = constants.edges.widthMax;
25
+
26
+ // initialize variables
27
+ this.id = undefined;
28
+ this.fromId = undefined;
29
+ this.toId = undefined;
30
+ this.style = constants.edges.style;
31
+ this.title = undefined;
32
+ this.width = constants.edges.width;
33
+ this.value = undefined;
34
+ this.length = constants.edges.length;
35
+
36
+ this.from = null; // a node
37
+ this.to = null; // a node
38
+
39
+ // we use this to be able to reconnect the edge to a cluster if its node is put into a cluster
40
+ // by storing the original information we can revert to the original connection when the cluser is opened.
41
+ this.originalFromId = [];
42
+ this.originalToId = [];
43
+
44
+ this.connected = false;
45
+
46
+ // Added to support dashed lines
47
+ // David Jordan
48
+ // 2012-08-08
49
+ this.dash = util.extend({}, constants.edges.dash); // contains properties length, gap, altLength
50
+
51
+ this.stiffness = undefined; // depends on the length of the edge
52
+ this.color = constants.edges.color;
53
+ this.widthFixed = false;
54
+ this.lengthFixed = false;
55
+
56
+ this.setProperties(properties, constants);
57
+
58
+ }
59
+
60
+ /**
61
+ * Set or overwrite properties for the edge
62
+ * @param {Object} properties an object with properties
63
+ * @param {Object} constants and object with default, global properties
64
+ */
65
+ Edge.prototype.setProperties = function(properties, constants) {
66
+ if (!properties) {
67
+ return;
68
+ }
69
+
70
+ if (properties.from !== undefined) {this.fromId = properties.from;}
71
+ if (properties.to !== undefined) {this.toId = properties.to;}
72
+
73
+ if (properties.id !== undefined) {this.id = properties.id;}
74
+ if (properties.style !== undefined) {this.style = properties.style;}
75
+ if (properties.label !== undefined) {this.label = properties.label;}
76
+ if (this.label) {
77
+ this.fontSize = constants.edges.fontSize;
78
+ this.fontFace = constants.edges.fontFace;
79
+ this.fontColor = constants.edges.fontColor;
80
+ if (properties.fontColor !== undefined) {this.fontColor = properties.fontColor;}
81
+ if (properties.fontSize !== undefined) {this.fontSize = properties.fontSize;}
82
+ if (properties.fontFace !== undefined) {this.fontFace = properties.fontFace;}
83
+ }
84
+ if (properties.title !== undefined) {this.title = properties.title;}
85
+ if (properties.width !== undefined) {this.width = properties.width;}
86
+ if (properties.value !== undefined) {this.value = properties.value;}
87
+ if (properties.length !== undefined) {this.length = properties.length;}
88
+
89
+ // Added to support dashed lines
90
+ // David Jordan
91
+ // 2012-08-08
92
+ if (properties.dash) {
93
+ if (properties.dash.length !== undefined) {this.dash.length = properties.dash.length;}
94
+ if (properties.dash.gap !== undefined) {this.dash.gap = properties.dash.gap;}
95
+ if (properties.dash.altLength !== undefined) {this.dash.altLength = properties.dash.altLength;}
96
+ }
97
+
98
+ if (properties.color !== undefined) {this.color = properties.color;}
99
+
100
+ // A node is connected when it has a from and to node.
101
+ this.connect();
102
+
103
+ this.widthFixed = this.widthFixed || (properties.width !== undefined);
104
+ this.lengthFixed = this.lengthFixed || (properties.length !== undefined);
105
+ this.stiffness = 1 / this.length;
106
+
107
+ // set draw method based on style
108
+ switch (this.style) {
109
+ case 'line': this.draw = this._drawLine; break;
110
+ case 'arrow': this.draw = this._drawArrow; break;
111
+ case 'arrow-center': this.draw = this._drawArrowCenter; break;
112
+ case 'dash-line': this.draw = this._drawDashLine; break;
113
+ default: this.draw = this._drawLine; break;
114
+ }
115
+ };
116
+
117
+ /**
118
+ * Connect an edge to its nodes
119
+ */
120
+ Edge.prototype.connect = function () {
121
+ this.disconnect();
122
+
123
+ this.from = this.graph.nodes[this.fromId] || null;
124
+ this.to = this.graph.nodes[this.toId] || null;
125
+ this.connected = (this.from && this.to);
126
+
127
+ if (this.connected) {
128
+ this.from.attachEdge(this);
129
+ this.to.attachEdge(this);
130
+ }
131
+ else {
132
+ if (this.from) {
133
+ this.from.detachEdge(this);
134
+ }
135
+ if (this.to) {
136
+ this.to.detachEdge(this);
137
+ }
138
+ }
139
+ };
140
+
141
+ /**
142
+ * Disconnect an edge from its nodes
143
+ */
144
+ Edge.prototype.disconnect = function () {
145
+ if (this.from) {
146
+ this.from.detachEdge(this);
147
+ this.from = null;
148
+ }
149
+ if (this.to) {
150
+ this.to.detachEdge(this);
151
+ this.to = null;
152
+ }
153
+
154
+ this.connected = false;
155
+ };
156
+
157
+ /**
158
+ * get the title of this edge.
159
+ * @return {string} title The title of the edge, or undefined when no title
160
+ * has been set.
161
+ */
162
+ Edge.prototype.getTitle = function() {
163
+ return this.title;
164
+ };
165
+
166
+
167
+ /**
168
+ * Retrieve the value of the edge. Can be undefined
169
+ * @return {Number} value
170
+ */
171
+ Edge.prototype.getValue = function() {
172
+ return this.value;
173
+ };
174
+
175
+ /**
176
+ * Adjust the value range of the edge. The edge will adjust it's width
177
+ * based on its value.
178
+ * @param {Number} min
179
+ * @param {Number} max
180
+ */
181
+ Edge.prototype.setValueRange = function(min, max) {
182
+ if (!this.widthFixed && this.value !== undefined) {
183
+ var scale = (this.widthMax - this.widthMin) / (max - min);
184
+ this.width = (this.value - min) * scale + this.widthMin;
185
+ }
186
+ };
187
+
188
+ /**
189
+ * Redraw a edge
190
+ * Draw this edge in the given canvas
191
+ * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
192
+ * @param {CanvasRenderingContext2D} ctx
193
+ */
194
+ Edge.prototype.draw = function(ctx) {
195
+ throw "Method draw not initialized in edge";
196
+ };
197
+
198
+ /**
199
+ * Check if this object is overlapping with the provided object
200
+ * @param {Object} obj an object with parameters left, top
201
+ * @return {boolean} True if location is located on the edge
202
+ */
203
+ Edge.prototype.isOverlappingWith = function(obj) {
204
+ var distMax = 10;
205
+
206
+ var xFrom = this.from.x;
207
+ var yFrom = this.from.y;
208
+ var xTo = this.to.x;
209
+ var yTo = this.to.y;
210
+ var xObj = obj.left;
211
+ var yObj = obj.top;
212
+
213
+
214
+ var dist = Edge._dist(xFrom, yFrom, xTo, yTo, xObj, yObj);
215
+
216
+ return (dist < distMax);
217
+ };
218
+
219
+
220
+ /**
221
+ * Redraw a edge as a line
222
+ * Draw this edge in the given canvas
223
+ * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
224
+ * @param {CanvasRenderingContext2D} ctx
225
+ * @private
226
+ */
227
+ Edge.prototype._drawLine = function(ctx) {
228
+ // set style
229
+ ctx.strokeStyle = this.color;
230
+ ctx.lineWidth = this._getLineWidth();
231
+
232
+ var point;
233
+ if (this.from != this.to) {
234
+ // draw line
235
+ this._line(ctx);
236
+
237
+ // draw label
238
+ if (this.label) {
239
+ point = this._pointOnLine(0.5);
240
+ this._label(ctx, this.label, point.x, point.y);
241
+ }
242
+ }
243
+ else {
244
+ var x, y;
245
+ var radius = this.length / 4;
246
+ var node = this.from;
247
+ if (!node.width) {
248
+ node.resize(ctx);
249
+ }
250
+ if (node.width > node.height) {
251
+ x = node.x + node.width / 2;
252
+ y = node.y - radius;
253
+ }
254
+ else {
255
+ x = node.x + radius;
256
+ y = node.y - node.height / 2;
257
+ }
258
+ this._circle(ctx, x, y, radius);
259
+ point = this._pointOnCircle(x, y, radius, 0.5);
260
+ this._label(ctx, this.label, point.x, point.y);
261
+ }
262
+ };
263
+
264
+ /**
265
+ * Get the line width of the edge. Depends on width and whether one of the
266
+ * connected nodes is selected.
267
+ * @return {Number} width
268
+ * @private
269
+ */
270
+ Edge.prototype._getLineWidth = function() {
271
+ if (this.from.selected || this.to.selected) {
272
+ return Math.min(this.width * 2, this.widthMax)*this.graphScaleInv;
273
+ }
274
+ else {
275
+ return this.width*this.graphScaleInv;
276
+ }
277
+ };
278
+
279
+ /**
280
+ * Draw a line between two nodes
281
+ * @param {CanvasRenderingContext2D} ctx
282
+ * @private
283
+ */
284
+ Edge.prototype._line = function (ctx) {
285
+ // draw a straight line
286
+ ctx.beginPath();
287
+ ctx.moveTo(this.from.x, this.from.y);
288
+ ctx.lineTo(this.to.x, this.to.y);
289
+ ctx.stroke();
290
+ };
291
+
292
+ /**
293
+ * Draw a line from a node to itself, a circle
294
+ * @param {CanvasRenderingContext2D} ctx
295
+ * @param {Number} x
296
+ * @param {Number} y
297
+ * @param {Number} radius
298
+ * @private
299
+ */
300
+ Edge.prototype._circle = function (ctx, x, y, radius) {
301
+ // draw a circle
302
+ ctx.beginPath();
303
+ ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
304
+ ctx.stroke();
305
+ };
306
+
307
+ /**
308
+ * Draw label with white background and with the middle at (x, y)
309
+ * @param {CanvasRenderingContext2D} ctx
310
+ * @param {String} text
311
+ * @param {Number} x
312
+ * @param {Number} y
313
+ * @private
314
+ */
315
+ Edge.prototype._label = function (ctx, text, x, y) {
316
+ if (text) {
317
+ // TODO: cache the calculated size
318
+ ctx.font = ((this.from.selected || this.to.selected) ? "bold " : "") +
319
+ this.fontSize + "px " + this.fontFace;
320
+ ctx.fillStyle = 'white';
321
+ var width = ctx.measureText(text).width;
322
+ var height = this.fontSize;
323
+ var left = x - width / 2;
324
+ var top = y - height / 2;
325
+
326
+ ctx.fillRect(left, top, width, height);
327
+
328
+ // draw text
329
+ ctx.fillStyle = this.fontColor || "black";
330
+ ctx.textAlign = "left";
331
+ ctx.textBaseline = "top";
332
+ ctx.fillText(text, left, top);
333
+ }
334
+ };
335
+
336
+ /**
337
+ * Redraw a edge as a dashed line
338
+ * Draw this edge in the given canvas
339
+ * @author David Jordan
340
+ * @date 2012-08-08
341
+ * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
342
+ * @param {CanvasRenderingContext2D} ctx
343
+ * @private
344
+ */
345
+ Edge.prototype._drawDashLine = function(ctx) {
346
+ // set style
347
+ ctx.strokeStyle = this.color;
348
+ ctx.lineWidth = this._getLineWidth();
349
+
350
+ // draw dashed line
351
+ ctx.beginPath();
352
+ ctx.lineCap = 'round';
353
+ if (this.dash.altLength !== undefined) //If an alt dash value has been set add to the array this value
354
+ {
355
+ ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,
356
+ [this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]);
357
+ }
358
+ else if (this.dash.length !== undefined && this.dash.gap !== undefined) //If a dash and gap value has been set add to the array this value
359
+ {
360
+ ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,
361
+ [this.dash.length,this.dash.gap]);
362
+ }
363
+ else //If all else fails draw a line
364
+ {
365
+ ctx.moveTo(this.from.x, this.from.y);
366
+ ctx.lineTo(this.to.x, this.to.y);
367
+ }
368
+ ctx.stroke();
369
+
370
+ // draw label
371
+ if (this.label) {
372
+ var point = this._pointOnLine(0.5);
373
+ this._label(ctx, this.label, point.x, point.y);
374
+ }
375
+ };
376
+
377
+ /**
378
+ * Get a point on a line
379
+ * @param {Number} percentage. Value between 0 (line start) and 1 (line end)
380
+ * @return {Object} point
381
+ * @private
382
+ */
383
+ Edge.prototype._pointOnLine = function (percentage) {
384
+ return {
385
+ x: (1 - percentage) * this.from.x + percentage * this.to.x,
386
+ y: (1 - percentage) * this.from.y + percentage * this.to.y
387
+ }
388
+ };
389
+
390
+ /**
391
+ * Get a point on a circle
392
+ * @param {Number} x
393
+ * @param {Number} y
394
+ * @param {Number} radius
395
+ * @param {Number} percentage. Value between 0 (line start) and 1 (line end)
396
+ * @return {Object} point
397
+ * @private
398
+ */
399
+ Edge.prototype._pointOnCircle = function (x, y, radius, percentage) {
400
+ var angle = (percentage - 3/8) * 2 * Math.PI;
401
+ return {
402
+ x: x + radius * Math.cos(angle),
403
+ y: y - radius * Math.sin(angle)
404
+ }
405
+ };
406
+
407
+ /**
408
+ * Redraw a edge as a line with an arrow halfway the line
409
+ * Draw this edge in the given canvas
410
+ * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
411
+ * @param {CanvasRenderingContext2D} ctx
412
+ * @private
413
+ */
414
+ Edge.prototype._drawArrowCenter = function(ctx) {
415
+ var point;
416
+ // set style
417
+ ctx.strokeStyle = this.color;
418
+ ctx.fillStyle = this.color;
419
+ ctx.lineWidth = this._getLineWidth();
420
+
421
+ if (this.from != this.to) {
422
+ // draw line
423
+ this._line(ctx);
424
+
425
+ // draw an arrow halfway the line
426
+ var angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x));
427
+ var length = 10 + 5 * this.width; // TODO: make customizable?
428
+ point = this._pointOnLine(0.5);
429
+ ctx.arrow(point.x, point.y, angle, length);
430
+ ctx.fill();
431
+ ctx.stroke();
432
+
433
+ // draw label
434
+ if (this.label) {
435
+ point = this._pointOnLine(0.5);
436
+ this._label(ctx, this.label, point.x, point.y);
437
+ }
438
+ }
439
+ else {
440
+ // draw circle
441
+ var x, y;
442
+ var radius = this.length / 4;
443
+ var node = this.from;
444
+ if (!node.width) {
445
+ node.resize(ctx);
446
+ }
447
+ if (node.width > node.height) {
448
+ x = node.x + node.width / 2;
449
+ y = node.y - radius;
450
+ }
451
+ else {
452
+ x = node.x + radius;
453
+ y = node.y - node.height / 2;
454
+ }
455
+ this._circle(ctx, x, y, radius);
456
+
457
+ // draw all arrows
458
+ var angle = 0.2 * Math.PI;
459
+ var length = 10 + 5 * this.width; // TODO: make customizable?
460
+ point = this._pointOnCircle(x, y, radius, 0.5);
461
+ ctx.arrow(point.x, point.y, angle, length);
462
+ ctx.fill();
463
+ ctx.stroke();
464
+
465
+ // draw label
466
+ if (this.label) {
467
+ point = this._pointOnCircle(x, y, radius, 0.5);
468
+ this._label(ctx, this.label, point.x, point.y);
469
+ }
470
+ }
471
+ };
472
+
473
+
474
+
475
+ /**
476
+ * Redraw a edge as a line with an arrow
477
+ * Draw this edge in the given canvas
478
+ * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
479
+ * @param {CanvasRenderingContext2D} ctx
480
+ * @private
481
+ */
482
+ Edge.prototype._drawArrow = function(ctx) {
483
+ // set style
484
+ ctx.strokeStyle = this.color;
485
+ ctx.fillStyle = this.color;
486
+ ctx.lineWidth = this._getLineWidth();
487
+
488
+ // draw line
489
+ var angle, length;
490
+ if (this.from != this.to) {
491
+ // calculate length and angle of the line
492
+ angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x));
493
+ var dx = (this.to.x - this.from.x);
494
+ var dy = (this.to.y - this.from.y);
495
+ var lEdge = Math.sqrt(dx * dx + dy * dy);
496
+
497
+ var lFrom = this.from.distanceToBorder(ctx, angle + Math.PI);
498
+ var pFrom = (lEdge - lFrom) / lEdge;
499
+ var xFrom = (pFrom) * this.from.x + (1 - pFrom) * this.to.x;
500
+ var yFrom = (pFrom) * this.from.y + (1 - pFrom) * this.to.y;
501
+
502
+ var lTo = this.to.distanceToBorder(ctx, angle);
503
+ var pTo = (lEdge - lTo) / lEdge;
504
+ var xTo = (1 - pTo) * this.from.x + pTo * this.to.x;
505
+ var yTo = (1 - pTo) * this.from.y + pTo * this.to.y;
506
+
507
+ ctx.beginPath();
508
+ ctx.moveTo(xFrom, yFrom);
509
+ ctx.lineTo(xTo, yTo);
510
+ ctx.stroke();
511
+
512
+ // draw arrow at the end of the line
513
+ length = 10 + 5 * this.width; // TODO: make customizable?
514
+ ctx.arrow(xTo, yTo, angle, length);
515
+ ctx.fill();
516
+ ctx.stroke();
517
+
518
+ // draw label
519
+ if (this.label) {
520
+ var point = this._pointOnLine(0.5);
521
+ this._label(ctx, this.label, point.x, point.y);
522
+ }
523
+ }
524
+ else {
525
+ // draw circle
526
+ var node = this.from;
527
+ var x, y, arrow;
528
+ var radius = this.length / 4;
529
+ if (!node.width) {
530
+ node.resize(ctx);
531
+ }
532
+ if (node.width > node.height) {
533
+ x = node.x + node.width / 2;
534
+ y = node.y - radius;
535
+ arrow = {
536
+ x: x,
537
+ y: node.y,
538
+ angle: 0.9 * Math.PI
539
+ };
540
+ }
541
+ else {
542
+ x = node.x + radius;
543
+ y = node.y - node.height / 2;
544
+ arrow = {
545
+ x: node.x,
546
+ y: y,
547
+ angle: 0.6 * Math.PI
548
+ };
549
+ }
550
+ ctx.beginPath();
551
+ // TODO: do not draw a circle, but an arc
552
+ // TODO: similarly, for a line without arrows, draw to the border of the nodes instead of the center
553
+ ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
554
+ ctx.stroke();
555
+
556
+ // draw all arrows
557
+ length = 10 + 5 * this.width; // TODO: make customizable?
558
+ ctx.arrow(arrow.x, arrow.y, arrow.angle, length);
559
+ ctx.fill();
560
+ ctx.stroke();
561
+
562
+ // draw label
563
+ if (this.label) {
564
+ point = this._pointOnCircle(x, y, radius, 0.5);
565
+ this._label(ctx, this.label, point.x, point.y);
566
+ }
567
+ }
568
+ };
569
+
570
+
571
+
572
+ /**
573
+ * Calculate the distance between a point (x3,y3) and a line segment from
574
+ * (x1,y1) to (x2,y2).
575
+ * http://stackoverflow.com/questions/849211/shortest-distancae-between-a-point-and-a-line-segment
576
+ * @param {number} x1
577
+ * @param {number} y1
578
+ * @param {number} x2
579
+ * @param {number} y2
580
+ * @param {number} x3
581
+ * @param {number} y3
582
+ * @private
583
+ */
584
+ Edge._dist = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point
585
+ var px = x2-x1,
586
+ py = y2-y1,
587
+ something = px*px + py*py,
588
+ u = ((x3 - x1) * px + (y3 - y1) * py) / something;
589
+
590
+ if (u > 1) {
591
+ u = 1;
592
+ }
593
+ else if (u < 0) {
594
+ u = 0;
595
+ }
596
+
597
+ var x = x1 + u * px,
598
+ y = y1 + u * py,
599
+ dx = x - x3,
600
+ dy = y - y3;
601
+
602
+ //# Note: If the actual distance does not matter,
603
+ //# if you only want to compare what this function
604
+ //# returns to other results of this function, you
605
+ //# can just return the squared distance instead
606
+ //# (i.e. remove the sqrt) to gain a little performance
607
+
608
+ return Math.sqrt(dx*dx + dy*dy);
609
+ };
610
+
611
+
612
+
613
+ /**
614
+ * This allows the zoom level of the graph to influence the rendering
615
+ *
616
+ * @param scale
617
+ */
618
+ Edge.prototype.setScale = function(scale) {
619
+ this.graphScaleInv = 1.0/scale;
620
+ };