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.

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