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.

231 lines
5.7 KiB

  1. var Hammer = require('../../module/hammer');
  2. var util = require('../../util');
  3. var Component = require('./Component');
  4. var moment = require('../../module/moment');
  5. var locales = require('../locales');
  6. /**
  7. * A custom time bar
  8. * @param {{range: Range, dom: Object}} body
  9. * @param {Object} [options] Available parameters:
  10. * {number | string} id
  11. * {string} locales
  12. * {string} locale
  13. * @constructor CustomTime
  14. * @extends Component
  15. */
  16. function CustomTime (body, options) {
  17. this.body = body;
  18. // default options
  19. this.defaultOptions = {
  20. moment: moment,
  21. locales: locales,
  22. locale: 'en',
  23. id: undefined
  24. };
  25. this.options = util.extend({}, this.defaultOptions);
  26. if (options && options.time) {
  27. this.customTime = options.time;
  28. } else {
  29. this.customTime = new Date();
  30. }
  31. this.eventParams = {}; // stores state parameters while dragging the bar
  32. this.setOptions(options);
  33. // create the DOM
  34. this._create();
  35. }
  36. CustomTime.prototype = new Component();
  37. /**
  38. * Set options for the component. Options will be merged in current options.
  39. * @param {Object} options Available parameters:
  40. * {number | string} id
  41. * {string} locales
  42. * {string} locale
  43. */
  44. CustomTime.prototype.setOptions = function(options) {
  45. if (options) {
  46. // copy all options that we know
  47. util.selectiveExtend(['moment', 'locale', 'locales', 'id'], this.options, options);
  48. }
  49. };
  50. /**
  51. * Create the DOM for the custom time
  52. * @private
  53. */
  54. CustomTime.prototype._create = function() {
  55. var bar = document.createElement('div');
  56. bar['custom-time'] = this;
  57. bar.className = 'vis-custom-time ' + (this.options.id || '');
  58. bar.style.position = 'absolute';
  59. bar.style.top = '0px';
  60. bar.style.height = '100%';
  61. this.bar = bar;
  62. var drag = document.createElement('div');
  63. drag.style.position = 'relative';
  64. drag.style.top = '0px';
  65. drag.style.left = '-10px';
  66. drag.style.height = '100%';
  67. drag.style.width = '20px';
  68. bar.appendChild(drag);
  69. // attach event listeners
  70. this.hammer = new Hammer(drag);
  71. this.hammer.on('panstart', this._onDragStart.bind(this));
  72. this.hammer.on('panmove', this._onDrag.bind(this));
  73. this.hammer.on('panend', this._onDragEnd.bind(this));
  74. this.hammer.get('pan').set({threshold:5, direction:30}); // 30 is ALL_DIRECTIONS in hammer.
  75. };
  76. /**
  77. * Destroy the CustomTime bar
  78. */
  79. CustomTime.prototype.destroy = function () {
  80. this.hide();
  81. this.hammer.destroy();
  82. this.hammer = null;
  83. this.body = null;
  84. };
  85. /**
  86. * Repaint the component
  87. * @return {boolean} Returns true if the component is resized
  88. */
  89. CustomTime.prototype.redraw = function () {
  90. var parent = this.body.dom.backgroundVertical;
  91. if (this.bar.parentNode != parent) {
  92. // attach to the dom
  93. if (this.bar.parentNode) {
  94. this.bar.parentNode.removeChild(this.bar);
  95. }
  96. parent.appendChild(this.bar);
  97. }
  98. var x = this.body.util.toScreen(this.customTime);
  99. var locale = this.options.locales[this.options.locale];
  100. if (!locale) {
  101. if (!this.warned) {
  102. console.log('WARNING: options.locales[\'' + this.options.locale + '\'] not found. See http://visjs.org/docs/timeline.html#Localization');
  103. this.warned = true;
  104. }
  105. locale = this.options.locales['en']; // fall back on english when not available
  106. }
  107. var title = locale.time + ': ' + this.options.moment(this.customTime).format('dddd, MMMM Do YYYY, H:mm:ss');
  108. title = title.charAt(0).toUpperCase() + title.substring(1);
  109. this.bar.style.left = x + 'px';
  110. this.bar.title = title;
  111. return false;
  112. };
  113. /**
  114. * Remove the CustomTime from the DOM
  115. */
  116. CustomTime.prototype.hide = function () {
  117. // remove the line from the DOM
  118. if (this.bar.parentNode) {
  119. this.bar.parentNode.removeChild(this.bar);
  120. }
  121. };
  122. /**
  123. * Set custom time.
  124. * @param {Date | number | string} time
  125. */
  126. CustomTime.prototype.setCustomTime = function(time) {
  127. this.customTime = util.convert(time, 'Date');
  128. this.redraw();
  129. };
  130. /**
  131. * Retrieve the current custom time.
  132. * @return {Date} customTime
  133. */
  134. CustomTime.prototype.getCustomTime = function() {
  135. return new Date(this.customTime.valueOf());
  136. };
  137. /**
  138. * Start moving horizontally
  139. * @param {Event} event
  140. * @private
  141. */
  142. CustomTime.prototype._onDragStart = function(event) {
  143. this.eventParams.dragging = true;
  144. this.eventParams.customTime = this.customTime;
  145. event.stopPropagation();
  146. };
  147. /**
  148. * Perform moving operating.
  149. * @param {Event} event
  150. * @private
  151. */
  152. CustomTime.prototype._onDrag = function (event) {
  153. if (!this.eventParams.dragging) return;
  154. var x = this.body.util.toScreen(this.eventParams.customTime) + event.deltaX;
  155. var time = this.body.util.toTime(x);
  156. this.setCustomTime(time);
  157. // fire a timechange event
  158. this.body.emitter.emit('timechange', {
  159. id: this.options.id,
  160. time: new Date(this.customTime.valueOf())
  161. });
  162. event.stopPropagation();
  163. };
  164. /**
  165. * Stop moving operating.
  166. * @param {Event} event
  167. * @private
  168. */
  169. CustomTime.prototype._onDragEnd = function (event) {
  170. if (!this.eventParams.dragging) return;
  171. // fire a timechanged event
  172. this.body.emitter.emit('timechanged', {
  173. id: this.options.id,
  174. time: new Date(this.customTime.valueOf())
  175. });
  176. event.stopPropagation();
  177. };
  178. /**
  179. * Find a custom time from an event target:
  180. * searches for the attribute 'custom-time' in the event target's element tree
  181. * @param {Event} event
  182. * @return {CustomTime | null} customTime
  183. */
  184. CustomTime.customTimeFromTarget = function(event) {
  185. var target = event.target;
  186. while (target) {
  187. if (target.hasOwnProperty('custom-time')) {
  188. return target['custom-time'];
  189. }
  190. target = target.parentNode;
  191. }
  192. return null;
  193. };
  194. module.exports = CustomTime;