vis-rails 0.0.6 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/lib/vis/rails/version.rb +1 -1
  3. data/vendor/assets/javascripts/vis.js +2 -9
  4. data/vendor/assets/vis/DataSet.js +17 -9
  5. data/vendor/assets/vis/graph/Edge.js +49 -24
  6. data/vendor/assets/vis/graph/Graph.js +268 -64
  7. data/vendor/assets/vis/graph/Groups.js +1 -1
  8. data/vendor/assets/vis/graph/Node.js +18 -67
  9. data/vendor/assets/vis/graph/Popup.js +40 -13
  10. data/vendor/assets/vis/graph/css/graph-navigation.css +18 -14
  11. data/vendor/assets/vis/graph/graphMixins/ClusterMixin.js +7 -5
  12. data/vendor/assets/vis/graph/graphMixins/HierarchicalLayoutMixin.js +20 -5
  13. data/vendor/assets/vis/graph/graphMixins/ManipulationMixin.js +33 -33
  14. data/vendor/assets/vis/graph/graphMixins/MixinLoader.js +30 -32
  15. data/vendor/assets/vis/graph/graphMixins/NavigationMixin.js +33 -1
  16. data/vendor/assets/vis/graph/graphMixins/SectorsMixin.js +2 -2
  17. data/vendor/assets/vis/graph/graphMixins/SelectionMixin.js +72 -60
  18. data/vendor/assets/vis/graph/graphMixins/physics/BarnesHut.js +43 -18
  19. data/vendor/assets/vis/graph/graphMixins/physics/HierarchialRepulsion.js +8 -8
  20. data/vendor/assets/vis/graph/graphMixins/physics/PhysicsMixin.js +309 -129
  21. data/vendor/assets/vis/graph/graphMixins/physics/Repulsion.js +10 -10
  22. data/vendor/assets/vis/module/exports.js +1 -2
  23. data/vendor/assets/vis/module/header.js +2 -2
  24. data/vendor/assets/vis/timeline/Range.js +53 -93
  25. data/vendor/assets/vis/timeline/Timeline.js +328 -224
  26. data/vendor/assets/vis/timeline/component/Component.js +17 -95
  27. data/vendor/assets/vis/timeline/component/CurrentTime.js +54 -59
  28. data/vendor/assets/vis/timeline/component/CustomTime.js +55 -83
  29. data/vendor/assets/vis/timeline/component/Group.js +398 -75
  30. data/vendor/assets/vis/timeline/component/ItemSet.js +662 -403
  31. data/vendor/assets/vis/timeline/component/Panel.js +118 -60
  32. data/vendor/assets/vis/timeline/component/RootPanel.js +80 -132
  33. data/vendor/assets/vis/timeline/component/TimeAxis.js +191 -277
  34. data/vendor/assets/vis/timeline/component/css/item.css +16 -23
  35. data/vendor/assets/vis/timeline/component/css/itemset.css +25 -4
  36. data/vendor/assets/vis/timeline/component/css/labelset.css +34 -0
  37. data/vendor/assets/vis/timeline/component/css/panel.css +15 -1
  38. data/vendor/assets/vis/timeline/component/css/timeaxis.css +8 -8
  39. data/vendor/assets/vis/timeline/component/item/Item.js +48 -26
  40. data/vendor/assets/vis/timeline/component/item/ItemBox.js +156 -230
  41. data/vendor/assets/vis/timeline/component/item/ItemPoint.js +118 -166
  42. data/vendor/assets/vis/timeline/component/item/ItemRange.js +135 -187
  43. data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +29 -92
  44. data/vendor/assets/vis/timeline/stack.js +112 -0
  45. data/vendor/assets/vis/util.js +136 -38
  46. metadata +4 -18
  47. data/vendor/assets/vis/.gitignore +0 -1
  48. data/vendor/assets/vis/EventBus.js +0 -89
  49. data/vendor/assets/vis/events.js +0 -116
  50. data/vendor/assets/vis/graph/ClusterMixin.js +0 -1019
  51. data/vendor/assets/vis/graph/NavigationMixin.js +0 -245
  52. data/vendor/assets/vis/graph/SectorsMixin.js +0 -547
  53. data/vendor/assets/vis/graph/SelectionMixin.js +0 -515
  54. data/vendor/assets/vis/graph/img/downarrow.png +0 -0
  55. data/vendor/assets/vis/graph/img/leftarrow.png +0 -0
  56. data/vendor/assets/vis/graph/img/rightarrow.png +0 -0
  57. data/vendor/assets/vis/graph/img/uparrow.png +0 -0
  58. data/vendor/assets/vis/timeline/Controller.js +0 -183
  59. data/vendor/assets/vis/timeline/Stack.js +0 -190
  60. data/vendor/assets/vis/timeline/component/ContentPanel.js +0 -113
  61. data/vendor/assets/vis/timeline/component/GroupSet.js +0 -580
  62. data/vendor/assets/vis/timeline/component/css/groupset.css +0 -59
