@ -1,170 +0,0 @@ | |||||
/** | |||||
* A panel can contain components | |||||
* @param {Object} [options] Available parameters: | |||||
* {String | Number | function} [left] | |||||
* {String | Number | function} [top] | |||||
* {String | Number | function} [width] | |||||
* {String | Number | function} [height] | |||||
* {String | function} [className] | |||||
* @constructor Panel | |||||
* @extends Component | |||||
*/ | |||||
function Panel(options) { | |||||
this.id = util.randomUUID(); | |||||
this.parent = null; | |||||
this.childs = []; | |||||
this.options = options || {}; | |||||
// create frame | |||||
this.frame = (typeof document !== 'undefined') ? document.createElement('div') : null; | |||||
} | |||||
Panel.prototype = new Component(); | |||||
/** | |||||
* Set options. Will extend the current options. | |||||
* @param {Object} [options] Available parameters: | |||||
* {String | function} [className] | |||||
* {String | Number | function} [left] | |||||
* {String | Number | function} [top] | |||||
* {String | Number | function} [width] | |||||
* {String | Number | function} [height] | |||||
*/ | |||||
Panel.prototype.setOptions = Component.prototype.setOptions; | |||||
/** | |||||
* Get the outer frame of the panel | |||||
* @returns {HTMLElement} frame | |||||
*/ | |||||
Panel.prototype.getFrame = function () { | |||||
return this.frame; | |||||
}; | |||||
/** | |||||
* Append a child to the panel | |||||
* @param {Component} child | |||||
*/ | |||||
Panel.prototype.appendChild = function (child) { | |||||
this.childs.push(child); | |||||
child.parent = this; | |||||
// attach to the DOM | |||||
var frame = child.getFrame(); | |||||
if (frame) { | |||||
if (frame.parentNode) { | |||||
frame.parentNode.removeChild(frame); | |||||
} | |||||
this.frame.appendChild(frame); | |||||
} | |||||
}; | |||||
/** | |||||
* Insert a child to the panel | |||||
* @param {Component} child | |||||
* @param {Component} beforeChild | |||||
*/ | |||||
Panel.prototype.insertBefore = function (child, beforeChild) { | |||||
var index = this.childs.indexOf(beforeChild); | |||||
if (index != -1) { | |||||
this.childs.splice(index, 0, child); | |||||
child.parent = this; | |||||
// attach to the DOM | |||||
var frame = child.getFrame(); | |||||
if (frame) { | |||||
if (frame.parentNode) { | |||||
frame.parentNode.removeChild(frame); | |||||
} | |||||
var beforeFrame = beforeChild.getFrame(); | |||||
if (beforeFrame) { | |||||
this.frame.insertBefore(frame, beforeFrame); | |||||
} | |||||
else { | |||||
this.frame.appendChild(frame); | |||||
} | |||||
} | |||||
} | |||||
}; | |||||
/** | |||||
* Remove a child from the panel | |||||
* @param {Component} child | |||||
*/ | |||||
Panel.prototype.removeChild = function (child) { | |||||
var index = this.childs.indexOf(child); | |||||
if (index != -1) { | |||||
this.childs.splice(index, 1); | |||||
child.parent = null; | |||||
// remove from the DOM | |||||
var frame = child.getFrame(); | |||||
if (frame && frame.parentNode) { | |||||
this.frame.removeChild(frame); | |||||
} | |||||
} | |||||
}; | |||||
/** | |||||
* Test whether the panel contains given child | |||||
* @param {Component} child | |||||
*/ | |||||
Panel.prototype.hasChild = function (child) { | |||||
var index = this.childs.indexOf(child); | |||||
return (index != -1); | |||||
}; | |||||
/** | |||||
* Repaint the component | |||||
* @return {boolean} Returns true if the component was resized since previous redraw | |||||
*/ | |||||
Panel.prototype.redraw = function () { | |||||
var asString = util.option.asString, | |||||
options = this.options, | |||||
frame = this.getFrame(); | |||||
// update className | |||||
frame.className = 'vpanel' + (options.className ? (' ' + asString(options.className)) : ''); | |||||
// redraw the child components | |||||
var childsResized = this._repaintChilds(); | |||||
// update frame size | |||||
this._updateSize(); | |||||
return this._isResized() || childsResized; | |||||
}; | |||||
/** | |||||
* Repaint all childs of the panel | |||||
* @return {boolean} Returns true if the component is resized | |||||
* @private | |||||
*/ | |||||
Panel.prototype._repaintChilds = function () { | |||||
var resized = false; | |||||
for (var i = 0, ii = this.childs.length; i < ii; i++) { | |||||
resized = this.childs[i].redraw() || resized; | |||||
} | |||||
return resized; | |||||
}; | |||||
/** | |||||
* Apply the size from options to the panel, and recalculate it's actual size. | |||||
* @private | |||||
*/ | |||||
Panel.prototype._updateSize = function () { | |||||
// apply size | |||||
this.frame.style.top = util.option.asSize(this.options.top); | |||||
this.frame.style.bottom = util.option.asSize(this.options.bottom); | |||||
this.frame.style.left = util.option.asSize(this.options.left); | |||||
this.frame.style.right = util.option.asSize(this.options.right); | |||||
this.frame.style.width = util.option.asSize(this.options.width, '100%'); | |||||
this.frame.style.height = util.option.asSize(this.options.height, ''); | |||||
// get actual size | |||||
this.top = this.frame.offsetTop; | |||||
this.left = this.frame.offsetLeft; | |||||
this.width = this.frame.offsetWidth; | |||||
this.height = this.frame.offsetHeight; | |||||
}; |
@ -1,176 +0,0 @@ | |||||
/** | |||||
* A root panel can hold components. The root panel must be initialized with | |||||
* a DOM element as container. | |||||
* @param {HTMLElement} container | |||||
* @param {Object} [options] Available parameters: see RootPanel.setOptions. | |||||
* @constructor RootPanel | |||||
* @extends Panel | |||||
*/ | |||||
function RootPanel(container, options) { | |||||
this.id = util.randomUUID(); | |||||
this.container = container; | |||||
this.options = options || {}; | |||||
this.defaultOptions = { | |||||
autoResize: true | |||||
}; | |||||
// create the HTML DOM | |||||
this._create(); | |||||
// attach the root panel to the provided container | |||||
if (!this.container) throw new Error('Cannot redraw root panel: no container attached'); | |||||
this.container.appendChild(this.getFrame()); | |||||
this._initWatch(); | |||||
} | |||||
RootPanel.prototype = new Panel(); | |||||
/** | |||||
* Create the HTML DOM for the root panel | |||||
*/ | |||||
RootPanel.prototype._create = function _create() { | |||||
// create frame | |||||
this.frame = document.createElement('div'); | |||||
// create event listeners for all interesting events, these events will be | |||||
// emitted via emitter | |||||
this.hammer = Hammer(this.frame, { | |||||
prevent_default: true | |||||
}); | |||||
this.listeners = {}; | |||||
var me = this; | |||||
var events = [ | |||||
'touch', 'pinch', 'tap', 'doubletap', 'hold', | |||||
'dragstart', 'drag', 'dragend', | |||||
'mousewheel', 'DOMMouseScroll' // DOMMouseScroll is for Firefox | |||||
]; | |||||
events.forEach(function (event) { | |||||
var listener = function () { | |||||
var args = [event].concat(Array.prototype.slice.call(arguments, 0)); | |||||
me.emit.apply(me, args); | |||||
}; | |||||
me.hammer.on(event, listener); | |||||
me.listeners[event] = listener; | |||||
}); | |||||
}; | |||||
/** | |||||
* Set options. Will extend the current options. | |||||
* @param {Object} [options] Available parameters: | |||||
* {String | function} [className] | |||||
* {String | Number | function} [left] | |||||
* {String | Number | function} [top] | |||||
* {String | Number | function} [width] | |||||
* {String | Number | function} [height] | |||||
* {Boolean | function} [autoResize] | |||||
*/ | |||||
RootPanel.prototype.setOptions = function setOptions(options) { | |||||
if (options) { | |||||
util.extend(this.options, options); | |||||
this.redraw(); | |||||
this._initWatch(); | |||||
} | |||||
}; | |||||
/** | |||||
* Get the frame of the root panel | |||||
*/ | |||||
RootPanel.prototype.getFrame = function getFrame() { | |||||
return this.frame; | |||||
}; | |||||
/** | |||||
* Repaint the root panel | |||||
*/ | |||||
RootPanel.prototype.redraw = function redraw() { | |||||
// update class name | |||||
var options = this.options; | |||||
var editable = options.editable.updateTime || options.editable.updateGroup; | |||||
var className = 'vis timeline rootpanel ' + options.orientation + (editable ? ' editable' : ''); | |||||
if (options.className) className += ' ' + util.option.asString(className); | |||||
this.frame.className = className; | |||||
// redraw the child components | |||||
var childsResized = this._repaintChilds(); | |||||
// update frame size | |||||
this.frame.style.maxHeight = util.option.asSize(this.options.maxHeight, ''); | |||||
this.frame.style.minHeight = util.option.asSize(this.options.minHeight, ''); | |||||
this._updateSize(); | |||||
// if the root panel or any of its childs is resized, redraw again, | |||||
// as other components may need to be resized accordingly | |||||
var resized = this._isResized() || childsResized; | |||||
if (resized) { | |||||
setTimeout(this.redraw.bind(this), 0); | |||||
} | |||||
}; | |||||
/** | |||||
* Initialize watching when option autoResize is true | |||||
* @private | |||||
*/ | |||||
RootPanel.prototype._initWatch = function _initWatch() { | |||||
var autoResize = this.getOption('autoResize'); | |||||
if (autoResize) { | |||||
this._watch(); | |||||
} | |||||
else { | |||||
this._unwatch(); | |||||
} | |||||
}; | |||||
/** | |||||
* Watch for changes in the size of the frame. On resize, the Panel will | |||||
* automatically redraw itself. | |||||
* @private | |||||
*/ | |||||
RootPanel.prototype._watch = function _watch() { | |||||
var me = this; | |||||
this._unwatch(); | |||||
var checkSize = function checkSize() { | |||||
var autoResize = me.getOption('autoResize'); | |||||
if (!autoResize) { | |||||
// stop watching when the option autoResize is changed to false | |||||
me._unwatch(); | |||||
return; | |||||
} | |||||
if (me.frame) { | |||||
// check whether the frame is resized | |||||
if ((me.frame.clientWidth != me.lastWidth) || | |||||
(me.frame.clientHeight != me.lastHeight)) { | |||||
me.lastWidth = me.frame.clientWidth; | |||||
me.lastHeight = me.frame.clientHeight; | |||||
me.redraw(); | |||||
// TODO: emit a resize event instead? | |||||
} | |||||
} | |||||
}; | |||||
// TODO: automatically cleanup the event listener when the frame is deleted | |||||
util.addEventListener(window, 'resize', checkSize); | |||||
this.watchTimer = setInterval(checkSize, 1000); | |||||
}; | |||||
/** | |||||
* Stop watching for a resize of the frame. | |||||
* @private | |||||
*/ | |||||
RootPanel.prototype._unwatch = function _unwatch() { | |||||
if (this.watchTimer) { | |||||
clearInterval(this.watchTimer); | |||||
this.watchTimer = undefined; | |||||
} | |||||
// TODO: remove event listener on window.resize | |||||
}; |