var util = require('../../util'); var Component = require('./Component'); var moment = require('../../module/moment'); var locales = require('../locales'); /** * A current time bar * @param {{range: Range, dom: Object, domProps: Object}} body * @param {Object} [options] Available parameters: * {Boolean} [showCurrentTime] * @constructor CurrentTime * @extends Component */ function CurrentTime (body, options) { this.body = body; // default options this.defaultOptions = { showCurrentTime: true, moment: moment, locales: locales, locale: 'en' }; this.options = util.extend({}, this.defaultOptions); this.offset = 0; this._create(); this.setOptions(options); } CurrentTime.prototype = new Component(); /** * Create the HTML DOM for the current time bar * @private */ CurrentTime.prototype._create = function() { var bar = document.createElement('div'); bar.className = 'vis-current-time'; bar.style.position = 'absolute'; bar.style.top = '0px'; bar.style.height = '100%'; this.bar = bar; }; /** * Destroy the CurrentTime bar */ CurrentTime.prototype.destroy = function () { this.options.showCurrentTime = false; this.redraw(); // will remove the bar from the DOM and stop refreshing this.body = null; }; /** * Set options for the component. Options will be merged in current options. * @param {Object} options Available parameters: * {boolean} [showCurrentTime] */ CurrentTime.prototype.setOptions = function(options) { if (options) { // copy all options that we know util.selectiveExtend(['showCurrentTime', 'moment', 'locale', 'locales'], this.options, options); } }; /** * Repaint the component * @return {boolean} Returns true if the component is resized */ CurrentTime.prototype.redraw = function() { if (this.options.showCurrentTime) { 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); this.start(); } var now = this.options.moment(new Date().valueOf() + this.offset); var x = this.body.util.toScreen(now); 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/#Localization'); this.warned = true; } locale = this.options.locales['en']; // fall back on english when not available } var title = locale.current + ' ' + locale.time + ': ' + now.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); } this.stop(); } return false; }; /** * Start auto refreshing the current time bar */ CurrentTime.prototype.start = function() { var me = this; function update () { me.stop(); // determine interval to refresh var scale = me.body.range.conversion(me.body.domProps.center.width).scale; var interval = 1 / scale / 10; if (interval < 30) interval = 30; if (interval > 1000) interval = 1000; me.redraw(); me.body.emitter.emit('currentTimeTick'); // start a renderTimer to adjust for the new time me.currentTimeTimer = setTimeout(update, interval); } update(); }; /** * Stop auto refreshing the current time bar */ CurrentTime.prototype.stop = function() { if (this.currentTimeTimer !== undefined) { clearTimeout(this.currentTimeTimer); delete this.currentTimeTimer; } }; /** * Set a current time. This can be used for example to ensure that a client's * time is synchronized with a shared server time. * @param {Date | String | Number} time A Date, unix timestamp, or * ISO date string. */ CurrentTime.prototype.setCurrentTime = function(time) { var t = util.convert(time, 'Date').valueOf(); var now = new Date().valueOf(); this.offset = t - now; this.redraw(); }; /** * Get the current time. * @return {Date} Returns the current time. */ CurrentTime.prototype.getCurrentTime = function() { return new Date(new Date().valueOf() + this.offset); }; module.exports = CurrentTime;