mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-08 09:04:53 +01:00
Replace jquery-ui swipe with tapandswipe library
This commit is contained in:
parent
a5fe6d938b
commit
b8d348d30c
@ -18,6 +18,7 @@ import {egwAction, egwActionImplementation, egwActionObject} from './egw_action.
|
|||||||
import {egwFnct} from './egw_action_common.js';
|
import {egwFnct} from './egw_action_common.js';
|
||||||
import {egwMenu, _egw_active_menu} from "./egw_menu.js";
|
import {egwMenu, _egw_active_menu} from "./egw_menu.js";
|
||||||
import {EGW_KEY_ENTER, EGW_KEY_MENU} from "./egw_action_constants.js";
|
import {EGW_KEY_ENTER, EGW_KEY_MENU} from "./egw_action_constants.js";
|
||||||
|
import {tapAndSwipe} from "../tapandswipe";
|
||||||
|
|
||||||
if (typeof window._egwActionClasses == "undefined")
|
if (typeof window._egwActionClasses == "undefined")
|
||||||
window._egwActionClasses = {};
|
window._egwActionClasses = {};
|
||||||
@ -280,35 +281,23 @@ export function egwPopupActionImplementation()
|
|||||||
};
|
};
|
||||||
ai._handleTapHold = function (_node, _callback)
|
ai._handleTapHold = function (_node, _callback)
|
||||||
{
|
{
|
||||||
let holdTimer = 600;
|
|
||||||
let maxDistanceAllowed = 40;
|
|
||||||
let tapTimeout = null;
|
|
||||||
let startx = 0;
|
|
||||||
let starty = 0;
|
|
||||||
|
|
||||||
//TODO (todo-jquery): ATM we need to convert the possible given jquery dom node object into DOM Element, this
|
//TODO (todo-jquery): ATM we need to convert the possible given jquery dom node object into DOM Element, this
|
||||||
// should be no longer neccessary after removing jQuery nodes.
|
// should be no longer neccessary after removing jQuery nodes.
|
||||||
if (_node instanceof jQuery)
|
if (_node instanceof jQuery)
|
||||||
{
|
{
|
||||||
_node = _node[0];
|
_node = _node[0];
|
||||||
}
|
}
|
||||||
_node.addEventListener('touchstart', function(e){
|
|
||||||
|
|
||||||
tapTimeout = setTimeout(function(event){
|
let tap = new tapAndSwipe(_node, {
|
||||||
_callback(e);
|
// this threshold must be the same as the one set in et2_dataview_view_aoi
|
||||||
}, holdTimer);
|
tapHoldThreshold: 600,
|
||||||
startx = (e.changedTouches) ? e.changedTouches[0].pageX: e.pageX;
|
tapAndHold: function(event)
|
||||||
starty = (e.changedTouches) ? e.changedTouches[0].pageY: e.pageY;
|
{
|
||||||
});
|
// don't trigger contextmenu if sorting is happening
|
||||||
_node.addEventListener('touchend', function(){
|
if (document.querySelector('.sortable-drag')) return;
|
||||||
clearTimeout(tapTimeout);
|
|
||||||
});
|
_callback(event);
|
||||||
_node.addEventListener('touchmove', function(_event){
|
}
|
||||||
if (tapTimeout == null) return;
|
|
||||||
let e = _event.originalEvent;
|
|
||||||
let x = (e.changedTouches) ? e.changedTouches[0].pageX: e.pageX;
|
|
||||||
let y = (e.changedTouches) ? e.changedTouches[0].pageY: e.pageY;
|
|
||||||
if (Math.sqrt((x-startx)*(x-startx) + (y-starty)+(y-starty)) > maxDistanceAllowed) clearTimeout(tapTimeout);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -350,7 +339,7 @@ export function egwPopupActionImplementation()
|
|||||||
// Safari still needs the taphold to trigger contextmenu
|
// Safari still needs the taphold to trigger contextmenu
|
||||||
// Chrome has default event on touch and hold which acts like right click
|
// Chrome has default event on touch and hold which acts like right click
|
||||||
this._handleTapHold(_node, contextHandler);
|
this._handleTapHold(_node, contextHandler);
|
||||||
jQuery(_node).on('contextmenu', contextHandler);
|
if (!egwIsMobile()) jQuery(_node).on('contextmenu', contextHandler);
|
||||||
};
|
};
|
||||||
|
|
||||||
ai.doRegisterAction = function(_aoi, _callback, _context)
|
ai.doRegisterAction = function(_aoi, _callback, _context)
|
||||||
|
@ -23,6 +23,7 @@ import {EGW_AO_SHIFT_STATE_MULTI,
|
|||||||
EGW_AO_STATE_SELECTED} from '../egw_action/egw_action_constants.js';
|
EGW_AO_STATE_SELECTED} from '../egw_action/egw_action_constants.js';
|
||||||
import {egwBitIsSet, egwGetShiftState, egwPreventSelect, egwSetBit, egwUnfocus, egwIsMobile} from "../egw_action/egw_action_common.js";
|
import {egwBitIsSet, egwGetShiftState, egwPreventSelect, egwSetBit, egwUnfocus, egwIsMobile} from "../egw_action/egw_action_common.js";
|
||||||
import {_egw_active_menu} from "../egw_action/egw_menu.js";
|
import {_egw_active_menu} from "../egw_action/egw_menu.js";
|
||||||
|
import {tapAndSwipe} from "../tapandswipe";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the action object interface implementation for the nextmatch widget
|
* Contains the action object interface implementation for the nextmatch widget
|
||||||
@ -114,23 +115,21 @@ export function et2_dataview_rowAOI(_node)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (egwIsMobile()) {
|
if (egwIsMobile()) {
|
||||||
jQuery(_node).swipe({
|
let swipe = new tapAndSwipe(_node,{
|
||||||
allowPageScroll: "vertical",
|
// set the same threshold as action_popup event to get the tapAndHold working
|
||||||
longTapThreshold: 10,
|
tapHoldThreshold: 600,
|
||||||
swipe: function (event, direction, distance)
|
swipe: function (event, direction, distance)
|
||||||
{
|
{
|
||||||
if (distance > 100) selectHandler(event, {swip:direction});
|
if (distance > 100) selectHandler(event, {swip:direction});
|
||||||
},
|
},
|
||||||
tap: function (event, duration)
|
tap: function (event)
|
||||||
{
|
{
|
||||||
selectHandler(event);
|
selectHandler(event);
|
||||||
},
|
},
|
||||||
// stop scrolling touch being confused from tap
|
tapAndHold: function(event)
|
||||||
longTap: function (event)
|
{
|
||||||
{
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
jQuery(_node).click(selectHandler);
|
jQuery(_node).click(selectHandler);
|
||||||
|
179
api/js/tapandswipe.ts
Normal file
179
api/js/tapandswipe.ts
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/**
|
||||||
|
* EGroupware TapAndSwipe helper library
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package Api
|
||||||
|
* @subpackage ui
|
||||||
|
* @link https://www.egroupware.org
|
||||||
|
* @author Hadi Nategh <hn@egroupware.org>
|
||||||
|
*/
|
||||||
|
export interface TapAndSwipeOptions {
|
||||||
|
// 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,
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TapAndSwipeOptionsType = TapAndSwipeOptions;
|
||||||
|
|
||||||
|
export class tapAndSwipe {
|
||||||
|
static readonly _default : TapAndSwipeOptionsType = {
|
||||||
|
threshold : 10,
|
||||||
|
tapHoldThreshold : 3000,
|
||||||
|
swipe : function(){},
|
||||||
|
tap : function(){},
|
||||||
|
tapAndHold: function(){}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Keeps the touch X start point
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _startX : number = null;
|
||||||
|
/**
|
||||||
|
* Keeps the touch Y start point
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _startY : number = null;
|
||||||
|
/**
|
||||||
|
* Keeps the touch X end point
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _endX : number = null;
|
||||||
|
/**
|
||||||
|
* Keeps the touch Y end point
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _endY : number = null;
|
||||||
|
/**
|
||||||
|
* keeps the distance travelled between start point and end point
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _distance : number = null;
|
||||||
|
/**
|
||||||
|
* flag to keep the status of type of tap
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _isTapAndHold : boolean = false;
|
||||||
|
/**
|
||||||
|
* keeps the timeout id for taphold
|
||||||
|
*/
|
||||||
|
private _tapHoldTimeout : number = null;
|
||||||
|
/**
|
||||||
|
* Options
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
protected options : TapAndSwipeOptionsType = null;
|
||||||
|
/**
|
||||||
|
* Keeps the html node
|
||||||
|
*/
|
||||||
|
private _element : HTMLElement = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param _element
|
||||||
|
* @param _options
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* on touch start event handler
|
||||||
|
* @param event
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _onTouchStart(event : TouchEvent)
|
||||||
|
{
|
||||||
|
this._startX = event.changedTouches[0].screenX;
|
||||||
|
this._startY = event.changedTouches[0].screenY;
|
||||||
|
this._isTapAndHold = false;
|
||||||
|
|
||||||
|
this._tapHoldTimeout = window.setTimeout(_=>{
|
||||||
|
this._isTapAndHold = true;
|
||||||
|
this.options.tapAndHold(event);
|
||||||
|
}, this.options.tapHoldThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On touch end event handler
|
||||||
|
* @param event
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _ontouchEnd(event : TouchEvent)
|
||||||
|
{
|
||||||
|
this._endX = event.changedTouches[0].screenX;
|
||||||
|
this._endY = event.changedTouches[0].screenY;
|
||||||
|
this._handler(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the type of gesture and calls the right callback for it
|
||||||
|
* @param event
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private _handler(event : TouchEvent)
|
||||||
|
{
|
||||||
|
//cleanup tapHoldTimeout
|
||||||
|
window.clearTimeout(this._tapHoldTimeout);
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
< this.options.threshold))
|
||||||
|
{
|
||||||
|
if (!this._isTapAndHold)
|
||||||
|
{
|
||||||
|
this.options.tap(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// left swipe handler
|
||||||
|
if (this._endX + this.options.threshold < this._startX) {
|
||||||
|
this._distance = this._startX - this._endX;
|
||||||
|
this.options.swipe(event, 'left', this._distance);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* destroy the event listeners
|
||||||
|
*/
|
||||||
|
public destroy()
|
||||||
|
{
|
||||||
|
this._element.removeEventListener('touchstart', this._onTouchStart);
|
||||||
|
this._element.removeEventListener('touchend', this._ontouchEnd);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user