diff --git a/src/timeline/Range.js b/src/timeline/Range.js index ef9c4ce3..aa2fd4f0 100644 --- a/src/timeline/Range.js +++ b/src/timeline/Range.js @@ -13,8 +13,6 @@ function Range(options) { this.options = options || {}; - this.listeners = []; - this.setOptions(options); } @@ -37,6 +35,17 @@ Range.prototype.setOptions = function (options) { } }; +/** + * Test whether direction has a valid value + * @param {String} direction 'horizontal' or 'vertical' + */ +function validateDirection (direction) { + if (direction != 'horizontal' && direction != 'vertical') { + throw new TypeError('Unknown direction "' + direction + '". ' + + 'Choose "horizontal" or "vertical".'); + } +} + /** * Add listeners for mouse and touch events to the component * @param {Component} component @@ -45,41 +54,32 @@ Range.prototype.setOptions = function (options) { */ Range.prototype.subscribe = function (component, event, direction) { var me = this; - var listener; - if (direction != 'horizontal' && direction != 'vertical') { - throw new TypeError('Unknown direction "' + direction + '". ' + - 'Choose "horizontal" or "vertical".'); - } - - //noinspection FallthroughInSwitchStatementJS if (event == 'move') { - listener = { - component: component, - event: event, - direction: direction, - callback: function (event) { - me._onMouseDown(event, listener); - }, - params: {} - }; + // drag start listener + component.on('dragstart', function (event) { + me._onDragStart(event, component); + }); + + // drag listener + component.on('drag', function (event) { + me._onDrag(event, component, direction); + }); - component.on('mousedown', listener.callback); - me.listeners.push(listener); + // drag end listener + component.on('dragend', function (event) { + me._onDragEnd(event, component); + }); } else if (event == 'zoom') { - listener = { - component: component, - event: event, - direction: direction, - callback: function (event) { - me._onMouseWheel(event, listener); - }, - params: {} - }; + // mouse wheel + function mousewheel (event) { + me._onMouseWheel(event, component, direction); + } + component.on('mousewheel', mousewheel); + component.on('DOMMouseScroll', mousewheel); // For FF - component.on('mousewheel', listener.callback); - me.listeners.push(listener); + // TODO: pinch } else { throw new TypeError('Unknown event "' + event + '". ' + @@ -252,9 +252,6 @@ Range.prototype.getRange = function() { * @returns {{offset: number, factor: number}} conversion */ Range.prototype.conversion = function (width) { - var start = this.start; - var end = this.end; - return Range.conversion(this.start, this.end, width); }; @@ -281,143 +278,71 @@ Range.conversion = function (start, end, width) { } }; +// global (private) object to store drag params +var dragParams = {}; + /** - * Start moving horizontally or vertically + * Start dragging horizontally or vertically * @param {Event} event - * @param {Object} listener Listener containing the component and params + * @param {Object} component * @private */ -Range.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.mouseY = util.getPageY(event); - params.previousLeft = 0; - params.previousOffset = 0; +Range.prototype._onDragStart = function(event, component) { + dragParams.start = this.start; + dragParams.end = this.end; - params.moved = false; - params.start = this.start; - params.end = this.end; - - var frame = listener.component.frame; + var frame = component.frame; if (frame) { frame.style.cursor = 'move'; } - - // add event listeners to handle moving the contents - // we store the function onmousemove and onmouseup in the timeaxis, - // so we can remove the eventlisteners lateron in the function onmouseup - 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.preventDefault(event); }; /** - * Perform moving operating. - * This function activated from within the funcion TimeAxis._onMouseDown(). + * Perform dragging operating. * @param {Event} event - * @param {Object} listener + * @param {Component} component + * @param {String} direction 'horizontal' or 'vertical' * @private */ -Range.prototype._onMouseMove = function (event, listener) { - event = event || window.event; +Range.prototype._onDrag = function (event, component, direction) { + validateDirection(direction); - var params = listener.params; + var delta = (direction == 'horizontal') ? event.gesture.deltaX : event.gesture.deltaY, + interval = (dragParams.end - dragParams.start), + width = (direction == 'horizontal') ? component.width : component.height, + diffRange = -delta / width * interval; - // calculate change in mouse position - var mouseX = util.getPageX(event); - var mouseY = util.getPageY(event); - - if (params.mouseX == undefined) { - params.mouseX = mouseX; - } - if (params.mouseY == undefined) { - params.mouseY = mouseY; - } - - var diffX = mouseX - params.mouseX; - var diffY = mouseY - params.mouseY; - var diff = (listener.direction == 'horizontal') ? diffX : diffY; - - // if mouse movement is big enough, register it as a "moved" event - if (Math.abs(diff) >= 1) { - params.moved = true; - } - - var interval = (params.end - params.start); - var width = (listener.direction == 'horizontal') ? - listener.component.width : listener.component.height; - var diffRange = -diff / width * interval; - this._applyRange(params.start + diffRange, params.end + diffRange); + this._applyRange(dragParams.start + diffRange, dragParams.end + diffRange); // fire a rangechange event this._trigger('rangechange'); - - util.preventDefault(event); }; /** - * Stop moving operating. - * This function activated from within the function Range._onMouseDown(). + * Stop dragging operating. * @param {event} event - * @param {Object} listener + * @param {Component} component * @private */ -Range.prototype._onMouseUp = function (event, listener) { - event = event || window.event; - - var params = listener.params; - - if (listener.component.frame) { - listener.component.frame.style.cursor = 'auto'; +Range.prototype._onDragEnd = function (event, component) { + if (component.frame) { + component.frame.style.cursor = 'auto'; } - // 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; - } - //util.preventDefault(event); - - if (params.moved) { - // fire a rangechanged event - this._trigger('rangechanged'); - } + // fire a rangechanged event + this._trigger('rangechanged'); }; /** * Event handler for mouse wheel event, used to zoom * Code from http://adomas.org/javascript-mouse-wheel/ * @param {Event} event - * @param {Object} listener + * @param {Component} component + * @param {String} direction 'horizontal' or 'vertical' * @private */ -Range.prototype._onMouseWheel = function(event, listener) { - event = event || window.event; +Range.prototype._onMouseWheel = function(event, component, direction) { + validateDirection(direction); // retrieve delta var delta = 0; @@ -438,18 +363,18 @@ Range.prototype._onMouseWheel = function(event, listener) { // perform the zoom action. Delta is normally 1 or -1 var zoomFactor = delta / 5.0; var zoomAround = null; - var frame = listener.component.frame; + var frame = component.frame; if (frame) { var size, conversion; - if (listener.direction == 'horizontal') { - size = listener.component.width; + if (direction == 'horizontal') { + size = component.width; conversion = me.conversion(size); var frameLeft = util.getAbsoluteLeft(frame); var mouseX = util.getPageX(event); zoomAround = (mouseX - frameLeft) / conversion.factor + conversion.offset; } else { - size = listener.component.height; + size = component.height; conversion = me.conversion(size); var frameTop = util.getAbsoluteTop(frame); var mouseY = util.getPageY(event); @@ -463,9 +388,8 @@ Range.prototype._onMouseWheel = function(event, listener) { zoom(); } - // Prevent default actions caused by mouse wheel. - // That might be ugly, but we handle scrolls somehow - // anyway, so don't bother here... + // Prevent default actions caused by mouse wheel + // (else the page and timeline both zoom and scroll) util.preventDefault(event); }; diff --git a/src/timeline/component/RootPanel.js b/src/timeline/component/RootPanel.js index 2b18ea99..f55af08f 100644 --- a/src/timeline/component/RootPanel.js +++ b/src/timeline/component/RootPanel.js @@ -198,7 +198,13 @@ RootPanel.prototype._updateEventEmitters = function () { }); }; me.emitters[event] = callback; - util.addEventListener(frame, event, callback); + + if (!me.hammer) { + me.hammer = Hammer(frame, { + prevent_default: true + }); + } + me.hammer.on(event, callback); } } });