import { Points } from './utils.js' import { Capabilities } from './capabilities.js' export class FrameContainer { constructor(element) { this.element = element this.delegate = new InteractionMapper(element, this, { mouseWheelElement: window }) } capture(event) { return true } findTarget(event, local, global) { let found = document.elementFromPoint(global.x, global.y) let iframe = found.querySelector('iframe') if (iframe) { let p = Points.fromPageToNode(found, global) let doc = iframe.contentWindow.document let target = doc.elementFromPoint(p.x, p.y) if (target != null) { console.log('iframe element', target) return new FrameTarget(iframe, target) } } return null } } export class FrameTarget { constructor(frame, target, debug = false) { this.frame = frame this.target = target this.debug = debug } capture(event) { return true } simulateMouseEvent(type, point) { let p = Points.fromPageToNode(this.frame, point) let event = new MouseEvent(type, { view: this.frame.contentWindow, bubbles: true, cancelable: true, clientX: p.x, clientY: p.y }) this.target.dispatchEvent(event) } createTouchList(pointMap) { let touches = [] let doc = this.frame.contentWindow.document for (let key of pointMap.keys()) { let point = pointMap.get(key) let p = Points.fromPageToNode(this.frame, point) let touchTarget = doc.elementFromPoint(p.x, p.y) let touch = new Touch(undefined, touchTarget, key, p.x, p.y, p.x, p.y) touches.push(touch) } return new TouchList(...touches) } simulateTouchEventChrome(type, point, pointMap) { let doc = this.frame.contentWindow.document let p = Points.fromPageToNode(this.frame, point) let touchTarget = doc.elementFromPoint(p.x, p.y) const touchObj = new Touch({ identifier: Date.now(), target: touchTarget, clientX: p.x, clientY: p.y, pageX: p.x, pageY: p.y, radiusX: 2.5, radiusY: 2.5, rotationAngle: 10, force: 0.5 }) const touchEvent = new TouchEvent(type, { cancelable: true, bubbles: true, touches: [touchObj], targetTouches: [touchObj], changedTouches: [touchObj], shiftKey: false }) if (this.debug) console.log('simulateTouchEventChrome', touchEvent) this.target.dispatchEvent(touchEvent) } simulateTouchEventSafari(type, point, pointMap, touchEventKey = 'targetTouches') { let p = Points.fromPageToNode(this.frame, point) let data = { view: this.frame.contentWindow, bubbles: true, cancelable: true, clientX: p.x, clientY: p.y } data[touchEventKey] = this.createTouchList(pointMap) let event = new TouchEvent(type, data) if (this.debug) console.log('simulateTouchEventChrome', touchEvent) this.target.dispatchEvent(event) } simulateTouchEvent(type, point, pointMap, touchEventKey = 'targetTouches') { if (Capabilities.isSafari) { this.simulateTouchEventSafari(type, point, pointMap, touchEventKey) } else { this.simulateTouchEventChrome(type, point, pointMap) } } isMouseLikeEvent(event) { return event.type.startsWith('mouse') || event.type.startsWith('pointer') } onStart(event, interaction) { if (this.debug) console.log('onStart', this.frame.parentNode) for (let [key, point] of interaction.current.entries()) { if (this.isMouseLikeEvent(event)) { this.simulateMouseEvent('mousedown', point) } else { this.simulateTouchEvent('touchstart', point, interaction.current) return } } } onMove(event, interaction) { if (this.debug) console.log('onMove') for (let [key, point] of interaction.current.entries()) { if (this.isMouseLikeEvent(event)) { this.simulateMouseEvent('mousemove', point) } else { this.simulateTouchEvent('touchmove', point, interaction.current) return } } } onEnd(event, interaction) { if (this.debug) console.log('onEnd') for (let [key, point] of interaction.current.entries()) { if (this.isMouseLikeEvent(event)) { this.simulateMouseEvent('mouseend', point) } else { this.simulateTouchEvent('touchend', point, interaction.ended, 'changedTouches') return } } } }