vis-rails 1.0.1 → 1.0.2
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/lib/vis/rails/version.rb +1 -1
- data/vendor/assets/vis/graph/Graph.js +112 -54
- data/vendor/assets/vis/graph/Groups.js +2 -2
- data/vendor/assets/vis/graph/Images.js +2 -2
- data/vendor/assets/vis/graph/graphMixins/ManipulationMixin.js +4 -4
- data/vendor/assets/vis/graph/graphMixins/SelectionMixin.js +4 -4
- data/vendor/assets/vis/graph/graphMixins/physics/PhysicsMixin.js +19 -15
- data/vendor/assets/vis/module/exports.js +1 -0
- data/vendor/assets/vis/timeline/TimeStep.js +16 -4
- data/vendor/assets/vis/timeline/Timeline.js +58 -6
- data/vendor/assets/vis/timeline/component/Group.js +22 -1
- data/vendor/assets/vis/timeline/component/ItemSet.js +6 -4
- data/vendor/assets/vis/timeline/component/RootPanel.js +1 -0
- data/vendor/assets/vis/timeline/component/TimeAxis.js +20 -20
- data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +4 -3
- data/vendor/assets/vis/util.js +34 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d28f18ffa726cedf2df18f07ed3f34a5881b8693
|
4
|
+
data.tar.gz: 716adb84278baadcd222bbecf802759ddd0a9eb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 90d77f98a4d5d2379703b87f96341180716d49e0e124bcc4d2fed368518255b5861863bf5efdd890ee8df7c98ecb753ccb89c40492928695959612cc1c0b38be
|
7
|
+
data.tar.gz: 56d1c95072854f202bda9c12dcd197cba4c005009b05cce79f4250d096da5c346ce488d0f6bbd2b01508591074fcdc45e4fa457be32490106400d1b0b68fcd09
|
data/lib/vis/rails/version.rb
CHANGED
@@ -179,7 +179,9 @@ function Graph (container, data, options) {
|
|
179
179
|
border: '#666',
|
180
180
|
background: '#FFFFC6'
|
181
181
|
}
|
182
|
-
}
|
182
|
+
},
|
183
|
+
moveable: true,
|
184
|
+
zoomable: true
|
183
185
|
};
|
184
186
|
this.editMode = this.constants.dataManipulation.initiallyVisible;
|
185
187
|
|
@@ -211,8 +213,11 @@ function Graph (container, data, options) {
|
|
211
213
|
this._loadHierarchySystem();
|
212
214
|
|
213
215
|
// apply options
|
216
|
+
this._setTranslation(this.frame.clientWidth / 2, this.frame.clientHeight / 2);
|
217
|
+
this._setScale(1);
|
214
218
|
this.setOptions(options);
|
215
219
|
|
220
|
+
|
216
221
|
// other vars
|
217
222
|
this.freezeSimulation = false;// freeze the simulation
|
218
223
|
this.cachedFunctions = {};
|
@@ -490,15 +495,19 @@ Graph.prototype.setData = function(data, disableStart) {
|
|
490
495
|
if (!disableStart) {
|
491
496
|
// find a stable position or start animating to a stable position
|
492
497
|
if (this.stabilize) {
|
493
|
-
this
|
498
|
+
var me = this;
|
499
|
+
setTimeout(function() {me._stabilize(); me.start();},0)
|
500
|
+
}
|
501
|
+
else {
|
502
|
+
this.start();
|
494
503
|
}
|
495
|
-
this.start();
|
496
504
|
}
|
497
505
|
};
|
498
506
|
|
499
507
|
/**
|
500
508
|
* Set options
|
501
509
|
* @param {Object} options
|
510
|
+
* @param {Boolean} [initializeView] | set zoom and translation to default.
|
502
511
|
*/
|
503
512
|
Graph.prototype.setOptions = function (options) {
|
504
513
|
if (options) {
|
@@ -512,7 +521,8 @@ Graph.prototype.setOptions = function (options) {
|
|
512
521
|
if (options.freezeForStabilization !== undefined) {this.constants.freezeForStabilization = options.freezeForStabilization;}
|
513
522
|
if (options.configurePhysics !== undefined){this.constants.configurePhysics = options.configurePhysics;}
|
514
523
|
if (options.stabilizationIterations !== undefined) {this.constants.stabilizationIterations = options.stabilizationIterations;}
|
515
|
-
|
524
|
+
if (options.moveable !== undefined) {this.constants.moveable = options.moveable;}
|
525
|
+
if (options.zoomable !== undefined) {this.constants.zoomable = options.zoomable;}
|
516
526
|
|
517
527
|
|
518
528
|
if (options.labels !== undefined) {
|
@@ -557,6 +567,17 @@ Graph.prototype.setOptions = function (options) {
|
|
557
567
|
}
|
558
568
|
}
|
559
569
|
}
|
570
|
+
|
571
|
+
if (options.physics.hierarchicalRepulsion) {
|
572
|
+
this.constants.hierarchicalLayout.enabled = true;
|
573
|
+
this.constants.physics.hierarchicalRepulsion.enabled = true;
|
574
|
+
this.constants.physics.barnesHut.enabled = false;
|
575
|
+
for (prop in options.physics.hierarchicalRepulsion) {
|
576
|
+
if (options.physics.hierarchicalRepulsion.hasOwnProperty(prop)) {
|
577
|
+
this.constants.physics.hierarchicalRepulsion[prop] = options.physics.hierarchicalRepulsion[prop];
|
578
|
+
}
|
579
|
+
}
|
580
|
+
}
|
560
581
|
}
|
561
582
|
|
562
583
|
if (options.hierarchicalLayout) {
|
@@ -716,11 +737,10 @@ Graph.prototype.setOptions = function (options) {
|
|
716
737
|
|
717
738
|
// bind keys. If disabled, this will not do anything;
|
718
739
|
this._createKeyBinds();
|
719
|
-
|
720
740
|
this.setSize(this.width, this.height);
|
721
|
-
this.
|
722
|
-
this.
|
723
|
-
|
741
|
+
this.moving = true;
|
742
|
+
this.start();
|
743
|
+
|
724
744
|
};
|
725
745
|
|
726
746
|
/**
|
@@ -936,11 +956,11 @@ Graph.prototype._handleOnDrag = function(event) {
|
|
936
956
|
var node = s.node;
|
937
957
|
|
938
958
|
if (!s.xFixed) {
|
939
|
-
node.x = me.
|
959
|
+
node.x = me._XconvertDOMtoCanvas(me._XconvertCanvasToDOM(s.x) + deltaX);
|
940
960
|
}
|
941
961
|
|
942
962
|
if (!s.yFixed) {
|
943
|
-
node.y = me.
|
963
|
+
node.y = me._YconvertDOMtoCanvas(me._YconvertCanvasToDOM(s.y) + deltaY);
|
944
964
|
}
|
945
965
|
});
|
946
966
|
|
@@ -951,15 +971,18 @@ Graph.prototype._handleOnDrag = function(event) {
|
|
951
971
|
}
|
952
972
|
}
|
953
973
|
else {
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
this.
|
960
|
-
|
961
|
-
|
962
|
-
|
974
|
+
if (this.constants.moveable == true) {
|
975
|
+
// move the graph
|
976
|
+
var diffX = pointer.x - this.drag.pointer.x;
|
977
|
+
var diffY = pointer.y - this.drag.pointer.y;
|
978
|
+
|
979
|
+
this._setTranslation(
|
980
|
+
this.drag.translation.x + diffX,
|
981
|
+
this.drag.translation.y + diffY);
|
982
|
+
this._redraw();
|
983
|
+
this.moving = true;
|
984
|
+
this.start();
|
985
|
+
}
|
963
986
|
}
|
964
987
|
};
|
965
988
|
|
@@ -1047,30 +1070,38 @@ Graph.prototype._onPinch = function (event) {
|
|
1047
1070
|
* @private
|
1048
1071
|
*/
|
1049
1072
|
Graph.prototype._zoom = function(scale, pointer) {
|
1050
|
-
|
1051
|
-
|
1052
|
-
scale
|
1053
|
-
|
1054
|
-
|
1055
|
-
scale
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1073
|
+
if (this.constants.zoomable == true) {
|
1074
|
+
var scaleOld = this._getScale();
|
1075
|
+
if (scale < 0.00001) {
|
1076
|
+
scale = 0.00001;
|
1077
|
+
}
|
1078
|
+
if (scale > 10) {
|
1079
|
+
scale = 10;
|
1080
|
+
}
|
1081
|
+
// + this.frame.canvas.clientHeight / 2
|
1082
|
+
var translation = this._getTranslation();
|
1059
1083
|
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1084
|
+
var scaleFrac = scale / scaleOld;
|
1085
|
+
var tx = (1 - scaleFrac) * pointer.x + translation.x * scaleFrac;
|
1086
|
+
var ty = (1 - scaleFrac) * pointer.y + translation.y * scaleFrac;
|
1063
1087
|
|
1064
|
-
|
1065
|
-
|
1088
|
+
this.areaCenter = {"x" : this._XconvertDOMtoCanvas(pointer.x),
|
1089
|
+
"y" : this._YconvertDOMtoCanvas(pointer.y)};
|
1066
1090
|
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1091
|
+
this._setScale(scale);
|
1092
|
+
this._setTranslation(tx, ty);
|
1093
|
+
this.updateClustersDefault();
|
1094
|
+
this._redraw();
|
1071
1095
|
|
1096
|
+
if (scaleOld < scale) {
|
1097
|
+
this.emit("zoom", {direction:"+"});
|
1098
|
+
}
|
1099
|
+
else {
|
1100
|
+
this.emit("zoom", {direction:"-"});
|
1101
|
+
}
|
1072
1102
|
|
1073
|
-
|
1103
|
+
return scale;
|
1104
|
+
}
|
1074
1105
|
};
|
1075
1106
|
|
1076
1107
|
|
@@ -1156,10 +1187,10 @@ Graph.prototype._onMouseMoveTitle = function (event) {
|
|
1156
1187
|
*/
|
1157
1188
|
Graph.prototype._checkShowPopup = function (pointer) {
|
1158
1189
|
var obj = {
|
1159
|
-
left: this.
|
1160
|
-
top: this.
|
1161
|
-
right: this.
|
1162
|
-
bottom: this.
|
1190
|
+
left: this._XconvertDOMtoCanvas(pointer.x),
|
1191
|
+
top: this._YconvertDOMtoCanvas(pointer.y),
|
1192
|
+
right: this._XconvertDOMtoCanvas(pointer.x),
|
1193
|
+
bottom: this._YconvertDOMtoCanvas(pointer.y)
|
1163
1194
|
};
|
1164
1195
|
|
1165
1196
|
var id;
|
@@ -1623,12 +1654,12 @@ Graph.prototype._redraw = function() {
|
|
1623
1654
|
ctx.scale(this.scale, this.scale);
|
1624
1655
|
|
1625
1656
|
this.canvasTopLeft = {
|
1626
|
-
"x": this.
|
1627
|
-
"y": this.
|
1657
|
+
"x": this._XconvertDOMtoCanvas(0),
|
1658
|
+
"y": this._YconvertDOMtoCanvas(0)
|
1628
1659
|
};
|
1629
1660
|
this.canvasBottomRight = {
|
1630
|
-
"x": this.
|
1631
|
-
"y": this.
|
1661
|
+
"x": this._XconvertDOMtoCanvas(this.frame.canvas.clientWidth),
|
1662
|
+
"y": this._YconvertDOMtoCanvas(this.frame.canvas.clientHeight)
|
1632
1663
|
};
|
1633
1664
|
|
1634
1665
|
this._doInAllSectors("_drawAllSectorNodes",ctx);
|
@@ -1662,6 +1693,8 @@ Graph.prototype._setTranslation = function(offsetX, offsetY) {
|
|
1662
1693
|
if (offsetY !== undefined) {
|
1663
1694
|
this.translation.y = offsetY;
|
1664
1695
|
}
|
1696
|
+
|
1697
|
+
this.emit('viewChanged');
|
1665
1698
|
};
|
1666
1699
|
|
1667
1700
|
/**
|
@@ -1695,45 +1728,70 @@ Graph.prototype._getScale = function() {
|
|
1695
1728
|
};
|
1696
1729
|
|
1697
1730
|
/**
|
1698
|
-
* Convert
|
1731
|
+
* Convert the X coordinate in DOM-space (coordinate point in browser relative to the container div) to
|
1732
|
+
* the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon)
|
1699
1733
|
* @param {number} x
|
1700
1734
|
* @returns {number}
|
1701
1735
|
* @private
|
1702
1736
|
*/
|
1703
|
-
Graph.prototype.
|
1737
|
+
Graph.prototype._XconvertDOMtoCanvas = function(x) {
|
1704
1738
|
return (x - this.translation.x) / this.scale;
|
1705
1739
|
};
|
1706
1740
|
|
1707
1741
|
/**
|
1708
|
-
* Convert
|
1742
|
+
* Convert the X coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to
|
1743
|
+
* the X coordinate in DOM-space (coordinate point in browser relative to the container div)
|
1709
1744
|
* @param {number} x
|
1710
1745
|
* @returns {number}
|
1711
1746
|
* @private
|
1712
1747
|
*/
|
1713
|
-
Graph.prototype.
|
1748
|
+
Graph.prototype._XconvertCanvasToDOM = function(x) {
|
1714
1749
|
return x * this.scale + this.translation.x;
|
1715
1750
|
};
|
1716
1751
|
|
1717
1752
|
/**
|
1718
|
-
* Convert
|
1753
|
+
* Convert the Y coordinate in DOM-space (coordinate point in browser relative to the container div) to
|
1754
|
+
* the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon)
|
1719
1755
|
* @param {number} y
|
1720
1756
|
* @returns {number}
|
1721
1757
|
* @private
|
1722
1758
|
*/
|
1723
|
-
Graph.prototype.
|
1759
|
+
Graph.prototype._YconvertDOMtoCanvas = function(y) {
|
1724
1760
|
return (y - this.translation.y) / this.scale;
|
1725
1761
|
};
|
1726
1762
|
|
1727
1763
|
/**
|
1728
|
-
* Convert
|
1764
|
+
* Convert the Y coordinate in canvas-space (the simulation sandbox, which the camera looks upon) to
|
1765
|
+
* the Y coordinate in DOM-space (coordinate point in browser relative to the container div)
|
1729
1766
|
* @param {number} y
|
1730
1767
|
* @returns {number}
|
1731
1768
|
* @private
|
1732
1769
|
*/
|
1733
|
-
Graph.prototype.
|
1770
|
+
Graph.prototype._YconvertCanvasToDOM = function(y) {
|
1734
1771
|
return y * this.scale + this.translation.y ;
|
1735
1772
|
};
|
1736
1773
|
|
1774
|
+
|
1775
|
+
/**
|
1776
|
+
*
|
1777
|
+
* @param {object} pos = {x: number, y: number}
|
1778
|
+
* @returns {{x: number, y: number}}
|
1779
|
+
* @constructor
|
1780
|
+
*/
|
1781
|
+
Graph.prototype.canvasToDOM = function(pos) {
|
1782
|
+
return {x:this._XconvertCanvasToDOM(pos.x),y:this._YconvertCanvasToDOM(pos.y)};
|
1783
|
+
}
|
1784
|
+
|
1785
|
+
/**
|
1786
|
+
*
|
1787
|
+
* @param {object} pos = {x: number, y: number}
|
1788
|
+
* @returns {{x: number, y: number}}
|
1789
|
+
* @constructor
|
1790
|
+
*/
|
1791
|
+
Graph.prototype.DOMtoCanvas = function(pos) {
|
1792
|
+
return {x:this._XconvertDOMtoCanvas(pos.x),y:this._YconvertDOMtoCanvas(pos.y)};
|
1793
|
+
}
|
1794
|
+
|
1737
1795
|
/**
|
1738
1796
|
* Redraw all nodes
|
1739
1797
|
* The 2d context of a HTML canvas can be retrieved by canvas.getContext('2d');
|
@@ -2,11 +2,11 @@
|
|
2
2
|
* @class Images
|
3
3
|
* This class loads images and keeps them stored.
|
4
4
|
*/
|
5
|
-
|
5
|
+
function Images() {
|
6
6
|
this.images = {};
|
7
7
|
|
8
8
|
this.callback = undefined;
|
9
|
-
}
|
9
|
+
}
|
10
10
|
|
11
11
|
/**
|
12
12
|
* Set an onload callback function. This will be called each time an image
|
@@ -243,10 +243,10 @@ var manipulationMixin = {
|
|
243
243
|
this.cachedFunctions["_handleOnDrag"] = this._handleOnDrag;
|
244
244
|
this._handleOnDrag = function(event) {
|
245
245
|
var pointer = this._getPointer(event.gesture.center);
|
246
|
-
this.sectors['support']['nodes']['targetNode'].x = this.
|
247
|
-
this.sectors['support']['nodes']['targetNode'].y = this.
|
248
|
-
this.sectors['support']['nodes']['targetViaNode'].x = 0.5 * (this.
|
249
|
-
this.sectors['support']['nodes']['targetViaNode'].y = this.
|
246
|
+
this.sectors['support']['nodes']['targetNode'].x = this._XconvertDOMtoCanvas(pointer.x);
|
247
|
+
this.sectors['support']['nodes']['targetNode'].y = this._YconvertDOMtoCanvas(pointer.y);
|
248
|
+
this.sectors['support']['nodes']['targetViaNode'].x = 0.5 * (this._XconvertDOMtoCanvas(pointer.x) + this.edges['connectionEdge'].from.x);
|
249
|
+
this.sectors['support']['nodes']['targetViaNode'].y = this._YconvertDOMtoCanvas(pointer.y);
|
250
250
|
};
|
251
251
|
|
252
252
|
this.moving = true;
|
@@ -40,8 +40,8 @@ var SelectionMixin = {
|
|
40
40
|
* @private
|
41
41
|
*/
|
42
42
|
_pointerToPositionObject : function(pointer) {
|
43
|
-
var x = this.
|
44
|
-
var y = this.
|
43
|
+
var x = this._XconvertDOMtoCanvas(pointer.x);
|
44
|
+
var y = this._YconvertDOMtoCanvas(pointer.y);
|
45
45
|
|
46
46
|
return {left: x,
|
47
47
|
top: y,
|
@@ -433,8 +433,8 @@ var SelectionMixin = {
|
|
433
433
|
var node = this._getNodeAt(pointer);
|
434
434
|
if (node != null && node !== undefined) {
|
435
435
|
// we reset the areaCenter here so the opening of the node will occur
|
436
|
-
this.areaCenter = {"x" : this.
|
437
|
-
"y" : this.
|
436
|
+
this.areaCenter = {"x" : this._XconvertDOMtoCanvas(pointer.x),
|
437
|
+
"y" : this._YconvertDOMtoCanvas(pointer.y)};
|
438
438
|
this.openCluster(node);
|
439
439
|
}
|
440
440
|
this.emit("doubleClick", this.getSelection());
|
@@ -188,7 +188,7 @@ var physicsMixin = {
|
|
188
188
|
*/
|
189
189
|
_calculateSpringForces: function () {
|
190
190
|
var edgeLength, edge, edgeId;
|
191
|
-
var dx, dy, fx, fy, springForce,
|
191
|
+
var dx, dy, fx, fy, springForce, distance;
|
192
192
|
var edges = this.edges;
|
193
193
|
|
194
194
|
// forces caused by the edges, modelled as springs
|
@@ -204,13 +204,14 @@ var physicsMixin = {
|
|
204
204
|
|
205
205
|
dx = (edge.from.x - edge.to.x);
|
206
206
|
dy = (edge.from.y - edge.to.y);
|
207
|
-
|
207
|
+
distance = Math.sqrt(dx * dx + dy * dy);
|
208
208
|
|
209
|
-
if (
|
210
|
-
|
209
|
+
if (distance == 0) {
|
210
|
+
distance = 0.01;
|
211
211
|
}
|
212
212
|
|
213
|
-
|
213
|
+
// the 1/distance is so the fx and fy can be calculated without sine or cosine.
|
214
|
+
springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance;
|
214
215
|
|
215
216
|
fx = dx * springForce;
|
216
217
|
fy = dy * springForce;
|
@@ -272,17 +273,18 @@ var physicsMixin = {
|
|
272
273
|
* @private
|
273
274
|
*/
|
274
275
|
_calculateSpringForce: function (node1, node2, edgeLength) {
|
275
|
-
var dx, dy, fx, fy, springForce,
|
276
|
+
var dx, dy, fx, fy, springForce, distance;
|
276
277
|
|
277
278
|
dx = (node1.x - node2.x);
|
278
279
|
dy = (node1.y - node2.y);
|
279
|
-
|
280
|
+
distance = Math.sqrt(dx * dx + dy * dy);
|
280
281
|
|
281
|
-
if (
|
282
|
-
|
282
|
+
if (distance == 0) {
|
283
|
+
distance = 0.01;
|
283
284
|
}
|
284
285
|
|
285
|
-
|
286
|
+
// the 1/distance is so the fx and fy can be calculated without sine or cosine.
|
287
|
+
springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance;
|
286
288
|
|
287
289
|
fx = dx * springForce;
|
288
290
|
fy = dy * springForce;
|
@@ -317,7 +319,7 @@ var physicsMixin = {
|
|
317
319
|
'<table id="graph_BH_table" style="display:none">' +
|
318
320
|
'<tr><td><b>Barnes Hut</b></td></tr>' +
|
319
321
|
'<tr>' +
|
320
|
-
'<td width="150px">gravitationalConstant</td><td>0</td><td><input type="range" min="
|
322
|
+
'<td width="150px">gravitationalConstant</td><td>0</td><td><input type="range" min="0" max="20000" value="' + (-1 * this.constants.physics.barnesHut.gravitationalConstant) + '" step="25" style="width:300px" id="graph_BH_gc"></td><td width="50px">-20000</td><td><input value="' + (-1 * this.constants.physics.barnesHut.gravitationalConstant) + '" id="graph_BH_gc_value" style="width:60px"></td>' +
|
321
323
|
'</tr>' +
|
322
324
|
'<tr>' +
|
323
325
|
'<td width="150px">centralGravity</td><td>0</td><td><input type="range" min="0" max="3" value="' + this.constants.physics.barnesHut.centralGravity + '" step="0.05" style="width:300px" id="graph_BH_cg"></td><td>3</td><td><input value="' + this.constants.physics.barnesHut.centralGravity + '" id="graph_BH_cg_value" style="width:60px"></td>' +
|
@@ -641,10 +643,12 @@ function switchConfigurations () {
|
|
641
643
|
this.constants.physics.barnesHut.enabled = false;
|
642
644
|
}
|
643
645
|
else if (radioButton == "H") {
|
644
|
-
this.constants.hierarchicalLayout.enabled
|
645
|
-
|
646
|
-
|
647
|
-
|
646
|
+
if (this.constants.hierarchicalLayout.enabled == false) {
|
647
|
+
this.constants.hierarchicalLayout.enabled = true;
|
648
|
+
this.constants.physics.hierarchicalRepulsion.enabled = true;
|
649
|
+
this.constants.physics.barnesHut.enabled = false;
|
650
|
+
this._setupHierarchicalLayout();
|
651
|
+
}
|
648
652
|
}
|
649
653
|
else {
|
650
654
|
this.constants.hierarchicalLayout.enabled = false;
|
@@ -24,7 +24,7 @@
|
|
24
24
|
* @param {Date} [end] The end date
|
25
25
|
* @param {Number} [minimumStep] Optional. Minimum step size in milliseconds
|
26
26
|
*/
|
27
|
-
TimeStep
|
27
|
+
function TimeStep(start, end, minimumStep) {
|
28
28
|
// variables
|
29
29
|
this.current = new Date();
|
30
30
|
this._start = new Date();
|
@@ -36,7 +36,7 @@ TimeStep = function(start, end, minimumStep) {
|
|
36
36
|
|
37
37
|
// initialize the range
|
38
38
|
this.setRange(start, end, minimumStep);
|
39
|
-
}
|
39
|
+
}
|
40
40
|
|
41
41
|
/// enum scale
|
42
42
|
TimeStep.SCALE = {
|
@@ -314,8 +314,7 @@ TimeStep.prototype.snap = function(date) {
|
|
314
314
|
clone.setSeconds(0);
|
315
315
|
clone.setMilliseconds(0);
|
316
316
|
}
|
317
|
-
else if (this.scale == TimeStep.SCALE.DAY
|
318
|
-
this.scale == TimeStep.SCALE.WEEKDAY) {
|
317
|
+
else if (this.scale == TimeStep.SCALE.DAY) {
|
319
318
|
//noinspection FallthroughInSwitchStatementJS
|
320
319
|
switch (this.step) {
|
321
320
|
case 5:
|
@@ -328,6 +327,19 @@ TimeStep.prototype.snap = function(date) {
|
|
328
327
|
clone.setSeconds(0);
|
329
328
|
clone.setMilliseconds(0);
|
330
329
|
}
|
330
|
+
else if (this.scale == TimeStep.SCALE.WEEKDAY) {
|
331
|
+
//noinspection FallthroughInSwitchStatementJS
|
332
|
+
switch (this.step) {
|
333
|
+
case 5:
|
334
|
+
case 2:
|
335
|
+
clone.setHours(Math.round(clone.getHours() / 12) * 12); break;
|
336
|
+
default:
|
337
|
+
clone.setHours(Math.round(clone.getHours() / 6) * 6); break;
|
338
|
+
}
|
339
|
+
clone.setMinutes(0);
|
340
|
+
clone.setSeconds(0);
|
341
|
+
clone.setMilliseconds(0);
|
342
|
+
}
|
331
343
|
else if (this.scale == TimeStep.SCALE.HOUR) {
|
332
344
|
switch (this.step) {
|
333
345
|
case 4:
|
@@ -11,7 +11,7 @@ function Timeline (container, items, options) {
|
|
11
11
|
|
12
12
|
var me = this;
|
13
13
|
var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0);
|
14
|
-
this.
|
14
|
+
this.defaultOptions = {
|
15
15
|
orientation: 'bottom',
|
16
16
|
direction: 'horizontal', // 'horizontal' or 'vertical'
|
17
17
|
autoResize: true,
|
@@ -25,7 +25,6 @@ function Timeline (container, items, options) {
|
|
25
25
|
},
|
26
26
|
|
27
27
|
selectable: true,
|
28
|
-
snap: null, // will be specified after timeaxis is created
|
29
28
|
|
30
29
|
min: null,
|
31
30
|
max: null,
|
@@ -39,6 +38,13 @@ function Timeline (container, items, options) {
|
|
39
38
|
showCurrentTime: false,
|
40
39
|
showCustomTime: false,
|
41
40
|
|
41
|
+
groupOrder: null,
|
42
|
+
|
43
|
+
width: null,
|
44
|
+
height: null,
|
45
|
+
maxHeight: null,
|
46
|
+
minHeight: null,
|
47
|
+
|
42
48
|
type: 'box',
|
43
49
|
align: 'center',
|
44
50
|
margin: {
|
@@ -58,11 +64,17 @@ function Timeline (container, items, options) {
|
|
58
64
|
},
|
59
65
|
onRemove: function (item, callback) {
|
60
66
|
callback(item);
|
61
|
-
}
|
67
|
+
}
|
68
|
+
};
|
69
|
+
|
70
|
+
this.options = {};
|
71
|
+
util.deepExtend(this.options, this.defaultOptions);
|
72
|
+
util.deepExtend(this.options, {
|
73
|
+
snap: null, // will be specified after timeaxis is created
|
62
74
|
|
63
75
|
toScreen: me._toScreen.bind(me),
|
64
76
|
toTime: me._toTime.bind(me)
|
65
|
-
};
|
77
|
+
});
|
66
78
|
|
67
79
|
// root panel
|
68
80
|
var rootOptions = util.extend(Object.create(this.options), {
|
@@ -280,7 +292,7 @@ Emitter(Timeline.prototype);
|
|
280
292
|
* @param {Object} options TODO: describe the available options
|
281
293
|
*/
|
282
294
|
Timeline.prototype.setOptions = function (options) {
|
283
|
-
util.
|
295
|
+
util.deepExtend(this.options, options);
|
284
296
|
|
285
297
|
if ('editable' in options) {
|
286
298
|
var isBoolean = typeof options.editable === 'boolean';
|
@@ -439,6 +451,33 @@ Timeline.prototype.setGroups = function setGroups(groups) {
|
|
439
451
|
this.itemSet.setGroups(newDataSet);
|
440
452
|
};
|
441
453
|
|
454
|
+
/**
|
455
|
+
* Clear the Timeline. By Default, items, groups and options are cleared.
|
456
|
+
* Example usage:
|
457
|
+
*
|
458
|
+
* timeline.clear(); // clear items, groups, and options
|
459
|
+
* timeline.clear({options: true}); // clear options only
|
460
|
+
*
|
461
|
+
* @param {Object} [what] Optionally specify what to clear. By default:
|
462
|
+
* {items: true, groups: true, options: true}
|
463
|
+
*/
|
464
|
+
Timeline.prototype.clear = function clear(what) {
|
465
|
+
// clear items
|
466
|
+
if (!what || what.items) {
|
467
|
+
this.setItems(null);
|
468
|
+
}
|
469
|
+
|
470
|
+
// clear groups
|
471
|
+
if (!what || what.groups) {
|
472
|
+
this.setGroups(null);
|
473
|
+
}
|
474
|
+
|
475
|
+
// clear options
|
476
|
+
if (!what || what.options) {
|
477
|
+
this.setOptions(this.defaultOptions);
|
478
|
+
}
|
479
|
+
};
|
480
|
+
|
442
481
|
/**
|
443
482
|
* Set Timeline window such that it fits all items
|
444
483
|
*/
|
@@ -535,7 +574,7 @@ Timeline.prototype.getSelection = function getSelection() {
|
|
535
574
|
* Where start and end can be a Date, number, or string, and range is an
|
536
575
|
* object with properties start and end.
|
537
576
|
*
|
538
|
-
* @param {Date | Number | String} [start] Start date of visible window
|
577
|
+
* @param {Date | Number | String | Object} [start] Start date of visible window
|
539
578
|
* @param {Date | Number | String} [end] End date of visible window
|
540
579
|
*/
|
541
580
|
Timeline.prototype.setWindow = function setWindow(start, end) {
|
@@ -560,6 +599,14 @@ Timeline.prototype.getWindow = function setWindow() {
|
|
560
599
|
};
|
561
600
|
};
|
562
601
|
|
602
|
+
/**
|
603
|
+
* Force a repaint of the Timeline. Can be useful to manually repaint when
|
604
|
+
* option autoResize=false
|
605
|
+
*/
|
606
|
+
Timeline.prototype.repaint = function repaint() {
|
607
|
+
this.rootPanel.repaint();
|
608
|
+
};
|
609
|
+
|
563
610
|
/**
|
564
611
|
* Handle selecting/deselecting an item when tapping it
|
565
612
|
* @param {Event} event
|
@@ -626,6 +673,11 @@ Timeline.prototype._onAddItem = function (event) {
|
|
626
673
|
content: 'new item'
|
627
674
|
};
|
628
675
|
|
676
|
+
// when default type is a range, add a default end date to the new item
|
677
|
+
if (this.options.type === 'range' || this.options.type == 'rangeoverflow') {
|
678
|
+
newItem.end = this.timeAxis.snap(this._toTime(x + this.rootPanel.width / 5));
|
679
|
+
}
|
680
|
+
|
629
681
|
var id = util.randomUUID();
|
630
682
|
newItem[this.itemsData.fieldId] = id;
|
631
683
|
|
@@ -51,6 +51,14 @@ Group.prototype._create = function() {
|
|
51
51
|
this.dom.background = document.createElement('div');
|
52
52
|
|
53
53
|
this.dom.axis = document.createElement('div');
|
54
|
+
|
55
|
+
// create a hidden marker to detect when the Timelines container is attached
|
56
|
+
// to the DOM, or the style of a parent of the Timeline is changed from
|
57
|
+
// display:none is changed to visible.
|
58
|
+
this.dom.marker = document.createElement('div');
|
59
|
+
this.dom.marker.style.visibility = 'hidden';
|
60
|
+
this.dom.marker.innerHTML = '?';
|
61
|
+
this.dom.background.appendChild(this.dom.marker);
|
54
62
|
};
|
55
63
|
|
56
64
|
/**
|
@@ -122,6 +130,20 @@ Group.prototype.repaint = function repaint(range, margin, restack) {
|
|
122
130
|
|
123
131
|
this.visibleItems = this._updateVisibleItems(this.orderedItems, this.visibleItems, range);
|
124
132
|
|
133
|
+
// force recalculation of the height of the items when the marker height changed
|
134
|
+
// (due to the Timeline being attached to the DOM or changed from display:none to visible)
|
135
|
+
var markerHeight = this.dom.marker.clientHeight;
|
136
|
+
if (markerHeight != this.lastMarkerHeight) {
|
137
|
+
this.lastMarkerHeight = markerHeight;
|
138
|
+
|
139
|
+
util.forEach(this.items, function (item) {
|
140
|
+
item.dirty = true;
|
141
|
+
if (item.displayed) item.repaint();
|
142
|
+
});
|
143
|
+
|
144
|
+
restack = true;
|
145
|
+
}
|
146
|
+
|
125
147
|
// reposition visible items vertically
|
126
148
|
if (this.itemSet.options.stack) { // TODO: ugly way to access options...
|
127
149
|
stack.stack(this.visibleItems, margin, restack);
|
@@ -129,7 +151,6 @@ Group.prototype.repaint = function repaint(range, margin, restack) {
|
|
129
151
|
else { // no stacking
|
130
152
|
stack.nostack(this.visibleItems, margin);
|
131
153
|
}
|
132
|
-
this.stackDirty = false;
|
133
154
|
for (var i = 0, ii = this.visibleItems.length; i < ii; i++) {
|
134
155
|
var item = this.visibleItems[i];
|
135
156
|
item.repositionY();
|
@@ -519,7 +519,8 @@ ItemSet.prototype.setGroups = function setGroups(groups) {
|
|
519
519
|
|
520
520
|
// remove all drawn groups
|
521
521
|
ids = this.groupsData.getIds();
|
522
|
-
this.
|
522
|
+
this.groupsData = null;
|
523
|
+
this._onRemoveGroups(ids); // note: this will cause a repaint
|
523
524
|
}
|
524
525
|
|
525
526
|
// replace the dataset
|
@@ -770,8 +771,7 @@ ItemSet.prototype._orderGroups = function () {
|
|
770
771
|
// hide all groups, removes them from the DOM
|
771
772
|
var groups = this.groups;
|
772
773
|
groupIds.forEach(function (groupId) {
|
773
|
-
|
774
|
-
group.hide();
|
774
|
+
groups[groupId].hide();
|
775
775
|
});
|
776
776
|
|
777
777
|
// show the groups again, attach them to the DOM in correct order
|
@@ -813,7 +813,9 @@ ItemSet.prototype._updateItem = function _updateItem(item, itemData) {
|
|
813
813
|
var oldGroupId = item.data.group;
|
814
814
|
|
815
815
|
item.data = itemData;
|
816
|
-
item.
|
816
|
+
if (item.displayed) {
|
817
|
+
item.repaint();
|
818
|
+
}
|
817
819
|
|
818
820
|
// update group
|
819
821
|
if (oldGroupId != item.data.group) {
|
@@ -101,6 +101,7 @@ RootPanel.prototype.repaint = function repaint() {
|
|
101
101
|
|
102
102
|
// update frame size
|
103
103
|
this.frame.style.maxHeight = util.option.asSize(this.options.maxHeight, '');
|
104
|
+
this.frame.style.minHeight = util.option.asSize(this.options.minHeight, '');
|
104
105
|
this._updateSize();
|
105
106
|
|
106
107
|
// if the root panel or any of its childs is resized, repaint again,
|
@@ -407,32 +407,32 @@ TimeAxis.prototype._repaintLine = function() {
|
|
407
407
|
* @private
|
408
408
|
*/
|
409
409
|
TimeAxis.prototype._calculateCharSize = function () {
|
410
|
-
//
|
411
|
-
|
412
|
-
var textMinor = document.createTextNode('0');
|
413
|
-
var measureCharMinor = document.createElement('DIV');
|
414
|
-
measureCharMinor.className = 'text minor measure';
|
415
|
-
measureCharMinor.appendChild(textMinor);
|
416
|
-
this.frame.appendChild(measureCharMinor);
|
410
|
+
// Note: We calculate char size with every repaint. Size may change, for
|
411
|
+
// example when any of the timelines parents had display:none for example.
|
417
412
|
|
418
|
-
|
419
|
-
|
413
|
+
// determine the char width and height on the minor axis
|
414
|
+
if (!this.dom.measureCharMinor) {
|
415
|
+
this.dom.measureCharMinor = document.createElement('DIV');
|
416
|
+
this.dom.measureCharMinor.className = 'text minor measure';
|
417
|
+
this.dom.measureCharMinor.style.position = 'absolute';
|
420
418
|
|
421
|
-
this.
|
419
|
+
this.dom.measureCharMinor.appendChild(document.createTextNode('0'));
|
420
|
+
this.frame.appendChild(this.dom.measureCharMinor);
|
422
421
|
}
|
422
|
+
this.props.minorCharHeight = this.dom.measureCharMinor.clientHeight;
|
423
|
+
this.props.minorCharWidth = this.dom.measureCharMinor.clientWidth;
|
423
424
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
measureCharMajor.className = 'text
|
428
|
-
measureCharMajor.
|
429
|
-
this.frame.appendChild(measureCharMajor);
|
430
|
-
|
431
|
-
this.props.majorCharHeight = measureCharMajor.clientHeight;
|
432
|
-
this.props.majorCharWidth = measureCharMajor.clientWidth;
|
425
|
+
// determine the char width and height on the major axis
|
426
|
+
if (!this.dom.measureCharMajor) {
|
427
|
+
this.dom.measureCharMajor = document.createElement('DIV');
|
428
|
+
this.dom.measureCharMajor.className = 'text minor measure';
|
429
|
+
this.dom.measureCharMajor.style.position = 'absolute';
|
433
430
|
|
434
|
-
this.
|
431
|
+
this.dom.measureCharMajor.appendChild(document.createTextNode('0'));
|
432
|
+
this.frame.appendChild(this.dom.measureCharMajor);
|
435
433
|
}
|
434
|
+
this.props.majorCharHeight = this.dom.measureCharMajor.clientHeight;
|
435
|
+
this.props.majorCharWidth = this.dom.measureCharMajor.clientWidth;
|
436
436
|
};
|
437
437
|
|
438
438
|
/**
|
@@ -46,9 +46,10 @@ ItemRangeOverflow.prototype.repositionX = function repositionX() {
|
|
46
46
|
|
47
47
|
this.left = start;
|
48
48
|
var boxWidth = Math.max(end - start, 1);
|
49
|
-
this.width =
|
50
|
-
|
51
|
-
|
49
|
+
this.width = boxWidth + this.props.content.width;
|
50
|
+
// Note: The calculation of width is an optimistic calculation, giving
|
51
|
+
// a width which will not change when moving the Timeline
|
52
|
+
// So no restacking needed, which is nicer for the eye
|
52
53
|
|
53
54
|
this.dom.box.style.left = this.left + 'px';
|
54
55
|
this.dom.box.style.width = boxWidth + 'px';
|
data/vendor/assets/vis/util.js
CHANGED
@@ -97,6 +97,40 @@ util.extend = function (a, b) {
|
|
97
97
|
return a;
|
98
98
|
};
|
99
99
|
|
100
|
+
/**
|
101
|
+
* Deep extend an object a with the properties of object b
|
102
|
+
* @param {Object} a
|
103
|
+
* @param {Object} b
|
104
|
+
* @returns {Object}
|
105
|
+
*/
|
106
|
+
util.deepExtend = function deepExtend (a, b) {
|
107
|
+
// TODO: add support for Arrays to deepExtend
|
108
|
+
if (Array.isArray(b)) {
|
109
|
+
throw new TypeError('Arrays are not supported by deepExtend');
|
110
|
+
}
|
111
|
+
|
112
|
+
for (var prop in b) {
|
113
|
+
if (b.hasOwnProperty(prop)) {
|
114
|
+
if (b[prop] && b[prop].constructor === Object) {
|
115
|
+
if (a[prop] === undefined) {
|
116
|
+
a[prop] = {};
|
117
|
+
}
|
118
|
+
if (a[prop].constructor === Object) {
|
119
|
+
deepExtend(a[prop], b[prop]);
|
120
|
+
}
|
121
|
+
else {
|
122
|
+
a[prop] = b[prop];
|
123
|
+
}
|
124
|
+
} else if (Array.isArray(b[prop])) {
|
125
|
+
throw new TypeError('Arrays are not supported by deepExtend');
|
126
|
+
} else {
|
127
|
+
a[prop] = b[prop];
|
128
|
+
}
|
129
|
+
}
|
130
|
+
}
|
131
|
+
return a;
|
132
|
+
};
|
133
|
+
|
100
134
|
/**
|
101
135
|
* Test whether all elements in two arrays are equal.
|
102
136
|
* @param {Array} a
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vis-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AlexVangelov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: momentjs-rails
|