vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
5.1 KiB

12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
  1. /**
  2. * Create a timeline visualization
  3. * @param {HTMLElement} container
  4. * @param {DataSet | Array | DataTable} [data]
  5. * @param {Object} [options] See Timeline.setOptions for the available options.
  6. * @constructor
  7. */
  8. function Timeline (container, data, options) {
  9. var me = this;
  10. this.options = {
  11. orientation: 'bottom',
  12. zoomMin: 10, // milliseconds
  13. zoomMax: 1000 * 60 * 60 * 24 * 365 * 10000, // milliseconds
  14. moveable: true,
  15. zoomable: true
  16. };
  17. // controller
  18. this.controller = new Controller();
  19. // main panel
  20. if (!container) {
  21. throw new Error('No container element provided');
  22. }
  23. this.main = new RootPanel(container, {
  24. autoResize: false
  25. });
  26. this.controller.add(this.main);
  27. // range
  28. var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0);
  29. this.range = new Range({
  30. start: now.clone().add('days', -3).valueOf(),
  31. end: now.clone().add('days', 4).valueOf()
  32. });
  33. // TODO: reckon with options moveable and zoomable
  34. this.range.subscribe(this.main, 'move', 'horizontal');
  35. this.range.subscribe(this.main, 'zoom', 'horizontal');
  36. this.range.on('rangechange', function () {
  37. var force = true;
  38. me.controller.requestReflow(force);
  39. });
  40. this.range.on('rangechanged', function () {
  41. var force = true;
  42. me.controller.requestReflow(force);
  43. });
  44. // TODO: put the listeners in setOptions, be able to dynamically change with options moveable and zoomable
  45. // time axis
  46. this.timeaxis = new TimeAxis(this.main, [], {
  47. orientation: this.options.orientation,
  48. range: this.range
  49. });
  50. this.timeaxis.setRange(this.range);
  51. this.controller.add(this.timeaxis);
  52. // items panel
  53. this.itemset = new ItemSet(this.main, [this.timeaxis], {
  54. orientation: this.options.orientation
  55. });
  56. this.itemset.setRange(this.range);
  57. this.controller.add(this.itemset);
  58. // set options (must take place before setting the data)
  59. this.setOptions(options);
  60. // set data
  61. if (data) {
  62. this.setData(data);
  63. }
  64. }
  65. /**
  66. * Set options
  67. * @param {Object} options TODO: describe the available options
  68. */
  69. Timeline.prototype.setOptions = function (options) {
  70. util.extend(this.options, options);
  71. // update options the timeaxis
  72. this.timeaxis.setOptions(this.options);
  73. // update options for the range
  74. this.range.setOptions(this.options);
  75. // update options the itemset
  76. var itemsTop,
  77. itemsHeight,
  78. mainHeight,
  79. maxHeight,
  80. me = this;
  81. if (this.options.orientation == 'top') {
  82. itemsTop = function () {
  83. return me.timeaxis.height;
  84. }
  85. }
  86. else {
  87. itemsTop = function () {
  88. return me.main.height - me.timeaxis.height - me.itemset.height;
  89. }
  90. }
  91. if (options.height) {
  92. // fixed height
  93. mainHeight = options.height;
  94. itemsHeight = function () {
  95. return me.main.height - me.timeaxis.height;
  96. };
  97. }
  98. else {
  99. // auto height
  100. mainHeight = function () {
  101. return me.timeaxis.height + me.itemset.height;
  102. };
  103. itemsHeight = null;
  104. }
  105. // TODO: maxHeight should be a string in px or % (currently only accepts a number)
  106. if (this.options.maxHeight) {
  107. if (!util.isNumber(this.options.maxHeight)) {
  108. throw new TypeError('Number expected for property maxHeight');
  109. }
  110. maxHeight = function () {
  111. return me.options.maxHeight - me.timeaxis.height;
  112. }
  113. }
  114. this.main.setOptions({
  115. height: mainHeight
  116. });
  117. this.itemset.setOptions({
  118. orientation: this.options.orientation,
  119. top: itemsTop,
  120. height: itemsHeight,
  121. maxHeight: maxHeight
  122. });
  123. this.controller.repaint();
  124. };
  125. /**
  126. * Set data
  127. * @param {DataSet | Array | DataTable} data
  128. */
  129. Timeline.prototype.setData = function(data) {
  130. var dataset = this.itemset.data;
  131. if (!dataset) {
  132. // first load of data
  133. this.itemset.setData(data);
  134. if (this.options.start == undefined || this.options.end == undefined) {
  135. // apply the data range as range
  136. var dataRange = this.itemset.getDataRange();
  137. // add 5% on both sides
  138. var min = dataRange.min;
  139. var max = dataRange.max;
  140. if (min != null && max != null) {
  141. var interval = (max.valueOf() - min.valueOf());
  142. min = new Date(min.valueOf() - interval * 0.05);
  143. max = new Date(max.valueOf() + interval * 0.05);
  144. }
  145. // override specified start and/or end date
  146. if (this.options.start != undefined) {
  147. min = new Date(this.options.start.valueOf());
  148. }
  149. if (this.options.end != undefined) {
  150. max = new Date(this.options.end.valueOf());
  151. }
  152. // apply range if there is a min or max available
  153. if (min != null || max != null) {
  154. this.range.setRange(min, max);
  155. }
  156. }
  157. }
  158. else {
  159. // updated data
  160. this.itemset.setData(data);
  161. }
  162. };