vis-rails 0.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 (71) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.gitmodules +3 -0
  4. data/.project +11 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +202 -0
  7. data/README.md +29 -0
  8. data/Rakefile +1 -0
  9. data/lib/vis/rails/engine.rb +6 -0
  10. data/lib/vis/rails/version.rb +5 -0
  11. data/lib/vis/rails.rb +7 -0
  12. data/vendor/assets/javascripts/vis.js +1 -0
  13. data/vendor/assets/stylesheets/vis.css +3 -0
  14. data/vendor/assets/vis/DataSet.js +936 -0
  15. data/vendor/assets/vis/DataView.js +281 -0
  16. data/vendor/assets/vis/EventBus.js +89 -0
  17. data/vendor/assets/vis/events.js +116 -0
  18. data/vendor/assets/vis/graph/ClusterMixin.js +1019 -0
  19. data/vendor/assets/vis/graph/Edge.js +620 -0
  20. data/vendor/assets/vis/graph/Graph.js +2111 -0
  21. data/vendor/assets/vis/graph/Groups.js +80 -0
  22. data/vendor/assets/vis/graph/Images.js +41 -0
  23. data/vendor/assets/vis/graph/NavigationMixin.js +245 -0
  24. data/vendor/assets/vis/graph/Node.js +978 -0
  25. data/vendor/assets/vis/graph/Popup.js +105 -0
  26. data/vendor/assets/vis/graph/SectorsMixin.js +547 -0
  27. data/vendor/assets/vis/graph/SelectionMixin.js +515 -0
  28. data/vendor/assets/vis/graph/dotparser.js +829 -0
  29. data/vendor/assets/vis/graph/img/downarrow.png +0 -0
  30. data/vendor/assets/vis/graph/img/leftarrow.png +0 -0
  31. data/vendor/assets/vis/graph/img/minus.png +0 -0
  32. data/vendor/assets/vis/graph/img/plus.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/graph/img/zoomExtends.png +0 -0
  36. data/vendor/assets/vis/graph/shapes.js +225 -0
  37. data/vendor/assets/vis/module/exports.js +68 -0
  38. data/vendor/assets/vis/module/header.js +24 -0
  39. data/vendor/assets/vis/module/imports.js +32 -0
  40. data/vendor/assets/vis/shim.js +252 -0
  41. data/vendor/assets/vis/timeline/Controller.js +172 -0
  42. data/vendor/assets/vis/timeline/Range.js +553 -0
  43. data/vendor/assets/vis/timeline/Stack.js +192 -0
  44. data/vendor/assets/vis/timeline/TimeStep.js +449 -0
  45. data/vendor/assets/vis/timeline/Timeline.js +476 -0
  46. data/vendor/assets/vis/timeline/component/Component.js +148 -0
  47. data/vendor/assets/vis/timeline/component/ContentPanel.js +113 -0
  48. data/vendor/assets/vis/timeline/component/CurrentTime.js +101 -0
  49. data/vendor/assets/vis/timeline/component/CustomTime.js +255 -0
  50. data/vendor/assets/vis/timeline/component/Group.js +129 -0
  51. data/vendor/assets/vis/timeline/component/GroupSet.js +546 -0
  52. data/vendor/assets/vis/timeline/component/ItemSet.js +612 -0
  53. data/vendor/assets/vis/timeline/component/Panel.js +112 -0
  54. data/vendor/assets/vis/timeline/component/RootPanel.js +215 -0
  55. data/vendor/assets/vis/timeline/component/TimeAxis.js +522 -0
  56. data/vendor/assets/vis/timeline/component/css/currenttime.css +5 -0
  57. data/vendor/assets/vis/timeline/component/css/customtime.css +6 -0
  58. data/vendor/assets/vis/timeline/component/css/groupset.css +59 -0
  59. data/vendor/assets/vis/timeline/component/css/item.css +93 -0
  60. data/vendor/assets/vis/timeline/component/css/itemset.css +17 -0
  61. data/vendor/assets/vis/timeline/component/css/panel.css +14 -0
  62. data/vendor/assets/vis/timeline/component/css/timeaxis.css +41 -0
  63. data/vendor/assets/vis/timeline/component/css/timeline.css +2 -0
  64. data/vendor/assets/vis/timeline/component/item/Item.js +81 -0
  65. data/vendor/assets/vis/timeline/component/item/ItemBox.js +302 -0
  66. data/vendor/assets/vis/timeline/component/item/ItemPoint.js +237 -0
  67. data/vendor/assets/vis/timeline/component/item/ItemRange.js +251 -0
  68. data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +91 -0
  69. data/vendor/assets/vis/util.js +673 -0
  70. data/vis-rails.gemspec +47 -0
  71. metadata +142 -0
