vis-rails 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -13
  2. data/lib/vis/rails/version.rb +1 -1
  3. data/vendor/assets/component/emitter.js +162 -0
  4. data/vendor/assets/javascripts/vis.js +1 -0
  5. data/vendor/assets/vis/DataSet.js +8 -2
  6. data/vendor/assets/vis/DataView.js +8 -4
  7. data/vendor/assets/vis/graph/Edge.js +210 -78
  8. data/vendor/assets/vis/graph/Graph.js +474 -652
  9. data/vendor/assets/vis/graph/Node.js +119 -82
  10. data/vendor/assets/vis/graph/css/graph-manipulation.css +128 -0
  11. data/vendor/assets/vis/graph/css/graph-navigation.css +62 -0
  12. data/vendor/assets/vis/graph/graphMixins/ClusterMixin.js +1141 -0
  13. data/vendor/assets/vis/graph/graphMixins/HierarchicalLayoutMixin.js +296 -0
  14. data/vendor/assets/vis/graph/graphMixins/ManipulationMixin.js +433 -0
  15. data/vendor/assets/vis/graph/graphMixins/MixinLoader.js +201 -0
  16. data/vendor/assets/vis/graph/graphMixins/NavigationMixin.js +173 -0
  17. data/vendor/assets/vis/graph/graphMixins/SectorsMixin.js +552 -0
  18. data/vendor/assets/vis/graph/graphMixins/SelectionMixin.js +558 -0
  19. data/vendor/assets/vis/graph/graphMixins/physics/BarnesHut.js +373 -0
  20. data/vendor/assets/vis/graph/graphMixins/physics/HierarchialRepulsion.js +64 -0
  21. data/vendor/assets/vis/graph/graphMixins/physics/PhysicsMixin.js +513 -0
  22. data/vendor/assets/vis/graph/graphMixins/physics/Repulsion.js +66 -0
  23. data/vendor/assets/vis/graph/img/acceptDeleteIcon.png +0 -0
  24. data/vendor/assets/vis/graph/img/addNodeIcon.png +0 -0
  25. data/vendor/assets/vis/graph/img/backIcon.png +0 -0
  26. data/vendor/assets/vis/graph/img/connectIcon.png +0 -0
  27. data/vendor/assets/vis/graph/img/cross.png +0 -0
  28. data/vendor/assets/vis/graph/img/cross2.png +0 -0
  29. data/vendor/assets/vis/graph/img/deleteIcon.png +0 -0
  30. data/vendor/assets/vis/graph/img/downArrow.png +0 -0
  31. data/vendor/assets/vis/graph/img/editIcon.png +0 -0
  32. data/vendor/assets/vis/graph/img/leftArrow.png +0 -0
  33. data/vendor/assets/vis/graph/img/rightArrow.png +0 -0
  34. data/vendor/assets/vis/graph/img/upArrow.png +0 -0
  35. data/vendor/assets/vis/module/exports.js +0 -2
  36. data/vendor/assets/vis/module/header.js +2 -2
  37. data/vendor/assets/vis/module/imports.js +1 -2
  38. data/vendor/assets/vis/timeline/Controller.js +56 -45
  39. data/vendor/assets/vis/timeline/Range.js +68 -62
  40. data/vendor/assets/vis/timeline/Stack.js +11 -13
  41. data/vendor/assets/vis/timeline/TimeStep.js +43 -38
  42. data/vendor/assets/vis/timeline/Timeline.js +215 -93
  43. data/vendor/assets/vis/timeline/component/Component.js +19 -3
  44. data/vendor/assets/vis/timeline/component/CurrentTime.js +1 -1
  45. data/vendor/assets/vis/timeline/component/CustomTime.js +39 -120
  46. data/vendor/assets/vis/timeline/component/GroupSet.js +35 -1
  47. data/vendor/assets/vis/timeline/component/ItemSet.js +272 -9
  48. data/vendor/assets/vis/timeline/component/RootPanel.js +59 -47
  49. data/vendor/assets/vis/timeline/component/TimeAxis.js +10 -0
  50. data/vendor/assets/vis/timeline/component/css/item.css +53 -22
  51. data/vendor/assets/vis/timeline/component/item/Item.js +40 -5
  52. data/vendor/assets/vis/timeline/component/item/ItemBox.js +3 -1
  53. data/vendor/assets/vis/timeline/component/item/ItemPoint.js +3 -1
  54. data/vendor/assets/vis/timeline/component/item/ItemRange.js +67 -3
  55. data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +37 -9
  56. data/vendor/assets/vis/timeline/img/delete.png +0 -0
  57. data/vendor/assets/vis/util.js +169 -30
  58. metadata +39 -12
