vis-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ };