vis-rails 1.0.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
*
|