vis-rails 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|