vis-rails 2.0.0 → 2.0.1

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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/lib/vis/rails/version.rb +1 -1
  3. data/vendor/assets/javascripts/vis.js +26 -26
  4. metadata +16 -85
  5. data/vendor/assets/vis/DataSet.js +0 -926
  6. data/vendor/assets/vis/DataView.js +0 -283
  7. data/vendor/assets/vis/graph/Edge.js +0 -957
  8. data/vendor/assets/vis/graph/Graph.js +0 -2291
  9. data/vendor/assets/vis/graph/Groups.js +0 -80
  10. data/vendor/assets/vis/graph/Images.js +0 -41
  11. data/vendor/assets/vis/graph/Node.js +0 -966
  12. data/vendor/assets/vis/graph/Popup.js +0 -132
  13. data/vendor/assets/vis/graph/css/graph-manipulation.css +0 -128
  14. data/vendor/assets/vis/graph/css/graph-navigation.css +0 -66
  15. data/vendor/assets/vis/graph/dotparser.js +0 -829
  16. data/vendor/assets/vis/graph/graphMixins/ClusterMixin.js +0 -1143
  17. data/vendor/assets/vis/graph/graphMixins/HierarchicalLayoutMixin.js +0 -311
  18. data/vendor/assets/vis/graph/graphMixins/ManipulationMixin.js +0 -576
  19. data/vendor/assets/vis/graph/graphMixins/MixinLoader.js +0 -199
  20. data/vendor/assets/vis/graph/graphMixins/NavigationMixin.js +0 -205
  21. data/vendor/assets/vis/graph/graphMixins/SectorsMixin.js +0 -552
  22. data/vendor/assets/vis/graph/graphMixins/SelectionMixin.js +0 -648
  23. data/vendor/assets/vis/graph/graphMixins/physics/BarnesHut.js +0 -398
  24. data/vendor/assets/vis/graph/graphMixins/physics/HierarchialRepulsion.js +0 -64
  25. data/vendor/assets/vis/graph/graphMixins/physics/PhysicsMixin.js +0 -697
  26. data/vendor/assets/vis/graph/graphMixins/physics/Repulsion.js +0 -66
  27. data/vendor/assets/vis/graph/img/acceptDeleteIcon.png +0 -0
  28. data/vendor/assets/vis/graph/img/addNodeIcon.png +0 -0
  29. data/vendor/assets/vis/graph/img/backIcon.png +0 -0
  30. data/vendor/assets/vis/graph/img/connectIcon.png +0 -0
  31. data/vendor/assets/vis/graph/img/cross.png +0 -0
  32. data/vendor/assets/vis/graph/img/cross2.png +0 -0
  33. data/vendor/assets/vis/graph/img/deleteIcon.png +0 -0
  34. data/vendor/assets/vis/graph/img/downArrow.png +0 -0
  35. data/vendor/assets/vis/graph/img/editIcon.png +0 -0
  36. data/vendor/assets/vis/graph/img/leftArrow.png +0 -0
  37. data/vendor/assets/vis/graph/img/minus.png +0 -0
  38. data/vendor/assets/vis/graph/img/plus.png +0 -0
  39. data/vendor/assets/vis/graph/img/rightArrow.png +0 -0
  40. data/vendor/assets/vis/graph/img/upArrow.png +0 -0
  41. data/vendor/assets/vis/graph/img/zoomExtends.png +0 -0
  42. data/vendor/assets/vis/graph/shapes.js +0 -225
  43. data/vendor/assets/vis/graph3d/Graph3d.js +0 -3306
  44. data/vendor/assets/vis/module/exports.js +0 -65
  45. data/vendor/assets/vis/module/header.js +0 -24
  46. data/vendor/assets/vis/module/imports.js +0 -31
  47. data/vendor/assets/vis/shim.js +0 -252
  48. data/vendor/assets/vis/timeline/Range.js +0 -532
  49. data/vendor/assets/vis/timeline/TimeStep.js +0 -466
  50. data/vendor/assets/vis/timeline/Timeline.js +0 -851
  51. data/vendor/assets/vis/timeline/component/Component.js +0 -52
  52. data/vendor/assets/vis/timeline/component/CurrentTime.js +0 -128
  53. data/vendor/assets/vis/timeline/component/CustomTime.js +0 -182
  54. data/vendor/assets/vis/timeline/component/Group.js +0 -470
  55. data/vendor/assets/vis/timeline/component/ItemSet.js +0 -1332
  56. data/vendor/assets/vis/timeline/component/TimeAxis.js +0 -389
  57. data/vendor/assets/vis/timeline/component/css/animation.css +0 -33
  58. data/vendor/assets/vis/timeline/component/css/currenttime.css +0 -5
  59. data/vendor/assets/vis/timeline/component/css/customtime.css +0 -6
  60. data/vendor/assets/vis/timeline/component/css/item.css +0 -107
  61. data/vendor/assets/vis/timeline/component/css/itemset.css +0 -33
  62. data/vendor/assets/vis/timeline/component/css/labelset.css +0 -36
  63. data/vendor/assets/vis/timeline/component/css/panel.css +0 -71
  64. data/vendor/assets/vis/timeline/component/css/timeaxis.css +0 -48
  65. data/vendor/assets/vis/timeline/component/css/timeline.css +0 -2
  66. data/vendor/assets/vis/timeline/component/item/Item.js +0 -139
  67. data/vendor/assets/vis/timeline/component/item/ItemBox.js +0 -230
  68. data/vendor/assets/vis/timeline/component/item/ItemPoint.js +0 -190
  69. data/vendor/assets/vis/timeline/component/item/ItemRange.js +0 -262
  70. data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +0 -57
  71. data/vendor/assets/vis/timeline/img/delete.png +0 -0
  72. data/vendor/assets/vis/timeline/stack.js +0 -112
  73. data/vendor/assets/vis/util.js +0 -990
