vis-rails 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/lib/vis/rails/version.rb +1 -1
- data/vendor/assets/component/emitter.js +162 -0
- data/vendor/assets/javascripts/vis.js +1 -0
- data/vendor/assets/vis/DataSet.js +8 -2
- data/vendor/assets/vis/DataView.js +8 -4
- data/vendor/assets/vis/graph/Edge.js +210 -78
- data/vendor/assets/vis/graph/Graph.js +474 -652
- data/vendor/assets/vis/graph/Node.js +119 -82
- data/vendor/assets/vis/graph/css/graph-manipulation.css +128 -0
- data/vendor/assets/vis/graph/css/graph-navigation.css +62 -0
- data/vendor/assets/vis/graph/graphMixins/ClusterMixin.js +1141 -0
- data/vendor/assets/vis/graph/graphMixins/HierarchicalLayoutMixin.js +296 -0
- data/vendor/assets/vis/graph/graphMixins/ManipulationMixin.js +433 -0
- data/vendor/assets/vis/graph/graphMixins/MixinLoader.js +201 -0
- data/vendor/assets/vis/graph/graphMixins/NavigationMixin.js +173 -0
- data/vendor/assets/vis/graph/graphMixins/SectorsMixin.js +552 -0
- data/vendor/assets/vis/graph/graphMixins/SelectionMixin.js +558 -0
- data/vendor/assets/vis/graph/graphMixins/physics/BarnesHut.js +373 -0
- data/vendor/assets/vis/graph/graphMixins/physics/HierarchialRepulsion.js +64 -0
- data/vendor/assets/vis/graph/graphMixins/physics/PhysicsMixin.js +513 -0
- data/vendor/assets/vis/graph/graphMixins/physics/Repulsion.js +66 -0
- data/vendor/assets/vis/graph/img/acceptDeleteIcon.png +0 -0
- data/vendor/assets/vis/graph/img/addNodeIcon.png +0 -0
- data/vendor/assets/vis/graph/img/backIcon.png +0 -0
- data/vendor/assets/vis/graph/img/connectIcon.png +0 -0
- data/vendor/assets/vis/graph/img/cross.png +0 -0
- data/vendor/assets/vis/graph/img/cross2.png +0 -0
- data/vendor/assets/vis/graph/img/deleteIcon.png +0 -0
- data/vendor/assets/vis/graph/img/downArrow.png +0 -0
- data/vendor/assets/vis/graph/img/editIcon.png +0 -0
- data/vendor/assets/vis/graph/img/leftArrow.png +0 -0
- data/vendor/assets/vis/graph/img/rightArrow.png +0 -0
- data/vendor/assets/vis/graph/img/upArrow.png +0 -0
- data/vendor/assets/vis/module/exports.js +0 -2
- data/vendor/assets/vis/module/header.js +2 -2
- data/vendor/assets/vis/module/imports.js +1 -2
- data/vendor/assets/vis/timeline/Controller.js +56 -45
- data/vendor/assets/vis/timeline/Range.js +68 -62
- data/vendor/assets/vis/timeline/Stack.js +11 -13
- data/vendor/assets/vis/timeline/TimeStep.js +43 -38
- data/vendor/assets/vis/timeline/Timeline.js +215 -93
- data/vendor/assets/vis/timeline/component/Component.js +19 -3
- data/vendor/assets/vis/timeline/component/CurrentTime.js +1 -1
- data/vendor/assets/vis/timeline/component/CustomTime.js +39 -120
- data/vendor/assets/vis/timeline/component/GroupSet.js +35 -1
- data/vendor/assets/vis/timeline/component/ItemSet.js +272 -9
- data/vendor/assets/vis/timeline/component/RootPanel.js +59 -47
- data/vendor/assets/vis/timeline/component/TimeAxis.js +10 -0
- data/vendor/assets/vis/timeline/component/css/item.css +53 -22
- data/vendor/assets/vis/timeline/component/item/Item.js +40 -5
- data/vendor/assets/vis/timeline/component/item/ItemBox.js +3 -1
- data/vendor/assets/vis/timeline/component/item/ItemPoint.js +3 -1
- data/vendor/assets/vis/timeline/component/item/ItemRange.js +67 -3
- data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +37 -9
- data/vendor/assets/vis/timeline/img/delete.png +0 -0
- data/vendor/assets/vis/util.js +169 -30
- metadata +39 -12
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NmZjNDhhYzgxOTVlYmNmNTYzNDg4NWE1YzJkN2U4ZDAyYzY3NzgzYw==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a580d6253ed70eb32d505bf44beff11f114a4f81
|
4
|
+
data.tar.gz: 2b0795e57a056c2347a7084bf93ae8e93cdb5e39
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
Mjk5NGQ3YTUxMTMzNGU4MDQ3M2FkNjM1OWUyZWIzMDRmZmUwOWI1YjEwOTQ2
|
11
|
-
MzIzNTUxNzE0MDcxMDVkMzc3NmFiNzczZDgzYzU3NTBjZTEwODQ=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MTRlNjE0YzNiZDgxOTVhOGY2OWY5NmM0YTAzZGUyZWRmNThkNjZlY2M1MGIz
|
14
|
-
Nzc1MDhiZTRlNDIyNGQ5MjhkNjE4YTE3ZDliNTM0NzllYmUwMjQyMmJjOTIw
|
15
|
-
NWY3ODg5MTc0Y2U0NWRhYzQyMGNmOGUxNzA0YjUwYzcwY2UzY2M=
|
6
|
+
metadata.gz: f74e570dad14bb4b1be2682f924e6153c7b5d47bc36b5449d43b9ebb99a6692d524ec873c7f1882c1912fdb8f5f6ce4aa47f9c901bd656f227d735c4a994e1a5
|
7
|
+
data.tar.gz: 4ac01a2a19d2b44dce0629621dca14eba2b4a77f3ba008cbae56449540c73151443efd9fe21c64f219205a1a6e888e2e801611cf1f6f2b9b0dd39868a29644a0
|
data/lib/vis/rails/version.rb
CHANGED
@@ -0,0 +1,162 @@
|
|
1
|
+
|
2
|
+
/**
|
3
|
+
* Expose `Emitter`.
|
4
|
+
*/
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Initialize a new `Emitter`.
|
8
|
+
*
|
9
|
+
* @api public
|
10
|
+
*/
|
11
|
+
|
12
|
+
function Emitter(obj) {
|
13
|
+
if (obj) return mixin(obj);
|
14
|
+
};
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Mixin the emitter properties.
|
18
|
+
*
|
19
|
+
* @param {Object} obj
|
20
|
+
* @return {Object}
|
21
|
+
* @api private
|
22
|
+
*/
|
23
|
+
|
24
|
+
function mixin(obj) {
|
25
|
+
for (var key in Emitter.prototype) {
|
26
|
+
obj[key] = Emitter.prototype[key];
|
27
|
+
}
|
28
|
+
return obj;
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Listen on the given `event` with `fn`.
|
33
|
+
*
|
34
|
+
* @param {String} event
|
35
|
+
* @param {Function} fn
|
36
|
+
* @return {Emitter}
|
37
|
+
* @api public
|
38
|
+
*/
|
39
|
+
|
40
|
+
Emitter.prototype.on =
|
41
|
+
Emitter.prototype.addEventListener = function(event, fn){
|
42
|
+
this._callbacks = this._callbacks || {};
|
43
|
+
(this._callbacks[event] = this._callbacks[event] || [])
|
44
|
+
.push(fn);
|
45
|
+
return this;
|
46
|
+
};
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Adds an `event` listener that will be invoked a single
|
50
|
+
* time then automatically removed.
|
51
|
+
*
|
52
|
+
* @param {String} event
|
53
|
+
* @param {Function} fn
|
54
|
+
* @return {Emitter}
|
55
|
+
* @api public
|
56
|
+
*/
|
57
|
+
|
58
|
+
Emitter.prototype.once = function(event, fn){
|
59
|
+
var self = this;
|
60
|
+
this._callbacks = this._callbacks || {};
|
61
|
+
|
62
|
+
function on() {
|
63
|
+
self.off(event, on);
|
64
|
+
fn.apply(this, arguments);
|
65
|
+
}
|
66
|
+
|
67
|
+
on.fn = fn;
|
68
|
+
this.on(event, on);
|
69
|
+
return this;
|
70
|
+
};
|
71
|
+
|
72
|
+
/**
|
73
|
+
* Remove the given callback for `event` or all
|
74
|
+
* registered callbacks.
|
75
|
+
*
|
76
|
+
* @param {String} event
|
77
|
+
* @param {Function} fn
|
78
|
+
* @return {Emitter}
|
79
|
+
* @api public
|
80
|
+
*/
|
81
|
+
|
82
|
+
Emitter.prototype.off =
|
83
|
+
Emitter.prototype.removeListener =
|
84
|
+
Emitter.prototype.removeAllListeners =
|
85
|
+
Emitter.prototype.removeEventListener = function(event, fn){
|
86
|
+
this._callbacks = this._callbacks || {};
|
87
|
+
|
88
|
+
// all
|
89
|
+
if (0 == arguments.length) {
|
90
|
+
this._callbacks = {};
|
91
|
+
return this;
|
92
|
+
}
|
93
|
+
|
94
|
+
// specific event
|
95
|
+
var callbacks = this._callbacks[event];
|
96
|
+
if (!callbacks) return this;
|
97
|
+
|
98
|
+
// remove all handlers
|
99
|
+
if (1 == arguments.length) {
|
100
|
+
delete this._callbacks[event];
|
101
|
+
return this;
|
102
|
+
}
|
103
|
+
|
104
|
+
// remove specific handler
|
105
|
+
var cb;
|
106
|
+
for (var i = 0; i < callbacks.length; i++) {
|
107
|
+
cb = callbacks[i];
|
108
|
+
if (cb === fn || cb.fn === fn) {
|
109
|
+
callbacks.splice(i, 1);
|
110
|
+
break;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
return this;
|
114
|
+
};
|
115
|
+
|
116
|
+
/**
|
117
|
+
* Emit `event` with the given args.
|
118
|
+
*
|
119
|
+
* @param {String} event
|
120
|
+
* @param {Mixed} ...
|
121
|
+
* @return {Emitter}
|
122
|
+
*/
|
123
|
+
|
124
|
+
Emitter.prototype.emit = function(event){
|
125
|
+
this._callbacks = this._callbacks || {};
|
126
|
+
var args = [].slice.call(arguments, 1)
|
127
|
+
, callbacks = this._callbacks[event];
|
128
|
+
|
129
|
+
if (callbacks) {
|
130
|
+
callbacks = callbacks.slice(0);
|
131
|
+
for (var i = 0, len = callbacks.length; i < len; ++i) {
|
132
|
+
callbacks[i].apply(this, args);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
return this;
|
137
|
+
};
|
138
|
+
|
139
|
+
/**
|
140
|
+
* Return array of callbacks for `event`.
|
141
|
+
*
|
142
|
+
* @param {String} event
|
143
|
+
* @return {Array}
|
144
|
+
* @api public
|
145
|
+
*/
|
146
|
+
|
147
|
+
Emitter.prototype.listeners = function(event){
|
148
|
+
this._callbacks = this._callbacks || {};
|
149
|
+
return this._callbacks[event] || [];
|
150
|
+
};
|
151
|
+
|
152
|
+
/**
|
153
|
+
* Check if this emitter has `event` handlers.
|
154
|
+
*
|
155
|
+
* @param {String} event
|
156
|
+
* @return {Boolean}
|
157
|
+
* @api public
|
158
|
+
*/
|
159
|
+
|
160
|
+
Emitter.prototype.hasListeners = function(event){
|
161
|
+
return !! this.listeners(event).length;
|
162
|
+
};
|
@@ -73,7 +73,7 @@ function DataSet (options) {
|
|
73
73
|
* {Object | null} params
|
74
74
|
* {String | Number} senderId
|
75
75
|
*/
|
76
|
-
DataSet.prototype.
|
76
|
+
DataSet.prototype.on = function on (event, callback) {
|
77
77
|
var subscribers = this.subscribers[event];
|
78
78
|
if (!subscribers) {
|
79
79
|
subscribers = [];
|
@@ -85,12 +85,15 @@ DataSet.prototype.subscribe = function (event, callback) {
|
|
85
85
|
});
|
86
86
|
};
|
87
87
|
|
88
|
+
// TODO: make this function deprecated (replaced with `on` since version 0.5)
|
89
|
+
DataSet.prototype.subscribe = DataSet.prototype.on;
|
90
|
+
|
88
91
|
/**
|
89
92
|
* Unsubscribe from an event, remove an event listener
|
90
93
|
* @param {String} event
|
91
94
|
* @param {function} callback
|
92
95
|
*/
|
93
|
-
DataSet.prototype.
|
96
|
+
DataSet.prototype.off = function off(event, callback) {
|
94
97
|
var subscribers = this.subscribers[event];
|
95
98
|
if (subscribers) {
|
96
99
|
this.subscribers[event] = subscribers.filter(function (listener) {
|
@@ -99,6 +102,9 @@ DataSet.prototype.unsubscribe = function (event, callback) {
|
|
99
102
|
}
|
100
103
|
};
|
101
104
|
|
105
|
+
// TODO: make this function deprecated (replaced with `on` since version 0.5)
|
106
|
+
DataSet.prototype.unsubscribe = DataSet.prototype.off;
|
107
|
+
|
102
108
|
/**
|
103
109
|
* Trigger an event
|
104
110
|
* @param {String} event
|
@@ -69,8 +69,8 @@ DataView.prototype.setData = function (data) {
|
|
69
69
|
this._trigger('add', {items: ids});
|
70
70
|
|
71
71
|
// subscribe to new dataset
|
72
|
-
if (this.data.
|
73
|
-
this.data.
|
72
|
+
if (this.data.on) {
|
73
|
+
this.data.on('*', this.listener);
|
74
74
|
}
|
75
75
|
}
|
76
76
|
};
|
@@ -276,6 +276,10 @@ DataView.prototype._onEvent = function (event, params, senderId) {
|
|
276
276
|
};
|
277
277
|
|
278
278
|
// copy subscription functionality from DataSet
|
279
|
-
DataView.prototype.
|
280
|
-
DataView.prototype.
|
279
|
+
DataView.prototype.on = DataSet.prototype.on;
|
280
|
+
DataView.prototype.off = DataSet.prototype.off;
|
281
281
|
DataView.prototype._trigger = DataSet.prototype._trigger;
|
282
|
+
|
283
|
+
// TODO: make these functions deprecated (replaced with `on` and `off` since version 0.5)
|
284
|
+
DataView.prototype.subscribe = DataView.prototype.on;
|
285
|
+
DataView.prototype.unsubscribe = DataView.prototype.off;
|
@@ -31,10 +31,14 @@ function Edge (properties, graph, constants) {
|
|
31
31
|
this.title = undefined;
|
32
32
|
this.width = constants.edges.width;
|
33
33
|
this.value = undefined;
|
34
|
-
this.length = constants.
|
34
|
+
this.length = constants.physics.springLength;
|
35
|
+
this.customLength = false;
|
36
|
+
this.selected = false;
|
37
|
+
this.smooth = constants.smoothCurves;
|
35
38
|
|
36
39
|
this.from = null; // a node
|
37
40
|
this.to = null; // a node
|
41
|
+
this.via = null; // a temp node
|
38
42
|
|
39
43
|
// we use this to be able to reconnect the edge to a cluster if its node is put into a cluster
|
40
44
|
// by storing the original information we can revert to the original connection when the cluser is opened.
|
@@ -48,13 +52,11 @@ function Edge (properties, graph, constants) {
|
|
48
52
|
// 2012-08-08
|
49
53
|
this.dash = util.extend({}, constants.edges.dash); // contains properties length, gap, altLength
|
50
54
|
|
51
|
-
this.stiffness = undefined; // depends on the length of the edge
|
52
55
|
this.color = constants.edges.color;
|
53
56
|
this.widthFixed = false;
|
54
57
|
this.lengthFixed = false;
|
55
58
|
|
56
59
|
this.setProperties(properties, constants);
|
57
|
-
|
58
60
|
}
|
59
61
|
|
60
62
|
/**
|
@@ -73,6 +75,7 @@ Edge.prototype.setProperties = function(properties, constants) {
|
|
73
75
|
if (properties.id !== undefined) {this.id = properties.id;}
|
74
76
|
if (properties.style !== undefined) {this.style = properties.style;}
|
75
77
|
if (properties.label !== undefined) {this.label = properties.label;}
|
78
|
+
|
76
79
|
if (this.label) {
|
77
80
|
this.fontSize = constants.edges.fontSize;
|
78
81
|
this.fontFace = constants.edges.fontFace;
|
@@ -81,10 +84,12 @@ Edge.prototype.setProperties = function(properties, constants) {
|
|
81
84
|
if (properties.fontSize !== undefined) {this.fontSize = properties.fontSize;}
|
82
85
|
if (properties.fontFace !== undefined) {this.fontFace = properties.fontFace;}
|
83
86
|
}
|
84
|
-
|
85
|
-
if (properties.
|
86
|
-
if (properties.
|
87
|
-
if (properties.
|
87
|
+
|
88
|
+
if (properties.title !== undefined) {this.title = properties.title;}
|
89
|
+
if (properties.width !== undefined) {this.width = properties.width;}
|
90
|
+
if (properties.value !== undefined) {this.value = properties.value;}
|
91
|
+
if (properties.length !== undefined) {this.length = properties.length;
|
92
|
+
this.customLength = true;}
|
88
93
|
|
89
94
|
// Added to support dashed lines
|
90
95
|
// David Jordan
|
@@ -102,7 +107,6 @@ Edge.prototype.setProperties = function(properties, constants) {
|
|
102
107
|
|
103
108
|
this.widthFixed = this.widthFixed || (properties.width !== undefined);
|
104
109
|
this.lengthFixed = this.lengthFixed || (properties.length !== undefined);
|
105
|
-
this.stiffness = 1 / this.length;
|
106
110
|
|
107
111
|
// set draw method based on style
|
108
112
|
switch (this.style) {
|
@@ -210,8 +214,7 @@ Edge.prototype.isOverlappingWith = function(obj) {
|
|
210
214
|
var xObj = obj.left;
|
211
215
|
var yObj = obj.top;
|
212
216
|
|
213
|
-
|
214
|
-
var dist = Edge._dist(xFrom, yFrom, xTo, yTo, xObj, yObj);
|
217
|
+
var dist = this._getDistanceToEdge(xFrom, yFrom, xTo, yTo, xObj, yObj);
|
215
218
|
|
216
219
|
return (dist < distMax);
|
217
220
|
};
|
@@ -229,14 +232,21 @@ Edge.prototype._drawLine = function(ctx) {
|
|
229
232
|
ctx.strokeStyle = this.color;
|
230
233
|
ctx.lineWidth = this._getLineWidth();
|
231
234
|
|
232
|
-
var point;
|
233
235
|
if (this.from != this.to) {
|
234
236
|
// draw line
|
235
237
|
this._line(ctx);
|
236
238
|
|
237
239
|
// draw label
|
240
|
+
var point;
|
238
241
|
if (this.label) {
|
239
|
-
|
242
|
+
if (this.smooth == true) {
|
243
|
+
var midpointX = 0.5*(0.5*(this.from.x + this.via.x) + 0.5*(this.to.x + this.via.x));
|
244
|
+
var midpointY = 0.5*(0.5*(this.from.y + this.via.y) + 0.5*(this.to.y + this.via.y));
|
245
|
+
point = {x:midpointX, y:midpointY};
|
246
|
+
}
|
247
|
+
else {
|
248
|
+
point = this._pointOnLine(0.5);
|
249
|
+
}
|
240
250
|
this._label(ctx, this.label, point.x, point.y);
|
241
251
|
}
|
242
252
|
}
|
@@ -268,7 +278,7 @@ Edge.prototype._drawLine = function(ctx) {
|
|
268
278
|
* @private
|
269
279
|
*/
|
270
280
|
Edge.prototype._getLineWidth = function() {
|
271
|
-
if (this.
|
281
|
+
if (this.selected == true) {
|
272
282
|
return Math.min(this.width * 2, this.widthMax)*this.graphScaleInv;
|
273
283
|
}
|
274
284
|
else {
|
@@ -285,7 +295,12 @@ Edge.prototype._line = function (ctx) {
|
|
285
295
|
// draw a straight line
|
286
296
|
ctx.beginPath();
|
287
297
|
ctx.moveTo(this.from.x, this.from.y);
|
288
|
-
|
298
|
+
if (this.smooth == true) {
|
299
|
+
ctx.quadraticCurveTo(this.via.x,this.via.y,this.to.x, this.to.y);
|
300
|
+
}
|
301
|
+
else {
|
302
|
+
ctx.lineTo(this.to.x, this.to.y);
|
303
|
+
}
|
289
304
|
ctx.stroke();
|
290
305
|
};
|
291
306
|
|
@@ -347,29 +362,82 @@ Edge.prototype._drawDashLine = function(ctx) {
|
|
347
362
|
ctx.strokeStyle = this.color;
|
348
363
|
ctx.lineWidth = this._getLineWidth();
|
349
364
|
|
350
|
-
//
|
351
|
-
ctx.
|
352
|
-
|
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
|
+
// only firefox and chrome support this method, else we use the legacy one.
|
366
|
+
if (ctx.mozDash !== undefined || ctx.setLineDash !== undefined) {
|
367
|
+
ctx.beginPath();
|
365
368
|
ctx.moveTo(this.from.x, this.from.y);
|
366
|
-
|
369
|
+
|
370
|
+
// configure the dash pattern
|
371
|
+
var pattern = [0];
|
372
|
+
if (this.dash.length !== undefined && this.dash.gap !== undefined) {
|
373
|
+
pattern = [this.dash.length,this.dash.gap];
|
374
|
+
}
|
375
|
+
else {
|
376
|
+
pattern = [5,5];
|
377
|
+
}
|
378
|
+
|
379
|
+
// set dash settings for chrome or firefox
|
380
|
+
if (typeof ctx.setLineDash !== 'undefined') { //Chrome
|
381
|
+
ctx.setLineDash(pattern);
|
382
|
+
ctx.lineDashOffset = 0;
|
383
|
+
|
384
|
+
} else { //Firefox
|
385
|
+
ctx.mozDash = pattern;
|
386
|
+
ctx.mozDashOffset = 0;
|
387
|
+
}
|
388
|
+
|
389
|
+
// draw the line
|
390
|
+
if (this.smooth == true) {
|
391
|
+
ctx.quadraticCurveTo(this.via.x,this.via.y,this.to.x, this.to.y);
|
392
|
+
}
|
393
|
+
else {
|
394
|
+
ctx.lineTo(this.to.x, this.to.y);
|
395
|
+
}
|
396
|
+
ctx.stroke();
|
397
|
+
|
398
|
+
// restore the dash settings.
|
399
|
+
if (typeof ctx.setLineDash !== 'undefined') { //Chrome
|
400
|
+
ctx.setLineDash([0]);
|
401
|
+
ctx.lineDashOffset = 0;
|
402
|
+
|
403
|
+
} else { //Firefox
|
404
|
+
ctx.mozDash = [0];
|
405
|
+
ctx.mozDashOffset = 0;
|
406
|
+
}
|
407
|
+
}
|
408
|
+
else { // unsupporting smooth lines
|
409
|
+
// draw dashed line
|
410
|
+
ctx.beginPath();
|
411
|
+
ctx.lineCap = 'round';
|
412
|
+
if (this.dash.altLength !== undefined) //If an alt dash value has been set add to the array this value
|
413
|
+
{
|
414
|
+
ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,
|
415
|
+
[this.dash.length,this.dash.gap,this.dash.altLength,this.dash.gap]);
|
416
|
+
}
|
417
|
+
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
|
418
|
+
{
|
419
|
+
ctx.dashedLine(this.from.x,this.from.y,this.to.x,this.to.y,
|
420
|
+
[this.dash.length,this.dash.gap]);
|
421
|
+
}
|
422
|
+
else //If all else fails draw a line
|
423
|
+
{
|
424
|
+
ctx.moveTo(this.from.x, this.from.y);
|
425
|
+
ctx.lineTo(this.to.x, this.to.y);
|
426
|
+
}
|
427
|
+
ctx.stroke();
|
367
428
|
}
|
368
|
-
ctx.stroke();
|
369
429
|
|
370
430
|
// draw label
|
371
431
|
if (this.label) {
|
372
|
-
var point
|
432
|
+
var point;
|
433
|
+
if (this.smooth == true) {
|
434
|
+
var midpointX = 0.5*(0.5*(this.from.x + this.via.x) + 0.5*(this.to.x + this.via.x));
|
435
|
+
var midpointY = 0.5*(0.5*(this.from.y + this.via.y) + 0.5*(this.to.y + this.via.y));
|
436
|
+
point = {x:midpointX, y:midpointY};
|
437
|
+
}
|
438
|
+
else {
|
439
|
+
point = this._pointOnLine(0.5);
|
440
|
+
}
|
373
441
|
this._label(ctx, this.label, point.x, point.y);
|
374
442
|
}
|
375
443
|
};
|
@@ -422,35 +490,42 @@ Edge.prototype._drawArrowCenter = function(ctx) {
|
|
422
490
|
// draw line
|
423
491
|
this._line(ctx);
|
424
492
|
|
425
|
-
// draw an arrow halfway the line
|
426
493
|
var angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x));
|
427
494
|
var length = 10 + 5 * this.width; // TODO: make customizable?
|
428
|
-
|
495
|
+
// draw an arrow halfway the line
|
496
|
+
if (this.smooth == true) {
|
497
|
+
var midpointX = 0.5*(0.5*(this.from.x + this.via.x) + 0.5*(this.to.x + this.via.x));
|
498
|
+
var midpointY = 0.5*(0.5*(this.from.y + this.via.y) + 0.5*(this.to.y + this.via.y));
|
499
|
+
point = {x:midpointX, y:midpointY};
|
500
|
+
}
|
501
|
+
else {
|
502
|
+
point = this._pointOnLine(0.5);
|
503
|
+
}
|
504
|
+
|
429
505
|
ctx.arrow(point.x, point.y, angle, length);
|
430
506
|
ctx.fill();
|
431
507
|
ctx.stroke();
|
432
508
|
|
433
509
|
// draw label
|
434
510
|
if (this.label) {
|
435
|
-
point = this._pointOnLine(0.5);
|
436
511
|
this._label(ctx, this.label, point.x, point.y);
|
437
512
|
}
|
438
513
|
}
|
439
514
|
else {
|
440
515
|
// draw circle
|
441
516
|
var x, y;
|
442
|
-
var radius = this.length
|
517
|
+
var radius = 0.25 * Math.max(100,this.length);
|
443
518
|
var node = this.from;
|
444
519
|
if (!node.width) {
|
445
520
|
node.resize(ctx);
|
446
521
|
}
|
447
522
|
if (node.width > node.height) {
|
448
|
-
x = node.x + node.width
|
523
|
+
x = node.x + node.width * 0.5;
|
449
524
|
y = node.y - radius;
|
450
525
|
}
|
451
526
|
else {
|
452
527
|
x = node.x + radius;
|
453
|
-
y = node.y - node.height
|
528
|
+
y = node.y - node.height * 0.5;
|
454
529
|
}
|
455
530
|
this._circle(ctx, x, y, radius);
|
456
531
|
|
@@ -485,39 +560,66 @@ Edge.prototype._drawArrow = function(ctx) {
|
|
485
560
|
ctx.fillStyle = this.color;
|
486
561
|
ctx.lineWidth = this._getLineWidth();
|
487
562
|
|
488
|
-
// draw line
|
489
563
|
var angle, length;
|
564
|
+
//draw a line
|
490
565
|
if (this.from != this.to) {
|
491
|
-
// calculate length and angle of the line
|
492
566
|
angle = Math.atan2((this.to.y - this.from.y), (this.to.x - this.from.x));
|
493
567
|
var dx = (this.to.x - this.from.x);
|
494
568
|
var dy = (this.to.y - this.from.y);
|
495
|
-
var
|
569
|
+
var edgeSegmentLength = Math.sqrt(dx * dx + dy * dy);
|
570
|
+
|
571
|
+
var fromBorderDist = this.from.distanceToBorder(ctx, angle + Math.PI);
|
572
|
+
var fromBorderPoint = (edgeSegmentLength - fromBorderDist) / edgeSegmentLength;
|
573
|
+
var xFrom = (fromBorderPoint) * this.from.x + (1 - fromBorderPoint) * this.to.x;
|
574
|
+
var yFrom = (fromBorderPoint) * this.from.y + (1 - fromBorderPoint) * this.to.y;
|
496
575
|
|
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
576
|
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
577
|
+
if (this.smooth == true) {
|
578
|
+
angle = Math.atan2((this.to.y - this.via.y), (this.to.x - this.via.x));
|
579
|
+
dx = (this.to.x - this.via.x);
|
580
|
+
dy = (this.to.y - this.via.y);
|
581
|
+
edgeSegmentLength = Math.sqrt(dx * dx + dy * dy);
|
582
|
+
}
|
583
|
+
var toBorderDist = this.to.distanceToBorder(ctx, angle);
|
584
|
+
var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength;
|
585
|
+
|
586
|
+
var xTo,yTo;
|
587
|
+
if (this.smooth == true) {
|
588
|
+
xTo = (1 - toBorderPoint) * this.via.x + toBorderPoint * this.to.x;
|
589
|
+
yTo = (1 - toBorderPoint) * this.via.y + toBorderPoint * this.to.y;
|
590
|
+
}
|
591
|
+
else {
|
592
|
+
xTo = (1 - toBorderPoint) * this.from.x + toBorderPoint * this.to.x;
|
593
|
+
yTo = (1 - toBorderPoint) * this.from.y + toBorderPoint * this.to.y;
|
594
|
+
}
|
506
595
|
|
507
596
|
ctx.beginPath();
|
508
|
-
ctx.moveTo(xFrom,
|
509
|
-
|
597
|
+
ctx.moveTo(xFrom,yFrom);
|
598
|
+
if (this.smooth == true) {
|
599
|
+
ctx.quadraticCurveTo(this.via.x,this.via.y,xTo, yTo);
|
600
|
+
}
|
601
|
+
else {
|
602
|
+
ctx.lineTo(xTo, yTo);
|
603
|
+
}
|
510
604
|
ctx.stroke();
|
511
605
|
|
512
606
|
// draw arrow at the end of the line
|
513
|
-
length = 10 + 5 * this.width;
|
607
|
+
length = 10 + 5 * this.width;
|
514
608
|
ctx.arrow(xTo, yTo, angle, length);
|
515
609
|
ctx.fill();
|
516
610
|
ctx.stroke();
|
517
611
|
|
518
612
|
// draw label
|
519
613
|
if (this.label) {
|
520
|
-
var point
|
614
|
+
var point;
|
615
|
+
if (this.smooth == true) {
|
616
|
+
var midpointX = 0.5*(0.5*(this.from.x + this.via.x) + 0.5*(this.to.x + this.via.x));
|
617
|
+
var midpointY = 0.5*(0.5*(this.from.y + this.via.y) + 0.5*(this.to.y + this.via.y));
|
618
|
+
point = {x:midpointX, y:midpointY};
|
619
|
+
}
|
620
|
+
else {
|
621
|
+
point = this._pointOnLine(0.5);
|
622
|
+
}
|
521
623
|
this._label(ctx, this.label, point.x, point.y);
|
522
624
|
}
|
523
625
|
}
|
@@ -525,12 +627,12 @@ Edge.prototype._drawArrow = function(ctx) {
|
|
525
627
|
// draw circle
|
526
628
|
var node = this.from;
|
527
629
|
var x, y, arrow;
|
528
|
-
var radius = this.length
|
630
|
+
var radius = 0.25 * Math.max(100,this.length);
|
529
631
|
if (!node.width) {
|
530
632
|
node.resize(ctx);
|
531
633
|
}
|
532
634
|
if (node.width > node.height) {
|
533
|
-
x = node.x + node.width
|
635
|
+
x = node.x + node.width * 0.5;
|
534
636
|
y = node.y - radius;
|
535
637
|
arrow = {
|
536
638
|
x: x,
|
@@ -540,7 +642,7 @@ Edge.prototype._drawArrow = function(ctx) {
|
|
540
642
|
}
|
541
643
|
else {
|
542
644
|
x = node.x + radius;
|
543
|
-
y = node.y - node.height
|
645
|
+
y = node.y - node.height * 0.5;
|
544
646
|
arrow = {
|
545
647
|
x: node.x,
|
546
648
|
y: y,
|
@@ -548,7 +650,6 @@ Edge.prototype._drawArrow = function(ctx) {
|
|
548
650
|
};
|
549
651
|
}
|
550
652
|
ctx.beginPath();
|
551
|
-
// TODO: do not draw a circle, but an arc
|
552
653
|
// TODO: similarly, for a line without arrows, draw to the border of the nodes instead of the center
|
553
654
|
ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
|
554
655
|
ctx.stroke();
|
@@ -581,31 +682,46 @@ Edge.prototype._drawArrow = function(ctx) {
|
|
581
682
|
* @param {number} y3
|
582
683
|
* @private
|
583
684
|
*/
|
584
|
-
Edge.
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
685
|
+
Edge.prototype._getDistanceToEdge = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point
|
686
|
+
if (this.smooth == true) {
|
687
|
+
var minDistance = 1e9;
|
688
|
+
var i,t,x,y,dx,dy;
|
689
|
+
for (i = 0; i < 10; i++) {
|
690
|
+
t = 0.1*i;
|
691
|
+
x = Math.pow(1-t,2)*x1 + (2*t*(1 - t))*this.via.x + Math.pow(t,2)*x2;
|
692
|
+
y = Math.pow(1-t,2)*y1 + (2*t*(1 - t))*this.via.y + Math.pow(t,2)*y2;
|
693
|
+
dx = Math.abs(x3-x);
|
694
|
+
dy = Math.abs(y3-y);
|
695
|
+
minDistance = Math.min(minDistance,Math.sqrt(dx*dx + dy*dy));
|
696
|
+
}
|
697
|
+
return minDistance
|
595
698
|
}
|
699
|
+
else {
|
700
|
+
var px = x2-x1,
|
701
|
+
py = y2-y1,
|
702
|
+
something = px*px + py*py,
|
703
|
+
u = ((x3 - x1) * px + (y3 - y1) * py) / something;
|
704
|
+
|
705
|
+
if (u > 1) {
|
706
|
+
u = 1;
|
707
|
+
}
|
708
|
+
else if (u < 0) {
|
709
|
+
u = 0;
|
710
|
+
}
|
596
711
|
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
712
|
+
var x = x1 + u * px,
|
713
|
+
y = y1 + u * py,
|
714
|
+
dx = x - x3,
|
715
|
+
dy = y - y3;
|
601
716
|
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
717
|
+
//# Note: If the actual distance does not matter,
|
718
|
+
//# if you only want to compare what this function
|
719
|
+
//# returns to other results of this function, you
|
720
|
+
//# can just return the squared distance instead
|
721
|
+
//# (i.e. remove the sqrt) to gain a little performance
|
607
722
|
|
608
|
-
|
723
|
+
return Math.sqrt(dx*dx + dy*dy);
|
724
|
+
}
|
609
725
|
};
|
610
726
|
|
611
727
|
|
@@ -617,4 +733,20 @@ Edge._dist = function (x1,y1, x2,y2, x3,y3) { // x3,y3 is the point
|
|
617
733
|
*/
|
618
734
|
Edge.prototype.setScale = function(scale) {
|
619
735
|
this.graphScaleInv = 1.0/scale;
|
736
|
+
};
|
737
|
+
|
738
|
+
|
739
|
+
Edge.prototype.select = function() {
|
740
|
+
this.selected = true;
|
741
|
+
};
|
742
|
+
|
743
|
+
Edge.prototype.unselect = function() {
|
744
|
+
this.selected = false;
|
745
|
+
};
|
746
|
+
|
747
|
+
Edge.prototype.positionBezierNode = function() {
|
748
|
+
if (this.via !== null) {
|
749
|
+
this.via.x = 0.5 * (this.from.x + this.to.x);
|
750
|
+
this.via.y = 0.5 * (this.from.y + this.to.y);
|
751
|
+
}
|
620
752
|
};
|