diff --git a/HISTORY.md b/HISTORY.md index a61baed3..3083a37c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -20,6 +20,7 @@ http://visjs.org - Implemented `currentTimeTick` event (see #1683). - Fixed #1630: method `getItemRange` missing in docs. +- Fixed #1455: allow vertical panning of the web page on touch devices. ### Graph2d diff --git a/lib/hammerUtil.js b/lib/hammerUtil.js index 4e1b79d2..d20a2376 100644 --- a/lib/hammerUtil.js +++ b/lib/hammerUtil.js @@ -46,3 +46,20 @@ exports.offTouch = function (hammer, callback) { * @param {function} callback Callback, called as callback(event) */ exports.offRelease = exports.offTouch; + +/** + * Hack the PinchRecognizer such that it doesn't prevent default behavior + * for vertical panning. + * @param {Hammer.Pinch} pinchRecognizer + * @return {Hammer.Pinch} returns the pinchRecognizer + */ +exports.disablePreventDefaultVertically = function (pinchRecognizer) { + var TOUCH_ACTION_PAN_Y = 'pan-y'; + + pinchRecognizer.getTouchAction = function() { + // default method returns [TOUCH_ACTION_NONE] + return [TOUCH_ACTION_PAN_Y]; + }; + + return pinchRecognizer; +}; diff --git a/lib/network/modules/Canvas.js b/lib/network/modules/Canvas.js index 726d1f63..e0f15abb 100644 --- a/lib/network/modules/Canvas.js +++ b/lib/network/modules/Canvas.js @@ -222,7 +222,7 @@ class Canvas { this.hammer = new Hammer(this.frame.canvas); this.hammer.get('pinch').set({enable: true}); // enable to get better response, todo: test on mobile. - this.hammer.get('pan').set({threshold:5, direction:30}); // 30 is ALL_DIRECTIONS in hammer. + this.hammer.get('pan').set({threshold:5, direction: Hammer.DIRECTION_ALL}); hammerUtil.onTouch(this.hammer, (event) => {this.body.eventListeners.onTouch(event)}); this.hammer.on('tap', (event) => {this.body.eventListeners.onTap(event)}); diff --git a/lib/timeline/Core.js b/lib/timeline/Core.js index 86350197..97281b73 100644 --- a/lib/timeline/Core.js +++ b/lib/timeline/Core.js @@ -118,8 +118,9 @@ Core.prototype._create = function (container) { // create event listeners for all interesting events, these events will be // emitted via emitter this.hammer = new Hammer(this.dom.root); - this.hammer.get('pinch').set({enable: true}); - this.hammer.get('pan').set({threshold:5, direction:30}); // 30 is ALL_DIRECTIONS in hammer. + var pinchRecognizer = this.hammer.get('pinch').set({enable: true}); + hammerUtil.disablePreventDefaultVertically(pinchRecognizer); + this.hammer.get('pan').set({threshold:5, direction: Hammer.DIRECTION_HORIZONTAL}); this.listeners = {}; var events = [ @@ -768,6 +769,12 @@ Core.prototype._redraw = function() { dom.shadowTopRight.style.visibility = visibilityTop; dom.shadowBottomRight.style.visibility = visibilityBottom; + // enable/disable vertical panning + var contentsOverflow = this.props.center.height > this.props.centerContainer.height; + this.hammer.get('pan').set({ + direction: contentsOverflow ? Hammer.DIRECTION_ALL : Hammer.DIRECTION_HORIZONTAL + }); + // redraw all components this.components.forEach(function (component) { resized = component.redraw() || resized; diff --git a/lib/timeline/component/CustomTime.js b/lib/timeline/component/CustomTime.js index 72ee0000..63c1545c 100644 --- a/lib/timeline/component/CustomTime.js +++ b/lib/timeline/component/CustomTime.js @@ -84,7 +84,7 @@ CustomTime.prototype._create = function() { this.hammer.on('panstart', this._onDragStart.bind(this)); this.hammer.on('panmove', this._onDrag.bind(this)); this.hammer.on('panend', this._onDragEnd.bind(this)); - this.hammer.get('pan').set({threshold:5, direction:30}); // 30 is ALL_DIRECTIONS in hammer. + this.hammer.get('pan').set({threshold:5, direction: Hammer.DIRECTION_HORIZONTAL}); }; /** diff --git a/lib/timeline/component/ItemSet.js b/lib/timeline/component/ItemSet.js index d66c77e4..27aaee38 100644 --- a/lib/timeline/component/ItemSet.js +++ b/lib/timeline/component/ItemSet.js @@ -220,7 +220,7 @@ ItemSet.prototype._create = function(){ this.hammer.on('panstart', this._onDragStart.bind(this)); this.hammer.on('panmove', this._onDrag.bind(this)); this.hammer.on('panend', this._onDragEnd.bind(this)); - this.hammer.get('pan').set({threshold:5, direction:30}); // 30 is ALL_DIRECTIONS in hammer. + this.hammer.get('pan').set({threshold:5, direction: Hammer.DIRECTION_HORIZONTAL}); // single select (or unselect) when tapping an item this.hammer.on('tap', this._onSelectItem.bind(this)); @@ -235,7 +235,7 @@ ItemSet.prototype._create = function(){ this.groupHammer.on('panstart', this._onGroupDragStart.bind(this)); this.groupHammer.on('panmove', this._onGroupDrag.bind(this)); this.groupHammer.on('panend', this._onGroupDragEnd.bind(this)); - this.groupHammer.get('pan').set({threshold:5, direction:30}); + this.groupHammer.get('pan').set({threshold:5, direction: Hammer.DIRECTION_HORIZONTAL}); // attach to the DOM this.show();