-
Notifications
You must be signed in to change notification settings - Fork 436
/
Copy pathframe_renderer.js
84 lines (72 loc) · 2.45 KB
/
frame_renderer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { activateScriptElement, nextRepaint } from "../../util"
import { Renderer } from "../renderer"
export class FrameRenderer extends Renderer {
static renderElement(currentElement, newElement) {
const destinationRange = document.createRange()
destinationRange.selectNodeContents(currentElement)
destinationRange.deleteContents()
const frameElement = newElement
const sourceRange = frameElement.ownerDocument?.createRange()
if (sourceRange) {
sourceRange.selectNodeContents(frameElement)
currentElement.appendChild(sourceRange.extractContents())
}
}
constructor(delegate, currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
super(currentSnapshot, newSnapshot, renderElement, isPreview, willRender)
this.delegate = delegate
}
get shouldRender() {
return true
}
async render() {
await nextRepaint()
this.preservingPermanentElements(() => {
this.loadFrameElement()
})
this.scrollFrameIntoView()
await nextRepaint()
this.focusFirstAutofocusableElement()
await nextRepaint()
this.activateScriptElements()
}
loadFrameElement() {
this.delegate.willRenderFrame(this.currentElement, this.newElement)
this.renderElement(this.currentElement, this.newElement)
}
scrollFrameIntoView() {
if (this.currentElement.autoscroll || this.newElement.autoscroll) {
const element = this.currentElement.firstElementChild
const block = readScrollLogicalPosition(this.currentElement.getAttribute("data-autoscroll-block"), "end")
const behavior = readScrollBehavior(this.currentElement.getAttribute("data-autoscroll-behavior"), "auto")
if (element) {
element.scrollIntoView({ block, behavior })
return true
}
}
return false
}
activateScriptElements() {
for (const inertScriptElement of this.newScriptElements) {
const activatedScriptElement = activateScriptElement(inertScriptElement)
inertScriptElement.replaceWith(activatedScriptElement)
}
}
get newScriptElements() {
return this.currentElement.querySelectorAll("script")
}
}
function readScrollLogicalPosition(value, defaultValue) {
if (value == "end" || value == "start" || value == "center" || value == "nearest") {
return value
} else {
return defaultValue
}
}
function readScrollBehavior(value, defaultValue) {
if (value == "auto" || value == "smooth") {
return value
} else {
return defaultValue
}
}