Fix swipe and popup contextmenu being triggered accidentally in touch devices

This commit is contained in:
hadi 2023-06-01 15:28:42 +02:00
parent 1d4bc10fbb
commit 8e0a3a2755
4 changed files with 45 additions and 30 deletions

View File

@ -290,7 +290,7 @@ export function egwPopupActionImplementation()
let tap = new tapAndSwipe(_node, { let tap = new tapAndSwipe(_node, {
// this threshold must be the same as the one set in et2_dataview_view_aoi // this threshold must be the same as the one set in et2_dataview_view_aoi
tapHoldThreshold: 600, tapHoldThreshold: 1000,
allowScrolling: "both", allowScrolling: "both",
tapAndHold: function(event, fingercount) tapAndHold: function(event, fingercount)
{ {

View File

@ -117,10 +117,10 @@ export function et2_dataview_rowAOI(_node)
if (egwIsMobile()) { if (egwIsMobile()) {
let swipe = new tapAndSwipe(_node,{ let swipe = new tapAndSwipe(_node,{
// set the same threshold as action_popup event to get the tapAndHold working // set the same threshold as action_popup event to get the tapAndHold working
tapHoldThreshold: 600, tapHoldThreshold: 1000,
swipe: function (event, direction, distance) swipe: function (event, direction, distance)
{ {
if (distance > 100) selectHandler(event, {swip:direction}); selectHandler(event, {swip:direction});
}, },
tap: function (event) tap: function (event)
{ {

View File

@ -11,7 +11,7 @@ export interface TapAndSwipeOptions {
// allow scrolling would stop swipe/tap events from being fired when there's scrolling available. It can be restricted // 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. // to Vertical/Horizental/Both scrolling. If no value set it means not allowed.
allowScrolling? : string|null, allowScrolling? : string|null,
// tolorated pixel to fire the swipe events // tolorated pixel for tap event
threshold? : number, threshold? : number,
// time delay for defirentiate between tap event and long tap event, threshold is in milliseconds // time delay for defirentiate between tap event and long tap event, threshold is in milliseconds
tapHoldThreshold? : number, tapHoldThreshold? : number,
@ -23,6 +23,8 @@ export interface TapAndSwipeOptions {
tap? : Function, tap? : Function,
// callback function being called on long tap(tap and hold) // callback function being called on long tap(tap and hold)
tapAndHold? : Function, tapAndHold? : Function,
// tolerate pixel to fire swipe events
minSwipeThreshold? : number,
} }
export type TapAndSwipeOptionsType = TapAndSwipeOptions; export type TapAndSwipeOptionsType = TapAndSwipeOptions;
@ -31,6 +33,7 @@ export class tapAndSwipe {
static readonly _default : TapAndSwipeOptionsType = { static readonly _default : TapAndSwipeOptionsType = {
threshold : 5, threshold : 5,
tapHoldThreshold : 3000, tapHoldThreshold : 3000,
minSwipeThreshold: 150,
allowScrolling : 'both', allowScrolling : 'both',
swipe : function(){}, swipe : function(){},
tap : function(){}, tap : function(){},
@ -57,10 +60,17 @@ export class tapAndSwipe {
*/ */
private _endY : number = null; private _endY : number = null;
/** /**
* keeps the distance travelled between start point and end point * keeps the distance travelled between startX point and endX point
* @private * @private
*/ */
private _distance : number = null; private _distanceX : number = null;
/**
* keeps the distance travelled between startY point and endY point
* @private
*/
private _distanceY : number = null;
/** /**
* flag to keep the status of type of tap * flag to keep the status of type of tap
* @private * @private
@ -86,6 +96,9 @@ export class tapAndSwipe {
private _hasBeenScrolled : boolean = false; private _hasBeenScrolled : boolean = false;
private _scrollEventTriggered : boolean = false; private _scrollEventTriggered : boolean = false;
private _stillMoving : boolean = false;
/** /**
* Options * Options
* @protected * @protected
@ -131,7 +144,7 @@ export class tapAndSwipe {
_onTouchMove(event) _onTouchMove(event)
{ {
this._stillMoving = true;
} }
/** /**
* on touch start event handler * on touch start event handler
@ -140,8 +153,8 @@ export class tapAndSwipe {
*/ */
private _onTouchStart(event : TouchEvent) private _onTouchStart(event : TouchEvent)
{ {
this._startX = event.changedTouches[0].screenX; this._startX = event.changedTouches[0].pageX;
this._startY = event.changedTouches[0].screenY; this._startY = event.changedTouches[0].pageY;
this._isTapAndHold = false; this._isTapAndHold = false;
this._fingercount = event.touches.length; this._fingercount = event.touches.length;
@ -165,7 +178,7 @@ export class tapAndSwipe {
this._tapHoldTimeout = window.setTimeout(_=>{ this._tapHoldTimeout = window.setTimeout(_=>{
this._isTapAndHold = true; this._isTapAndHold = true;
//check scrolling //check scrolling
if (this.options.allowScrolling && this._hasBeenScrolled) if (this.options.allowScrolling && this._stillMoving)
{ {
return; return;
} }
@ -181,8 +194,9 @@ export class tapAndSwipe {
*/ */
private _ontouchEnd(event : TouchEvent) private _ontouchEnd(event : TouchEvent)
{ {
this._endX = event.changedTouches[0].screenX; this._endX = event.changedTouches[0].pageX;
this._endY = event.changedTouches[0].screenY; this._endY = event.changedTouches[0].pageY;
this._stillMoving = false;
if (this._scrolledElementObj) { if (this._scrolledElementObj) {
switch (this.options.allowScrolling) switch (this.options.allowScrolling)
@ -218,10 +232,13 @@ export class tapAndSwipe {
{ {
//cleanup tapHoldTimeout //cleanup tapHoldTimeout
window.clearTimeout(this._tapHoldTimeout); window.clearTimeout(this._tapHoldTimeout);
this._distanceX = Math.abs(this._endX-this._startX);
this._distanceY = Math.abs(this._endY-this._startY);
const isTabOrHold = (this._endX == this._startX && this._endY == this._startY const isTabOrHold = (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)) || (Math.sqrt((this._distanceX)*(this._distanceX) + (this._distanceY*2))
< this.options.threshold)); < this.options.threshold));
this._hasBeenScrolled = this._hasBeenScrolled ?? (!isTabOrHold && this._scrollEventTriggered); this._hasBeenScrolled = this._hasBeenScrolled ?? (!isTabOrHold && this._scrollEventTriggered);
//check scrolling //check scrolling
if (this.options.allowScrolling && this._hasBeenScrolled) if (this.options.allowScrolling && this._hasBeenScrolled)
@ -231,13 +248,11 @@ export class tapAndSwipe {
} }
// Tap & TapAndHold handler // Tap & TapAndHold handler
if (this._endX == this._startX && this._endY == this._startY if (isTabOrHold)
|| (Math.sqrt((this._endX-this._startX)*(this._endX-this._startX) + (this._endY-this._startY)+(this._endY-this._startY))
< this.options.threshold))
{ {
if (!this._isTapAndHold) if (!this._isTapAndHold)
{ {
this._tapHoldTimeout = window.setTimeout(_=> { this._tapTimeout = window.setTimeout(_=> {
this.options.tap.call(this,event, this._fingercount); this.options.tap.call(this,event, this._fingercount);
}, 100); }, 100);
} }
@ -246,30 +261,30 @@ export class tapAndSwipe {
} }
// left swipe handler // left swipe handler
if (this._endX + this.options.threshold < this._startX) { if (this._endX + this.options.threshold < this._startX && this._distanceX > this._distanceY) {
this._distance = this._startX - this._endX; if (this._distanceX < this.options.minSwipeThreshold) return;
this.options.swipe.call(this, event, 'left', this._distance, this._fingercount); this.options.swipe.call(this, event, 'left', this._distanceX, this._fingercount);
return; return;
} }
// right swipe handler // right swipe handler
if (this._endX - this.options.threshold > this._startX) { if (this._endX - this.options.threshold > this._startX && this._distanceX > this._distanceY) {
this._distance = this._endX - this._startX; if (this._distanceX < this.options.minSwipeThreshold) return;
this.options.swipe.call(this, event, 'right', this._distance, this._fingercount); this.options.swipe.call(this, event, 'right', this._distanceX, this._fingercount);
return; return;
} }
// up swipe handler // up swipe handler
if (this._endY + this.options.threshold < this._startY) { if (this._endY + this.options.threshold < this._startY && this._distanceY > this._distanceX) {
this._distance = this._startY - this._endY; if (this._distanceY < this.options.minSwipeThreshold) return;
this.options.swipe.call(this, event, 'up', this._distance, this._fingercount); this.options.swipe.call(this, event, 'up', this._distanceY, this._fingercount);
return; return;
} }
// down swipe handler // down swipe handler
if (this._endY - this.options.threshold > this._startY) { if (this._endY - this.options.threshold > this._startY && this._distanceY > this._distanceX) {
this._distance = this._endY - this._startY; if (this._distanceY < this.options.minSwipeThreshold) return;
this.options.swipe.call(this, event, 'down', this._distance, this._fingercount); this.options.swipe.call(this, event, 'down', this._distanceY, this._fingercount);
return; return;
} }
} }

View File

@ -1287,7 +1287,7 @@ export class CalendarApp extends EgwApp
scroll_animate.call(jQuery(event.target).closest('.calendar_calTimeGrid, .calendar_plannerWidget')[0], direction, delta); scroll_animate.call(jQuery(event.target).closest('.calendar_calTimeGrid, .calendar_plannerWidget')[0], direction, delta);
return false; return false;
}, },
threshold: 100, minSwipeThreshold: 100,
allowScrolling: 'vertical' allowScrolling: 'vertical'
}); });