@@ -1,851 +0,0 @@
1
- /**
2
- * Create a timeline visualization
3
- * @param {HTMLElement} container
4
- * @param {vis.DataSet | Array | google.visualization.DataTable} [items]
5
- * @param {Object} [options] See Timeline.setOptions for the available options.
6
- * @constructor
7
- */
8
- function Timeline (container, items, options) {
9
- var me = this;
10
- this.defaultOptions = {
11
- start: null,
12
- end: null,
13
-
14
- autoResize: true,
15
-
16
- orientation: 'bottom',
17
- width: null,
18
- height: null,
19
- maxHeight: null,
20
- minHeight: null
21
- };
22
- this.options = util.deepExtend({}, this.defaultOptions);
23
-
24
- // Create the DOM, props, and emitter
25
- this._create(container);
26
-
27
- // all components listed here will be repainted automatically
28
- this.components = [];
29
-
30
- this.body = {
31
- dom: this.dom,
32
- domProps: this.props,
33
- emitter: {
34
- on: this.on.bind(this),
35
- off: this.off.bind(this),
36
- emit: this.emit.bind(this)
37
- },
38
- util: {
39
- snap: null, // will be specified after TimeAxis is created
40
- toScreen: me._toScreen.bind(me),
41
- toTime: me._toTime.bind(me)
42
- }
43
- };
44
-
45
- // range
46
- this.range = new Range(this.body);
47
- this.components.push(this.range);
48
- this.body.range = this.range;
49
-
50
- // time axis
51
- this.timeAxis = new TimeAxis(this.body);
52
- this.components.push(this.timeAxis);
53
- this.body.util.snap = this.timeAxis.snap.bind(this.timeAxis);
54
-
55
- // current time bar
56
- this.currentTime = new CurrentTime(this.body);
57
- this.components.push(this.currentTime);
58
-
59
- // custom time bar
60
- // Note: time bar will be attached in this.setOptions when selected
61
- this.customTime = new CustomTime(this.body);
62
- this.components.push(this.customTime);
63
-
64
- // item set
65
- this.itemSet = new ItemSet(this.body);
66
- this.components.push(this.itemSet);
67
-
68
- this.itemsData = null; // DataSet
69
- this.groupsData = null; // DataSet
70
-
71
- // apply options
72
- if (options) {
73
- this.setOptions(options);
74
- }
75
-
76
- // create itemset
77
- if (items) {
78
- this.setItems(items);
79
- }
80
- else {
81
- this.redraw();
82
- }
83
- }
84
-
85
- // turn Timeline into an event emitter
86
- Emitter(Timeline.prototype);
87
-
88
- /**
89
- * Create the main DOM for the Timeline: a root panel containing left, right,
90
- * top, bottom, content, and background panel.
91
- * @param {Element} container The container element where the Timeline will
92
- * be attached.
93
- * @private
94
- */
95
- Timeline.prototype._create = function (container) {
96
- this.dom = {};
97
-
98
- this.dom.root = document.createElement('div');
99
- this.dom.background = document.createElement('div');
100
- this.dom.backgroundVertical = document.createElement('div');
101
- this.dom.backgroundHorizontal = document.createElement('div');
102
- this.dom.centerContainer = document.createElement('div');
103
- this.dom.leftContainer = document.createElement('div');
104
- this.dom.rightContainer = document.createElement('div');
105
- this.dom.center = document.createElement('div');
106
- this.dom.left = document.createElement('div');
107
- this.dom.right = document.createElement('div');
108
- this.dom.top = document.createElement('div');
109
- this.dom.bottom = document.createElement('div');
110
- this.dom.shadowTop = document.createElement('div');
111
- this.dom.shadowBottom = document.createElement('div');
112
- this.dom.shadowTopLeft = document.createElement('div');
113
- this.dom.shadowBottomLeft = document.createElement('div');
114
- this.dom.shadowTopRight = document.createElement('div');
115
- this.dom.shadowBottomRight = document.createElement('div');
116
-
117
- this.dom.background.className = 'vispanel background';
118
- this.dom.backgroundVertical.className = 'vispanel background vertical';
119
- this.dom.backgroundHorizontal.className = 'vispanel background horizontal';
120
- this.dom.centerContainer.className = 'vispanel center';
121
- this.dom.leftContainer.className = 'vispanel left';
122
- this.dom.rightContainer.className = 'vispanel right';
123
- this.dom.top.className = 'vispanel top';
124
- this.dom.bottom.className = 'vispanel bottom';
125
- this.dom.left.className = 'content';
126
- this.dom.center.className = 'content';
127
- this.dom.right.className = 'content';
128
- this.dom.shadowTop.className = 'shadow top';
129
- this.dom.shadowBottom.className = 'shadow bottom';
130
- this.dom.shadowTopLeft.className = 'shadow top';
131
- this.dom.shadowBottomLeft.className = 'shadow bottom';
132
- this.dom.shadowTopRight.className = 'shadow top';
133
- this.dom.shadowBottomRight.className = 'shadow bottom';
134
-
135
- this.dom.root.appendChild(this.dom.background);
136
- this.dom.root.appendChild(this.dom.backgroundVertical);
137
- this.dom.root.appendChild(this.dom.backgroundHorizontal);
138
- this.dom.root.appendChild(this.dom.centerContainer);
139
- this.dom.root.appendChild(this.dom.leftContainer);
140
- this.dom.root.appendChild(this.dom.rightContainer);
141
- this.dom.root.appendChild(this.dom.top);
142
- this.dom.root.appendChild(this.dom.bottom);
143
-
144
- this.dom.centerContainer.appendChild(this.dom.center);
145
- this.dom.leftContainer.appendChild(this.dom.left);
146
- this.dom.rightContainer.appendChild(this.dom.right);
147
-
148
- this.dom.centerContainer.appendChild(this.dom.shadowTop);
149
- this.dom.centerContainer.appendChild(this.dom.shadowBottom);
150
- this.dom.leftContainer.appendChild(this.dom.shadowTopLeft);
151
- this.dom.leftContainer.appendChild(this.dom.shadowBottomLeft);
152
- this.dom.rightContainer.appendChild(this.dom.shadowTopRight);
153
- this.dom.rightContainer.appendChild(this.dom.shadowBottomRight);
154
-
155
- this.on('rangechange', this.redraw.bind(this));
156
- this.on('change', this.redraw.bind(this));
157
- this.on('touch', this._onTouch.bind(this));
158
- this.on('pinch', this._onPinch.bind(this));
159
- this.on('dragstart', this._onDragStart.bind(this));
160
- this.on('drag', this._onDrag.bind(this));
161
-
162
- // create event listeners for all interesting events, these events will be
163
- // emitted via emitter
164
- this.hammer = Hammer(this.dom.root, {
165
- prevent_default: true
166
- });
167
- this.listeners = {};
168
-
169
- var me = this;
170
- var events = [
171
- 'touch', 'pinch',
172
- 'tap', 'doubletap', 'hold',
173
- 'dragstart', 'drag', 'dragend',
174
- 'mousewheel', 'DOMMouseScroll' // DOMMouseScroll is needed for Firefox
175
- ];
176
- events.forEach(function (event) {
177
- var listener = function () {
178
- var args = [event].concat(Array.prototype.slice.call(arguments, 0));
179
- me.emit.apply(me, args);
180
- };
181
- me.hammer.on(event, listener);
182
- me.listeners[event] = listener;
183
- });
184
-
185
- // size properties of each of the panels
186
- this.props = {
187
- root: {},
188
- background: {},
189
- centerContainer: {},
190
- leftContainer: {},
191
- rightContainer: {},
192
- center: {},
193
- left: {},
194
- right: {},
195
- top: {},
196
- bottom: {},
197
- border: {},
198
- scrollTop: 0,
199
- scrollTopMin: 0
200
- };
201
- this.touch = {}; // store state information needed for touch events
202
-
203
- // attach the root panel to the provided container
204
- if (!container) throw new Error('No container provided');
205
- container.appendChild(this.dom.root);
206
- };
207
-
208
- /**
209
- * Destroy the Timeline, clean up all DOM elements and event listeners.
210
- */
211
- Timeline.prototype.destroy = function () {
212
- // unbind datasets
213
- this.clear();
214
-
215
- // remove all event listeners
216
- this.off();
217
-
218
- // stop checking for changed size
219
- this._stopAutoResize();
220
-
221
- // remove from DOM
222
- if (this.dom.root.parentNode) {
223
- this.dom.root.parentNode.removeChild(this.dom.root);
224
- }
225
- this.dom = null;
226
-
227
- // cleanup hammer touch events
228
- for (var event in this.listeners) {
229
- if (this.listeners.hasOwnProperty(event)) {
230
- delete this.listeners[event];
231
- }
232
- }
233
- this.listeners = null;
234
- this.hammer = null;
235
-
236
- // give all components the opportunity to cleanup
237
- this.components.forEach(function (component) {
238
- component.destroy();
239
- });
240
-
241
- this.body = null;
242
- };
243
-
244
- /**
245
- * Set options. Options will be passed to all components loaded in the Timeline.
246
- * @param {Object} [options]
247
- * {String} orientation
248
- * Vertical orientation for the Timeline,
249
- * can be 'bottom' (default) or 'top'.
250
- * {String | Number} width
251
- * Width for the timeline, a number in pixels or
252
- * a css string like '1000px' or '75%'. '100%' by default.
253
- * {String | Number} height
254
- * Fixed height for the Timeline, a number in pixels or
255
- * a css string like '400px' or '75%'. If undefined,
256
- * The Timeline will automatically size such that
257
- * its contents fit.
258
- * {String | Number} minHeight
259
- * Minimum height for the Timeline, a number in pixels or
260
- * a css string like '400px' or '75%'.
261
- * {String | Number} maxHeight
262
- * Maximum height for the Timeline, a number in pixels or
263
- * a css string like '400px' or '75%'.
264
- * {Number | Date | String} start
265
- * Start date for the visible window
266
- * {Number | Date | String} end
267
- * End date for the visible window
268
- */
269
- Timeline.prototype.setOptions = function (options) {
270
- if (options) {
271
- // copy the known options
272
- var fields = ['width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'start', 'end', 'orientation'];
273
- util.selectiveExtend(fields, this.options, options);
274
-
275
- // enable/disable autoResize
276
- this._initAutoResize();
277
- }
278
-
279
- // propagate options to all components
280
- this.components.forEach(function (component) {
281
- component.setOptions(options);
282
- });
283
-
284
- // TODO: remove deprecation error one day (deprecated since version 0.8.0)
285
- if (options && options.order) {
286
- throw new Error('Option order is deprecated. There is no replacement for this feature.');
287
- }
288
-
289
- // redraw everything
290
- this.redraw();
291
- };
292
-
293
- /**
294
- * Set a custom time bar
295
- * @param {Date} time
296
- */
297
- Timeline.prototype.setCustomTime = function (time) {
298
- if (!this.customTime) {
299
- throw new Error('Cannot get custom time: Custom time bar is not enabled');
300
- }
301
-
302
- this.customTime.setCustomTime(time);
303
- };
304
-
305
- /**
306
- * Retrieve the current custom time.
307
- * @return {Date} customTime
308
- */
309
- Timeline.prototype.getCustomTime = function() {
310
- if (!this.customTime) {
311
- throw new Error('Cannot get custom time: Custom time bar is not enabled');
312
- }
313
-
314
- return this.customTime.getCustomTime();
315
- };
316
-
317
- /**
318
- * Set items
319
- * @param {vis.DataSet | Array | google.visualization.DataTable | null} items
320
- */
321
- Timeline.prototype.setItems = function(items) {
322
- var initialLoad = (this.itemsData == null);
323
-
324
- // convert to type DataSet when needed
325
- var newDataSet;
326
- if (!items) {
327
- newDataSet = null;
328
- }
329
- else if (items instanceof DataSet || items instanceof DataView) {
330
- newDataSet = items;
331
- }
332
- else {
333
- // turn an array into a dataset
334
- newDataSet = new DataSet(items, {
335
- type: {
336
- start: 'Date',
337
- end: 'Date'
338
- }
339
- });
340
- }
341
-
342
- // set items
343
- this.itemsData = newDataSet;
344
- this.itemSet && this.itemSet.setItems(newDataSet);
345
-
346
- if (initialLoad && ('start' in this.options || 'end' in this.options)) {
347
- this.fit();
348
-
349
- var start = ('start' in this.options) ? util.convert(this.options.start, 'Date') : null;
350
- var end = ('end' in this.options) ? util.convert(this.options.end, 'Date') : null;
351
-
352
- this.setWindow(start, end);
353
- }
354
- };
355
-
356
- /**
357
- * Set groups
358
- * @param {vis.DataSet | Array | google.visualization.DataTable} groups
359
- */
360
- Timeline.prototype.setGroups = function(groups) {
361
- // convert to type DataSet when needed
362
- var newDataSet;
363
- if (!groups) {
364
- newDataSet = null;
365
- }
366
- else if (groups instanceof DataSet || groups instanceof DataView) {
367
- newDataSet = groups;
368
- }
369
- else {
370
- // turn an array into a dataset
371
- newDataSet = new DataSet(groups);
372
- }
373
-
374
- this.groupsData = newDataSet;
375
- this.itemSet.setGroups(newDataSet);
376
- };
377
-
378
- /**
379
- * Clear the Timeline. By Default, items, groups and options are cleared.
380
- * Example usage:
381
- *
382
- * timeline.clear(); // clear items, groups, and options
383
- * timeline.clear({options: true}); // clear options only
384
- *
385
- * @param {Object} [what] Optionally specify what to clear. By default:
386
- * {items: true, groups: true, options: true}
387
- */
388
- Timeline.prototype.clear = function(what) {
389
- // clear items
390
- if (!what || what.items) {
391
- this.setItems(null);
392
- }
393
-
394
- // clear groups
395
- if (!what || what.groups) {
396
- this.setGroups(null);
397
- }
398
-
399
- // clear options of timeline and of each of the components
400
- if (!what || what.options) {
401
- this.components.forEach(function (component) {
402
- component.setOptions(component.defaultOptions);
403
- });
404
-
405
- this.setOptions(this.defaultOptions); // this will also do a redraw
406
- }
407
- };
408
-
409
- /**
410
- * Set Timeline window such that it fits all items
411
- */
412
- Timeline.prototype.fit = function() {
413
- // apply the data range as range
414
- var dataRange = this.getItemRange();
415
-
416
- // add 5% space on both sides
417
- var start = dataRange.min;
418
- var end = dataRange.max;
419
- if (start != null && end != null) {
420
- var interval = (end.valueOf() - start.valueOf());
421
- if (interval <= 0) {
422
- // prevent an empty interval
423
- interval = 24 * 60 * 60 * 1000; // 1 day
424
- }
425
- start = new Date(start.valueOf() - interval * 0.05);
426
- end = new Date(end.valueOf() + interval * 0.05);
427
- }
428
-
429
- // skip range set if there is no start and end date
430
- if (start === null && end === null) {
431
- return;
432
- }
433
-
434
- this.range.setRange(start, end);
435
- };
436
-
437
- /**
438
- * Get the data range of the item set.
439
- * @returns {{min: Date, max: Date}} range A range with a start and end Date.
440
- * When no minimum is found, min==null
441
- * When no maximum is found, max==null
442
- */
443
- Timeline.prototype.getItemRange = function() {
444
- // calculate min from start filed
445
- var itemsData = this.itemsData,
446
- min = null,
447
- max = null;
448
-
449
- if (itemsData) {
450
- // calculate the minimum value of the field 'start'
451
- var minItem = itemsData.min('start');
452
- min = minItem ? util.convert(minItem.start, 'Date').valueOf() : null;
453
- // Note: we convert first to Date and then to number because else
454
- // a conversion from ISODate to Number will fail
455
-
456
- // calculate maximum value of fields 'start' and 'end'
457
- var maxStartItem = itemsData.max('start');
458
- if (maxStartItem) {
459
- max = util.convert(maxStartItem.start, 'Date').valueOf();
460
- }
461
- var maxEndItem = itemsData.max('end');
462
- if (maxEndItem) {
463
- if (max == null) {
464
- max = util.convert(maxEndItem.end, 'Date').valueOf();
465
- }
466
- else {
467
- max = Math.max(max, util.convert(maxEndItem.end, 'Date').valueOf());
468
- }
469
- }
470
- }
471
-
472
- return {
473
- min: (min != null) ? new Date(min) : null,
474
- max: (max != null) ? new Date(max) : null
475
- };
476
- };
477
-
478
- /**
479
- * Set selected items by their id. Replaces the current selection
480
- * Unknown id's are silently ignored.
481
- * @param {Array} [ids] An array with zero or more id's of the items to be
482
- * selected. If ids is an empty array, all items will be
483
- * unselected.
484
- */
485
- Timeline.prototype.setSelection = function(ids) {
486
- this.itemSet && this.itemSet.setSelection(ids);
487
- };
488
-
489
- /**
490
- * Get the selected items by their id
491
- * @return {Array} ids The ids of the selected items
492
- */
493
- Timeline.prototype.getSelection = function() {
494
- return this.itemSet && this.itemSet.getSelection() || [];
495
- };
496
-
497
- /**
498
- * Set the visible window. Both parameters are optional, you can change only
499
- * start or only end. Syntax:
500
- *
501
- * TimeLine.setWindow(start, end)
502
- * TimeLine.setWindow(range)
503
- *
504
- * Where start and end can be a Date, number, or string, and range is an
505
- * object with properties start and end.
506
- *
507
- * @param {Date | Number | String | Object} [start] Start date of visible window
508
- * @param {Date | Number | String} [end] End date of visible window
509
- */
510
- Timeline.prototype.setWindow = function(start, end) {
511
- if (arguments.length == 1) {
512
- var range = arguments[0];
513
- this.range.setRange(range.start, range.end);
514
- }
515
- else {
516
- this.range.setRange(start, end);
517
- }
518
- };
519
-
520
- /**
521
- * Get the visible window
522
- * @return {{start: Date, end: Date}} Visible range
523
- */
524
- Timeline.prototype.getWindow = function() {
525
- var range = this.range.getRange();
526
- return {
527
- start: new Date(range.start),
528
- end: new Date(range.end)
529
- };
530
- };
531
-
532
- /**
533
- * Force a redraw of the Timeline. Can be useful to manually redraw when
534
- * option autoResize=false
535
- */
536
- Timeline.prototype.redraw = function() {
537
- var resized = false,
538
- options = this.options,
539
- props = this.props,
540
- dom = this.dom;
541
-
542
- if (!dom) return; // when destroyed
543
-
544
- // update class names
545
- dom.root.className = 'vis timeline root ' + options.orientation;
546
-
547
- // update root width and height options
548
- dom.root.style.maxHeight = util.option.asSize(options.maxHeight, '');
549
- dom.root.style.minHeight = util.option.asSize(options.minHeight, '');
550
- dom.root.style.width = util.option.asSize(options.width, '');
551
-
552
- // calculate border widths
553
- props.border.left = (dom.centerContainer.offsetWidth - dom.centerContainer.clientWidth) / 2;
554
- props.border.right = props.border.left;
555
- props.border.top = (dom.centerContainer.offsetHeight - dom.centerContainer.clientHeight) / 2;
556
- props.border.bottom = props.border.top;
557
- var borderRootHeight= dom.root.offsetHeight - dom.root.clientHeight;
558
- var borderRootWidth = dom.root.offsetWidth - dom.root.clientWidth;
559
-
560
- // calculate the heights. If any of the side panels is empty, we set the height to
561
- // minus the border width, such that the border will be invisible
562
- props.center.height = dom.center.offsetHeight;
563
- props.left.height = dom.left.offsetHeight;
564
- props.right.height = dom.right.offsetHeight;
565
- props.top.height = dom.top.clientHeight || -props.border.top;
566
- props.bottom.height = dom.bottom.clientHeight || -props.border.bottom;
567
-
568
- // TODO: compensate borders when any of the panels is empty.
569
-
570
- // apply auto height
571
- // TODO: only calculate autoHeight when needed (else we cause an extra reflow/repaint of the DOM)
572
- var contentHeight = Math.max(props.left.height, props.center.height, props.right.height);
573
- var autoHeight = props.top.height + contentHeight + props.bottom.height +
574
- borderRootHeight + props.border.top + props.border.bottom;
575
- dom.root.style.height = util.option.asSize(options.height, autoHeight + 'px');
576
-
577
- // calculate heights of the content panels
578
- props.root.height = dom.root.offsetHeight;
579
- props.background.height = props.root.height - borderRootHeight;
580
- var containerHeight = props.root.height - props.top.height - props.bottom.height -
581
- borderRootHeight;
582
- props.centerContainer.height = containerHeight;
583
- props.leftContainer.height = containerHeight;
584
- props.rightContainer.height = props.leftContainer.height;
585
-
586
- // calculate the widths of the panels
587
- props.root.width = dom.root.offsetWidth;
588
- props.background.width = props.root.width - borderRootWidth;
589
- props.left.width = dom.leftContainer.clientWidth || -props.border.left;
590
- props.leftContainer.width = props.left.width;
591
- props.right.width = dom.rightContainer.clientWidth || -props.border.right;
592
- props.rightContainer.width = props.right.width;
593
- var centerWidth = props.root.width - props.left.width - props.right.width - borderRootWidth;
594
- props.center.width = centerWidth;
595
- props.centerContainer.width = centerWidth;
596
- props.top.width = centerWidth;
597
- props.bottom.width = centerWidth;
598
-
599
- // resize the panels
600
- dom.background.style.height = props.background.height + 'px';
601
- dom.backgroundVertical.style.height = props.background.height + 'px';
602
- dom.backgroundHorizontal.style.height = props.centerContainer.height + 'px';
603
- dom.centerContainer.style.height = props.centerContainer.height + 'px';
604
- dom.leftContainer.style.height = props.leftContainer.height + 'px';
605
- dom.rightContainer.style.height = props.rightContainer.height + 'px';
606
-
607
- dom.background.style.width = props.background.width + 'px';
608
- dom.backgroundVertical.style.width = props.centerContainer.width + 'px';
609
- dom.backgroundHorizontal.style.width = props.background.width + 'px';
610
- dom.centerContainer.style.width = props.center.width + 'px';
611
- dom.top.style.width = props.top.width + 'px';
612
- dom.bottom.style.width = props.bottom.width + 'px';
613
-
614
- // reposition the panels
615
- dom.background.style.left = '0';
616
- dom.background.style.top = '0';
617
- dom.backgroundVertical.style.left = props.left.width + 'px';
618
- dom.backgroundVertical.style.top = '0';
619
- dom.backgroundHorizontal.style.left = '0';
620
- dom.backgroundHorizontal.style.top = props.top.height + 'px';
621
- dom.centerContainer.style.left = props.left.width + 'px';
622
- dom.centerContainer.style.top = props.top.height + 'px';
623
- dom.leftContainer.style.left = '0';
624
- dom.leftContainer.style.top = props.top.height + 'px';
625
- dom.rightContainer.style.left = (props.left.width + props.center.width) + 'px';
626
- dom.rightContainer.style.top = props.top.height + 'px';
627
- dom.top.style.left = props.left.width + 'px';
628
- dom.top.style.top = '0';
629
- dom.bottom.style.left = props.left.width + 'px';
630
- dom.bottom.style.top = (props.top.height + props.centerContainer.height) + 'px';
631
-
632
- // update the scrollTop, feasible range for the offset can be changed
633
- // when the height of the Timeline or of the contents of the center changed
634
- this._updateScrollTop();
635
-
636
- // reposition the scrollable contents
637
- var offset = this.props.scrollTop;
638
- if (options.orientation == 'bottom') {
639
- offset += Math.max(this.props.centerContainer.height - this.props.center.height, 0);
640
- }
641
- dom.center.style.left = '0';
642
- dom.center.style.top = offset + 'px';
643
- dom.left.style.left = '0';
644
- dom.left.style.top = offset + 'px';
645
- dom.right.style.left = '0';
646
- dom.right.style.top = offset + 'px';
647
-
648
- // show shadows when vertical scrolling is available
649
- var visibilityTop = this.props.scrollTop == 0 ? 'hidden' : '';
650
- var visibilityBottom = this.props.scrollTop == this.props.scrollTopMin ? 'hidden' : '';
651
- dom.shadowTop.style.visibility = visibilityTop;
652
- dom.shadowBottom.style.visibility = visibilityBottom;
653
- dom.shadowTopLeft.style.visibility = visibilityTop;
654
- dom.shadowBottomLeft.style.visibility = visibilityBottom;
655
- dom.shadowTopRight.style.visibility = visibilityTop;
656
- dom.shadowBottomRight.style.visibility = visibilityBottom;
657
-
658
- // redraw all components
659
- this.components.forEach(function (component) {
660
- resized = component.redraw() || resized;
661
- });
662
- if (resized) {
663
- // keep repainting until all sizes are settled
664
- this.redraw();
665
- }
666
- };
667
-
668
- // TODO: deprecated since version 1.1.0, remove some day
669
- Timeline.prototype.repaint = function () {
670
- throw new Error('Function repaint is deprecated. Use redraw instead.');
671
- };
672
-
673
- /**
674
- * Convert a position on screen (pixels) to a datetime
675
- * @param {int} x Position on the screen in pixels
676
- * @return {Date} time The datetime the corresponds with given position x
677
- * @private
678
- */
679
- // TODO: move this function to Range
680
- Timeline.prototype._toTime = function(x) {
681
- var conversion = this.range.conversion(this.props.center.width);
682
- return new Date(x / conversion.scale + conversion.offset);
683
- };
684
-
685
- /**
686
- * Convert a datetime (Date object) into a position on the screen
687
- * @param {Date} time A date
688
- * @return {int} x The position on the screen in pixels which corresponds
689
- * with the given date.
690
- * @private
691
- */
692
- // TODO: move this function to Range
693
- Timeline.prototype._toScreen = function(time) {
694
- var conversion = this.range.conversion(this.props.center.width);
695
- return (time.valueOf() - conversion.offset) * conversion.scale;
696
- };
697
-
698
- /**
699
- * Initialize watching when option autoResize is true
700
- * @private
701
- */
702
- Timeline.prototype._initAutoResize = function () {
703
- if (this.options.autoResize == true) {
704
- this._startAutoResize();
705
- }
706
- else {
707
- this._stopAutoResize();
708
- }
709
- };
710
-
711
- /**
712
- * Watch for changes in the size of the container. On resize, the Panel will
713
- * automatically redraw itself.
714
- * @private
715
- */
716
- Timeline.prototype._startAutoResize = function () {
717
- var me = this;
718
-
719
- this._stopAutoResize();
720
-
721
- this._onResize = function() {
722
- if (me.options.autoResize != true) {
723
- // stop watching when the option autoResize is changed to false
724
- me._stopAutoResize();
725
- return;
726
- }
727
-
728
- if (me.dom.root) {
729
- // check whether the frame is resized
730
- if ((me.dom.root.clientWidth != me.props.lastWidth) ||
731
- (me.dom.root.clientHeight != me.props.lastHeight)) {
732
- me.props.lastWidth = me.dom.root.clientWidth;
733
- me.props.lastHeight = me.dom.root.clientHeight;
734
-
735
- me.emit('change');
736
- }
737
- }
738
- };
739
-
740
- // add event listener to window resize
741
- util.addEventListener(window, 'resize', this._onResize);
742
-
743
- this.watchTimer = setInterval(this._onResize, 1000);
744
- };
745
-
746
- /**
747
- * Stop watching for a resize of the frame.
748
- * @private
749
- */
750
- Timeline.prototype._stopAutoResize = function () {
751
- if (this.watchTimer) {
752
- clearInterval(this.watchTimer);
753
- this.watchTimer = undefined;
754
- }
755
-
756
- // remove event listener on window.resize
757
- util.removeEventListener(window, 'resize', this._onResize);
758
- this._onResize = null;
759
- };
760
-
761
- /**
762
- * Start moving the timeline vertically
763
- * @param {Event} event
764
- * @private
765
- */
766
- Timeline.prototype._onTouch = function (event) {
767
- this.touch.allowDragging = true;
768
- };
769
-
770
- /**
771
- * Start moving the timeline vertically
772
- * @param {Event} event
773
- * @private
774
- */
775
- Timeline.prototype._onPinch = function (event) {
776
- this.touch.allowDragging = false;
777
- };
778
-
779
- /**
780
- * Start moving the timeline vertically
781
- * @param {Event} event
782
- * @private
783
- */
784
- Timeline.prototype._onDragStart = function (event) {
785
- this.touch.initialScrollTop = this.props.scrollTop;
786
- };
787
-
788
- /**
789
- * Move the timeline vertically
790
- * @param {Event} event
791
- * @private
792
- */
793
- Timeline.prototype._onDrag = function (event) {
794
- // refuse to drag when we where pinching to prevent the timeline make a jump
795
- // when releasing the fingers in opposite order from the touch screen
796
- if (!this.touch.allowDragging) return;
797
-
798
- var delta = event.gesture.deltaY;
799
-
800
- var oldScrollTop = this._getScrollTop();
801
- var newScrollTop = this._setScrollTop(this.touch.initialScrollTop + delta);
802
-
803
- if (newScrollTop != oldScrollTop) {
804
- this.redraw(); // TODO: this causes two redraws when dragging, the other is triggered by rangechange already
805
- }
806
- };
807
-
808
- /**
809
- * Apply a scrollTop
810
- * @param {Number} scrollTop
811
- * @returns {Number} scrollTop Returns the applied scrollTop
812
- * @private
813
- */
814
- Timeline.prototype._setScrollTop = function (scrollTop) {
815
- this.props.scrollTop = scrollTop;
816
- this._updateScrollTop();
817
- return this.props.scrollTop;
818
- };
819
-
820
- /**
821
- * Update the current scrollTop when the height of the containers has been changed
822
- * @returns {Number} scrollTop Returns the applied scrollTop
823
- * @private
824
- */
825
- Timeline.prototype._updateScrollTop = function () {
826
- // recalculate the scrollTopMin
827
- var scrollTopMin = Math.min(this.props.centerContainer.height - this.props.center.height, 0); // is negative or zero
828
- if (scrollTopMin != this.props.scrollTopMin) {
829
- // in case of bottom orientation, change the scrollTop such that the contents
830
- // do not move relative to the time axis at the bottom
831
- if (this.options.orientation == 'bottom') {
832
- this.props.scrollTop += (scrollTopMin - this.props.scrollTopMin);
833
- }
834
- this.props.scrollTopMin = scrollTopMin;
835
- }
836
-
837
- // limit the scrollTop to the feasible scroll range
838
- if (this.props.scrollTop > 0) this.props.scrollTop = 0;
839
- if (this.props.scrollTop < scrollTopMin) this.props.scrollTop = scrollTopMin;
840
-
841
- return this.props.scrollTop;
842
- };
843
-
844
- /**
845
- * Get the current scrollTop
846
- * @returns {number} scrollTop
847
- * @private
848
- */
849
- Timeline.prototype._getScrollTop = function () {
850
- return this.props.scrollTop;
851
- };