egroupware_official/api/js/tapandswipe.ts
2022-05-25 17:40:54 +02:00

179 lines
4.4 KiB
TypeScript

/**
* 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);
}
}