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.

283 lines
8.3 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. var Emitter = require('emitter-component');
  2. var Hammer = require('../module/hammer');
  3. var util = require('../util');
  4. var DataSet = require('../DataSet');
  5. var DataView = require('../DataView');
  6. var Range = require('./Range');
  7. var Core = require('./Core');
  8. var TimeAxis = require('./component/TimeAxis');
  9. var CurrentTime = require('./component/CurrentTime');
  10. var CustomTime = require('./component/CustomTime');
  11. var LineGraph = require('./component/LineGraph');
  12. /**
  13. * Create a timeline visualization
  14. * @param {HTMLElement} container
  15. * @param {vis.DataSet | Array | google.visualization.DataTable} [items]
  16. * @param {Object} [options] See Graph2d.setOptions for the available options.
  17. * @constructor
  18. * @extends Core
  19. */
  20. function Graph2d (container, items, options, groups) {
  21. var me = this;
  22. this.defaultOptions = {
  23. start: null,
  24. end: null,
  25. autoResize: true,
  26. orientation: 'bottom',
  27. width: null,
  28. height: null,
  29. maxHeight: null,
  30. minHeight: null
  31. };
  32. this.options = util.deepExtend({}, this.defaultOptions);
  33. // Create the DOM, props, and emitter
  34. this._create(container);
  35. // all components listed here will be repainted automatically
  36. this.components = [];
  37. this.body = {
  38. dom: this.dom,
  39. domProps: this.props,
  40. emitter: {
  41. on: this.on.bind(this),
  42. off: this.off.bind(this),
  43. emit: this.emit.bind(this)
  44. },
  45. util: {
  46. snap: null, // will be specified after TimeAxis is created
  47. toScreen: me._toScreen.bind(me),
  48. toGlobalScreen: me._toGlobalScreen.bind(me), // this refers to the root.width
  49. toTime: me._toTime.bind(me),
  50. toGlobalTime : me._toGlobalTime.bind(me)
  51. }
  52. };
  53. // range
  54. this.range = new Range(this.body);
  55. this.components.push(this.range);
  56. this.body.range = this.range;
  57. // time axis
  58. this.timeAxis = new TimeAxis(this.body);
  59. this.components.push(this.timeAxis);
  60. this.body.util.snap = this.timeAxis.snap.bind(this.timeAxis);
  61. // current time bar
  62. this.currentTime = new CurrentTime(this.body);
  63. this.components.push(this.currentTime);
  64. // custom time bar
  65. // Note: time bar will be attached in this.setOptions when selected
  66. this.customTime = new CustomTime(this.body);
  67. this.components.push(this.customTime);
  68. // item set
  69. this.linegraph = new LineGraph(this.body);
  70. this.components.push(this.linegraph);
  71. this.itemsData = null; // DataSet
  72. this.groupsData = null; // DataSet
  73. // apply options
  74. if (options) {
  75. this.setOptions(options);
  76. }
  77. // IMPORTANT: THIS HAPPENS BEFORE SET ITEMS!
  78. if (groups) {
  79. this.setGroups(groups);
  80. }
  81. // create itemset
  82. if (items) {
  83. this.setItems(items);
  84. }
  85. else {
  86. this.redraw();
  87. }
  88. }
  89. // Extend the functionality from Core
  90. Graph2d.prototype = new Core();
  91. /**
  92. * Set options. Options will be passed to all components loaded in the Graph2d.
  93. * @param {Object} [options]
  94. * {String} orientation
  95. * Vertical orientation for the Graph2d,
  96. * can be 'bottom' (default) or 'top'.
  97. * {String | Number} width
  98. * Width for the timeline, a number in pixels or
  99. * a css string like '1000px' or '75%'. '100%' by default.
  100. * {String | Number} height
  101. * Fixed height for the Graph2d, a number in pixels or
  102. * a css string like '400px' or '75%'. If undefined,
  103. * The Graph2d will automatically size such that
  104. * its contents fit.
  105. * {String | Number} minHeight
  106. * Minimum height for the Graph2d, a number in pixels or
  107. * a css string like '400px' or '75%'.
  108. * {String | Number} maxHeight
  109. * Maximum height for the Graph2d, a number in pixels or
  110. * a css string like '400px' or '75%'.
  111. * {Number | Date | String} start
  112. * Start date for the visible window
  113. * {Number | Date | String} end
  114. * End date for the visible window
  115. */
  116. Graph2d.prototype.setOptions = function (options) {
  117. if (options) {
  118. // copy the known options
  119. var fields = ['width', 'height', 'minHeight', 'maxHeight', 'autoResize', 'start', 'end', 'orientation'];
  120. util.selectiveExtend(fields, this.options, options);
  121. // enable/disable autoResize
  122. this._initAutoResize();
  123. }
  124. // propagate options to all components
  125. this.components.forEach(function (component) {
  126. component.setOptions(options);
  127. });
  128. // TODO: remove deprecation error one day (deprecated since version 0.8.0)
  129. if (options && options.order) {
  130. throw new Error('Option order is deprecated. There is no replacement for this feature.');
  131. }
  132. // redraw everything
  133. this.redraw();
  134. };
  135. /**
  136. * Set items
  137. * @param {vis.DataSet | Array | google.visualization.DataTable | null} items
  138. */
  139. Graph2d.prototype.setItems = function(items) {
  140. var initialLoad = (this.itemsData == null);
  141. // convert to type DataSet when needed
  142. var newDataSet;
  143. if (!items) {
  144. newDataSet = null;
  145. }
  146. else if (items instanceof DataSet || items instanceof DataView) {
  147. newDataSet = items;
  148. }
  149. else {
  150. // turn an array into a dataset
  151. newDataSet = new DataSet(items, {
  152. type: {
  153. start: 'Date',
  154. end: 'Date'
  155. }
  156. });
  157. }
  158. // set items
  159. this.itemsData = newDataSet;
  160. this.linegraph && this.linegraph.setItems(newDataSet);
  161. if (initialLoad && ('start' in this.options || 'end' in this.options)) {
  162. this.fit();
  163. var start = ('start' in this.options) ? util.convert(this.options.start, 'Date') : null;
  164. var end = ('end' in this.options) ? util.convert(this.options.end, 'Date') : null;
  165. this.setWindow(start, end);
  166. }
  167. };
  168. /**
  169. * Set groups
  170. * @param {vis.DataSet | Array | google.visualization.DataTable} groups
  171. */
  172. Graph2d.prototype.setGroups = function(groups) {
  173. // convert to type DataSet when needed
  174. var newDataSet;
  175. if (!groups) {
  176. newDataSet = null;
  177. }
  178. else if (groups instanceof DataSet || groups instanceof DataView) {
  179. newDataSet = groups;
  180. }
  181. else {
  182. // turn an array into a dataset
  183. newDataSet = new DataSet(groups);
  184. }
  185. this.groupsData = newDataSet;
  186. this.linegraph.setGroups(newDataSet);
  187. };
  188. /**
  189. * Returns an object containing an SVG element with the icon of the group (size determined by iconWidth and iconHeight), the label of the group (content) and the yAxisOrientation of the group (left or right).
  190. * @param groupId
  191. * @param width
  192. * @param height
  193. */
  194. Graph2d.prototype.getLegend = function(groupId, width, height) {
  195. if (width === undefined) {width = 15;}
  196. if (height === undefined) {height = 15;}
  197. if (this.linegraph.groups[groupId] !== undefined) {
  198. return this.linegraph.groups[groupId].getLegend(width,height);
  199. }
  200. else {
  201. return "cannot find group:" + groupId;
  202. }
  203. }
  204. /**
  205. * This checks if the visible option of the supplied group (by ID) is true or false.
  206. * @param groupId
  207. * @returns {*}
  208. */
  209. Graph2d.prototype.isGroupVisible = function(groupId) {
  210. if (this.linegraph.groups[groupId] !== undefined) {
  211. return this.linegraph.groups[groupId].visible;
  212. }
  213. else {
  214. return false;
  215. }
  216. }
  217. /**
  218. * Get the data range of the item set.
  219. * @returns {{min: Date, max: Date}} range A range with a start and end Date.
  220. * When no minimum is found, min==null
  221. * When no maximum is found, max==null
  222. */
  223. Graph2d.prototype.getItemRange = function() {
  224. var min = null;
  225. var max = null;
  226. // calculate min from start filed
  227. for (var groupId in this.linegraph.groups) {
  228. if (this.linegraph.groups.hasOwnProperty(groupId)) {
  229. if (this.linegraph.groups[groupId].visible == true) {
  230. for (var i = 0; i < this.linegraph.groups[groupId].itemsData.length; i++) {
  231. var item = this.linegraph.groups[groupId].itemsData[i];
  232. var value = util.convert(item.x, 'Date').valueOf();
  233. min = min == null ? value : min > value ? value : min;
  234. max = max == null ? value : max < value ? value : max;
  235. }
  236. }
  237. }
  238. }
  239. return {
  240. min: (min != null) ? new Date(min) : null,
  241. max: (max != null) ? new Date(max) : null
  242. };
  243. };
  244. module.exports = Graph2d;