iwmlib/lib/frames.js

160 lines
5.0 KiB
JavaScript
Executable File

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
}
}
}
}