From e19502ebc79afc0f9a31daffc9e7fcf183ef2602 Mon Sep 17 00:00:00 2001 From: jos Date: Thu, 11 Dec 2014 15:32:13 +0100 Subject: [PATCH] Moving Timeline working with hammer2 (stop event propagation still an issue) --- lib/timeline/Core.js | 24 ++++++++++++++++++-- lib/timeline/Range.js | 29 ++++++++++++------------ lib/timeline/component/ItemSet.js | 26 +++++++++++---------- lib/timeline/component/item/Item.js | 7 +++++- lib/timeline/component/item/RangeItem.js | 24 ++++++++++---------- test/timeline.html | 6 +++++ 6 files changed, 74 insertions(+), 42 deletions(-) diff --git a/lib/timeline/Core.js b/lib/timeline/Core.js index 8fc5c340..a7121973 100644 --- a/lib/timeline/Core.js +++ b/lib/timeline/Core.js @@ -117,9 +117,11 @@ Core.prototype._create = function (container) { this.listeners = {}; var events = [ - 'tap', 'pinch', 'press', + 'tap', 'doubletap', 'press', + 'pinch', 'panstart', 'panmove', 'panend' - // TODO: mouse wheel + // TODO: mouse wheel? + // TODO: cleanup //'touch', 'pinch', //'tap', 'doubletap', 'hold', //'dragstart', 'drag', 'dragend', @@ -136,6 +138,24 @@ Core.prototype._create = function (container) { me.listeners[event] = listener; }); + this.hammer.on('hammer.input', function (event) { + if (event.isFirst) { + var args = ['touch'].concat(Array.prototype.slice.call(arguments, 0)); + if (me.isActive()) { + me.emit.apply(me, args); + } + } + }.bind(this)); + + function onMouseWheel() { + var args = ['mousewheel'].concat(Array.prototype.slice.call(arguments, 0)); + if (me.isActive()) { + me.emit.apply(me, args); + } + } + this.dom.root.addEventListener('mousewheel', onMouseWheel); + this.dom.root.addEventListener('DOMMouseScroll', onMouseWheel); + // size properties of each of the panels this.props = { root: {}, diff --git a/lib/timeline/Range.js b/lib/timeline/Range.js index 15bd6993..f35b76b3 100644 --- a/lib/timeline/Range.js +++ b/lib/timeline/Range.js @@ -51,8 +51,7 @@ function Range(body, options) { this.body.emitter.on('press', this._onHold.bind(this)); // mouse wheel for zooming - this.body.emitter.on('mousewheel', this._onMouseWheel.bind(this)); - this.body.emitter.on('DOMMouseScroll', this._onMouseWheel.bind(this)); // For FF + this.body.emitter.on('mousewheel', this._onMouseWheel.bind(this)); // pinch to zoom this.body.emitter.on('touch', this._onTouch.bind(this)); @@ -374,14 +373,15 @@ Range.prototype._onDragStart = function(event) { Range.prototype._onDrag = function (event) { // only allow dragging when configured as movable if (!this.options.moveable) return; + + // TODO: this may be redundant in hammerjs2 // refuse to drag when we where pinching to prevent the timeline make a jump // when releasing the fingers in opposite order from the touch screen if (!this.props.touch.allowDragging) return; var direction = this.options.direction; validateDirection(direction); - - var delta = (direction == 'horizontal') ? event.gesture.deltaX : event.gesture.deltaY; + var delta = (direction == 'horizontal') ? event.deltaX : event.deltaY; delta -= this.deltaDifference; var interval = (this.props.touch.end - this.props.touch.start); @@ -394,7 +394,6 @@ Range.prototype._onDrag = function (event) { var newStart = this.props.touch.start + diffRange; var newEnd = this.props.touch.end + diffRange; - // snapping times away from hidden zones var safeStart = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newStart, this.previousDelta-delta, true); var safeEnd = DateUtil.snapAwayFromHidden(this.body.hiddenDates, newEnd, this.previousDelta-delta, true); @@ -425,6 +424,7 @@ Range.prototype._onDragEnd = function (event) { // only allow dragging when configured as movable if (!this.options.moveable) return; + // TODO: this may be redundant in hammerjs2 // refuse to drag when we where pinching to prevent the timeline make a jump // when releasing the fingers in opposite order from the touch screen if (!this.props.touch.allowDragging) return; @@ -478,9 +478,8 @@ Range.prototype._onMouseWheel = function(event) { } // calculate center, the date to zoom around - var gesture = hammerUtil.fakeGesture(this, event), - pointer = getPointer(gesture.center, this.body.dom.center), - pointerDate = this._pointerToDate(pointer); + var pointer = getPointer({x: event.pageX, y: event.pageY}, this.body.dom.center); + var pointerDate = this._pointerToDate(pointer); this.zoom(scale, pointerDate, delta); } @@ -522,12 +521,12 @@ Range.prototype._onPinch = function (event) { this.props.touch.allowDragging = false; - if (event.gesture.touches.length > 1) { + if (event.touches.length > 1) { if (!this.props.touch.center) { - this.props.touch.center = getPointer(event.gesture.center, this.body.dom.center); + this.props.touch.center = getPointer(event.center, this.body.dom.center); } - var scale = 1 / (event.gesture.scale + this.scaleOffset); + var scale = 1 / (event.scale + this.scaleOffset); var centerDate = this._pointerToDate(this.props.touch.center); var hiddenDuration = DateUtil.getHiddenDurationBetween(this.body.hiddenDates, this.start, this.end); @@ -547,7 +546,7 @@ Range.prototype._onPinch = function (event) { if (safeStart != newStart || safeEnd != newEnd) { this.props.touch.start = safeStart; this.props.touch.end = safeEnd; - this.scaleOffset = 1 - event.gesture.scale; + this.scaleOffset = 1 - event.scale; newStart = safeStart; newEnd = safeEnd; } @@ -583,15 +582,15 @@ Range.prototype._pointerToDate = function (pointer) { /** * Get the pointer location relative to the location of the dom element - * @param {{pageX: Number, pageY: Number}} touch + * @param {{x: Number, y: Number}} touch * @param {Element} element HTML DOM element * @return {{x: Number, y: Number}} pointer * @private */ function getPointer (touch, element) { return { - x: touch.pageX - util.getAbsoluteLeft(element), - y: touch.pageY - util.getAbsoluteTop(element) + x: touch.x - util.getAbsoluteLeft(element), + y: touch.y - util.getAbsoluteTop(element) }; } diff --git a/lib/timeline/component/ItemSet.js b/lib/timeline/component/ItemSet.js index 16f7fa56..894aea4e 100644 --- a/lib/timeline/component/ItemSet.js +++ b/lib/timeline/component/ItemSet.js @@ -184,7 +184,12 @@ ItemSet.prototype._create = function(){ this.hammer = new Hammer(this.body.dom.centerContainer); // drag items when selected - this.hammer.on('pandown', this._onTouch.bind(this)); + //this.hammer.on('pandown', this._onTouch.bind(this)); // TODO + this.hammer.on('hammer.input', function (event) { + if (event.isFirst) { + this._onTouch(event); + } + }.bind(this)); this.hammer.on('panstart', this._onDragStart.bind(this)); this.hammer.on('panmove', this._onDrag.bind(this)); this.hammer.on('panend', this._onDragEnd.bind(this)); @@ -1060,8 +1065,9 @@ ItemSet.prototype._constructByEndArray = function(array) { /** * Register the clicked item on touch, before dragStart is initiated. * - * dragStart is initiated from a mousemove event, which can have left the item - * already, resulting in an item == null + * dragStart is initiated from a mousemove event, AFTER the mouse/touch is + * already moving. Therefore, the mouse/touch can sometimes be above an other + * DOM element than the item itself. * * @param {Event} event * @private @@ -1069,7 +1075,8 @@ ItemSet.prototype._constructByEndArray = function(array) { ItemSet.prototype._onTouch = function (event) { // store the touched item, used in _onDragStart this.touchParams.item = ItemSet.itemFromTarget(event); - console.log('pandown') + this.touchParams.dragLeftItem = event.target.dragLeftItem || false; + this.touchParams.dragRightItem = event.target.dragRightItem || false; }; /** @@ -1082,18 +1089,13 @@ ItemSet.prototype._onDragStart = function (event) { return; } - // TODO: test if this works ok - this.touchParams.item = ItemSet.itemFromTarget(event); - - console.log('item', this.touchParams.item) - var item = this.touchParams.item || null; var me = this; var props; if (item && item.selected) { - var dragLeftItem = event.target.dragLeftItem; - var dragRightItem = event.target.dragRightItem; + var dragLeftItem = this.touchParams.dragLeftItem; + var dragRightItem = this.touchParams.dragRightItem; if (dragLeftItem) { props = { @@ -1155,7 +1157,7 @@ ItemSet.prototype._onDragStart = function (event) { * @private */ ItemSet.prototype._onDrag = function (event) { - event.preventDefault() + event.preventDefault(); if (this.touchParams.itemProps) { var me = this; diff --git a/lib/timeline/component/item/Item.js b/lib/timeline/component/item/Item.js index 01e854a0..b7bf7941 100644 --- a/lib/timeline/component/item/Item.js +++ b/lib/timeline/component/item/Item.js @@ -140,8 +140,13 @@ Item.prototype._repaintDeleteButton = function (anchor) { // TODO: neatly handle button click new Hammer(deleteButton).on('tap', function (event) { me.parent.removeFromDataSet(me); - event.srcEvent.stopPropagation(); + event.srcEvent.stopPropagation(); // TODO: stopPropagation seems not to work }); + //deleteButton.addEventListener('click', function (event) { + // me.parent.removeFromDataSet(me); + // event.stopPropagation(); + // event.preventDefault(); + //}); anchor.appendChild(deleteButton); this.dom.deleteButton = deleteButton; diff --git a/lib/timeline/component/item/RangeItem.js b/lib/timeline/component/item/RangeItem.js index d3964652..61696124 100644 --- a/lib/timeline/component/item/RangeItem.js +++ b/lib/timeline/component/item/RangeItem.js @@ -249,12 +249,12 @@ RangeItem.prototype._repaintDragLeft = function () { dragLeft.className = 'drag-left'; dragLeft.dragLeftItem = this; - // TODO: this should be redundant? - Hammer(dragLeft, { - preventDefault: true - }).on('drag', function () { - //console.log('drag left') - }); + //// TODO: this should be redundant? + //Hammer(dragLeft, { + // preventDefault: true + //}).on('drag', function () { + // //console.log('drag left') + // }); this.dom.box.appendChild(dragLeft); this.dom.dragLeft = dragLeft; @@ -279,12 +279,12 @@ RangeItem.prototype._repaintDragRight = function () { dragRight.className = 'drag-right'; dragRight.dragRightItem = this; - // TODO: this should be redundant? - Hammer(dragRight, { - preventDefault: true - }).on('drag', function () { - //console.log('drag right') - }); + //// TODO: this should be redundant? + //Hammer(dragRight, { + // preventDefault: true + //}).on('drag', function () { + // //console.log('drag right') + //}); this.dom.box.appendChild(dragRight); this.dom.dragRight = dragRight; diff --git a/test/timeline.html b/test/timeline.html index cd8ae25c..ff8880c8 100644 --- a/test/timeline.html +++ b/test/timeline.html @@ -19,6 +19,12 @@ #visualization .itemset { /*background: rgba(255, 255, 0, 0.5);*/ } + + .vis.timeline .item.range .drag-left, + .vis.timeline .item.range .drag-right { + width: 40px; + background: rgba(255,255,255,0.5); + }