@@ -10,12 +10,29 @@ function RootPanel(container, options) {
10
10
  this.id = util.randomUUID();
11
11
  this.container = container;
12
12
 
13
+ // create functions to be used as DOM event listeners
14
+ var me = this;
15
+ this.hammer = null;
16
+
17
+ // create listeners for all interesting events, these events will be emitted
18
+ // via the controller
19
+ var events = [
20
+ 'touch', 'pinch', 'tap', 'doubletap', 'hold',
21
+ 'dragstart', 'drag', 'dragend',
22
+ 'mousewheel', 'DOMMouseScroll' // DOMMouseScroll is for Firefox
23
+ ];
24
+ this.listeners = {};
25
+ events.forEach(function (event) {
26
+ me.listeners[event] = function () {
27
+ var args = [event].concat(Array.prototype.slice.call(arguments, 0));
28
+ me.controller.emit.apply(me.controller, args);
29
+ };
30
+ });
31
+
13
32
  this.options = options || {};
14
33
  this.defaultOptions = {
15
34
  autoResize: true
16
35
  };
17
-
18
- this.listeners = {}; // event listeners
19
36
  }
20
37
 
21
38
  RootPanel.prototype = new Panel();
@@ -48,6 +65,8 @@ RootPanel.prototype.repaint = function () {
48
65
 
49
66
  this.frame = frame;
50
67
 
68
+ this._registerListeners();
69
+
51
70
  changed += 1;
52
71
  }
