diff --git a/api/js/tapandswipe.ts b/api/js/tapandswipe.ts index abbf57f515..63712e51b6 100644 --- a/api/js/tapandswipe.ts +++ b/api/js/tapandswipe.ts @@ -8,16 +8,21 @@ * @author Hadi Nategh */ export interface TapAndSwipeOptions { + // allow scrolling would stop swipe/tap events from being fired when there's scrolling available. It can be restricted + // to Vertical/Horizental/Both scrolling. If no value set it means not allowed. + allowScrolling? : string|null, // tolorated pixel to fire the swipe events threshold? : number, // time delay for defirentiate between tap event and long tap event, threshold is in milliseconds tapHoldThreshold? : number, + // DOM node(s) that event handler has to be bound to, it can be a selector or acctual HTMLElement + element? : string|HTMLElement, // callback function being called on swipe gestures swipe? : Function, // callback function being called on tap tap? : Function, // callback function being called on long tap(tap and hold) - tapAndHold? : Function + tapAndHold? : Function, } export type TapAndSwipeOptionsType = TapAndSwipeOptions; @@ -26,6 +31,7 @@ export class tapAndSwipe { static readonly _default : TapAndSwipeOptionsType = { threshold : 10, tapHoldThreshold : 3000, + allowScrolling : null, swipe : function(){}, tap : function(){}, tapAndHold: function(){} @@ -71,15 +77,19 @@ export class tapAndSwipe { */ private _fingercount : number = null; + private _scrolledElementObj : {el : HTMLElement, scrollTop : number, scrollLeft : number} = null; + + private _hasBeenScrolled : boolean = false; /** * Options * @protected */ protected options : TapAndSwipeOptionsType = null; + /** * Keeps the html node */ - private _element : HTMLElement = null; + public element : HTMLElement = null; /** * Constructor @@ -89,11 +99,17 @@ export class tapAndSwipe { public constructor(_element : string | HTMLElement, _options? : TapAndSwipeOptionsType) { this.options = {...tapAndSwipe._default, ..._options}; - this._element = (_element instanceof EventTarget) ? _element : document.querySelector(_element); - this._element.addEventListener('touchstart', this._onTouchStart.bind(this), false); - this._element.addEventListener('touchend', this._ontouchEnd.bind(this), false); + const element = _element||_options.element; + this.element = (element instanceof EventTarget) ? element : document.querySelector(element); + this.element.addEventListener('touchstart', this._onTouchStart.bind(this), false); + this.element.addEventListener('touchend', this._ontouchEnd.bind(this), false); + this.element.addEventListener('touchmove', this._onTouchMove.bind(this), false); } + _onTouchMove(event) + { + + } /** * on touch start event handler * @param event @@ -106,9 +122,28 @@ export class tapAndSwipe { this._isTapAndHold = false; this._fingercount = event.touches.length; + const scrolledItem = event.path.filter(_item => { + return _item instanceof HTMLElement && this.element.contains(_item) && (_item.scrollTop != 0 || _item.scrollLeft !=0); + }); + if (scrolledItem.length>0) + { + this._scrolledElementObj = {el: scrolledItem[0], scrollTop: scrolledItem[0].scrollTop, scrollLeft: scrolledItem[0].scrollLeft}; + } + else + { + this._scrolledElementObj = null; + } + + this._tapHoldTimeout = window.setTimeout(_=>{ this._isTapAndHold = true; - this.options.tapAndHold(event, this._fingercount); + //check scrolling + if (this.options.allowScrolling && this._hasBeenScrolled) + { + return; + } + + this.options.tapAndHold.call(this, event, this._fingercount); }, this.options.tapHoldThreshold); } @@ -121,6 +156,29 @@ export class tapAndSwipe { { this._endX = event.changedTouches[0].screenX; this._endY = event.changedTouches[0].screenY; + + if (this._scrolledElementObj) { + switch (this.options.allowScrolling) + { + case "vertical": + this._hasBeenScrolled = this._scrolledElementObj.el.scrollTop != this._scrolledElementObj.scrollTop; + break; + case "horizental": + this._hasBeenScrolled = this._scrolledElementObj.el.scrollLeft != this._scrolledElementObj.scrollLeft; + break; + case "both": + this._hasBeenScrolled = (this._scrolledElementObj.el.scrollTop != this._scrolledElementObj.scrollTop) || + (this._scrolledElementObj.el.scrollLeft != this._scrolledElementObj.scrollLeft); + break; + default: + this._hasBeenScrolled = false; + } + } + else + { + this._hasBeenScrolled = false; + } + this._handler(event); } @@ -134,6 +192,13 @@ export class tapAndSwipe { //cleanup tapHoldTimeout window.clearTimeout(this._tapHoldTimeout); + //check scrolling + if (this.options.allowScrolling && this._hasBeenScrolled) + { + // let the scrolling happens + return; + } + // Tap & TapAndHold handler if (this._endX == this._startX && this._endY == this._startY || (Math.sqrt((this._endX-this._startX)*(this._endX-this._startX) + (this._endY-this._startY)+(this._endY-this._startY)) @@ -141,7 +206,7 @@ export class tapAndSwipe { { if (!this._isTapAndHold) { - this.options.tap(event, this._fingercount); + this.options.tap.call(this,event, this._fingercount); } return; @@ -150,28 +215,28 @@ export class tapAndSwipe { // left swipe handler if (this._endX + this.options.threshold < this._startX) { this._distance = this._startX - this._endX; - this.options.swipe(event, 'left', this._distance, this._fingercount); + this.options.swipe.call(this, event, 'left', this._distance, this._fingercount); return; } // right swipe handler if (this._endX - this.options.threshold > this._startX) { this._distance = this._endX - this._startX; - this.options.swipe(event, 'right', this._distance, this._fingercount); + this.options.swipe.call(this, event, 'right', this._distance, this._fingercount); return; } // up swipe handler if (this._endY + this.options.threshold < this._startY) { this._distance = this._startY - this._endY; - this.options.swipe(event, 'up', this._distance, this._fingercount); + this.options.swipe.call(this, event, 'up', this._distance, this._fingercount); return; } // down swipe handler if (this._endY - this.options.threshold > this._startY) { this._distance = this._endY - this._startY; - this.options.swipe(event, 'down', this._distance, this._fingercount); + this.options.swipe.call(this, event, 'down', this._distance, this._fingercount); return; } } @@ -181,7 +246,7 @@ export class tapAndSwipe { */ public destroy() { - this._element.removeEventListener('touchstart', this._onTouchStart); - this._element.removeEventListener('touchend', this._ontouchEnd); + this.element.removeEventListener('touchstart', this._onTouchStart); + this.element.removeEventListener('touchend', this._ontouchEnd); } } \ No newline at end of file