160 lines
5.0 KiB
JavaScript
Executable File
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
|
|
}
|
|
}
|
|
}
|
|
}
|