@@ -0,0 +1,546 @@
1
+ /**
2
+ * An GroupSet holds a set of groups
3
+ * @param {Component} parent
4
+ * @param {Component[]} [depends] Components on which this components depends
5
+ * (except for the parent)
6
+ * @param {Object} [options] See GroupSet.setOptions for the available
7
+ * options.
8
+ * @constructor GroupSet
9
+ * @extends Panel
10
+ */
11
+ function GroupSet(parent, depends, options) {
12
+ this.id = util.randomUUID();
13
+ this.parent = parent;
14
+ this.depends = depends;
15
+
16
+ this.options = options || {};
17
+
18
+ this.range = null; // Range or Object {start: number, end: number}
19
+ this.itemsData = null; // DataSet with items
20
+ this.groupsData = null; // DataSet with groups
21
+
22
+ this.groups = {}; // map with groups
23
+
24
+ this.dom = {};
25
+ this.props = {
26
+ labels: {
27
+ width: 0
28
+ }
29
+ };
30
+
31
+ // TODO: implement right orientation of the labels
32
+
33
+ // changes in groups are queued key/value map containing id/action
34
+ this.queue = {};
35
+
36
+ var me = this;
37
+ this.listeners = {
38
+ 'add': function (event, params) {
39
+ me._onAdd(params.items);
40
+ },
41
+ 'update': function (event, params) {
42
+ me._onUpdate(params.items);
43
+ },
44
+ 'remove': function (event, params) {
45
+ me._onRemove(params.items);
46
+ }
47
+ };
48
+ }
49
+
50
+ GroupSet.prototype = new Panel();
51
+
52
+ /**
53
+ * Set options for the GroupSet. Existing options will be extended/overwritten.
54
+ * @param {Object} [options] The following options are available:
55
+ * {String | function} groupsOrder
56
+ * TODO: describe options
57
+ */
58
+ GroupSet.prototype.setOptions = Component.prototype.setOptions;
59
+
60
+ GroupSet.prototype.setRange = function (range) {
61
+ // TODO: implement setRange
62
+ };
63
+
64
+ /**
65
+ * Set items
66
+ * @param {vis.DataSet | null} items
67
+ */
68
+ GroupSet.prototype.setItems = function setItems(items) {
69
+ this.itemsData = items;
70
+
71
+ for (var id in this.groups) {
72
+ if (this.groups.hasOwnProperty(id)) {
73
+ var group = this.groups[id];
74
+ group.setItems(items);
75
+ }
76
+ }
77
+ };
78
+
79
+ /**
80
+ * Get items
81
+ * @return {vis.DataSet | null} items
82
+ */
83
+ GroupSet.prototype.getItems = function getItems() {
84
+ return this.itemsData;
85
+ };
86
+
87
+ /**
88
+ * Set range (start and end).
89
+ * @param {Range | Object} range A Range or an object containing start and end.
90
+ */
91
+ GroupSet.prototype.setRange = function setRange(range) {
92
+ this.range = range;
93
+ };
94
+
95
+ /**
96
+ * Set groups
97
+ * @param {vis.DataSet} groups
98
+ */
99
+ GroupSet.prototype.setGroups = function setGroups(groups) {
100
+ var me = this,
101
+ ids;
102
+
103
+ // unsubscribe from current dataset
104
+ if (this.groupsData) {
105
+ util.forEach(this.listeners, function (callback, event) {
106
+ me.groupsData.unsubscribe(event, callback);
107
+ });
108
+
109
+ // remove all drawn groups
110
+ ids = this.groupsData.getIds();
111
+ this._onRemove(ids);
112
+ }
113
+
114
+ // replace the dataset
115
+ if (!groups) {
116
+ this.groupsData = null;
117
+ }
118
+ else if (groups instanceof DataSet) {
119
+ this.groupsData = groups;
120
+ }
121
+ else {
122
+ this.groupsData = new DataSet({
123
+ convert: {
124
+ start: 'Date',
125
+ end: 'Date'
126
+ }
127
+ });
128
+ this.groupsData.add(groups);
129
+ }
130
+
131
+ if (this.groupsData) {
132
+ // subscribe to new dataset
133
+ var id = this.id;
134
+ util.forEach(this.listeners, function (callback, event) {
135
+ me.groupsData.subscribe(event, callback, id);
136
+ });
137
+
138
+ // draw all new groups
139
+ ids = this.groupsData.getIds();
140
+ this._onAdd(ids);
141
+ }
142
+ };
143
+
144
+ /**
145
+ * Get groups
146
+ * @return {vis.DataSet | null} groups
147
+ */
148
+ GroupSet.prototype.getGroups = function getGroups() {
149
+ return this.groupsData;
150
+ };
151
+
152
+ /**
153
+ * Set selected items by their id. Replaces the current selection.
154
+ * Unknown id's are silently ignored.
155
+ * @param {Array} [ids] An array with zero or more id's of the items to be
156
+ * selected. If ids is an empty array, all items will be
157
+ * unselected.
158
+ */
159
+ GroupSet.prototype.setSelection = function setSelection(ids) {
160
+ var selection = [],
161
+ groups = this.groups;
162
+
163
+ // iterate over each of the groups
164
+ for (var id in groups) {
165
+ if (groups.hasOwnProperty(id)) {
166
+ var group = groups[id];
167
+ group.setSelection(ids);
168
+ }
169
+ }
170
+
171
+ return selection;
172
+ };
173
+
174
+ /**
175
+ * Get the selected items by their id
176
+ * @return {Array} ids The ids of the selected items
177
+ */
178
+ GroupSet.prototype.getSelection = function getSelection() {
179
+ var selection = [],
180
+ groups = this.groups;
181
+
182
+ // iterate over each of the groups
183
+ for (var id in groups) {
184
+ if (groups.hasOwnProperty(id)) {
185
+ var group = groups[id];
186
+ selection = selection.concat(group.getSelection());
187
+ }
188
+ }
189
+
190
+ return selection;
191
+ };
192
+
193
+ /**
194
+ * Repaint the component
195
+ * @return {Boolean} changed
196
+ */
197
+ GroupSet.prototype.repaint = function repaint() {
198
+ var changed = 0,
199
+ i, id, group, label,
200
+ update = util.updateProperty,
201
+ asSize = util.option.asSize,
202
+ asElement = util.option.asElement,
203
+ options = this.options,
204
+ frame = this.dom.frame,
205
+ labels = this.dom.labels,
206
+ labelSet = this.dom.labelSet;
207
+
208
+ // create frame
209
+ if (!this.parent) {
210
+ throw new Error('Cannot repaint groupset: no parent attached');
211
+ }
212
+ var parentContainer = this.parent.getContainer();
213
+ if (!parentContainer) {
214
+ throw new Error('Cannot repaint groupset: parent has no container element');
215
+ }
216
+ if (!frame) {
217
+ frame = document.createElement('div');
218
+ frame.className = 'groupset';
219
+ this.dom.frame = frame;
220
+
221
+ var className = options.className;
222
+ if (className) {
223
+ util.addClassName(frame, util.option.asString(className));
224
+ }
225
+
226
+ changed += 1;
227
+ }
228
+ if (!frame.parentNode) {
229
+ parentContainer.appendChild(frame);
230
+ changed += 1;
231
+ }
232
+
233
+ // create labels
234
+ var labelContainer = asElement(options.labelContainer);
235
+ if (!labelContainer) {
236
+ throw new Error('Cannot repaint groupset: option "labelContainer" not defined');
237
+ }
238
+ if (!labels) {
239
+ labels = document.createElement('div');
240
+ labels.className = 'labels';
241
+ this.dom.labels = labels;
242
+ }
243
+ if (!labelSet) {
244
+ labelSet = document.createElement('div');
245
+ labelSet.className = 'label-set';
246
+ labels.appendChild(labelSet);
247
+ this.dom.labelSet = labelSet;
248
+ }
249
+ if (!labels.parentNode || labels.parentNode != labelContainer) {
250
+ if (labels.parentNode) {
251
+ labels.parentNode.removeChild(labels.parentNode);
252
+ }
253
+ labelContainer.appendChild(labels);
254
+ }
255
+
256
+ // reposition frame
257
+ changed += update(frame.style, 'height', asSize(options.height, this.height + 'px'));
258
+ changed += update(frame.style, 'top', asSize(options.top, '0px'));
259
+ changed += update(frame.style, 'left', asSize(options.left, '0px'));
260
+ changed += update(frame.style, 'width', asSize(options.width, '100%'));
261
+
262
+ // reposition labels
263
+ changed += update(labelSet.style, 'top', asSize(options.top, '0px'));
264
+ changed += update(labelSet.style, 'height', asSize(options.height, this.height + 'px'));
265
+
266
+ var me = this,
267
+ queue = this.queue,
268
+ groups = this.groups,
269
+ groupsData = this.groupsData;
270
+
271
+ // show/hide added/changed/removed groups
272
+ var ids = Object.keys(queue);
273
+ if (ids.length) {
274
+ ids.forEach(function (id) {
275
+ var action = queue[id];
276
+ var group = groups[id];
277
+
278
+ //noinspection FallthroughInSwitchStatementJS
279
+ switch (action) {
280
+ case 'add':
281
+ case 'update':
282
+ if (!group) {
283
+ var groupOptions = Object.create(me.options);
284
+ util.extend(groupOptions, {
285
+ height: null,
286
+ maxHeight: null
287
+ });
288
+
289
+ group = new Group(me, id, groupOptions);
290
+ group.setItems(me.itemsData); // attach items data
291
+ groups[id] = group;
292
+
293
+ me.controller.add(group);
294
+ }
295
+
296
+ // TODO: update group data
297
+ group.data = groupsData.get(id);
298
+
299
+ delete queue[id];
300
+ break;
301
+
302
+ case 'remove':
303
+ if (group) {
304
+ group.setItems(); // detach items data
305
+ delete groups[id];
306
+
307
+ me.controller.remove(group);
308
+ }
309
+
310
+ // update lists
311
+ delete queue[id];
312
+ break;
313
+
314
+ default:
315
+ console.log('Error: unknown action "' + action + '"');
316
+ }
317
+ });
318
+
319
+ // the groupset depends on each of the groups
320
+ //this.depends = this.groups; // TODO: gives a circular reference through the parent
321
+
322
+ // TODO: apply dependencies of the groupset
323
+
324
+ // update the top positions of the groups in the correct order
325
+ var orderedGroups = this.groupsData.getIds({
326
+ order: this.options.groupOrder
327
+ });
328
+ for (i = 0; i < orderedGroups.length; i++) {
329
+ (function (group, prevGroup) {
330
+ var top = 0;
331
+ if (prevGroup) {
332
+ top = function () {
333
+ // TODO: top must reckon with options.maxHeight
334
+ return prevGroup.top + prevGroup.height;
335
+ }
336
+ }
337
+ group.setOptions({
338
+ top: top
339
+ });
340
+ })(groups[orderedGroups[i]], groups[orderedGroups[i - 1]]);
341
+ }
342
+
343
+ // (re)create the labels
344
+ while (labelSet.firstChild) {
345
+ labelSet.removeChild(labelSet.firstChild);
346
+ }
347
+ for (i = 0; i < orderedGroups.length; i++) {
348
+ id = orderedGroups[i];
349
+ label = this._createLabel(id);
350
+ labelSet.appendChild(label);
351
+ }
352
+
353
+ changed++;
354
+ }
355
+
356
+ // reposition the labels
357
+ // TODO: labels are not displayed correctly when orientation=='top'
358
+ // TODO: width of labelPanel is not immediately updated on a change in groups
359
+ for (id in groups) {
360
+ if (groups.hasOwnProperty(id)) {
361
+ group = groups[id];
362
+ label = group.label;
363
+ if (label) {
364
+ label.style.top = group.top + 'px';
365
+ label.style.height = group.height + 'px';
366
+ }
367
+ }
368
+ }
369
+
370
+ return (changed > 0);
371
+ };
372
+
373
+ /**
374
+ * Create a label for group with given id
375
+ * @param {Number} id
376
+ * @return {Element} label
377
+ * @private
378
+ */
379
+ GroupSet.prototype._createLabel = function(id) {
380
+ var group = this.groups[id];
381
+ var label = document.createElement('div');
382
+ label.className = 'label';
383
+ var inner = document.createElement('div');
384
+ inner.className = 'inner';
385
+ label.appendChild(inner);
386
+
387
+ var content = group.data && group.data.content;
388
+ if (content instanceof Element) {
389
+ inner.appendChild(content);
390
+ }
391
+ else if (content != undefined) {
392
+ inner.innerHTML = content;
393
+ }
394
+
395
+ var className = group.data && group.data.className;
396
+ if (className) {
397
+ util.addClassName(label, className);
398
+ }
399
+
400
+ group.label = label; // TODO: not so nice, parking labels in the group this way!!!
401
+
402
+ return label;
403
+ };
404
+
405
+ /**
406
+ * Get container element
407
+ * @return {HTMLElement} container
408
+ */
409
+ GroupSet.prototype.getContainer = function getContainer() {
410
+ return this.dom.frame;
411
+ };
412
+
413
+ /**
414
+ * Get the width of the group labels
415
+ * @return {Number} width
416
+ */
417
+ GroupSet.prototype.getLabelsWidth = function getContainer() {
418
+ return this.props.labels.width;
419
+ };
420
+
421
+ /**
422
+ * Reflow the component
423
+ * @return {Boolean} resized
424
+ */
425
+ GroupSet.prototype.reflow = function reflow() {
426
+ var changed = 0,
427
+ id, group,
428
+ options = this.options,
429
+ update = util.updateProperty,
430
+ asNumber = util.option.asNumber,
431
+ asSize = util.option.asSize,
432
+ frame = this.dom.frame;
433
+
434
+ if (frame) {
435
+ var maxHeight = asNumber(options.maxHeight);
436
+ var fixedHeight = (asSize(options.height) != null);
437
+ var height;
438
+ if (fixedHeight) {
439
+ height = frame.offsetHeight;
440
+ }
441
+ else {
442
+ // height is not specified, calculate the sum of the height of all groups
443
+ height = 0;
444
+
445
+ for (id in this.groups) {
446
+ if (this.groups.hasOwnProperty(id)) {
447
+ group = this.groups[id];
448
+ height += group.height;
449
+ }
450
+ }
451
+ }
452
+ if (maxHeight != null) {
453
+ height = Math.min(height, maxHeight);
454
+ }
455
+ changed += update(this, 'height', height);
456
+
457
+ changed += update(this, 'top', frame.offsetTop);
458
+ changed += update(this, 'left', frame.offsetLeft);
459
+ changed += update(this, 'width', frame.offsetWidth);
460
+ }
461
+
462
+ // calculate the maximum width of the labels
463
+ var width = 0;
464
+ for (id in this.groups) {
465
+ if (this.groups.hasOwnProperty(id)) {
466
+ group = this.groups[id];
467
+ var labelWidth = group.props && group.props.label && group.props.label.width || 0;
468
+ width = Math.max(width, labelWidth);
469
+ }
470
+ }
471
+ changed += update(this.props.labels, 'width', width);
472
+
473
+ return (changed > 0);
474
+ };
475
+
476
+ /**
477
+ * Hide the component from the DOM
478
+ * @return {Boolean} changed
479
+ */
480
+ GroupSet.prototype.hide = function hide() {
481
+ if (this.dom.frame && this.dom.frame.parentNode) {
482
+ this.dom.frame.parentNode.removeChild(this.dom.frame);
483
+ return true;
484
+ }
485
+ else {
486
+ return false;
487
+ }
488
+ };
489
+
490
+ /**
491
+ * Show the component in the DOM (when not already visible).
492
+ * A repaint will be executed when the component is not visible
493
+ * @return {Boolean} changed
494
+ */
495
+ GroupSet.prototype.show = function show() {
496
+ if (!this.dom.frame || !this.dom.frame.parentNode) {
497
+ return this.repaint();
498
+ }
499
+ else {
500
+ return false;
501
+ }
502
+ };
503
+
504
+ /**
505
+ * Handle updated groups
506
+ * @param {Number[]} ids
507
+ * @private
508
+ */
509
+ GroupSet.prototype._onUpdate = function _onUpdate(ids) {
510
+ this._toQueue(ids, 'update');
511
+ };
512
+
513
+ /**
514
+ * Handle changed groups
515
+ * @param {Number[]} ids
516
+ * @private
517
+ */
518
+ GroupSet.prototype._onAdd = function _onAdd(ids) {
519
+ this._toQueue(ids, 'add');
520
+ };
521
+
522
+ /**
523
+ * Handle removed groups
524
+ * @param {Number[]} ids
525
+ * @private
526
+ */
527
+ GroupSet.prototype._onRemove = function _onRemove(ids) {
528
+ this._toQueue(ids, 'remove');
529
+ };
530
+
531
+ /**
532
+ * Put groups in the queue to be added/updated/remove
533
+ * @param {Number[]} ids
534
+ * @param {String} action can be 'add', 'update', 'remove'
535
+ */
536
+ GroupSet.prototype._toQueue = function _toQueue(ids, action) {
537
+ var queue = this.queue;
538
+ ids.forEach(function (id) {
539
+ queue[id] = action;
540
+ });
541
+
542
+ if (this.controller) {
543
+ //this.requestReflow();
544
+ this.requestRepaint();
545
+ }
546
+ };