|
|
@ -0,0 +1,255 @@ |
|
|
|
/** |
|
|
|
* A custom time bar |
|
|
|
* @param {Component} parent |
|
|
|
* @param {Component[]} [depends] Components on which this components depends |
|
|
|
* (except for the parent) |
|
|
|
* @param {Object} [options] Available parameters: |
|
|
|
* {Boolean} [showCustomTime] |
|
|
|
* @constructor CustomTime |
|
|
|
* @extends Component |
|
|
|
*/ |
|
|
|
|
|
|
|
function CustomTime (parent, depends, options) { |
|
|
|
this.id = util.randomUUID(); |
|
|
|
this.parent = parent; |
|
|
|
this.depends = depends; |
|
|
|
|
|
|
|
this.options = options || {}; |
|
|
|
this.defaultOptions = { |
|
|
|
showCustomTime: false |
|
|
|
}; |
|
|
|
|
|
|
|
this.listeners = []; |
|
|
|
this.customTime = new Date(); |
|
|
|
} |
|
|
|
|
|
|
|
CustomTime.prototype = new Component(); |
|
|
|
|
|
|
|
CustomTime.prototype.setOptions = Component.prototype.setOptions; |
|
|
|
|
|
|
|
/** |
|
|
|
* Get the container element of the bar, which can be used by a child to |
|
|
|
* add its own widgets. |
|
|
|
* @returns {HTMLElement} container |
|
|
|
*/ |
|
|
|
CustomTime.prototype.getContainer = function () { |
|
|
|
return this.frame; |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Repaint the component |
|
|
|
* @return {Boolean} changed |
|
|
|
*/ |
|
|
|
CustomTime.prototype.repaint = function () { |
|
|
|
var bar = this.frame, |
|
|
|
parent = this.parent, |
|
|
|
parentContainer = parent.parent.getContainer(); |
|
|
|
|
|
|
|
if (!parent) { |
|
|
|
throw new Error('Cannot repaint bar: no parent attached'); |
|
|
|
} |
|
|
|
|
|
|
|
if (!parentContainer) { |
|
|
|
throw new Error('Cannot repaint bar: parent has no container element'); |
|
|
|
} |
|
|
|
|
|
|
|
if (!this.getOption('showCustomTime')) { |
|
|
|
if (bar) { |
|
|
|
parentContainer.removeChild(bar); |
|
|
|
delete this.frame; |
|
|
|
} |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (!bar) { |
|
|
|
bar = document.createElement('div'); |
|
|
|
bar.className = 'customtime'; |
|
|
|
bar.style.position = 'absolute'; |
|
|
|
bar.style.top = '0px'; |
|
|
|
bar.style.height = '100%'; |
|
|
|
|
|
|
|
parentContainer.appendChild(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); |
|
|
|
|
|
|
|
this.frame = bar; |
|
|
|
|
|
|
|
this.subscribe(this, 'movetime'); |
|
|
|
} |
|
|
|
|
|
|
|
if (!parent.conversion) { |
|
|
|
parent._updateConversion(); |
|
|
|
} |
|
|
|
|
|
|
|
var x = parent.toScreen(this.customTime); |
|
|
|
|
|
|
|
bar.style.left = x + 'px'; |
|
|
|
bar.title = 'Time: ' + this.customTime; |
|
|
|
|
|
|
|
return false; |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Set custom time. |
|
|
|
* @param {Date} time |
|
|
|
*/ |
|
|
|
CustomTime.prototype._setCustomTime = function(time) { |
|
|
|
this.customTime = new Date(time.valueOf()); |
|
|
|
this.repaint(); |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Retrieve the current custom time. |
|
|
|
* @return {Date} customTime |
|
|
|
*/ |
|
|
|
CustomTime.prototype._getCustomTime = function() { |
|
|
|
return new Date(this.customTime.valueOf()); |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Add listeners for mouse and touch events to the component |
|
|
|
* @param {Component} component |
|
|
|
*/ |
|
|
|
CustomTime.prototype.subscribe = function (component, event) { |
|
|
|
var me = this; |
|
|
|
var listener = { |
|
|
|
component: component, |
|
|
|
event: event, |
|
|
|
callback: function (event) { |
|
|
|
me._onMouseDown(event, listener); |
|
|
|
}, |
|
|
|
params: {} |
|
|
|
}; |
|
|
|
|
|
|
|
component.on('mousedown', listener.callback); |
|
|
|
me.listeners.push(listener); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Event handler |
|
|
|
* @param {String} event name of the event, for example 'click', 'mousemove' |
|
|
|
* @param {function} callback callback handler, invoked with the raw HTML Event |
|
|
|
* as parameter. |
|
|
|
*/ |
|
|
|
CustomTime.prototype.on = function (event, callback) { |
|
|
|
var bar = this.frame; |
|
|
|
if (!bar) { |
|
|
|
throw new Error('Cannot add event listener: no parent attached'); |
|
|
|
} |
|
|
|
|
|
|
|
events.addListener(this, event, callback); |
|
|
|
util.addEventListener(bar, event, callback); |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Start moving horizontally |
|
|
|
* @param {Event} event |
|
|
|
* @param {Object} listener Listener containing the component and params |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
CustomTime.prototype._onMouseDown = function(event, listener) { |
|
|
|
event = event || window.event; |
|
|
|
var params = listener.params; |
|
|
|
|
|
|
|
// only react on left mouse button down
|
|
|
|
var leftButtonDown = event.which ? (event.which == 1) : (event.button == 1); |
|
|
|
if (!leftButtonDown) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// get mouse position
|
|
|
|
params.mouseX = util.getPageX(event); |
|
|
|
params.moved = false; |
|
|
|
|
|
|
|
params.customTime = this.customTime; |
|
|
|
|
|
|
|
// add event listeners to handle moving the custom time bar
|
|
|
|
var me = this; |
|
|
|
if (!params.onMouseMove) { |
|
|
|
params.onMouseMove = function (event) { |
|
|
|
me._onMouseMove(event, listener); |
|
|
|
}; |
|
|
|
util.addEventListener(document, 'mousemove', params.onMouseMove); |
|
|
|
} |
|
|
|
if (!params.onMouseUp) { |
|
|
|
params.onMouseUp = function (event) { |
|
|
|
me._onMouseUp(event, listener); |
|
|
|
}; |
|
|
|
util.addEventListener(document, 'mouseup', params.onMouseUp); |
|
|
|
} |
|
|
|
|
|
|
|
util.stopPropagation(event); |
|
|
|
util.preventDefault(event); |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Perform moving operating. |
|
|
|
* This function activated from within the funcion CustomTime._onMouseDown(). |
|
|
|
* @param {Event} event |
|
|
|
* @param {Object} listener |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
CustomTime.prototype._onMouseMove = function (event, listener) { |
|
|
|
event = event || window.event; |
|
|
|
var params = listener.params; |
|
|
|
var parent = this.parent; |
|
|
|
|
|
|
|
// calculate change in mouse position
|
|
|
|
var mouseX = util.getPageX(event); |
|
|
|
|
|
|
|
if (params.mouseX === undefined) { |
|
|
|
params.mouseX = mouseX; |
|
|
|
} |
|
|
|
|
|
|
|
var diff = mouseX - params.mouseX; |
|
|
|
|
|
|
|
// if mouse movement is big enough, register it as a "moved" event
|
|
|
|
if (Math.abs(diff) >= 1) { |
|
|
|
params.moved = true; |
|
|
|
} |
|
|
|
|
|
|
|
var x = parent.toScreen(params.customTime); |
|
|
|
var xnew = x + diff; |
|
|
|
var time = parent.toTime(xnew); |
|
|
|
this._setCustomTime(time); |
|
|
|
|
|
|
|
// fire a timechange event
|
|
|
|
events.trigger(this, 'timechange', {customTime: this.customTime}); |
|
|
|
|
|
|
|
util.preventDefault(event); |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Stop moving operating. |
|
|
|
* This function activated from within the function CustomTime._onMouseDown(). |
|
|
|
* @param {event} event |
|
|
|
* @param {Object} listener |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
CustomTime.prototype._onMouseUp = function (event, listener) { |
|
|
|
event = event || window.event; |
|
|
|
var params = listener.params; |
|
|
|
|
|
|
|
// remove event listeners here, important for Safari
|
|
|
|
if (params.onMouseMove) { |
|
|
|
util.removeEventListener(document, 'mousemove', params.onMouseMove); |
|
|
|
params.onMouseMove = null; |
|
|
|
} |
|
|
|
if (params.onMouseUp) { |
|
|
|
util.removeEventListener(document, 'mouseup', params.onMouseUp); |
|
|
|
params.onMouseUp = null; |
|
|
|
} |
|
|
|
|
|
|
|
if (params.moved) { |
|
|
|
// fire a timechanged event
|
|
|
|
events.trigger(this, 'timechanged', {customTime: this.customTime}); |
|
|
|
} |
|
|
|
}; |