53
72
  if (!frame.parentNode) {
@@ -58,7 +77,8 @@ RootPanel.prototype.repaint = function () {
58
77
  changed += 1;
59
78
  }
60
79
 
61
- frame.className = 'vis timeline rootpanel ' + options.orientation;
80
+ frame.className = 'vis timeline rootpanel ' + options.orientation +
81
+ (options.editable ? ' editable' : '');
62
82
  var className = options.className;
63
83
  if (className) {
64
84
  util.addClassName(frame, util.option.asString(className));
@@ -69,7 +89,6 @@ RootPanel.prototype.repaint = function () {
69
89
  changed += update(frame.style, 'width', asSize(options.width, '100%'));
70
90
  changed += update(frame.style, 'height', asSize(options.height, '100%'));
71
91
 
72
- this._updateEventEmitters();
73
92
  this._updateWatch();
74
93
 
75
94
  return (changed > 0);
@@ -158,58 +177,51 @@ RootPanel.prototype._unwatch = function () {
158
177
  };
159
178
 
160
179
  /**
161
- * Event handler
162
- * @param {String} event name of the event, for example 'click', 'mousemove'
163
- * @param {function} callback callback handler, invoked with the raw HTML Event
164
- * as parameter.
180
+ * Set controller for this component, or remove current controller by passing
181
+ * null as parameter value.
182
+ * @param {Controller | null} controller
165
183
  */
166
- RootPanel.prototype.on = function (event, callback) {
167
- // register the listener at this component
168
- var arr = this.listeners[event];
169
- if (!arr) {
170
- arr = [];
171
- this.listeners[event] = arr;
172
- }
173
- arr.push(callback);
184
+ RootPanel.prototype.setController = function setController (controller) {
185
+ this.controller = controller || null;
174
186
 
175
- this._updateEventEmitters();
187
+ if (this.controller) {
188
+ this._registerListeners();
189
+ }
190
+ else {
191
+ this._unregisterListeners();
192
+ }
176
193
  };
177
194
 
178
195
  /**
179
- * Update the event listeners for all event emitters
196
+ * Register event emitters emitted by the rootpanel
180
197
  * @private
181
198
  */
182
- RootPanel.prototype._updateEventEmitters = function () {
183
- if (this.listeners) {
184
- var me = this;
185
- util.forEach(this.listeners, function (listeners, event) {
186
- if (!me.emitters) {
187
- me.emitters = {};
199
+ RootPanel.prototype._registerListeners = function () {
200
+ if (this.frame && this.controller && !this.hammer) {
201
+ this.hammer = Hammer(this.frame, {
202
+ prevent_default: true
203
+ });
204
+
205
+ for (var event in this.listeners) {
206
+ if (this.listeners.hasOwnProperty(event)) {
207
+ this.hammer.on(event, this.listeners[event]);
188
208
  }
189
- if (!(event in me.emitters)) {
190
- // create event
191
- var frame = me.frame;
192
- if (frame) {
193
- //console.log('Created a listener for event ' + event + ' on component ' + me.id); // TODO: cleanup logging
194
- var callback = function(event) {
195
- listeners.forEach(function (listener) {
196
- // TODO: filter on event target!
197
- listener(event);
198
- });
199
- };
200
- me.emitters[event] = callback;
201
-
202
- if (!me.hammer) {
203
- me.hammer = Hammer(frame, {
204
- prevent_default: true
205
- });
206
- }
207
- me.hammer.on(event, callback);
208
- }
209
+ }
210
+ }
211
+ };
212
+
213
+ /**
214
+ * Unregister event emitters from the rootpanel
215
+ * @private
216
+ */
217
+ RootPanel.prototype._unregisterListeners = function () {
218
+ if (this.hammer) {
219
+ for (var event in this.listeners) {
220
+ if (this.listeners.hasOwnProperty(event)) {
221
+ this.hammer.off(event, this.listeners[event]);
209
222
  }
210
- });
223
+ }
211
224
 
212
- // TODO: be able to delete event listeners
213
- // TODO: be able to move event listeners to a parent when available
225
+ this.hammer = null;
214
226
  }
215
227
  };
@@ -520,3 +520,13 @@ TimeAxis.prototype._updateConversion = function() {
520
520
  this.conversion = Range.conversion(range.start, range.end, this.width);
521
521
  }
522
522
  };
523
+
524
+ /**
525
+ * Snap a date to a rounded value.
526
+ * The snap intervals are dependent on the current scale and step.
527
+ * @param {Date} date the date to be snapped.
528
+ * @return {Date} snappedDate
529
+ */
530
+ TimeAxis.prototype.snap = function snap (date) {
531
+ return this.step.snap(date);
532
+ };
@@ -5,6 +5,7 @@
5
5
  border-color: #97B0F8;
6
6
  background-color: #D5DDF6;
7
7
  display: inline-block;
8
+ padding: 5px;
8
9
  }
9
10
 
10
11
  .vis.timeline .item.selected {
@@ -13,6 +14,10 @@
13
14
  z-index: 999;
14
15
  }
15
16
 
17
+ .vis.timeline.editable .item.selected {
18
+ cursor: move;
19
+ }
20
+
16
21
  .vis.timeline .item.point.selected {
17
22
  background-color: #FFF785;
18
23
  z-index: 999;
@@ -42,44 +47,37 @@
42
47
  background: none;
43
48
  }
44
49
 
45
- .vis.timeline .dot {
50
+ .vis.timeline .dot,
51
+ .vis.timeline .item.dot {
52
+ padding: 0;
46
53
  border: 5px solid #97B0F8;
47
54
  position: absolute;
48
55
  border-radius: 5px;
49
56
  -moz-border-radius: 5px; /* For Firefox 3.6 and older */
50
57
  }
51
58
 
52
- .vis.timeline .item.range {
53
- overflow: hidden;
54
- border-style: solid;
55
- border-width: 1px;
56
- border-radius: 2px;
57
- -moz-border-radius: 2px; /* For Firefox 3.6 and older */
58
- }
59
-
60
- .vis.timeline .item.rangeoverflow {
59
+ .vis.timeline .item.range,
60
+ .vis.timeline .item.rangeoverflow{
61
61
  border-style: solid;
62
62
  border-width: 1px;
63
63
  border-radius: 2px;
64
64
  -moz-border-radius: 2px; /* For Firefox 3.6 and older */
65
+ box-sizing: border-box;
65
66
  }
66
67
 
67
- .vis.timeline .item.range .drag-left, .vis.timeline .item.rangeoverflow .drag-left {
68
- cursor: w-resize;
69
- z-index: 1000;
70
- }
71
-
72
- .vis.timeline .item.range .drag-right, .vis.timeline .item.rangeoverflow .drag-right {
73
- cursor: e-resize;
74
- z-index: 1000;
75
- }
76
-
77
- .vis.timeline .item.range .content, .vis.timeline .item.rangeoverflow .content {
68
+ .vis.timeline .item.range .content,
69
+ .vis.timeline .item.rangeoverflow .content {
78
70
  position: relative;
79
71
  display: inline-block;
80
72
  }
81
73
 
74
+ .vis.timeline .item.range .content {
75
+ overflow: hidden;
76
+ max-width: 100%;
77
+ }
78
+
82
79
  .vis.timeline .item.line {
80
+ padding: 0;
83
81
  position: absolute;
84
82
  width: 0;
85
83
  border-left-width: 1px;
@@ -87,7 +85,40 @@
87
85
  }
88
86
 
89
87
  .vis.timeline .item .content {
90
- margin: 5px;
91
88
  white-space: nowrap;
92
89
  overflow: hidden;
93
90
  }
91
+
92
+ .vis.timeline .item .delete {
93
+ background: url('img/timeline/delete.png') no-repeat top center;
94
+ position: absolute;
95
+ width: 24px;
96
+ height: 24px;
97
+ top: 0;
98
+ right: -24px;
99
+ cursor: pointer;
100
+ }
101
+
102
+ .vis.timeline .item.range .drag-left,
103
+ .vis.timeline .item.rangeoverflow .drag-left {
104
+ position: absolute;
105
+ width: 24px;
106
+ height: 100%;
107
+ top: 0;
108
+ left: -4px;
109
+
110
+ cursor: w-resize;
111
+ z-index: 10000;
112
+ }
113
+
114
+ .vis.timeline .item.range .drag-right,
115
+ .vis.timeline .item.rangeoverflow .drag-right {
116
+ position: absolute;
117
+ width: 24px;
118
+ height: 100%;
119
+ top: 0;
120
+ right: -4px;
121
+
122
+ cursor: e-resize;
123
+ z-index: 10001; /* a little higher z-index than .drag-left */
124
+ }
@@ -20,6 +20,7 @@ function Item (parent, data, options, defaultOptions) {
20
20
  this.left = 0;
21
21
  this.width = 0;
22
22
  this.height = 0;
23
+ this.offset = 0;
23
24
  }
24
25
 
25
26
  /**
@@ -73,9 +74,43 @@ Item.prototype.reflow = function reflow() {
73
74
  };
74
75
 
75
76
  /**
76
- * Return the items width
77
- * @return {Integer} width
77
+ * Give the item a display offset in pixels
78
+ * @param {Number} offset Offset on screen in pixels
78
79
  */
79
- Item.prototype.getWidth = function getWidth() {
80
- return this.width;
81
- }
80
+ Item.prototype.setOffset = function setOffset(offset) {
81
+ this.offset = offset;
82
+ };
83
+
84
+ /**
85
+ * Repaint a delete button on the top right of the item when the item is selected
86
+ * @param {HTMLElement} anchor
87
+ * @private
88
+ */
89
+ Item.prototype._repaintDeleteButton = function (anchor) {
90
+ if (this.selected && this.options.editable && !this.dom.deleteButton) {
91
+ // create and show button
92
+ var parent = this.parent;
93
+ var id = this.id;
94
+
95
+ var deleteButton = document.createElement('div');
96
+ deleteButton.className = 'delete';
97
+ deleteButton.title = 'Delete this item';
98
+
99
+ Hammer(deleteButton, {
100
+ preventDefault: true
101
+ }).on('tap', function (event) {
102
+ parent.removeItem(id);
103
+ event.stopPropagation();
104
+ });
105
+
106
+ anchor.appendChild(deleteButton);
107
+ this.dom.deleteButton = deleteButton;
108
+ }
109
+ else if (!this.selected && this.dom.deleteButton) {
110
+ // remove button
111
+ if (this.dom.deleteButton.parentNode) {
112
+ this.dom.deleteButton.parentNode.removeChild(this.dom.deleteButton);
113
+ }
114
+ this.dom.deleteButton = null;
115
+ }
116
+ };
@@ -79,6 +79,8 @@ ItemBox.prototype.repaint = function repaint() {
79
79
  changed = true;
80
80
  }
81
81
 
82
+ this._repaintDeleteButton(dom.box);
83
+
82
84
  // update contents
83
85
  if (this.data.content != this.content) {
84
86
  this.content = this.data.content;
@@ -187,7 +189,7 @@ ItemBox.prototype.reflow = function reflow() {
187
189
  update = util.updateProperty;
188
190
  props = this.props;
189
191
  options = this.options;
190
- start = this.parent.toScreen(this.data.start);
192
+ start = this.parent.toScreen(this.data.start) + this.offset;
191
193
  align = options.align || this.defaultOptions.align;
192
194
  margin = options.margin && options.margin.axis || this.defaultOptions.margin.axis;
193
195
  orientation = options.orientation || this.defaultOptions.orientation;
@@ -73,6 +73,8 @@ ItemPoint.prototype.repaint = function repaint() {
73
73
  changed = true;
74
74
  }
75
75
 
76
+ this._repaintDeleteButton(dom.point);
77
+
76
78
  // update class
77
79
  var className = (this.data.className? ' ' + this.data.className : '') +
78
80
  (this.selected ? ' selected' : '');
@@ -157,7 +159,7 @@ ItemPoint.prototype.reflow = function reflow() {
157
159
  options = this.options;
158
160
  orientation = options.orientation || this.defaultOptions.orientation;
159
161
  margin = options.margin && options.margin.axis || this.defaultOptions.margin.axis;
160
- start = this.parent.toScreen(this.data.start);
162
+ start = this.parent.toScreen(this.data.start) + this.offset;
161
163
 
162
164
  changed += update(this, 'width', dom.point.offsetWidth);
163
165
  changed += update(this, 'height', dom.point.offsetHeight);
@@ -67,8 +67,12 @@ ItemRange.prototype.repaint = function repaint() {
67
67
  changed = true;
68
68
  }
69
69
 
70
+ this._repaintDeleteButton(dom.box);
71
+ this._repaintDragLeft();
72
+ this._repaintDragRight();
73
+
70
74
  // update class
71
- var className = (this.data.className? ' ' + this.data.className : '') +
75
+ var className = (this.data.className ? (' ' + this.data.className) : '') +
72
76
  (this.selected ? ' selected' : '');
73
77
  if (this.className != className) {
74
78
  this.className = className;
@@ -157,8 +161,8 @@ ItemRange.prototype.reflow = function reflow() {
157
161
  props = this.props;
158
162
  options = this.options;
159
163
  parent = this.parent;
160
- start = parent.toScreen(this.data.start);
161
- end = parent.toScreen(this.data.end);
164
+ start = parent.toScreen(this.data.start) + this.offset;
165
+ end = parent.toScreen(this.data.end) + this.offset;
162
166
  update = util.updateProperty;
163
167
  box = dom.box;
164
168
  parentWidth = parent.width;
@@ -249,3 +253,63 @@ ItemRange.prototype.reposition = function reposition() {
249
253
  dom.content.style.left = props.content.left + 'px';
250
254
  }
251
255
  };
256
+
257
+ /**
258
+ * Repaint a drag area on the left side of the range when the range is selected
259
+ * @private
260
+ */
261
+ ItemRange.prototype._repaintDragLeft = function () {
262
+ if (this.selected && this.options.editable && !this.dom.dragLeft) {
263
+ // create and show drag area
264
+ var dragLeft = document.createElement('div');
265
+ dragLeft.className = 'drag-left';
266
+ dragLeft.dragLeftItem = this;
267
+
268
+ // TODO: this should be redundant?
269
+ Hammer(dragLeft, {
270
+ preventDefault: true
271
+ }).on('drag', function () {
272
+ //console.log('drag left')
273
+ });
274
+
275
+ this.dom.box.appendChild(dragLeft);
276
+ this.dom.dragLeft = dragLeft;
277
+ }
278
+ else if (!this.selected && this.dom.dragLeft) {
279
+ // delete drag area
280
+ if (this.dom.dragLeft.parentNode) {
281
+ this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft);
282
+ }
283
+ this.dom.dragLeft = null;
284
+ }
285
+ };
286
+
287
+ /**
288
+ * Repaint a drag area on the right side of the range when the range is selected
289
+ * @private
290
+ */
291
+ ItemRange.prototype._repaintDragRight = function () {
292
+ if (this.selected && this.options.editable && !this.dom.dragRight) {
293
+ // create and show drag area
294
+ var dragRight = document.createElement('div');
295
+ dragRight.className = 'drag-right';
296
+ dragRight.dragRightItem = this;
297
+
298
+ // TODO: this should be redundant?
299
+ Hammer(dragRight, {
300
+ preventDefault: true
301
+ }).on('drag', function () {
302
+ //console.log('drag right')
303
+ });
304
+
305
+ this.dom.box.appendChild(dragRight);
306
+ this.dom.dragRight = dragRight;
307
+ }
308
+ else if (!this.selected && this.dom.dragRight) {
309
+ // delete drag area
310
+ if (this.dom.dragRight.parentNode) {
311
+ this.dom.dragRight.parentNode.removeChild(this.dom.dragRight);
312
+ }
313
+ this.dom.dragRight = null;
314
+ }
315
+ };