vis-rails 1.0.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/README.md +2 -0
- data/lib/vis/rails/version.rb +1 -1
- data/vendor/assets/javascripts/module/exports-only-timeline.js +55 -0
- data/vendor/assets/javascripts/vis-only-timeline.js +23 -0
- data/vendor/assets/javascripts/vis.js +3 -3
- data/vendor/assets/stylesheets/vis-only-timeline.css +3 -0
- data/vendor/assets/vis/DataSet.js +106 -130
- data/vendor/assets/vis/DataView.js +35 -37
- data/vendor/assets/vis/graph/Edge.js +225 -45
- data/vendor/assets/vis/graph/Graph.js +120 -24
- data/vendor/assets/vis/graph/Node.js +16 -16
- data/vendor/assets/vis/graph/graphMixins/HierarchicalLayoutMixin.js +1 -1
- data/vendor/assets/vis/graph/graphMixins/ManipulationMixin.js +143 -0
- data/vendor/assets/vis/graph/graphMixins/SelectionMixin.js +81 -3
- data/vendor/assets/vis/graph3d/Graph3d.js +3306 -0
- data/vendor/assets/vis/module/exports.js +2 -3
- data/vendor/assets/vis/timeline/Range.js +93 -80
- data/vendor/assets/vis/timeline/Timeline.js +525 -428
- data/vendor/assets/vis/timeline/component/Component.js +19 -53
- data/vendor/assets/vis/timeline/component/CurrentTime.js +57 -25
- data/vendor/assets/vis/timeline/component/CustomTime.js +55 -19
- data/vendor/assets/vis/timeline/component/Group.js +47 -50
- data/vendor/assets/vis/timeline/component/ItemSet.js +402 -206
- data/vendor/assets/vis/timeline/component/TimeAxis.js +112 -169
- data/vendor/assets/vis/timeline/component/css/animation.css +33 -0
- data/vendor/assets/vis/timeline/component/css/currenttime.css +1 -1
- data/vendor/assets/vis/timeline/component/css/customtime.css +1 -1
- data/vendor/assets/vis/timeline/component/css/item.css +1 -11
- data/vendor/assets/vis/timeline/component/css/itemset.css +13 -18
- data/vendor/assets/vis/timeline/component/css/labelset.css +8 -6
- data/vendor/assets/vis/timeline/component/css/panel.css +56 -13
- data/vendor/assets/vis/timeline/component/css/timeaxis.css +15 -8
- data/vendor/assets/vis/timeline/component/item/Item.js +16 -15
- data/vendor/assets/vis/timeline/component/item/ItemBox.js +30 -30
- data/vendor/assets/vis/timeline/component/item/ItemPoint.js +20 -21
- data/vendor/assets/vis/timeline/component/item/ItemRange.js +23 -24
- data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +10 -10
- data/vendor/assets/vis/timeline/stack.js +5 -5
- data/vendor/assets/vis/util.js +81 -35
- metadata +7 -4
- data/vendor/assets/vis/timeline/component/Panel.js +0 -170
- data/vendor/assets/vis/timeline/component/RootPanel.js +0 -176
@@ -23,14 +23,14 @@ function Graph (container, data, options) {
|
|
23
23
|
this.renderTimestep = 1000 / this.renderRefreshRate; // ms -- saves calculation later on
|
24
24
|
this.renderTime = 0.5 * this.renderTimestep; // measured time it takes to render a frame
|
25
25
|
this.maxPhysicsTicksPerRender = 3; // max amount of physics ticks per render step.
|
26
|
-
this.physicsDiscreteStepsize = 0.
|
26
|
+
this.physicsDiscreteStepsize = 0.50; // discrete stepsize of the simulation
|
27
27
|
|
28
28
|
this.stabilize = true; // stabilize before displaying the graph
|
29
29
|
this.selectable = true;
|
30
30
|
this.initializing = true;
|
31
31
|
|
32
32
|
// these functions are triggered when the dataset is edited
|
33
|
-
this.triggerFunctions = {add:null,edit:null,connect:null,del:null};
|
33
|
+
this.triggerFunctions = {add:null,edit:null,editEdge:null,connect:null,del:null};
|
34
34
|
|
35
35
|
// set constant values
|
36
36
|
this.constants = {
|
@@ -53,6 +53,10 @@ function Graph (container, data, options) {
|
|
53
53
|
highlight: {
|
54
54
|
border: '#2B7CE9',
|
55
55
|
background: '#D2E5FF'
|
56
|
+
},
|
57
|
+
hover: {
|
58
|
+
border: '#2B7CE9',
|
59
|
+
background: '#D2E5FF'
|
56
60
|
}
|
57
61
|
},
|
58
62
|
borderColor: '#2B7CE9',
|
@@ -64,10 +68,12 @@ function Graph (container, data, options) {
|
|
64
68
|
widthMin: 1,
|
65
69
|
widthMax: 15,
|
66
70
|
width: 1,
|
71
|
+
hoverWidth: 1.5,
|
67
72
|
style: 'line',
|
68
73
|
color: {
|
69
74
|
color:'#848484',
|
70
|
-
highlight:'#848484'
|
75
|
+
highlight:'#848484',
|
76
|
+
hover: '#848484'
|
71
77
|
},
|
72
78
|
fontColor: '#343434',
|
73
79
|
fontSize: 14, // px
|
@@ -160,9 +166,11 @@ function Graph (container, data, options) {
|
|
160
166
|
link:"Add Link",
|
161
167
|
del:"Delete selected",
|
162
168
|
editNode:"Edit Node",
|
169
|
+
editEdge:"Edit Edge",
|
163
170
|
back:"Back",
|
164
171
|
addDescription:"Click in an empty space to place a new node.",
|
165
172
|
linkDescription:"Click on a node and drag the edge to another node to connect them.",
|
173
|
+
editEdgeDescription:"Click on the control points and drag them to a node to connect to it.",
|
166
174
|
addError:"The function for add does not support two arguments (data,callback).",
|
167
175
|
linkError:"The function for connect does not support two arguments (data,callback).",
|
168
176
|
editError:"The function for edit does not support two arguments (data, callback).",
|
@@ -180,10 +188,13 @@ function Graph (container, data, options) {
|
|
180
188
|
background: '#FFFFC6'
|
181
189
|
}
|
182
190
|
},
|
183
|
-
|
184
|
-
|
191
|
+
dragGraph: true,
|
192
|
+
dragNodes: true,
|
193
|
+
zoomable: true,
|
194
|
+
hover: false
|
185
195
|
};
|
186
|
-
this.
|
196
|
+
this.hoverObj = {nodes:{},edges:{}};
|
197
|
+
|
187
198
|
|
188
199
|
// Node variables
|
189
200
|
var graph = this;
|
@@ -217,7 +228,6 @@ function Graph (container, data, options) {
|
|
217
228
|
this._setScale(1);
|
218
229
|
this.setOptions(options);
|
219
230
|
|
220
|
-
|
221
231
|
// other vars
|
222
232
|
this.freezeSimulation = false;// freeze the simulation
|
223
233
|
this.cachedFunctions = {};
|
@@ -521,9 +531,10 @@ Graph.prototype.setOptions = function (options) {
|
|
521
531
|
if (options.freezeForStabilization !== undefined) {this.constants.freezeForStabilization = options.freezeForStabilization;}
|
522
532
|
if (options.configurePhysics !== undefined){this.constants.configurePhysics = options.configurePhysics;}
|
523
533
|
if (options.stabilizationIterations !== undefined) {this.constants.stabilizationIterations = options.stabilizationIterations;}
|
524
|
-
if (options.
|
525
|
-
if (options.
|
526
|
-
|
534
|
+
if (options.dragGraph !== undefined) {this.constants.dragGraph = options.dragGraph;}
|
535
|
+
if (options.dragNodes !== undefined) {this.constants.dragNodes = options.dragNodes;}
|
536
|
+
if (options.zoomable !== undefined) {this.constants.zoomable = options.zoomable;}
|
537
|
+
if (options.hover !== undefined) {this.constants.hover = options.hover;}
|
527
538
|
|
528
539
|
if (options.labels !== undefined) {
|
529
540
|
for (prop in options.labels) {
|
@@ -541,6 +552,10 @@ Graph.prototype.setOptions = function (options) {
|
|
541
552
|
this.triggerFunctions.edit = options.onEdit;
|
542
553
|
}
|
543
554
|
|
555
|
+
if (options.onEditEdge) {
|
556
|
+
this.triggerFunctions.editEdge = options.onEditEdge;
|
557
|
+
}
|
558
|
+
|
544
559
|
if (options.onConnect) {
|
545
560
|
this.triggerFunctions.connect = options.onConnect;
|
546
561
|
}
|
@@ -635,6 +650,7 @@ Graph.prototype.setOptions = function (options) {
|
|
635
650
|
this.constants.dataManipulation[prop] = options.dataManipulation[prop];
|
636
651
|
}
|
637
652
|
}
|
653
|
+
this.editMode = this.constants.dataManipulation.initiallyVisible;
|
638
654
|
}
|
639
655
|
else if (options.dataManipulation !== undefined) {
|
640
656
|
this.constants.dataManipulation.enabled = false;
|
@@ -656,10 +672,12 @@ Graph.prototype.setOptions = function (options) {
|
|
656
672
|
this.constants.edges.color = {};
|
657
673
|
this.constants.edges.color.color = options.edges.color;
|
658
674
|
this.constants.edges.color.highlight = options.edges.color;
|
675
|
+
this.constants.edges.color.hover = options.edges.color;
|
659
676
|
}
|
660
677
|
else {
|
661
678
|
if (options.edges.color.color !== undefined) {this.constants.edges.color.color = options.edges.color.color;}
|
662
679
|
if (options.edges.color.highlight !== undefined) {this.constants.edges.color.highlight = options.edges.color.highlight;}
|
680
|
+
if (options.edges.color.hover !== undefined) {this.constants.edges.color.hover = options.edges.color.hover;}
|
663
681
|
}
|
664
682
|
}
|
665
683
|
|
@@ -946,7 +964,7 @@ Graph.prototype._handleOnDrag = function(event) {
|
|
946
964
|
var me = this,
|
947
965
|
drag = this.drag,
|
948
966
|
selection = drag.selection;
|
949
|
-
if (selection && selection.length) {
|
967
|
+
if (selection && selection.length && this.constants.dragNodes == true) {
|
950
968
|
// calculate delta's and new location
|
951
969
|
var deltaX = pointer.x - drag.pointer.x,
|
952
970
|
deltaY = pointer.y - drag.pointer.y;
|
@@ -971,7 +989,7 @@ Graph.prototype._handleOnDrag = function(event) {
|
|
971
989
|
}
|
972
990
|
}
|
973
991
|
else {
|
974
|
-
if (this.constants.
|
992
|
+
if (this.constants.dragGraph == true) {
|
975
993
|
// move the graph
|
976
994
|
var diffX = pointer.x - this.drag.pointer.x;
|
977
995
|
var diffY = pointer.y - this.drag.pointer.y;
|
@@ -1159,7 +1177,7 @@ Graph.prototype._onMouseMoveTitle = function (event) {
|
|
1159
1177
|
var pointer = this._getPointer(gesture.center);
|
1160
1178
|
|
1161
1179
|
// check if the previously selected node is still selected
|
1162
|
-
if (this.
|
1180
|
+
if (this.popupObj) {
|
1163
1181
|
this._checkHidePopup(pointer);
|
1164
1182
|
}
|
1165
1183
|
|
@@ -1175,6 +1193,40 @@ Graph.prototype._onMouseMoveTitle = function (event) {
|
|
1175
1193
|
if (!this.drag.dragging) {
|
1176
1194
|
this.popupTimer = setTimeout(checkShow, this.constants.tooltip.delay);
|
1177
1195
|
}
|
1196
|
+
|
1197
|
+
|
1198
|
+
/**
|
1199
|
+
* Adding hover highlights
|
1200
|
+
*/
|
1201
|
+
if (this.constants.hover == true) {
|
1202
|
+
// removing all hover highlights
|
1203
|
+
for (var edgeId in this.hoverObj.edges) {
|
1204
|
+
if (this.hoverObj.edges.hasOwnProperty(edgeId)) {
|
1205
|
+
this.hoverObj.edges[edgeId].hover = false;
|
1206
|
+
delete this.hoverObj.edges[edgeId];
|
1207
|
+
}
|
1208
|
+
}
|
1209
|
+
|
1210
|
+
// adding hover highlights
|
1211
|
+
var obj = this._getNodeAt(pointer);
|
1212
|
+
if (obj == null) {
|
1213
|
+
obj = this._getEdgeAt(pointer);
|
1214
|
+
}
|
1215
|
+
if (obj != null) {
|
1216
|
+
this._hoverObject(obj);
|
1217
|
+
}
|
1218
|
+
|
1219
|
+
// removing all node hover highlights except for the selected one.
|
1220
|
+
for (var nodeId in this.hoverObj.nodes) {
|
1221
|
+
if (this.hoverObj.nodes.hasOwnProperty(nodeId)) {
|
1222
|
+
if (obj instanceof Node && obj.id != nodeId || obj instanceof Edge || obj == null) {
|
1223
|
+
this._blurObject(this.hoverObj.nodes[nodeId]);
|
1224
|
+
delete this.hoverObj.nodes[nodeId];
|
1225
|
+
}
|
1226
|
+
}
|
1227
|
+
}
|
1228
|
+
this.redraw();
|
1229
|
+
}
|
1178
1230
|
};
|
1179
1231
|
|
1180
1232
|
/**
|
@@ -1194,23 +1246,23 @@ Graph.prototype._checkShowPopup = function (pointer) {
|
|
1194
1246
|
};
|
1195
1247
|
|
1196
1248
|
var id;
|
1197
|
-
var lastPopupNode = this.
|
1249
|
+
var lastPopupNode = this.popupObj;
|
1198
1250
|
|
1199
|
-
if (this.
|
1251
|
+
if (this.popupObj == undefined) {
|
1200
1252
|
// search the nodes for overlap, select the top one in case of multiple nodes
|
1201
1253
|
var nodes = this.nodes;
|
1202
1254
|
for (id in nodes) {
|
1203
1255
|
if (nodes.hasOwnProperty(id)) {
|
1204
1256
|
var node = nodes[id];
|
1205
1257
|
if (node.getTitle() !== undefined && node.isOverlappingWith(obj)) {
|
1206
|
-
this.
|
1258
|
+
this.popupObj = node;
|
1207
1259
|
break;
|
1208
1260
|
}
|
1209
1261
|
}
|
1210
1262
|
}
|
1211
1263
|
}
|
1212
1264
|
|
1213
|
-
if (this.
|
1265
|
+
if (this.popupObj === undefined) {
|
1214
1266
|
// search the edges for overlap
|
1215
1267
|
var edges = this.edges;
|
1216
1268
|
for (id in edges) {
|
@@ -1218,16 +1270,16 @@ Graph.prototype._checkShowPopup = function (pointer) {
|
|
1218
1270
|
var edge = edges[id];
|
1219
1271
|
if (edge.connected && (edge.getTitle() !== undefined) &&
|
1220
1272
|
edge.isOverlappingWith(obj)) {
|
1221
|
-
this.
|
1273
|
+
this.popupObj = edge;
|
1222
1274
|
break;
|
1223
1275
|
}
|
1224
1276
|
}
|
1225
1277
|
}
|
1226
1278
|
}
|
1227
1279
|
|
1228
|
-
if (this.
|
1280
|
+
if (this.popupObj) {
|
1229
1281
|
// show popup message window
|
1230
|
-
if (this.
|
1282
|
+
if (this.popupObj != lastPopupNode) {
|
1231
1283
|
var me = this;
|
1232
1284
|
if (!me.popup) {
|
1233
1285
|
me.popup = new Popup(me.frame, me.constants.tooltip);
|
@@ -1237,7 +1289,7 @@ Graph.prototype._checkShowPopup = function (pointer) {
|
|
1237
1289
|
// bottom left location of the popup, and you can easily move over the
|
1238
1290
|
// popup area
|
1239
1291
|
me.popup.setPosition(pointer.x - 3, pointer.y - 3);
|
1240
|
-
me.popup.setText(me.
|
1292
|
+
me.popup.setText(me.popupObj.getTitle());
|
1241
1293
|
me.popup.show();
|
1242
1294
|
}
|
1243
1295
|
}
|
@@ -1256,8 +1308,8 @@ Graph.prototype._checkShowPopup = function (pointer) {
|
|
1256
1308
|
* @private
|
1257
1309
|
*/
|
1258
1310
|
Graph.prototype._checkHidePopup = function (pointer) {
|
1259
|
-
if (!this.
|
1260
|
-
this.
|
1311
|
+
if (!this.popupObj || !this._getNodeAt(pointer) ) {
|
1312
|
+
this.popupObj = undefined;
|
1261
1313
|
if (this.popup) {
|
1262
1314
|
this.popup.hide();
|
1263
1315
|
}
|
@@ -1633,7 +1685,6 @@ Graph.prototype._updateValueRange = function(obj) {
|
|
1633
1685
|
*/
|
1634
1686
|
Graph.prototype.redraw = function() {
|
1635
1687
|
this.setSize(this.width, this.height);
|
1636
|
-
|
1637
1688
|
this._redraw();
|
1638
1689
|
};
|
1639
1690
|
|
@@ -1665,6 +1716,7 @@ Graph.prototype._redraw = function() {
|
|
1665
1716
|
this._doInAllSectors("_drawAllSectorNodes",ctx);
|
1666
1717
|
this._doInAllSectors("_drawEdges",ctx);
|
1667
1718
|
this._doInAllSectors("_drawNodes",ctx,false);
|
1719
|
+
this._doInAllSectors("_drawControlNodes",ctx);
|
1668
1720
|
|
1669
1721
|
// this._doInSupportSector("_drawNodes",ctx,true);
|
1670
1722
|
// this._drawTree(ctx,"#F00F0F");
|
@@ -1849,6 +1901,21 @@ Graph.prototype._drawEdges = function(ctx) {
|
|
1849
1901
|
}
|
1850
1902
|
};
|
1851
1903
|
|
1904
|
+
/**
|
1905
|
+
* Redraw all edges
|
1906
|
+
* The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d');
|
1907
|
+
* @param {CanvasRenderingContext2D} ctx
|
1908
|
+
* @private
|
1909
|
+
*/
|
1910
|
+
Graph.prototype._drawControlNodes = function(ctx) {
|
1911
|
+
var edges = this.edges;
|
1912
|
+
for (var id in edges) {
|
1913
|
+
if (edges.hasOwnProperty(id)) {
|
1914
|
+
edges[id]._drawControlNodes(ctx);
|
1915
|
+
}
|
1916
|
+
}
|
1917
|
+
};
|
1918
|
+
|
1852
1919
|
/**
|
1853
1920
|
* Find a stable position for all nodes
|
1854
1921
|
* @private
|
@@ -2183,7 +2250,36 @@ Graph.prototype.storePosition = function() {
|
|
2183
2250
|
};
|
2184
2251
|
|
2185
2252
|
|
2253
|
+
/**
|
2254
|
+
* Center a node in view.
|
2255
|
+
*
|
2256
|
+
* @param {Number} nodeId
|
2257
|
+
* @param {Number} [zoomLevel]
|
2258
|
+
*/
|
2259
|
+
Graph.prototype.focusOnNode = function (nodeId, zoomLevel) {
|
2260
|
+
if (this.nodes.hasOwnProperty(nodeId)) {
|
2261
|
+
if (zoomLevel === undefined) {
|
2262
|
+
zoomLevel = this._getScale();
|
2263
|
+
}
|
2264
|
+
var nodePosition= {x: this.nodes[nodeId].x, y: this.nodes[nodeId].y};
|
2265
|
+
|
2266
|
+
var requiredScale = zoomLevel;
|
2267
|
+
this._setScale(requiredScale);
|
2268
|
+
|
2269
|
+
var canvasCenter = this.DOMtoCanvas({x:0.5 * this.frame.canvas.width,y:0.5 * this.frame.canvas.height});
|
2270
|
+
var translation = this._getTranslation();
|
2186
2271
|
|
2272
|
+
var distanceFromCenter = {x:canvasCenter.x - nodePosition.x,
|
2273
|
+
y:canvasCenter.y - nodePosition.y};
|
2274
|
+
|
2275
|
+
this._setTranslation(translation.x + requiredScale * distanceFromCenter.x,
|
2276
|
+
translation.y + requiredScale * distanceFromCenter.y);
|
2277
|
+
this.redraw();
|
2278
|
+
}
|
2279
|
+
else {
|
2280
|
+
console.log("This nodeId cannot be found.")
|
2281
|
+
}
|
2282
|
+
};
|
2187
2283
|
|
2188
2284
|
|
2189
2285
|
|
@@ -25,13 +25,14 @@
|
|
25
25
|
*/
|
26
26
|
function Node(properties, imagelist, grouplist, constants) {
|
27
27
|
this.selected = false;
|
28
|
+
this.hover = false;
|
28
29
|
|
29
30
|
this.edges = []; // all edges connected to this node
|
30
31
|
this.dynamicEdges = [];
|
31
32
|
this.reroutedEdges = {};
|
32
|
-
this.group = constants.nodes.group;
|
33
33
|
|
34
|
-
this.
|
34
|
+
this.group = constants.nodes.group;
|
35
|
+
this.fontSize = Number(constants.nodes.fontSize);
|
35
36
|
this.fontFace = constants.nodes.fontFace;
|
36
37
|
this.fontColor = constants.nodes.fontColor;
|
37
38
|
this.fontDrawThreshold = 3;
|
@@ -569,7 +570,7 @@ Node.prototype._drawBox = function (ctx) {
|
|
569
570
|
var clusterLineWidth = 2.5;
|
570
571
|
var selectionLineWidth = 2;
|
571
572
|
|
572
|
-
ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border;
|
573
|
+
ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border;
|
573
574
|
|
574
575
|
// draw the outer border
|
575
576
|
if (this.clusterSize > 1) {
|
@@ -618,7 +619,7 @@ Node.prototype._drawDatabase = function (ctx) {
|
|
618
619
|
var clusterLineWidth = 2.5;
|
619
620
|
var selectionLineWidth = 2;
|
620
621
|
|
621
|
-
ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border;
|
622
|
+
ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border;
|
622
623
|
|
623
624
|
// draw the outer border
|
624
625
|
if (this.clusterSize > 1) {
|
@@ -633,7 +634,7 @@ Node.prototype._drawDatabase = function (ctx) {
|
|
633
634
|
ctx.lineWidth *= this.graphScaleInv;
|
634
635
|
ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
|
635
636
|
|
636
|
-
ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background;
|
637
|
+
ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background;
|
637
638
|
ctx.database(this.x - this.width/2, this.y - this.height*0.5, this.width, this.height);
|
638
639
|
ctx.fill();
|
639
640
|
ctx.stroke();
|
@@ -668,7 +669,7 @@ Node.prototype._drawCircle = function (ctx) {
|
|
668
669
|
var clusterLineWidth = 2.5;
|
669
670
|
var selectionLineWidth = 2;
|
670
671
|
|
671
|
-
ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border;
|
672
|
+
ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border;
|
672
673
|
|
673
674
|
// draw the outer border
|
674
675
|
if (this.clusterSize > 1) {
|
@@ -683,7 +684,7 @@ Node.prototype._drawCircle = function (ctx) {
|
|
683
684
|
ctx.lineWidth *= this.graphScaleInv;
|
684
685
|
ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
|
685
686
|
|
686
|
-
ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background;
|
687
|
+
ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background;
|
687
688
|
ctx.circle(this.x, this.y, this.radius);
|
688
689
|
ctx.fill();
|
689
690
|
ctx.stroke();
|
@@ -718,7 +719,7 @@ Node.prototype._drawEllipse = function (ctx) {
|
|
718
719
|
var clusterLineWidth = 2.5;
|
719
720
|
var selectionLineWidth = 2;
|
720
721
|
|
721
|
-
ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border;
|
722
|
+
ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border;
|
722
723
|
|
723
724
|
// draw the outer border
|
724
725
|
if (this.clusterSize > 1) {
|
@@ -733,7 +734,7 @@ Node.prototype._drawEllipse = function (ctx) {
|
|
733
734
|
ctx.lineWidth *= this.graphScaleInv;
|
734
735
|
ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
|
735
736
|
|
736
|
-
ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background;
|
737
|
+
ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background;
|
737
738
|
|
738
739
|
ctx.ellipse(this.left, this.top, this.width, this.height);
|
739
740
|
ctx.fill();
|
@@ -795,7 +796,7 @@ Node.prototype._drawShape = function (ctx, shape) {
|
|
795
796
|
case 'star': radiusMultiplier = 4; break;
|
796
797
|
}
|
797
798
|
|
798
|
-
ctx.strokeStyle = this.selected ? this.color.highlight.border : this.color.border;
|
799
|
+
ctx.strokeStyle = this.selected ? this.color.highlight.border : this.hover ? this.color.hover.border : this.color.border;
|
799
800
|
|
800
801
|
// draw the outer border
|
801
802
|
if (this.clusterSize > 1) {
|
@@ -810,8 +811,7 @@ Node.prototype._drawShape = function (ctx, shape) {
|
|
810
811
|
ctx.lineWidth *= this.graphScaleInv;
|
811
812
|
ctx.lineWidth = Math.min(0.1 * this.width,ctx.lineWidth);
|
812
813
|
|
813
|
-
ctx.fillStyle = this.selected ? this.color.highlight.background : this.color.background;
|
814
|
-
|
814
|
+
ctx.fillStyle = this.selected ? this.color.highlight.background : this.hover ? this.color.hover.background : this.color.background;
|
815
815
|
ctx[shape](this.x, this.y, this.radius);
|
816
816
|
ctx.fill();
|
817
817
|
ctx.stroke();
|
@@ -892,10 +892,10 @@ Node.prototype.getTextSize = function(ctx) {
|
|
892
892
|
*/
|
893
893
|
Node.prototype.inArea = function() {
|
894
894
|
if (this.width !== undefined) {
|
895
|
-
return (this.x + this.width*this.graphScaleInv >= this.canvasTopLeft.x
|
896
|
-
this.x - this.width*this.graphScaleInv < this.canvasBottomRight.x &&
|
897
|
-
this.y + this.height*this.graphScaleInv
|
898
|
-
this.y - this.height*this.graphScaleInv
|
895
|
+
return (this.x + this.width *this.graphScaleInv >= this.canvasTopLeft.x &&
|
896
|
+
this.x - this.width *this.graphScaleInv < this.canvasBottomRight.x &&
|
897
|
+
this.y + this.height*this.graphScaleInv >= this.canvasTopLeft.y &&
|
898
|
+
this.y - this.height*this.graphScaleInv < this.canvasBottomRight.y);
|
899
899
|
}
|
900
900
|
else {
|
901
901
|
return true;
|
@@ -20,7 +20,7 @@ var HierarchicalLayoutMixin = {
|
|
20
20
|
* @private
|
21
21
|
*/
|
22
22
|
_setupHierarchicalLayout : function() {
|
23
|
-
if (this.constants.hierarchicalLayout.enabled == true) {
|
23
|
+
if (this.constants.hierarchicalLayout.enabled == true && this.nodeIndices.length > 0) {
|
24
24
|
if (this.constants.hierarchicalLayout.direction == "RL" || this.constants.hierarchicalLayout.direction == "DU") {
|
25
25
|
this.constants.hierarchicalLayout.levelSeparation *= -1;
|
26
26
|
}
|
@@ -65,6 +65,11 @@ var manipulationMixin = {
|
|
65
65
|
if (this.boundFunction) {
|
66
66
|
this.off('select', this.boundFunction);
|
67
67
|
}
|
68
|
+
if (this.edgeBeingEdited !== undefined) {
|
69
|
+
this.edgeBeingEdited._disableControlNodes();
|
70
|
+
this.edgeBeingEdited = undefined;
|
71
|
+
this.selectedControlNode = null;
|
72
|
+
}
|
68
73
|
|
69
74
|
// restore overloaded functions
|
70
75
|
this._restoreOverloadedFunctions();
|
@@ -93,6 +98,12 @@ var manipulationMixin = {
|
|
93
98
|
"<span class='graph-manipulationUI edit' id='graph-manipulate-editNode'>" +
|
94
99
|
"<span class='graph-manipulationLabel'>"+this.constants.labels['editNode'] +"</span></span>";
|
95
100
|
}
|
101
|
+
else if (this._getSelectedEdgeCount() == 1 && this._getSelectedNodeCount() == 0) {
|
102
|
+
this.manipulationDiv.innerHTML += "" +
|
103
|
+
"<div class='graph-seperatorLine'></div>" +
|
104
|
+
"<span class='graph-manipulationUI edit' id='graph-manipulate-editEdge'>" +
|
105
|
+
"<span class='graph-manipulationLabel'>"+this.constants.labels['editEdge'] +"</span></span>";
|
106
|
+
}
|
96
107
|
if (this._selectionIsEmpty() == false) {
|
97
108
|
this.manipulationDiv.innerHTML += "" +
|
98
109
|
"<div class='graph-seperatorLine'></div>" +
|
@@ -110,6 +121,10 @@ var manipulationMixin = {
|
|
110
121
|
var editButton = document.getElementById("graph-manipulate-editNode");
|
111
122
|
editButton.onclick = this._editNode.bind(this);
|
112
123
|
}
|
124
|
+
else if (this._getSelectedEdgeCount() == 1 && this._getSelectedNodeCount() == 0) {
|
125
|
+
var editButton = document.getElementById("graph-manipulate-editEdge");
|
126
|
+
editButton.onclick = this._createEditEdgeToolbar.bind(this);
|
127
|
+
}
|
113
128
|
if (this._selectionIsEmpty() == false) {
|
114
129
|
var deleteButton = document.getElementById("graph-manipulate-delete");
|
115
130
|
deleteButton.onclick = this._deleteSelected.bind(this);
|
@@ -203,10 +218,106 @@ var manipulationMixin = {
|
|
203
218
|
|
204
219
|
// redraw to show the unselect
|
205
220
|
this._redraw();
|
221
|
+
},
|
206
222
|
|
223
|
+
/**
|
224
|
+
* create the toolbar to edit edges
|
225
|
+
*
|
226
|
+
* @private
|
227
|
+
*/
|
228
|
+
_createEditEdgeToolbar : function() {
|
229
|
+
// clear the toolbar
|
230
|
+
this._clearManipulatorBar();
|
231
|
+
|
232
|
+
if (this.boundFunction) {
|
233
|
+
this.off('select', this.boundFunction);
|
234
|
+
}
|
235
|
+
|
236
|
+
this.edgeBeingEdited = this._getSelectedEdge();
|
237
|
+
this.edgeBeingEdited._enableControlNodes();
|
238
|
+
|
239
|
+
this.manipulationDiv.innerHTML = "" +
|
240
|
+
"<span class='graph-manipulationUI back' id='graph-manipulate-back'>" +
|
241
|
+
"<span class='graph-manipulationLabel'>" + this.constants.labels['back'] + " </span></span>" +
|
242
|
+
"<div class='graph-seperatorLine'></div>" +
|
243
|
+
"<span class='graph-manipulationUI none' id='graph-manipulate-back'>" +
|
244
|
+
"<span id='graph-manipulatorLabel' class='graph-manipulationLabel'>" + this.constants.labels['editEdgeDescription'] + "</span></span>";
|
245
|
+
|
246
|
+
// bind the icon
|
247
|
+
var backButton = document.getElementById("graph-manipulate-back");
|
248
|
+
backButton.onclick = this._createManipulatorBar.bind(this);
|
249
|
+
|
250
|
+
// temporarily overload functions
|
251
|
+
this.cachedFunctions["_handleTouch"] = this._handleTouch;
|
252
|
+
this.cachedFunctions["_handleOnRelease"] = this._handleOnRelease;
|
253
|
+
this.cachedFunctions["_handleTap"] = this._handleTap;
|
254
|
+
this.cachedFunctions["_handleDragStart"] = this._handleDragStart;
|
255
|
+
this.cachedFunctions["_handleOnDrag"] = this._handleOnDrag;
|
256
|
+
this._handleTouch = this._selectControlNode;
|
257
|
+
this._handleTap = function () {};
|
258
|
+
this._handleOnDrag = this._controlNodeDrag;
|
259
|
+
this._handleDragStart = function () {}
|
260
|
+
this._handleOnRelease = this._releaseControlNode;
|
261
|
+
|
262
|
+
// redraw to show the unselect
|
263
|
+
this._redraw();
|
207
264
|
},
|
208
265
|
|
209
266
|
|
267
|
+
|
268
|
+
|
269
|
+
|
270
|
+
/**
|
271
|
+
* the function bound to the selection event. It checks if you want to connect a cluster and changes the description
|
272
|
+
* to walk the user through the process.
|
273
|
+
*
|
274
|
+
* @private
|
275
|
+
*/
|
276
|
+
_selectControlNode : function(pointer) {
|
277
|
+
this.edgeBeingEdited.controlNodes.from.unselect();
|
278
|
+
this.edgeBeingEdited.controlNodes.to.unselect();
|
279
|
+
this.selectedControlNode = this.edgeBeingEdited._getSelectedControlNode(this._XconvertDOMtoCanvas(pointer.x),this._YconvertDOMtoCanvas(pointer.y));
|
280
|
+
if (this.selectedControlNode !== null) {
|
281
|
+
this.selectedControlNode.select();
|
282
|
+
this.freezeSimulation = true;
|
283
|
+
}
|
284
|
+
this._redraw();
|
285
|
+
},
|
286
|
+
|
287
|
+
/**
|
288
|
+
* the function bound to the selection event. It checks if you want to connect a cluster and changes the description
|
289
|
+
* to walk the user through the process.
|
290
|
+
*
|
291
|
+
* @private
|
292
|
+
*/
|
293
|
+
_controlNodeDrag : function(event) {
|
294
|
+
var pointer = this._getPointer(event.gesture.center);
|
295
|
+
if (this.selectedControlNode !== null && this.selectedControlNode !== undefined) {
|
296
|
+
this.selectedControlNode.x = this._XconvertDOMtoCanvas(pointer.x);
|
297
|
+
this.selectedControlNode.y = this._YconvertDOMtoCanvas(pointer.y);
|
298
|
+
}
|
299
|
+
this._redraw();
|
300
|
+
},
|
301
|
+
|
302
|
+
_releaseControlNode : function(pointer) {
|
303
|
+
var newNode = this._getNodeAt(pointer);
|
304
|
+
if (newNode != null) {
|
305
|
+
if (this.edgeBeingEdited.controlNodes.from.selected == true) {
|
306
|
+
this._editEdge(newNode.id, this.edgeBeingEdited.to.id);
|
307
|
+
this.edgeBeingEdited.controlNodes.from.unselect();
|
308
|
+
}
|
309
|
+
if (this.edgeBeingEdited.controlNodes.to.selected == true) {
|
310
|
+
this._editEdge(this.edgeBeingEdited.from.id, newNode.id);
|
311
|
+
this.edgeBeingEdited.controlNodes.to.unselect();
|
312
|
+
}
|
313
|
+
}
|
314
|
+
else {
|
315
|
+
this.edgeBeingEdited._restoreControlNodes();
|
316
|
+
}
|
317
|
+
this.freezeSimulation = false;
|
318
|
+
this._redraw();
|
319
|
+
},
|
320
|
+
|
210
321
|
/**
|
211
322
|
* the function bound to the selection event. It checks if you want to connect a cluster and changes the description
|
212
323
|
* to walk the user through the process.
|
@@ -351,6 +462,36 @@ var manipulationMixin = {
|
|
351
462
|
}
|
352
463
|
},
|
353
464
|
|
465
|
+
/**
|
466
|
+
* connect two nodes with a new edge.
|
467
|
+
*
|
468
|
+
* @private
|
469
|
+
*/
|
470
|
+
_editEdge : function(sourceNodeId,targetNodeId) {
|
471
|
+
if (this.editMode == true) {
|
472
|
+
var defaultData = {id: this.edgeBeingEdited.id, from:sourceNodeId, to:targetNodeId};
|
473
|
+
if (this.triggerFunctions.editEdge) {
|
474
|
+
if (this.triggerFunctions.editEdge.length == 2) {
|
475
|
+
var me = this;
|
476
|
+
this.triggerFunctions.editEdge(defaultData, function(finalizedData) {
|
477
|
+
me.edgesData.update(finalizedData);
|
478
|
+
me.moving = true;
|
479
|
+
me.start();
|
480
|
+
});
|
481
|
+
}
|
482
|
+
else {
|
483
|
+
alert(this.constants.labels["linkError"]);
|
484
|
+
this.moving = true;
|
485
|
+
this.start();
|
486
|
+
}
|
487
|
+
}
|
488
|
+
else {
|
489
|
+
this.edgesData.update(defaultData);
|
490
|
+
this.moving = true;
|
491
|
+
this.start();
|
492
|
+
}
|
493
|
+
}
|
494
|
+
},
|
354
495
|
|
355
496
|
/**
|
356
497
|
* Create the toolbar to edit the selected node. The label and the color can be changed. Other colors are derived from the chosen color.
|
@@ -391,6 +532,8 @@ var manipulationMixin = {
|
|
391
532
|
},
|
392
533
|
|
393
534
|
|
535
|
+
|
536
|
+
|
394
537
|
/**
|
395
538
|
* delete everything in the selection
|
396
539
|
*
|