@@ -1,14 +1,13 @@
1
1
  /**
2
2
  * @constructor ItemPoint
3
3
  * @extends Item
4
- * @param {ItemSet} parent
5
4
  * @param {Object} data Object containing parameters start
6
5
  * content, className.
7
6
  * @param {Object} [options] Options to set initial property values
8
7
  * @param {Object} [defaultOptions] default options
9
8
  * // TODO: describe available options
10
9
  */
11
- function ItemPoint (parent, data, options, defaultOptions) {
10
+ function ItemPoint (data, options, defaultOptions) {
12
11
  this.props = {
13
12
  dot: {
14
13
  top: 0,
@@ -21,219 +20,172 @@ function ItemPoint (parent, data, options, defaultOptions) {
21
20
  }
22
21
  };
23
22
 
24
- Item.call(this, parent, data, options, defaultOptions);
23
+ // validate data
24
+ if (data) {
25
+ if (data.start == undefined) {
26
+ throw new Error('Property "start" missing in item ' + data);
27
+ }
28
+ }
29
+
30
+ Item.call(this, data, options, defaultOptions);
25
31
  }
26
32
 
27
- ItemPoint.prototype = new Item (null, null);
33
+ ItemPoint.prototype = new Item (null);
34
+
35
+ /**
36
+ * Check whether this item is visible inside given range
37
+ * @returns {{start: Number, end: Number}} range with a timestamp for start and end
38
+ * @returns {boolean} True if visible
39
+ */
40
+ ItemPoint.prototype.isVisible = function isVisible (range) {
41
+ // determine visibility
42
+ // TODO: account for the real width of the item. Right now we just add 1/4 to the window
43
+ var interval = (range.end - range.start) / 4;
44
+ return (this.data.start > range.start - interval) && (this.data.start < range.end + interval);
45
+ };
28
46
 
29
47
  /**
30
48
  * Repaint the item
31
- * @return {Boolean} changed
32
49
  */
33
50
  ItemPoint.prototype.repaint = function repaint() {
34
- // TODO: make an efficient repaint
35
- var changed = false;
36
51
  var dom = this.dom;
37
-
38
52
  if (!dom) {
39
- this._create();
53
+ // create DOM
54
+ this.dom = {};
40
55
  dom = this.dom;
41
- changed = true;
56
+
57
+ // background box
58
+ dom.point = document.createElement('div');
59
+ // className is updated in repaint()
60
+
61
+ // contents box, right from the dot
62
+ dom.content = document.createElement('div');
63
+ dom.content.className = 'content';
64
+ dom.point.appendChild(dom.content);
65
+
66
+ // dot at start
67
+ dom.dot = document.createElement('div');
68
+ dom.point.appendChild(dom.dot);
69
+
70
+ // attach this item as attribute
71
+ dom.point['timeline-item'] = this;
42
72
  }
43
73
 
44
- if (dom) {
45
- if (!this.parent) {
46
- throw new Error('Cannot repaint item: no parent attached');
47
- }
74
+ // append DOM to parent DOM
75
+ if (!this.parent) {
76
+ throw new Error('Cannot repaint item: no parent attached');
77
+ }
78
+ if (!dom.point.parentNode) {
48
79
  var foreground = this.parent.getForeground();
49
80
  if (!foreground) {
50
- throw new Error('Cannot repaint time axis: ' +
51
- 'parent has no foreground container element');
81
+ throw new Error('Cannot repaint time axis: parent has no foreground container element');
52
82
  }
53
-
54
- if (!dom.point.parentNode) {
55
- foreground.appendChild(dom.point);
56
- foreground.appendChild(dom.point);
57
- changed = true;
83
+ foreground.appendChild(dom.point);
84
+ }
85
+ this.displayed = true;
86
+
87
+ // update contents
88
+ if (this.data.content != this.content) {
89
+ this.content = this.data.content;
90
+ if (this.content instanceof Element) {
91
+ dom.content.innerHTML = '';
92
+ dom.content.appendChild(this.content);
58
93
  }
59
-
60
- // update contents
61
- if (this.data.content != this.content) {
62
- this.content = this.data.content;
63
- if (this.content instanceof Element) {
64
- dom.content.innerHTML = '';
65
- dom.content.appendChild(this.content);
66
- }
67
- else if (this.data.content != undefined) {
68
- dom.content.innerHTML = this.content;
69
- }
70
- else {
71
- throw new Error('Property "content" missing in item ' + this.data.id);
72
- }
73
- changed = true;
94
+ else if (this.data.content != undefined) {
95
+ dom.content.innerHTML = this.content;
96
+ }
97
+ else {
98
+ throw new Error('Property "content" missing in item ' + this.data.id);
74
99
  }
75
100
 
76
- this._repaintDeleteButton(dom.point);
101
+ this.dirty = true;
102
+ }
77
103
 
78
- // update class
79
- var className = (this.data.className? ' ' + this.data.className : '') +
80
- (this.selected ? ' selected' : '');
81
- if (this.className != className) {
82
- this.className = className;
83
- dom.point.className = 'item point' + className;
84
- changed = true;
85
- }
104
+ // update class
105
+ var className = (this.data.className? ' ' + this.data.className : '') +
106
+ (this.selected ? ' selected' : '');
107
+ if (this.className != className) {
108
+ this.className = className;
109
+ dom.point.className = 'item point' + className;
110
+ dom.dot.className = 'item dot' + className;
111
+
112
+ this.dirty = true;
113
+ }
114
+
115
+ // recalculate size
116
+ if (this.dirty) {
117
+ this.width = dom.point.offsetWidth;
118
+ this.height = dom.point.offsetHeight;
119
+ this.props.dot.width = dom.dot.offsetWidth;
120
+ this.props.dot.height = dom.dot.offsetHeight;
121
+ this.props.content.height = dom.content.offsetHeight;
122
+
123
+ // resize contents
124
+ dom.content.style.marginLeft = 2 * this.props.dot.width + 'px';
125
+ //dom.content.style.marginRight = ... + 'px'; // TODO: margin right
126
+
127
+ dom.dot.style.top = ((this.height - this.props.dot.height) / 2) + 'px';
128
+ dom.dot.style.left = (this.props.dot.width / 2) + 'px';
129
+
130
+ this.dirty = false;
86
131
  }
87
132
 
88
- return changed;
133
+ this._repaintDeleteButton(dom.point);
89
134
  };
90
135
 
91
136
  /**
92
137
  * Show the item in the DOM (when not already visible). The items DOM will
93
138
  * be created when needed.
94
- * @return {Boolean} changed
95
139
  */
96
140
  ItemPoint.prototype.show = function show() {
97
- if (!this.dom || !this.dom.point.parentNode) {
98
- return this.repaint();
99
- }
100
- else {
101
- return false;
141
+ if (!this.displayed) {
142
+ this.repaint();
102
143
  }
103
144
  };
104
145
 
105
146
  /**
106
147
  * Hide the item from the DOM (when visible)
107
- * @return {Boolean} changed
108
148
  */
109
149
  ItemPoint.prototype.hide = function hide() {
110
- var changed = false,
111
- dom = this.dom;
112
- if (dom) {
113
- if (dom.point.parentNode) {
114
- dom.point.parentNode.removeChild(dom.point);
115
- changed = true;
150
+ if (this.displayed) {
151
+ if (this.dom.point.parentNode) {
152
+ this.dom.point.parentNode.removeChild(this.dom.point);
116
153
  }
117
- }
118
- return changed;
119
- };
120
154
 
121
- /**
122
- * Reflow the item: calculate its actual size from the DOM
123
- * @return {boolean} resized returns true if the axis is resized
124
- * @override
125
- */
126
- ItemPoint.prototype.reflow = function reflow() {
127
- var changed = 0,
128
- update,
129
- dom,
130
- props,
131
- options,
132
- margin,
133
- orientation,
134
- start,
135
- top,
136
- data,
137
- range;
138
-
139
- if (this.data.start == undefined) {
140
- throw new Error('Property "start" missing in item ' + this.data.id);
141
- }
155
+ this.top = null;
156
+ this.left = null;
142
157
 
143
- data = this.data;
144
- range = this.parent && this.parent.range;
145
- if (data && range) {
146
- // TODO: account for the width of the item
147
- var interval = (range.end - range.start);
148
- this.visible = (data.start > range.start - interval) && (data.start < range.end);
149
- }
150
- else {
151
- this.visible = false;
158
+ this.displayed = false;
152
159
  }
153
-
154
- if (this.visible) {
155
- dom = this.dom;
156
- if (dom) {
157
- update = util.updateProperty;
158
- props = this.props;
159
- options = this.options;
160
- orientation = options.orientation || this.defaultOptions.orientation;
161
- margin = options.margin && options.margin.axis || this.defaultOptions.margin.axis;
162
- start = this.parent.toScreen(this.data.start) + this.offset;
163
-
164
- changed += update(this, 'width', dom.point.offsetWidth);
165
- changed += update(this, 'height', dom.point.offsetHeight);
166
- changed += update(props.dot, 'width', dom.dot.offsetWidth);
167
- changed += update(props.dot, 'height', dom.dot.offsetHeight);
168
- changed += update(props.content, 'height', dom.content.offsetHeight);
169
-
170
- if (orientation == 'top') {
171
- top = margin;
172
- }
173
- else {
174
- // default or 'bottom'
175
- var parentHeight = this.parent.height;
176
- top = Math.max(parentHeight - this.height - margin, 0);
177
- }
178
- changed += update(this, 'top', top);
179
- changed += update(this, 'left', start - props.dot.width / 2);
180
- changed += update(props.content, 'marginLeft', 1.5 * props.dot.width);
181
- //changed += update(props.content, 'marginRight', 0.5 * props.dot.width); // TODO
182
-
183
- changed += update(props.dot, 'top', (this.height - props.dot.height) / 2);
184
- }
185
- else {
186
- changed += 1;
187
- }
188
- }
189
-
190
- return (changed > 0);
191
160
  };
192
161
 
193
162
  /**
194
- * Create an items DOM
195
- * @private
163
+ * Reposition the item horizontally
164
+ * @Override
196
165
  */
197
- ItemPoint.prototype._create = function _create() {
198
- var dom = this.dom;
199
- if (!dom) {
200
- this.dom = dom = {};
166
+ ItemPoint.prototype.repositionX = function repositionX() {
167
+ var start = this.defaultOptions.toScreen(this.data.start);
201
168
 
202
- // background box
203
- dom.point = document.createElement('div');
204
- // className is updated in repaint()
205
-
206
- // contents box, right from the dot
207
- dom.content = document.createElement('div');
208
- dom.content.className = 'content';
209
- dom.point.appendChild(dom.content);
169
+ this.left = start - this.props.dot.width;
210
170
 
211
- // dot at start
212
- dom.dot = document.createElement('div');
213
- dom.dot.className = 'dot';
214
- dom.point.appendChild(dom.dot);
215
-
216
- // attach this item as attribute
217
- dom.point['timeline-item'] = this;
218
- }
171
+ // reposition point
172
+ this.dom.point.style.left = this.left + 'px';
219
173
  };
220
174
 
221
175
  /**
222
- * Reposition the item, recalculate its left, top, and width, using the current
223
- * range and size of the items itemset
224
- * @override
176
+ * Reposition the item vertically
177
+ * @Override
225
178
  */
226
- ItemPoint.prototype.reposition = function reposition() {
227
- var dom = this.dom,
228
- props = this.props;
179
+ ItemPoint.prototype.repositionY = function repositionY () {
180
+ var orientation = this.options.orientation || this.defaultOptions.orientation,
181
+ point = this.dom.point;
229
182
 
230
- if (dom) {
231
- dom.point.style.top = this.top + 'px';
232
- dom.point.style.left = this.left + 'px';
233
-
234
- dom.content.style.marginLeft = props.content.marginLeft + 'px';
235
- //dom.content.style.marginRight = props.content.marginRight + 'px'; // TODO
236
-
237
- dom.dot.style.top = props.dot.top + 'px';
183
+ if (orientation == 'top') {
184
+ point.style.top = this.top + 'px';
185
+ point.style.bottom = '';
186
+ }
187
+ else {
188
+ point.style.top = '';
189
+ point.style.bottom = this.top + 'px';
238
190
  }
239
191
  };
@@ -1,100 +1,129 @@
1
1
  /**
2
2
  * @constructor ItemRange
3
3
  * @extends Item
4
- * @param {ItemSet} parent
5
4
  * @param {Object} data Object containing parameters start, end
6
5
  * content, className.
7
6
  * @param {Object} [options] Options to set initial property values
8
7
  * @param {Object} [defaultOptions] default options
9
8
  * // TODO: describe available options
10
9
  */
11
- function ItemRange (parent, data, options, defaultOptions) {
10
+ function ItemRange (data, options, defaultOptions) {
12
11
  this.props = {
13
12
  content: {
14
- left: 0,
15
13
  width: 0
16
14
  }
17
15
  };
18
16
 
19
- Item.call(this, parent, data, options, defaultOptions);
17
+ // validate data
18
+ if (data) {
19
+ if (data.start == undefined) {
20
+ throw new Error('Property "start" missing in item ' + data.id);
21
+ }
22
+ if (data.end == undefined) {
23
+ throw new Error('Property "end" missing in item ' + data.id);
24
+ }
25
+ }
26
+
27
+ Item.call(this, data, options, defaultOptions);
20
28
  }
21
29
 
22
- ItemRange.prototype = new Item (null, null);
30
+ ItemRange.prototype = new Item (null);
31
+
32
+ ItemRange.prototype.baseClassName = 'item range';
33
+
34
+ /**
35
+ * Check whether this item is visible inside given range
36
+ * @returns {{start: Number, end: Number}} range with a timestamp for start and end
37
+ * @returns {boolean} True if visible
38
+ */
39
+ ItemRange.prototype.isVisible = function isVisible (range) {
40
+ // determine visibility
41
+ return (this.data.start < range.end) && (this.data.end > range.start);
42
+ };
23
43
 
24
44
  /**
25
45
  * Repaint the item
26
- * @return {Boolean} changed
27
46
  */
28
47
  ItemRange.prototype.repaint = function repaint() {
29
- // TODO: make an efficient repaint
30
- var changed = false;
31
48
  var dom = this.dom;
32
-
33
49
  if (!dom) {
34
- this._create();
50
+ // create DOM
51
+ this.dom = {};
35
52
  dom = this.dom;
36
- changed = true;
53
+
54
+ // background box
55
+ dom.box = document.createElement('div');
56
+ // className is updated in repaint()
57
+
58
+ // contents box
59
+ dom.content = document.createElement('div');
60
+ dom.content.className = 'content';
61
+ dom.box.appendChild(dom.content);
62
+
63
+ // attach this item as attribute
64
+ dom.box['timeline-item'] = this;
37
65
  }
38
66
 
39
- if (dom) {
40
- if (!this.parent) {
41
- throw new Error('Cannot repaint item: no parent attached');
42
- }
67
+ // append DOM to parent DOM
68
+ if (!this.parent) {
69
+ throw new Error('Cannot repaint item: no parent attached');
70
+ }
71
+ if (!dom.box.parentNode) {
43
72
  var foreground = this.parent.getForeground();
44
73
  if (!foreground) {
45
- throw new Error('Cannot repaint time axis: ' +
46
- 'parent has no foreground container element');
74
+ throw new Error('Cannot repaint time axis: parent has no foreground container element');
47
75
  }
48
-
49
- if (!dom.box.parentNode) {
50
- foreground.appendChild(dom.box);
51
- changed = true;
76
+ foreground.appendChild(dom.box);
77
+ }
78
+ this.displayed = true;
79
+
80
+ // update contents
81
+ if (this.data.content != this.content) {
82
+ this.content = this.data.content;
83
+ if (this.content instanceof Element) {
84
+ dom.content.innerHTML = '';
85
+ dom.content.appendChild(this.content);
52
86
  }
53
-
54
- // update content
55
- if (this.data.content != this.content) {
56
- this.content = this.data.content;
57
- if (this.content instanceof Element) {
58
- dom.content.innerHTML = '';
59
- dom.content.appendChild(this.content);
60
- }
61
- else if (this.data.content != undefined) {
62
- dom.content.innerHTML = this.content;
63
- }
64
- else {
65
- throw new Error('Property "content" missing in item ' + this.data.id);
66
- }
67
- changed = true;
87
+ else if (this.data.content != undefined) {
88
+ dom.content.innerHTML = this.content;
68
89
  }
69
-
70
- this._repaintDeleteButton(dom.box);
71
- this._repaintDragLeft();
72
- this._repaintDragRight();
73
-
74
- // update class
75
- var className = (this.data.className ? (' ' + this.data.className) : '') +
76
- (this.selected ? ' selected' : '');
77
- if (this.className != className) {
78
- this.className = className;
79
- dom.box.className = 'item range' + className;
80
- changed = true;
90
+ else {
91
+ throw new Error('Property "content" missing in item ' + this.data.id);
81
92
  }
93
+
94
+ this.dirty = true;
95
+ }
96
+
97
+ // update class
98
+ var className = (this.data.className ? (' ' + this.data.className) : '') +
99
+ (this.selected ? ' selected' : '');
100
+ if (this.className != className) {
101
+ this.className = className;
102
+ dom.box.className = this.baseClassName + className;
103
+
104
+ this.dirty = true;
82
105
  }
83
106
 
84
- return changed;
107
+ // recalculate size
108
+ if (this.dirty) {
109
+ this.props.content.width = this.dom.content.offsetWidth;
110
+ this.height = this.dom.box.offsetHeight;
111
+
112
+ this.dirty = false;
113
+ }
114
+
115
+ this._repaintDeleteButton(dom.box);
116
+ this._repaintDragLeft();
117
+ this._repaintDragRight();
85
118
  };
86
119
 
87
120
  /**
88
121
  * Show the item in the DOM (when not already visible). The items DOM will
89
122
  * be created when needed.
90
- * @return {Boolean} changed
91
123
  */
92
124
  ItemRange.prototype.show = function show() {
93
- if (!this.dom || !this.dom.box.parentNode) {
94
- return this.repaint();
95
- }
96
- else {
97
- return false;
125
+ if (!this.displayed) {
126
+ this.repaint();
98
127
  }
99
128
  };
100
129
 
@@ -103,163 +132,82 @@ ItemRange.prototype.show = function show() {
103
132
  * @return {Boolean} changed
104
133
  */
105
134
  ItemRange.prototype.hide = function hide() {
106
- var changed = false,
107
- dom = this.dom;
108
- if (dom) {
109
- if (dom.box.parentNode) {
110
- dom.box.parentNode.removeChild(dom.box);
111
- changed = true;
135
+ if (this.displayed) {
136
+ var box = this.dom.box;
137
+
138
+ if (box.parentNode) {
139
+ box.parentNode.removeChild(box);
112
140
  }
141
+
142
+ this.top = null;
143
+ this.left = null;
144
+
145
+ this.displayed = false;
113
146
  }
114
- return changed;
115
147
  };
116
148
 
117
149
  /**
118
- * Reflow the item: calculate its actual size from the DOM
119
- * @return {boolean} resized returns true if the axis is resized
120
- * @override
150
+ * Reposition the item horizontally
151
+ * @Override
121
152
  */
122
- ItemRange.prototype.reflow = function reflow() {
123
- var changed = 0,
124
- dom,
125
- props,
126
- options,
127
- margin,
128
- padding,
129
- parent,
130
- start,
131
- end,
132
- data,
133
- range,
134
- update,
135
- box,
136
- parentWidth,
137
- contentLeft,
138
- orientation,
139
- top;
140
-
141
- if (this.data.start == undefined) {
142
- throw new Error('Property "start" missing in item ' + this.data.id);
153
+ ItemRange.prototype.repositionX = function repositionX() {
154
+ var props = this.props,
155
+ parentWidth = this.parent.width,
156
+ start = this.defaultOptions.toScreen(this.data.start),
157
+ end = this.defaultOptions.toScreen(this.data.end),
158
+ padding = 'padding' in this.options ? this.options.padding : this.defaultOptions.padding,
159
+ contentLeft;
160
+
161
+ // limit the width of the this, as browsers cannot draw very wide divs
162
+ if (start < -parentWidth) {
163
+ start = -parentWidth;
143
164
  }
144
- if (this.data.end == undefined) {
145
- throw new Error('Property "end" missing in item ' + this.data.id);
165
+ if (end > 2 * parentWidth) {
166
+ end = 2 * parentWidth;
146
167
  }
147
168
 
148
- data = this.data;
149
- range = this.parent && this.parent.range;
150
- if (data && range) {
151
- // TODO: account for the width of the item. Take some margin
152
- this.visible = (data.start < range.end) && (data.end > range.start);
169
+ // when range exceeds left of the window, position the contents at the left of the visible area
170
+ if (start < 0) {
171
+ contentLeft = Math.min(-start,
172
+ (end - start - props.content.width - 2 * padding));
173
+ // TODO: remove the need for options.padding. it's terrible.
153
174
  }
154
175
  else {
155
- this.visible = false;
176
+ contentLeft = 0;
156
177
  }
157
178
 
158
- if (this.visible) {
159
- dom = this.dom;
160
- if (dom) {
161
- props = this.props;
162
- options = this.options;
163
- parent = this.parent;
164
- start = parent.toScreen(this.data.start) + this.offset;
165
- end = parent.toScreen(this.data.end) + this.offset;
166
- update = util.updateProperty;
167
- box = dom.box;
168
- parentWidth = parent.width;
169
- orientation = options.orientation || this.defaultOptions.orientation;
170
- margin = options.margin && options.margin.axis || this.defaultOptions.margin.axis;
171
- padding = options.padding || this.defaultOptions.padding;
172
-
173
- changed += update(props.content, 'width', dom.content.offsetWidth);
174
-
175
- changed += update(this, 'height', box.offsetHeight);
176
-
177
- // limit the width of the this, as browsers cannot draw very wide divs
178
- if (start < -parentWidth) {
179
- start = -parentWidth;
180
- }
181
- if (end > 2 * parentWidth) {
182
- end = 2 * parentWidth;
183
- }
184
-
185
- // when range exceeds left of the window, position the contents at the left of the visible area
186
- if (start < 0) {
187
- contentLeft = Math.min(-start,
188
- (end - start - props.content.width - 2 * padding));
189
- // TODO: remove the need for options.padding. it's terrible.
190
- }
191
- else {
192
- contentLeft = 0;
193
- }
194
- changed += update(props.content, 'left', contentLeft);
195
-
196
- if (orientation == 'top') {
197
- top = margin;
198
- changed += update(this, 'top', top);
199
- }
200
- else {
201
- // default or 'bottom'
202
- top = parent.height - this.height - margin;
203
- changed += update(this, 'top', top);
204
- }
205
-
206
- changed += update(this, 'left', start);
207
- changed += update(this, 'width', Math.max(end - start, 1)); // TODO: reckon with border width;
208
- }
209
- else {
210
- changed += 1;
211
- }
212
- }
179
+ this.left = start;
180
+ this.width = Math.max(end - start, 1);
213
181
 
214
- return (changed > 0);
182
+ this.dom.box.style.left = this.left + 'px';
183
+ this.dom.box.style.width = this.width + 'px';
184
+ this.dom.content.style.left = contentLeft + 'px';
215
185
  };
216
186
 
217
187
  /**
218
- * Create an items DOM
219
- * @private
188
+ * Reposition the item vertically
189
+ * @Override
220
190
  */
221
- ItemRange.prototype._create = function _create() {
222
- var dom = this.dom;
223
- if (!dom) {
224
- this.dom = dom = {};
225
- // background box
226
- dom.box = document.createElement('div');
227
- // className is updated in repaint()
228
-
229
- // contents box
230
- dom.content = document.createElement('div');
231
- dom.content.className = 'content';
232
- dom.box.appendChild(dom.content);
191
+ ItemRange.prototype.repositionY = function repositionY() {
192
+ var orientation = this.options.orientation || this.defaultOptions.orientation,
193
+ box = this.dom.box;
233
194
 
234
- // attach this item as attribute
235
- dom.box['timeline-item'] = this;
195
+ if (orientation == 'top') {
196
+ box.style.top = this.top + 'px';
197
+ box.style.bottom = '';
236
198
  }
237
- };
238
-
239
- /**
240
- * Reposition the item, recalculate its left, top, and width, using the current
241
- * range and size of the items itemset
242
- * @override
243
- */
244
- ItemRange.prototype.reposition = function reposition() {
245
- var dom = this.dom,
246
- props = this.props;
247
-
248
- if (dom) {
249
- dom.box.style.top = this.top + 'px';
250
- dom.box.style.left = this.left + 'px';
251
- dom.box.style.width = this.width + 'px';
252
-
253
- dom.content.style.left = props.content.left + 'px';
199
+ else {
200
+ box.style.top = '';
201
+ box.style.bottom = this.top + 'px';
254
202
  }
255
203
  };
256
204
 
257
205
  /**
258
206
  * Repaint a drag area on the left side of the range when the range is selected
259
- * @private
207
+ * @protected
260
208
  */
261
209
  ItemRange.prototype._repaintDragLeft = function () {
262
- if (this.selected && this.options.editable && !this.dom.dragLeft) {
210
+ if (this.selected && this.options.editable.updateTime && !this.dom.dragLeft) {
263
211
  // create and show drag area
264
212
  var dragLeft = document.createElement('div');
265
213
  dragLeft.className = 'drag-left';
@@ -286,10 +234,10 @@ ItemRange.prototype._repaintDragLeft = function () {
286
234
 
287
235
  /**
288
236
  * Repaint a drag area on the right side of the range when the range is selected
289
- * @private
237
+ * @protected
290
238
  */
291
239
  ItemRange.prototype._repaintDragRight = function () {
292
- if (this.selected && this.options.editable && !this.dom.dragRight) {
240
+ if (this.selected && this.options.editable.updateTime && !this.dom.dragRight) {
293
241
  // create and show drag area
294
242
  var dragRight = document.createElement('div');
295
243
  dragRight.className = 'drag-right';