|   | 
| /* global document */ | 
|   | 
| import { | 
|     addEventListener, | 
|     removeEventListener, | 
|     normalizeEvent, | 
|     getNativeEvent | 
| } from '../core/event'; | 
| import * as zrUtil from '../core/util'; | 
| import Eventful from '../core/Eventful'; | 
| import env from '../core/env'; | 
| import { Dictionary, ZRRawEvent, ZRRawMouseEvent } from '../core/types'; | 
| import { VectorArray } from '../core/vector'; | 
| import Handler from '../Handler'; | 
|   | 
| type DomHandlersMap = Dictionary<(this: HandlerDomProxy, event: ZRRawEvent) => void> | 
|   | 
| type DomExtended = Node & { | 
|     domBelongToZr: boolean | 
| } | 
|   | 
| const TOUCH_CLICK_DELAY = 300; | 
|   | 
| const globalEventSupported = env.domSupported; | 
|   | 
|   | 
| const localNativeListenerNames = (function () { | 
|     const mouseHandlerNames = [ | 
|         'click', 'dblclick', 'mousewheel', 'wheel', 'mouseout', | 
|         'mouseup', 'mousedown', 'mousemove', 'contextmenu' | 
|     ]; | 
|     const touchHandlerNames = [ | 
|         'touchstart', 'touchend', 'touchmove' | 
|     ]; | 
|     const pointerEventNameMap = { | 
|         pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1 | 
|     }; | 
|     const pointerHandlerNames = zrUtil.map(mouseHandlerNames, function (name) { | 
|         const nm = name.replace('mouse', 'pointer'); | 
|         return pointerEventNameMap.hasOwnProperty(nm) ? nm : name; | 
|     }); | 
|   | 
|     return { | 
|         mouse: mouseHandlerNames, | 
|         touch: touchHandlerNames, | 
|         pointer: pointerHandlerNames | 
|     }; | 
| })(); | 
|   | 
| const globalNativeListenerNames = { | 
|     mouse: ['mousemove', 'mouseup'], | 
|     pointer: ['pointermove', 'pointerup'] | 
| }; | 
|   | 
| let wheelEventSupported = false; | 
|   | 
|   | 
| // Although firfox has 'DOMMouseScroll' event and do not has 'mousewheel' event, | 
| // the 'DOMMouseScroll' event do not performe the same behavior on touch pad device | 
| // (like on Mac) ('DOMMouseScroll' will be triggered only if a big wheel delta). | 
| // So we should not use it. | 
| // function eventNameFix(name: string) { | 
| //     return (name === 'mousewheel' && env.browser.firefox) ? 'DOMMouseScroll' : name; | 
| // } | 
|   | 
| function isPointerFromTouch(event: ZRRawEvent) { | 
|     const pointerType = (event as any).pointerType; | 
|     return pointerType === 'pen' || pointerType === 'touch'; | 
| } | 
|   | 
| // function useMSGuesture(handlerProxy, event) { | 
| //     return isPointerFromTouch(event) && !!handlerProxy._msGesture; | 
| // } | 
|   | 
| // function onMSGestureChange(proxy, event) { | 
| //     if (event.translationX || event.translationY) { | 
| //         // mousemove is carried by MSGesture to reduce the sensitivity. | 
| //         proxy.handler.dispatchToElement(event.target, 'mousemove', event); | 
| //     } | 
| //     if (event.scale !== 1) { | 
| //         event.pinchX = event.offsetX; | 
| //         event.pinchY = event.offsetY; | 
| //         event.pinchScale = event.scale; | 
| //         proxy.handler.dispatchToElement(event.target, 'pinch', event); | 
| //     } | 
| // } | 
|   | 
| /** | 
|  * Prevent mouse event from being dispatched after Touch Events action | 
|  * @see <https://github.com/deltakosh/handjs/blob/master/src/hand.base.js> | 
|  * 1. Mobile browsers dispatch mouse events 300ms after touchend. | 
|  * 2. Chrome for Android dispatch mousedown for long-touch about 650ms | 
|  * Result: Blocking Mouse Events for 700ms. | 
|  * | 
|  * @param {DOMHandlerScope} scope | 
|  */ | 
| function setTouchTimer(scope: DOMHandlerScope) { | 
|     scope.touching = true; | 
|     if (scope.touchTimer != null) { | 
|         clearTimeout(scope.touchTimer); | 
|         scope.touchTimer = null; | 
|     } | 
|     scope.touchTimer = setTimeout(function () { | 
|         scope.touching = false; | 
|         scope.touchTimer = null; | 
|     }, 700); | 
| } | 
|   | 
| // Mark touch, which is useful in distinguish touch and | 
| // mouse event in upper applicatoin. | 
| function markTouch(event: ZRRawEvent) { | 
|     event && (event.zrByTouch = true); | 
| } | 
|   | 
|   | 
| // function markTriggeredFromLocal(event) { | 
| //     event && (event.__zrIsFromLocal = true); | 
| // } | 
|   | 
| // function isTriggeredFromLocal(instance, event) { | 
| //     return !!(event && event.__zrIsFromLocal); | 
| // } | 
|   | 
| function normalizeGlobalEvent(instance: HandlerDomProxy, event: ZRRawEvent) { | 
|     // offsetX, offsetY still need to be calculated. They are necessary in the event | 
|     // handlers of the upper applications. Set `true` to force calculate them. | 
|     return normalizeEvent( | 
|         instance.dom, | 
|         // TODO ANY TYPE | 
|         new FakeGlobalEvent(instance, event) as any as ZRRawEvent, | 
|         true | 
|     ); | 
| } | 
|   | 
| /** | 
|  * Detect whether the given el is in `painterRoot`. | 
|  */ | 
| function isLocalEl(instance: HandlerDomProxy, el: Node) { | 
|     let elTmp = el; | 
|     let isLocal = false; | 
|     while (elTmp && elTmp.nodeType !== 9 | 
|         && !( | 
|             isLocal = (elTmp as DomExtended).domBelongToZr | 
|                 || (elTmp !== el && elTmp === instance.painterRoot) | 
|         ) | 
|     ) { | 
|         elTmp = elTmp.parentNode; | 
|     } | 
|     return isLocal; | 
| } | 
|   | 
| /** | 
|  * Make a fake event but not change the original event, | 
|  * becuase the global event probably be used by other | 
|  * listeners not belonging to zrender. | 
|  * @class | 
|  */ | 
| class FakeGlobalEvent { | 
|     type: string | 
|     target: HTMLElement | 
|     currentTarget: HTMLElement | 
|   | 
|     pointerType: string | 
|     clientX: number | 
|     clientY: number | 
|   | 
|     constructor(instance: HandlerDomProxy, event: ZRRawEvent) { | 
|         this.type = event.type; | 
|         this.target = this.currentTarget = instance.dom; | 
|         this.pointerType = (event as any).pointerType; | 
|         // Necessray for the force calculation of zrX, zrY | 
|         this.clientX = (event as ZRRawMouseEvent).clientX; | 
|         this.clientY = (event as ZRRawMouseEvent).clientY; | 
|         // Because we do not mount global listeners to touch events, | 
|         // we do not copy `targetTouches` and `changedTouches` here. | 
|     } | 
|   | 
|     // we make the default methods on the event do nothing, | 
|     // otherwise it is dangerous. See more details in | 
|     // [DRAG_OUTSIDE] in `Handler.js`. | 
|     stopPropagation = zrUtil.noop | 
|     stopImmediatePropagation = zrUtil.noop | 
|     preventDefault = zrUtil.noop | 
| } | 
|   | 
|   | 
| /** | 
|  * Local DOM Handlers | 
|  * @this {HandlerProxy} | 
|  */ | 
| const localDOMHandlers: DomHandlersMap = { | 
|   | 
|     mousedown(event: ZRRawEvent) { | 
|         event = normalizeEvent(this.dom, event); | 
|   | 
|         this.__mayPointerCapture = [event.zrX, event.zrY]; | 
|   | 
|         this.trigger('mousedown', event); | 
|     }, | 
|   | 
|     mousemove(event: ZRRawEvent) { | 
|         event = normalizeEvent(this.dom, event); | 
|   | 
|         const downPoint = this.__mayPointerCapture; | 
|         if (downPoint && (event.zrX !== downPoint[0] || event.zrY !== downPoint[1])) { | 
|             this.__togglePointerCapture(true); | 
|         } | 
|   | 
|         this.trigger('mousemove', event); | 
|     }, | 
|   | 
|     mouseup(event: ZRRawEvent) { | 
|         event = normalizeEvent(this.dom, event); | 
|   | 
|         this.__togglePointerCapture(false); | 
|   | 
|         this.trigger('mouseup', event); | 
|     }, | 
|   | 
|     mouseout(event: ZRRawEvent) { | 
|         event = normalizeEvent(this.dom, event); | 
|   | 
|         // There might be some doms created by upper layer application | 
|         // at the same level of painter.getViewportRoot() (e.g., tooltip | 
|         // dom created by echarts), where 'globalout' event should not | 
|         // be triggered when mouse enters these doms. (But 'mouseout' | 
|         // should be triggered at the original hovered element as usual). | 
|         const element = (event as any).toElement || (event as ZRRawMouseEvent).relatedTarget; | 
|   | 
|         // For SVG rendering, there are SVG elements inside `this.dom`. | 
|         // (especially in decal case). Should not to handle those "mouseout".. | 
|         if (!isLocalEl(this, element)) { | 
|             // Similarly to the browser did on `document` and touch event, | 
|             // `globalout` will be delayed to final pointer cature release. | 
|             if (this.__pointerCapturing) { | 
|                 event.zrEventControl = 'no_globalout'; | 
|             } | 
|   | 
|             this.trigger('mouseout', event); | 
|         } | 
|     }, | 
|   | 
|     wheel(event: ZRRawEvent) { | 
|         // Morden agent has supported event `wheel` instead of `mousewheel`. | 
|         // About the polyfill of the props "delta", see "arc/core/event.ts". | 
|   | 
|         // Firefox only support `wheel` rather than `mousewheel`. Although firfox has been supporting | 
|         // event `DOMMouseScroll`, it do not act the same behavior as `wheel` on touch pad device | 
|         // like on Mac, where `DOMMouseScroll` will be triggered only if a big wheel delta occurs, | 
|         // and it results in no chance to "preventDefault". So we should not use `DOMMouseScroll`. | 
|   | 
|         wheelEventSupported = true; | 
|         event = normalizeEvent(this.dom, event); | 
|         // Follow the definition of the previous version, the zrender event name is still 'mousewheel'. | 
|         this.trigger('mousewheel', event); | 
|     }, | 
|   | 
|     mousewheel(event: ZRRawEvent) { | 
|         // IE8- and some other lagacy agent do not support event `wheel`, so we still listen | 
|         // to the legacy event `mouseevent`. | 
|         // Typically if event `wheel` is suppored and the handler has been mounted on a | 
|         // DOM element, the lagecy `mousewheel` event will not be triggered (Chrome and Safari). | 
|         // But we still do this guard to avoid to duplicated handle. | 
|         if (wheelEventSupported) { | 
|             return; | 
|         } | 
|         event = normalizeEvent(this.dom, event); | 
|         this.trigger('mousewheel', event); | 
|     }, | 
|   | 
|     touchstart(event: ZRRawEvent) { | 
|         // Default mouse behaviour should not be disabled here. | 
|         // For example, page may needs to be slided. | 
|         event = normalizeEvent(this.dom, event); | 
|   | 
|         markTouch(event); | 
|   | 
|         this.__lastTouchMoment = new Date(); | 
|   | 
|         this.handler.processGesture(event, 'start'); | 
|   | 
|         // For consistent event listener for both touch device and mouse device, | 
|         // we simulate "mouseover-->mousedown" in touch device. So we trigger | 
|         // `mousemove` here (to trigger `mouseover` inside), and then trigger | 
|         // `mousedown`. | 
|         localDOMHandlers.mousemove.call(this, event); | 
|         localDOMHandlers.mousedown.call(this, event); | 
|     }, | 
|   | 
|     touchmove(event: ZRRawEvent) { | 
|         event = normalizeEvent(this.dom, event); | 
|   | 
|         markTouch(event); | 
|   | 
|         this.handler.processGesture(event, 'change'); | 
|   | 
|         // Mouse move should always be triggered no matter whether | 
|         // there is gestrue event, because mouse move and pinch may | 
|         // be used at the same time. | 
|         localDOMHandlers.mousemove.call(this, event); | 
|     }, | 
|   | 
|     touchend(event: ZRRawEvent) { | 
|         event = normalizeEvent(this.dom, event); | 
|   | 
|         markTouch(event); | 
|   | 
|         this.handler.processGesture(event, 'end'); | 
|   | 
|         localDOMHandlers.mouseup.call(this, event); | 
|   | 
|         // Do not trigger `mouseout` here, in spite of `mousemove`(`mouseover`) is | 
|         // triggered in `touchstart`. This seems to be illogical, but by this mechanism, | 
|         // we can conveniently implement "hover style" in both PC and touch device just | 
|         // by listening to `mouseover` to add "hover style" and listening to `mouseout` | 
|         // to remove "hover style" on an element, without any additional code for | 
|         // compatibility. (`mouseout` will not be triggered in `touchend`, so "hover | 
|         // style" will remain for user view) | 
|   | 
|         // click event should always be triggered no matter whether | 
|         // there is gestrue event. System click can not be prevented. | 
|         if (+new Date() - (+this.__lastTouchMoment) < TOUCH_CLICK_DELAY) { | 
|             localDOMHandlers.click.call(this, event); | 
|         } | 
|     }, | 
|   | 
|     pointerdown(event: ZRRawEvent) { | 
|         localDOMHandlers.mousedown.call(this, event); | 
|   | 
|         // if (useMSGuesture(this, event)) { | 
|         //     this._msGesture.addPointer(event.pointerId); | 
|         // } | 
|     }, | 
|   | 
|     pointermove(event: ZRRawEvent) { | 
|         // FIXME | 
|         // pointermove is so sensitive that it always triggered when | 
|         // tap(click) on touch screen, which affect some judgement in | 
|         // upper application. So, we dont support mousemove on MS touch | 
|         // device yet. | 
|         if (!isPointerFromTouch(event)) { | 
|             localDOMHandlers.mousemove.call(this, event); | 
|         } | 
|     }, | 
|   | 
|     pointerup(event: ZRRawEvent) { | 
|         localDOMHandlers.mouseup.call(this, event); | 
|     }, | 
|   | 
|     pointerout(event: ZRRawEvent) { | 
|         // pointerout will be triggered when tap on touch screen | 
|         // (IE11+/Edge on MS Surface) after click event triggered, | 
|         // which is inconsistent with the mousout behavior we defined | 
|         // in touchend. So we unify them. | 
|         // (check localDOMHandlers.touchend for detailed explanation) | 
|         if (!isPointerFromTouch(event)) { | 
|             localDOMHandlers.mouseout.call(this, event); | 
|         } | 
|     } | 
|   | 
| }; | 
|   | 
| /** | 
|  * Othere DOM UI Event handlers for zr dom. | 
|  * @this {HandlerProxy} | 
|  */ | 
| zrUtil.each(['click', 'dblclick', 'contextmenu'], function (name) { | 
|     localDOMHandlers[name] = function (event) { | 
|         event = normalizeEvent(this.dom, event); | 
|         this.trigger(name, event); | 
|     }; | 
| }); | 
|   | 
|   | 
| /** | 
|  * DOM UI Event handlers for global page. | 
|  * | 
|  * [Caution]: | 
|  * those handlers should both support in capture phase and bubble phase! | 
|  */ | 
| const globalDOMHandlers: DomHandlersMap = { | 
|   | 
|     pointermove: function (event: ZRRawEvent) { | 
|         // FIXME | 
|         // pointermove is so sensitive that it always triggered when | 
|         // tap(click) on touch screen, which affect some judgement in | 
|         // upper application. So, we dont support mousemove on MS touch | 
|         // device yet. | 
|         if (!isPointerFromTouch(event)) { | 
|             globalDOMHandlers.mousemove.call(this, event); | 
|         } | 
|     }, | 
|   | 
|     pointerup: function (event: ZRRawEvent) { | 
|         globalDOMHandlers.mouseup.call(this, event); | 
|     }, | 
|   | 
|     mousemove: function (event: ZRRawEvent) { | 
|         this.trigger('mousemove', event); | 
|     }, | 
|   | 
|     mouseup: function (event: ZRRawEvent) { | 
|         const pointerCaptureReleasing = this.__pointerCapturing; | 
|   | 
|         this.__togglePointerCapture(false); | 
|   | 
|         this.trigger('mouseup', event); | 
|   | 
|         if (pointerCaptureReleasing) { | 
|             event.zrEventControl = 'only_globalout'; | 
|             this.trigger('mouseout', event); | 
|         } | 
|     } | 
|   | 
| }; | 
|   | 
|   | 
| function mountLocalDOMEventListeners(instance: HandlerDomProxy, scope: DOMHandlerScope) { | 
|     const domHandlers = scope.domHandlers; | 
|   | 
|     if (env.pointerEventsSupported) { // Only IE11+/Edge | 
|         // 1. On devices that both enable touch and mouse (e.g., MS Surface and lenovo X240), | 
|         // IE11+/Edge do not trigger touch event, but trigger pointer event and mouse event | 
|         // at the same time. | 
|         // 2. On MS Surface, it probablely only trigger mousedown but no mouseup when tap on | 
|         // screen, which do not occurs in pointer event. | 
|         // So we use pointer event to both detect touch gesture and mouse behavior. | 
|         zrUtil.each(localNativeListenerNames.pointer, function (nativeEventName) { | 
|             mountSingleDOMEventListener(scope, nativeEventName, function (event) { | 
|                 // markTriggeredFromLocal(event); | 
|                 domHandlers[nativeEventName].call(instance, event); | 
|             }); | 
|         }); | 
|   | 
|         // FIXME | 
|         // Note: MS Gesture require CSS touch-action set. But touch-action is not reliable, | 
|         // which does not prevent defuault behavior occasionally (which may cause view port | 
|         // zoomed in but use can not zoom it back). And event.preventDefault() does not work. | 
|         // So we have to not to use MSGesture and not to support touchmove and pinch on MS | 
|         // touch screen. And we only support click behavior on MS touch screen now. | 
|   | 
|         // MS Gesture Event is only supported on IE11+/Edge and on Windows 8+. | 
|         // We dont support touch on IE on win7. | 
|         // See <https://msdn.microsoft.com/en-us/library/dn433243(v=vs.85).aspx> | 
|         // if (typeof MSGesture === 'function') { | 
|         //     (this._msGesture = new MSGesture()).target = dom; // jshint ignore:line | 
|         //     dom.addEventListener('MSGestureChange', onMSGestureChange); | 
|         // } | 
|     } | 
|     else { | 
|         if (env.touchEventsSupported) { | 
|             zrUtil.each(localNativeListenerNames.touch, function (nativeEventName) { | 
|                 mountSingleDOMEventListener(scope, nativeEventName, function (event) { | 
|                     // markTriggeredFromLocal(event); | 
|                     domHandlers[nativeEventName].call(instance, event); | 
|                     setTouchTimer(scope); | 
|                 }); | 
|             }); | 
|             // Handler of 'mouseout' event is needed in touch mode, which will be mounted below. | 
|             // addEventListener(root, 'mouseout', this._mouseoutHandler); | 
|         } | 
|   | 
|         // 1. Considering some devices that both enable touch and mouse event (like on MS Surface | 
|         // and lenovo X240, @see #2350), we make mouse event be always listened, otherwise | 
|         // mouse event can not be handle in those devices. | 
|         // 2. On MS Surface, Chrome will trigger both touch event and mouse event. How to prevent | 
|         // mouseevent after touch event triggered, see `setTouchTimer`. | 
|         zrUtil.each(localNativeListenerNames.mouse, function (nativeEventName) { | 
|             mountSingleDOMEventListener(scope, nativeEventName, function (event: ZRRawEvent) { | 
|                 event = getNativeEvent(event); | 
|                 if (!scope.touching) { | 
|                     // markTriggeredFromLocal(event); | 
|                     domHandlers[nativeEventName].call(instance, event); | 
|                 } | 
|             }); | 
|         }); | 
|     } | 
| } | 
|   | 
| function mountGlobalDOMEventListeners(instance: HandlerDomProxy, scope: DOMHandlerScope) { | 
|     // Only IE11+/Edge. See the comment in `mountLocalDOMEventListeners`. | 
|     if (env.pointerEventsSupported) { | 
|         zrUtil.each(globalNativeListenerNames.pointer, mount); | 
|     } | 
|     // Touch event has implemented "drag outside" so we do not mount global listener for touch event. | 
|     // (see https://www.w3.org/TR/touch-events/#the-touchmove-event) (see also `DRAG_OUTSIDE`). | 
|     // We do not consider "both-support-touch-and-mouse device" for this feature (see the comment of | 
|     // `mountLocalDOMEventListeners`) to avoid bugs util some requirements come. | 
|     else if (!env.touchEventsSupported) { | 
|         zrUtil.each(globalNativeListenerNames.mouse, mount); | 
|     } | 
|   | 
|     function mount(nativeEventName: string) { | 
|         function nativeEventListener(event: ZRRawEvent) { | 
|             event = getNativeEvent(event); | 
|             // See the reason in [DRAG_OUTSIDE] in `Handler.js` | 
|             // This checking supports both `useCapture` or not. | 
|             // PENDING: if there is performance issue in some devices, | 
|             // we probably can not use `useCapture` and change a easier | 
|             // to judes whether local (mark). | 
|             if (!isLocalEl(instance, event.target as Node)) { | 
|                 event = normalizeGlobalEvent(instance, event); | 
|                 scope.domHandlers[nativeEventName].call(instance, event); | 
|             } | 
|         } | 
|         mountSingleDOMEventListener( | 
|             scope, nativeEventName, nativeEventListener, | 
|             {capture: true} // See [DRAG_OUTSIDE] in `Handler.js` | 
|         ); | 
|     } | 
| } | 
|   | 
| function mountSingleDOMEventListener( | 
|     scope: DOMHandlerScope, | 
|     nativeEventName: string, | 
|     listener: EventListener, | 
|     opt?: boolean | AddEventListenerOptions | 
| ) { | 
|     scope.mounted[nativeEventName] = listener; | 
|     scope.listenerOpts[nativeEventName] = opt; | 
|     addEventListener(scope.domTarget, nativeEventName, listener, opt); | 
| } | 
|   | 
| function unmountDOMEventListeners(scope: DOMHandlerScope) { | 
|     const mounted = scope.mounted; | 
|     for (let nativeEventName in mounted) { | 
|         if (mounted.hasOwnProperty(nativeEventName)) { | 
|             removeEventListener( | 
|                 scope.domTarget, nativeEventName, mounted[nativeEventName], | 
|                 scope.listenerOpts[nativeEventName] | 
|             ); | 
|         } | 
|     } | 
|     scope.mounted = {}; | 
| } | 
|   | 
|   | 
| class DOMHandlerScope { | 
|     domTarget: HTMLElement | HTMLDocument | 
|     domHandlers: DomHandlersMap | 
|   | 
|     // Key: eventName, value: mounted handler funcitons. | 
|     // Used for unmount. | 
|     mounted: Dictionary<EventListener> = {}; | 
|   | 
|     listenerOpts: Dictionary<boolean | AddEventListenerOptions> = {}; | 
|   | 
|     touchTimer: ReturnType<typeof setTimeout>; | 
|     touching = false; | 
|   | 
|     constructor( | 
|         domTarget: HTMLElement | HTMLDocument, | 
|         domHandlers: DomHandlersMap | 
|     ) { | 
|         this.domTarget = domTarget; | 
|         this.domHandlers = domHandlers; | 
|   | 
|     } | 
| } | 
|   | 
|   | 
| export default class HandlerDomProxy extends Eventful { | 
|   | 
|     dom: HTMLElement | 
|     painterRoot: HTMLElement | 
|   | 
|     handler: Handler | 
|   | 
|     private _localHandlerScope: DOMHandlerScope | 
|     private _globalHandlerScope: DOMHandlerScope | 
|   | 
|     __lastTouchMoment: Date | 
|   | 
|     // See [DRAG_OUTSIDE] in `Handler.ts`. | 
|     __pointerCapturing = false | 
|     // [x, y] | 
|     __mayPointerCapture: VectorArray | 
|   | 
|   | 
|     constructor(dom: HTMLElement, painterRoot: HTMLElement) { | 
|         super(); | 
|   | 
|         this.dom = dom; | 
|         this.painterRoot = painterRoot; | 
|   | 
|         this._localHandlerScope = new DOMHandlerScope(dom, localDOMHandlers); | 
|   | 
|         if (globalEventSupported) { | 
|             this._globalHandlerScope = new DOMHandlerScope(document, globalDOMHandlers); | 
|         } | 
|   | 
|         mountLocalDOMEventListeners(this, this._localHandlerScope); | 
|     } | 
|   | 
|     dispose() { | 
|         unmountDOMEventListeners(this._localHandlerScope); | 
|         if (globalEventSupported) { | 
|             unmountDOMEventListeners(this._globalHandlerScope); | 
|         } | 
|     } | 
|   | 
|     setCursor(cursorStyle: string) { | 
|         this.dom.style && (this.dom.style.cursor = cursorStyle || 'default'); | 
|     } | 
|   | 
|     /** | 
|      * See [DRAG_OUTSIDE] in `Handler.js`. | 
|      * @implement | 
|      * @param isPointerCapturing Should never be `null`/`undefined`. | 
|      *        `true`: start to capture pointer if it is not capturing. | 
|      *        `false`: end the capture if it is capturing. | 
|      */ | 
|     __togglePointerCapture(isPointerCapturing?: boolean) { | 
|         this.__mayPointerCapture = null; | 
|   | 
|         if (globalEventSupported | 
|             && ((+this.__pointerCapturing) ^ (+isPointerCapturing)) | 
|         ) { | 
|             this.__pointerCapturing = isPointerCapturing; | 
|   | 
|             const globalHandlerScope = this._globalHandlerScope; | 
|             isPointerCapturing | 
|                 ? mountGlobalDOMEventListeners(this, globalHandlerScope) | 
|                 : unmountDOMEventListeners(globalHandlerScope); | 
|         } | 
|     } | 
| } | 
|   | 
| export interface HandlerProxyInterface extends Eventful { | 
|     handler: Handler | 
|     dispose: () => void | 
|     setCursor: (cursorStyle?: string) => void | 
| } |