UNPKG

igniteui-angular-sovn

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

184 lines (167 loc) 6.12 kB
import { Inject, Injectable, NgZone } from "@angular/core"; import { ɵgetDOM as getDOM } from "@angular/platform-browser"; import { DOCUMENT } from "@angular/common"; import { PlatformUtil } from "./utils"; const EVENT_SUFFIX = "precise"; /** * Touch gestures manager based on Hammer.js * Use with caution, this will track references for single manager per element. Very TBD. Much TODO. * * @hidden */ @Injectable() export class HammerGesturesManager { /** * Event option defaults for each recognizer, see http://hammerjs.github.io/api/ for API listing. */ protected hammerOptions: HammerOptions = {}; private platformBrowser: boolean; private _hammerManagers: Array<{ element: EventTarget; manager: HammerManager; }> = []; constructor( private _zone: NgZone, @Inject(DOCUMENT) private doc: any, private platformUtil: PlatformUtil ) { this.platformBrowser = this.platformUtil.isBrowser; if (this.platformBrowser) { this.hammerOptions = { // D.P. #447 Force TouchInput due to PointerEventInput bug (https://github.com/hammerjs/hammer.js/issues/1065) // see https://github.com/IgniteUI/igniteui-angular-sovn/issues/447#issuecomment-324601803 inputClass: Hammer.TouchInput, recognizers: [ [Hammer.Pan, { threshold: 0 }], [Hammer.Swipe, { direction: Hammer.DIRECTION_HORIZONTAL }], [Hammer.Tap], [Hammer.Tap, { event: "doubletap", taps: 2 }, ["tap"]], ], }; } } public supports(eventName: string): boolean { return eventName.toLowerCase().endsWith("." + EVENT_SUFFIX); } /** * Add listener extended with options for Hammer.js. Will use defaults if none are provided. * Modeling after other event plugins for easy future modifications. */ public addEventListener( element: HTMLElement, eventName: string, eventHandler: (eventObj) => void, options: HammerOptions = null ): () => void { if (!this.platformBrowser) { return; } // Creating the manager bind events, must be done outside of angular return this._zone.runOutsideAngular(() => { let mc: HammerManager = this.getManagerForElement(element); if (mc === null) { // new Hammer is a shortcut for Manager with defaults mc = new Hammer( element, Object.assign(this.hammerOptions, options) ); this.addManagerForElement(element, mc); } const handler = (eventObj) => this._zone.run(() => eventHandler(eventObj)); mc.on(eventName, handler); return () => mc.off(eventName, handler); }); } /** * Add listener extended with options for Hammer.js. Will use defaults if none are provided. * Modeling after other event plugins for easy future modifications. * * @param target Can be one of either window, body or document(fallback default). */ public addGlobalEventListener( target: string, eventName: string, eventHandler: (eventObj) => void ): () => void { if (!this.platformBrowser) { return; } const element = this.getGlobalEventTarget(target); // Creating the manager bind events, must be done outside of angular return this.addEventListener( element as HTMLElement, eventName, eventHandler ); } /** * Exposes [Dom]Adapter.getGlobalEventTarget to get global event targets. * Supported: window, document, body. Defaults to document for invalid args. * * @param target Target name */ public getGlobalEventTarget(target: string): EventTarget { return getDOM().getGlobalEventTarget(this.doc, target); } /** * Set HammerManager options. * * @param element The DOM element used to create the manager on. * * ### Example * * ```ts * manager.setManagerOption(myElem, "pan", { pointers: 1 }); * ``` */ public setManagerOption(element: EventTarget, event: string, options: any) { const manager = this.getManagerForElement(element); manager.get(event).set(options); } /** * Add an element and manager map to the internal collection. * * @param element The DOM element used to create the manager on. */ public addManagerForElement(element: EventTarget, manager: HammerManager) { this._hammerManagers.push({ element, manager }); } /** * Get HammerManager for the element or null * * @param element The DOM element used to create the manager on. */ public getManagerForElement(element: EventTarget): HammerManager { const result = this._hammerManagers.filter( (value) => value.element === element ); return result.length ? result[0].manager : null; } /** * Destroys the HammerManager for the element, removing event listeners in the process. * * @param element The DOM element used to create the manager on. */ public removeManagerForElement(element: HTMLElement) { let index: number = null; for (let i = 0; i < this._hammerManagers.length; i++) { if (element === this._hammerManagers[i].element) { index = i; break; } } if (index !== null) { const item = this._hammerManagers.splice(index, 1)[0]; // destroy also item.manager.destroy(); } } /** Destroys all internally tracked HammerManagers, removing event listeners in the process. */ public destroy() { for (const item of this._hammerManagers) { item.manager.destroy(); } this._hammerManagers = []; } }