var Hammer = require('../../module/hammer'); var util = require('../../util'); var Component = require('./Component'); var moment = require('../../module/moment'); var locales = require('../locales'); /** * A custom time bar * @param {{range: Range, dom: Object}} body * @param {Object} [options] Available parameters: * {Boolean} [showCustomTime] * @constructor CustomTime * @extends Component */ function CustomTime (body, options) { this.body = body; // default options this.defaultOptions = { showCustomTime: false, locales: locales, locale: 'en', id: 0 }; this.options = util.extend({}, this.defaultOptions); if (options && options.time) { this.customTime = options.time; } else { this.customTime = new Date(); } this.eventParams = {}; // stores state parameters while dragging the bar // create the DOM this._create(); this.setOptions(options); } CustomTime.prototype = new Component(); /** * Set options for the component. Options will be merged in current options. * @param {Object} options Available parameters: * {boolean} [showCustomTime] */ CustomTime.prototype.setOptions = function(options) { if (options) { // copy all options that we know util.selectiveExtend(['showCustomTime', 'locale', 'locales', 'id'], this.options, options); // Triggered by addCustomTimeBar, redraw to add new bar if (this.options.id) { this.redraw(); } } }; /** * Create the DOM for the custom time * @private */ CustomTime.prototype._create = function() { var bar = document.createElement('div'); bar.className = 'vis-custom-time'; bar.style.position = 'absolute'; bar.style.top = '0px'; bar.style.height = '100%'; this.bar = bar; var drag = document.createElement('div'); drag.style.position = 'relative'; drag.style.top = '0px'; drag.style.left = '-10px'; drag.style.height = '100%'; drag.style.width = '20px'; bar.appendChild(drag); // attach event listeners this.hammer = new Hammer(drag); this.hammer.on('panstart', this._onDragStart.bind(this)); this.hammer.on('panmove', this._onDrag.bind(this)); this.hammer.on('panend', this._onDragEnd.bind(this)); // TODO: cleanup //this.hammer.on('pan', function (event) { // event.preventDefault(); //}); }; /** * Destroy the CustomTime bar */ CustomTime.prototype.destroy = function () { this.options.showCustomTime = false; this.redraw(); // will remove the bar from the DOM this.hammer.enable(false); this.hammer = null; this.body = null; }; /** * Repaint the component * @return {boolean} Returns true if the component is resized */ CustomTime.prototype.redraw = function () { if (this.options.showCustomTime) { var parent = this.body.dom.backgroundVertical; if (this.bar.parentNode != parent) { // attach to the dom if (this.bar.parentNode) { this.bar.parentNode.removeChild(this.bar); } parent.appendChild(this.bar); } var x = this.body.util.toScreen(this.customTime); var locale = this.options.locales[this.options.locale]; if (!locale) { if (!this.warned) { console.log('WARNING: options.locales[\'' + this.options.locale + '\'] not found. See http://visjs.org/docs/timeline.html#Localization'); this.warned = true; } locale = this.options.locales['en']; // fall back on english when not available } var title = locale.time + ': ' + moment(this.customTime).format('dddd, MMMM Do YYYY, H:mm:ss'); title = title.charAt(0).toUpperCase() + title.substring(1); this.bar.style.left = x + 'px'; this.bar.title = title; } else { // remove the line from the DOM if (this.bar.parentNode) { this.bar.parentNode.removeChild(this.bar); } } return false; }; /** * Set custom time. * @param {Date | number | string} time */ CustomTime.prototype.setCustomTime = function(time) { this.customTime = util.convert(time, 'Date'); this.redraw(); }; /** * Retrieve the current custom time. * @return {Date} customTime */ CustomTime.prototype.getCustomTime = function() { return new Date(this.customTime.valueOf()); }; /** * Start moving horizontally * @param {Event} event * @private */ CustomTime.prototype._onDragStart = function(event) { this.eventParams.dragging = true; this.eventParams.customTime = this.customTime; event.stopPropagation(); }; /** * Perform moving operating. * @param {Event} event * @private */ CustomTime.prototype._onDrag = function (event) { if (!this.eventParams.dragging) return; var x = this.body.util.toScreen(this.eventParams.customTime) + event.deltaX; var time = this.body.util.toTime(x); this.setCustomTime(time); // fire a timechange event this.body.emitter.emit('timechange', { id: this.options.id, time: new Date(this.customTime.valueOf()) }); event.stopPropagation(); }; /** * Stop moving operating. * @param {Event} event * @private */ CustomTime.prototype._onDragEnd = function (event) { if (!this.eventParams.dragging) return; // fire a timechanged event this.body.emitter.emit('timechanged', { id: this.options.id, time: new Date(this.customTime.valueOf()) }); event.stopPropagation(); }; module.exports = CustomTime;