diff --git a/src/timeline/Range.js b/src/timeline/Range.js index 96f26381..0e72daa2 100644 --- a/src/timeline/Range.js +++ b/src/timeline/Range.js @@ -3,39 +3,37 @@ * A Range controls a numeric range with a start and end value. * The Range adjusts the range based on mouse events or programmatic changes, * and triggers events when the range is changing or has been changed. - * @param {Component} parent - * @param {Emitter} emitter - * @param {Object} [options] See description at Range.setOptions + * @param {RootPanel} root Root panel, used to subscribe to events + * @param {Panel} parent Parent panel, used to attach to the DOM + * @param {Object} [options] See description at Range.setOptions */ -function Range(parent, emitter, options) { +function Range(root, parent, options) { this.id = util.randomUUID(); this.start = null; // Number this.end = null; // Number + this.root = root; this.parent = parent; - this.emitter = emitter; this.options = options || {}; - // TODO: not so nice having to specify an emitter (different from parent) where to subscribe for events - // drag start listener var me = this; - emitter.on('dragstart', function (event) { + this.root.on('dragstart', function (event) { me._onDragStart(event, parent); }); // drag listener - emitter.on('drag', function (event) { + this.root.on('drag', function (event) { me._onDrag(event, parent); }); // drag end listener - emitter.on('dragend', function (event) { - me._onDragEnd(event, parent); + this.root.on('dragend', function (event) { + me._onDragEnd(event); }); // ignore dragging when holding - emitter.on('hold', function (event) { + this.root.on('hold', function (event) { me._onHold(); }); @@ -43,21 +41,21 @@ function Range(parent, emitter, options) { function mousewheel (event) { me._onMouseWheel(event, parent); } - emitter.on('mousewheel', mousewheel); - emitter.on('DOMMouseScroll', mousewheel); // For FF + this.root.on('mousewheel', mousewheel); + this.root.on('DOMMouseScroll', mousewheel); // For FF // pinch - emitter.on('touch', function (event) { + this.root.on('touch', function (event) { me._onTouch(event); }); - emitter.on('pinch', function (event) { - me._onPinch(event, parent); + this.root.on('pinch', function (event) { + me._onPinch(event); }); this.setOptions(options); } - +// turn Range into an event emitter Emitter(Range.prototype); /** diff --git a/src/timeline/Timeline.js b/src/timeline/Timeline.js index 395dfaba..cb799e84 100644 --- a/src/timeline/Timeline.js +++ b/src/timeline/Timeline.js @@ -56,10 +56,6 @@ function Timeline (container, items, options) { toTime: me._toTime.bind(me) }; - // event bus - // TODO: make the Timeline itself an emitter - this.emitter = new Emitter(); - // root panel var rootOptions = Object.create(this.options); rootOptions.height = function () { @@ -73,20 +69,16 @@ function Timeline (container, items, options) { // TODO: return the sum of the height of the childs } }; - this.rootPanel = new RootPanel(container, this.emitter, rootOptions); + this.rootPanel = new RootPanel(container, rootOptions); // single select (or unselect) when tapping an item - this.emitter.on('tap', this._onSelectItem.bind(this)); + this.rootPanel.on('tap', this._onSelectItem.bind(this)); // multi select when holding mouse/touch, or on ctrl+click - this.emitter.on('hold', this._onMultiSelectItem.bind(this)); + this.rootPanel.on('hold', this._onMultiSelectItem.bind(this)); // add item on doubletap - this.emitter.on('doubletap', this._onAddItem.bind(this)); - - // repaint on range change - this.emitter.on('rangechange', this.rootPanel.repaint.bind(this.rootPanel)); - this.emitter.on('rangechanged', this.rootPanel.repaint.bind(this.rootPanel)); + this.rootPanel.on('doubletap', this._onAddItem.bind(this)); // label panel var labelOptions = Object.create(this.options); @@ -125,16 +117,18 @@ function Timeline (container, items, options) { // range // TODO: move range inside rootPanel? var rangeOptions = Object.create(this.options); - this.range = new Range(this.mainPanel, this.emitter, rangeOptions); + this.range = new Range(this.rootPanel, this.mainPanel, rangeOptions); this.range.setRange( now.clone().add('days', -3).valueOf(), now.clone().add('days', 4).valueOf() ); this.range.on('rangechange', function (properties) { - me.emitter.emit('rangechange', properties); + me.rootPanel.repaint(); + me.emit('rangechange', properties); }); this.range.on('rangechanged', function (properties) { - me.emitter.emit('rangechanged', properties); + me.rootPanel.repaint(); + me.emit('rangechanged', properties); }); // panel with time axis @@ -170,10 +164,10 @@ function Timeline (container, items, options) { this.customTime = new CustomTime(rootOptions); this.mainPanel.appendChild(this.customTime); this.customTime.on('timechange', function (time) { - me.emitter.emit('timechange', time); + me.emit('timechange', time); }); this.customTime.on('timechanged', function (time) { - me.emitter.emit('timechanged', time); + me.emit('timechanged', time); }); // create groupset @@ -193,24 +187,8 @@ function Timeline (container, items, options) { } } -/** - * Add an event listener to the timeline - * @param {String} event Available events: select, rangechange, rangechanged, - * timechange, timechanged - * @param {function} callback - */ -Timeline.prototype.on = function on (event, callback) { - this.emitter.on(event, callback); -}; - -/** - * Add an event listener from the timeline - * @param {String} event - * @param {function} callback - */ -Timeline.prototype.off = function off (event, callback) { - this.emitter.off(event, callback); -}; +// turn Timeline into an event emitter +Emitter(Timeline.prototype); /** * Set options @@ -510,7 +488,7 @@ Timeline.prototype._onSelectItem = function (event) { var selection = item ? [item.id] : []; this.setSelection(selection); - this.emitter.emit('select', { + this.emit('select', { items: this.getSelection() }); @@ -561,16 +539,7 @@ Timeline.prototype._onAddItem = function (event) { this.options.onAdd(newItem, function (item) { if (item) { me.itemsData.add(newItem); - - // select the created item after it is repainted - // FIXME: just repaint the whole thing, not via an emitted event - me.emitter.once('repaint', function () { - me.setSelection([id]); - - me.emitter.emit('select', { - items: me.getSelection() - }); - }.bind(me)); + // TODO: need to trigger a repaint? } }); } diff --git a/src/timeline/component/RootPanel.js b/src/timeline/component/RootPanel.js index 0d2469b3..5cc36a4d 100644 --- a/src/timeline/component/RootPanel.js +++ b/src/timeline/component/RootPanel.js @@ -2,15 +2,13 @@ * A root panel can hold components. The root panel must be initialized with * a DOM element as container. * @param {HTMLElement} container - * @param {Emitter} emitter * @param {Object} [options] Available parameters: see RootPanel.setOptions. * @constructor RootPanel * @extends Panel */ -function RootPanel(container, emitter, options) { +function RootPanel(container, options) { this.id = util.randomUUID(); this.container = container; - this.emitter = emitter; this.options = options || {}; this.defaultOptions = { @@ -20,6 +18,9 @@ function RootPanel(container, emitter, options) { RootPanel.prototype = new Panel(); +// turn RootPanel into an event emitter +Emitter(RootPanel.prototype); + /** * Set options. Will extend the current options. * @param {Object} [options] Available parameters: @@ -72,7 +73,7 @@ RootPanel.prototype.repaint = function () { events.forEach(function (event) { var listener = function () { var args = [event].concat(Array.prototype.slice.call(arguments, 0)); - me.emitter.emit.apply(me.emitter, args); + me.emit.apply(me, args); }; me.hammer.on(event, listener); me.listeners[event] = listener;