| 
					
				 | 
			
			
				@@ -1,11 +1,18 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { AbstractDisplayInteractionManager } from "./AbstractDisplayInteractionManager"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { PointF2D } from "../Common/DataObjects/PointF2D"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Dictionary } from "typescript-collections"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 export class WebDisplayInteractionManager extends AbstractDisplayInteractionManager { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     protected isTouchDevice: boolean = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     protected osmdSheetMusicContainer: HTMLElement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     protected fullOffsetLeft: number = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     protected fullOffsetTop: number = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected fullScrollTop: number = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected fullScrollLeft: number = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //Using map instead of collections dictionary because map supports using objects as keys properly 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected parentScrollMap: Map<HTMLElement, number[]> = new Map<HTMLElement, number[]>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected scrollCallbackMap: Map<HTMLElement, (this: HTMLElement, ev: Event) => any> = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 new Map<HTMLElement, (this: HTMLElement, ev: Event) => any>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     constructor(osmdContainer: HTMLElement) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         super(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -14,22 +21,136 @@ export class WebDisplayInteractionManager extends AbstractDisplayInteractionMana 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         this.listenForInteractions(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public get FullOffsetTop(): number { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return this.fullOffsetTop; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public get FullScrollTop(): number { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return this.fullScrollTop; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public get FullOffsetLeft(): number { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return this.fullOffsetLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public get FullScrollLeft(): number { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return this.fullScrollLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected timeout: NodeJS.Timeout = undefined; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected static resizeCallback(entries: ResizeObserverEntry[]|HTMLElement[], self: WebDisplayInteractionManager): void { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //debounce resize callback 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        clearTimeout(self.timeout); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.timeout = setTimeout(()=> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self.fullOffsetLeft = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self.fullOffsetTop = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let nextOffsetParent: HTMLElement = self.osmdSheetMusicContainer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            while (nextOffsetParent) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.fullOffsetLeft += nextOffsetParent.offsetLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.fullOffsetTop += nextOffsetParent.offsetTop; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                nextOffsetParent = nextOffsetParent.offsetParent as HTMLElement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self.resizeEventListener(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self.deregisterScrollOffsets(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            self.registerScrollOffsets(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }, 500); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected registerScrollOffsets(): void { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let nextScrollParent: HTMLElement = this.osmdSheetMusicContainer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.fullScrollTop = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.fullScrollLeft = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const self: WebDisplayInteractionManager = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        while(nextScrollParent && nextScrollParent !== document.documentElement){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.parentScrollMap.set(nextScrollParent, [nextScrollParent.scrollTop, nextScrollParent.scrollLeft]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.fullScrollLeft += nextScrollParent.scrollLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.fullScrollTop += nextScrollParent.scrollTop; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(nextScrollParent.scrollHeight > nextScrollParent.clientHeight){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const nextScrollCallback: (this: HTMLElement, ev: Event) => any = function(scrollEvent: Event): void{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    //@ts-ignore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    const currentScroll: number[] = self.parentScrollMap.get(this); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    const currentScrollTop: number = currentScroll[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    const currentScrollLeft: number = currentScroll[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    //@ts-ignore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self.fullScrollTop = self.fullScrollTop - currentScrollTop + this.scrollTop; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    //@ts-ignore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self.fullScrollLeft = self.fullScrollLeft - currentScrollLeft + this.scrollLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    //@ts-ignore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    self.parentScrollMap.set(this, [this.scrollTop, this.scrollLeft]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                this.scrollCallbackMap.set(nextScrollParent, nextScrollCallback); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                nextScrollParent.addEventListener("scroll", nextScrollCallback); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            nextScrollParent = nextScrollParent.parentElement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected deregisterScrollOffsets(): void { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for(const key of this.scrollCallbackMap.keys()){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            key.removeEventListener("scroll", this.scrollCallbackMap.get(key)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.scrollCallbackMap.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected disposeResizeListener: Function; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected resizeObserver: ResizeObserver = undefined; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     protected initialize(): void { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         this.fullOffsetLeft = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         this.fullOffsetTop = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let nextParent: HTMLElement = this.osmdSheetMusicContainer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        while (nextParent) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            this.fullOffsetLeft += nextParent.offsetLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            this.fullOffsetTop += nextParent.offsetTop; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            nextParent = nextParent.offsetParent as HTMLElement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let nextOffsetParent: HTMLElement = this.osmdSheetMusicContainer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const entries: HTMLElement[] = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const self: WebDisplayInteractionManager = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(ResizeObserver){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.resizeObserver = new ResizeObserver((observedElements: ResizeObserverEntry[]) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                WebDisplayInteractionManager.resizeCallback(observedElements, self); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        while (nextOffsetParent) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.fullOffsetLeft += nextOffsetParent.offsetLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.fullOffsetTop += nextOffsetParent.offsetTop; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(!ResizeObserver){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                entries.push(nextOffsetParent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                this.resizeObserver.observe(nextOffsetParent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            nextOffsetParent = nextOffsetParent.offsetParent as HTMLElement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(!ResizeObserver){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let resizeListener: (this: Window, ev: UIEvent) => any = (): void => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                WebDisplayInteractionManager.resizeCallback(entries, self); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //Resize observer not avail. on this browser, default to window event 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            window.addEventListener("resize", resizeListener); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.disposeResizeListener = (): void => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                window.removeEventListener("resize", resizeListener); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                resizeListener = undefined; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.disposeResizeListener = (): void => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.resizeObserver.disconnect(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.resizeObserver = undefined; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.registerScrollOffsets(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     protected dispose(): void { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        this.osmdSheetMusicContainer.removeEventListener(this.downEventName, this.downEventListener); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        this.osmdSheetMusicContainer.removeEventListener("touchend", this.touchEndEventListener.bind(this)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        this.osmdSheetMusicContainer.removeEventListener(this.moveEventName, this.moveEventListener); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        window.removeEventListener("resize", this.resizeEventListener.bind(this)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.disposeResizeListener(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for(const eventName of this.EventCallbackMap.keys()){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const result: [HTMLElement|Document, EventListener] = this.EventCallbackMap.getValue(eventName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result[0].removeEventListener(eventName, result[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.EventCallbackMap.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.deregisterScrollOffsets(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.scrollCallbackMap.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.parentScrollMap.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     //TODO: Much of this pulled from annotations code. Once we get the two branches together, combine common code 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -51,17 +172,19 @@ export class WebDisplayInteractionManager extends AbstractDisplayInteractionMana 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     protected get moveEventName(): string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return this.isTouchDevice ? "touchmove" : "mousemove"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected EventCallbackMap: Dictionary<string, [HTMLElement|Document, EventListener]> = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                new Dictionary<string, [HTMLElement|Document, EventListener]>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private listenForInteractions(): void { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        const self: WebDisplayInteractionManager = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //this.osmdSheetMusicContainer[this.downEventName] = this.downEventListener.bind(this); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        this.osmdSheetMusicContainer.addEventListener(this.downEventName, this.downEventListener.bind(this)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        this.osmdSheetMusicContainer.addEventListener("touchend", this.touchEndEventListener.bind(this)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        document.addEventListener(self.moveEventName, this.moveEventListener.bind(this)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        window.addEventListener("resize", this.resizeEventListener.bind(this)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const downEvent: (clickEvent: MouseEvent | TouchEvent) => void = this.downEventListener.bind(this); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const endTouchEvent: (clickEvent: TouchEvent) => void = this.touchEndEventListener.bind(this); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const moveEvent: (clickEvent: MouseEvent | TouchEvent) => void = this.moveEventListener.bind(this); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.osmdSheetMusicContainer.addEventListener(this.downEventName, downEvent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.osmdSheetMusicContainer.addEventListener("touchend", endTouchEvent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        document.addEventListener(this.moveEventName, moveEvent); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.EventCallbackMap.setValue(this.downEventName, [this.osmdSheetMusicContainer, downEvent]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.EventCallbackMap.setValue("touchend", [this.osmdSheetMusicContainer, endTouchEvent]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.EventCallbackMap.setValue(this.moveEventName, [document, moveEvent]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     //Millis of how long is valid for the next click of a double click 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -102,12 +225,18 @@ export class WebDisplayInteractionManager extends AbstractDisplayInteractionMana 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private moveEventListener(mouseMoveEvent: MouseEvent | TouchEvent): void { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        //mouseMoveEvent.preventDefault(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let x: number = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let y: number = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (this.isTouchDevice && mouseMoveEvent instanceof TouchEvent) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            x = mouseMoveEvent.touches[0].clientX; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            y = mouseMoveEvent.touches[0].clientY; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let touch: Touch = undefined; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(mouseMoveEvent.touches && mouseMoveEvent.touches.length > 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                touch = mouseMoveEvent.touches[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else if(mouseMoveEvent.changedTouches && mouseMoveEvent.changedTouches.length > 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                touch = mouseMoveEvent.changedTouches[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            x = touch?.clientX; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            y = touch?.clientY; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else if (mouseMoveEvent instanceof MouseEvent) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             x = mouseMoveEvent.clientX; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             y = mouseMoveEvent.clientY; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -117,7 +246,13 @@ export class WebDisplayInteractionManager extends AbstractDisplayInteractionMana 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private touchEndEventListener(clickEvent: TouchEvent): void { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        const touchMinusOffset: PointF2D = this.getOffsetCoordinates(clickEvent.touches[0].pageX, clickEvent.touches[0].pageY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let touch: Touch = undefined; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(clickEvent.touches && clickEvent.touches.length > 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            touch = clickEvent.touches[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else if(clickEvent.changedTouches && clickEvent.changedTouches.length > 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            touch = clickEvent.changedTouches[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const touchMinusOffset: PointF2D = this.getOffsetCoordinates(touch?.pageX, touch?.pageY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         this.touchUp(touchMinusOffset.x, touchMinusOffset.y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -127,8 +262,8 @@ export class WebDisplayInteractionManager extends AbstractDisplayInteractionMana 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private getOffsetCoordinates(clickX: number, clickY: number): PointF2D { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        const sheetX: number = clickX - this.fullOffsetLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        const sheetY: number = clickY - this.fullOffsetTop; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const sheetX: number = clickX - this.fullOffsetLeft + this.fullScrollLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const sheetY: number = clickY - this.fullOffsetTop + this.fullScrollTop; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return new PointF2D(sheetX, sheetY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |