Slightly improved diff performance
This commit is contained in:
parent
d8367b6172
commit
44369cb916
@ -1,5 +1,4 @@
|
||||
.anime-list-container
|
||||
vertical
|
||||
width 100%
|
||||
max-width 800px
|
||||
margin 0 auto
|
||||
|
@ -9,8 +9,11 @@ export function load(arn: AnimeNotifier, element: HTMLElement) {
|
||||
// Diff
|
||||
export function diff(arn: AnimeNotifier, element: HTMLElement) {
|
||||
let url = element.dataset.url || (element as HTMLAnchorElement).getAttribute("href")
|
||||
|
||||
|
||||
arn.diff(url)
|
||||
.then(() => arn.scrollTo(element))
|
||||
.then(() => {
|
||||
// Avoid instant layout thrashing
|
||||
arn.requestIdleCallback(() => arn.scrollTo(element))
|
||||
})
|
||||
.catch(console.error)
|
||||
}
|
@ -294,6 +294,10 @@ export class AnimeNotifier {
|
||||
}
|
||||
|
||||
countUp() {
|
||||
if(!this.app.currentPath.includes("/paypal/success")) {
|
||||
return
|
||||
}
|
||||
|
||||
for(let element of findAll("count-up")) {
|
||||
let final = parseInt(element.innerText)
|
||||
let duration = 2000.0
|
||||
@ -384,9 +388,7 @@ export class AnimeNotifier {
|
||||
return Promise.resolve(response)
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
Diff.root(document.documentElement, html)
|
||||
})
|
||||
.then(html => Diff.root(document.documentElement, html))
|
||||
.then(() => this.app.emit("DOMContentLoaded"))
|
||||
.then(() => this.loading(false)) // Because our loading element gets reset due to full page diff
|
||||
}
|
||||
@ -605,9 +607,7 @@ export class AnimeNotifier {
|
||||
let request = fetch(path, {
|
||||
credentials: "same-origin"
|
||||
})
|
||||
.then(response => {
|
||||
return response.text()
|
||||
})
|
||||
.then(response => response.text())
|
||||
|
||||
history.pushState(url, null, url)
|
||||
this.app.currentPath = url
|
||||
@ -617,7 +617,7 @@ export class AnimeNotifier {
|
||||
|
||||
// Delay by transition-speed
|
||||
return delay(200).then(() => request)
|
||||
.then(html => this.app.setContent(html, true))
|
||||
.then(html => Diff.innerHTML(this.app.content, html))
|
||||
.then(() => this.app.emit("DOMContentLoaded"))
|
||||
.then(() => this.loading(false))
|
||||
.catch(console.error)
|
||||
@ -664,9 +664,11 @@ export class AnimeNotifier {
|
||||
const contentPadding = 24
|
||||
|
||||
let scrollHandle: number
|
||||
let oldScroll = this.app.content.parentElement.scrollTop
|
||||
let newScroll = 0
|
||||
let finalScroll = Math.max(target.offsetTop - contentPadding, 0)
|
||||
|
||||
// Calculating scrollTop will force a layout - careful!
|
||||
let oldScroll = this.app.content.parentElement.scrollTop
|
||||
let scrollDistance = finalScroll - oldScroll
|
||||
|
||||
if(scrollDistance > 0 && scrollDistance < 4) {
|
||||
|
@ -39,7 +39,7 @@ export class Application {
|
||||
this.lastRequest.abort()
|
||||
this.lastRequest = null
|
||||
}
|
||||
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let request = new XMLHttpRequest()
|
||||
|
||||
@ -71,7 +71,7 @@ export class Application {
|
||||
if(options.addToHistory === undefined) {
|
||||
options.addToHistory = true
|
||||
}
|
||||
|
||||
|
||||
// Set current path
|
||||
this.currentPath = url
|
||||
|
||||
@ -85,14 +85,14 @@ export class Application {
|
||||
if(e.target !== this.content) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Remove listener after we finally got the correct event.
|
||||
this.content.removeEventListener("transitionend", onTransitionEnd)
|
||||
|
||||
// Wait for the network request to end.
|
||||
request.then(html => {
|
||||
// Set content
|
||||
this.setContent(html, false)
|
||||
this.setContent(html)
|
||||
this.scrollToTop()
|
||||
|
||||
// Fade animations
|
||||
@ -113,19 +113,15 @@ export class Application {
|
||||
return request
|
||||
}
|
||||
|
||||
setContent(html: string, diff: boolean) {
|
||||
if(diff) {
|
||||
Diff.innerHTML(this.content, html)
|
||||
} else {
|
||||
this.content.innerHTML = html
|
||||
}
|
||||
setContent(html: string) {
|
||||
this.content.innerHTML = html
|
||||
}
|
||||
|
||||
markActiveLinks(element?: HTMLElement) {
|
||||
if(element === undefined)
|
||||
element = document.body
|
||||
|
||||
let links = element.querySelectorAll("a")
|
||||
let links = element.getElementsByTagName("a")
|
||||
|
||||
for(let i = 0; i < links.length; i++) {
|
||||
let link = links[i]
|
||||
@ -165,7 +161,7 @@ export class Application {
|
||||
|
||||
if(!url || url === self.currentPath)
|
||||
return
|
||||
|
||||
|
||||
// Load requested page
|
||||
self.load(url)
|
||||
}
|
||||
|
@ -7,23 +7,35 @@ export class Diff {
|
||||
static rootContainer: HTMLElement
|
||||
|
||||
// innerHTML will diff the element with the given HTML string and apply DOM mutations.
|
||||
static innerHTML(aRoot: HTMLElement, html: string) {
|
||||
static innerHTML(aRoot: HTMLElement, html: string): Promise<void> {
|
||||
if(!Diff.container) {
|
||||
Diff.container = document.createElement("main")
|
||||
}
|
||||
|
||||
|
||||
Diff.container.innerHTML = html
|
||||
Diff.childNodes(aRoot, Diff.container)
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
window.requestAnimationFrame(() => {
|
||||
Diff.childNodes(aRoot, Diff.container)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// root will diff the document root element with the given HTML string and apply DOM mutations.
|
||||
static root(aRoot: HTMLElement, html: string) {
|
||||
if(!Diff.rootContainer) {
|
||||
Diff.rootContainer = document.createElement("html")
|
||||
}
|
||||
|
||||
Diff.rootContainer.innerHTML = html.replace("<!DOCTYPE html>", "")
|
||||
Diff.childNodes(aRoot.getElementsByTagName("body")[0], Diff.rootContainer.getElementsByTagName("body")[0])
|
||||
return new Promise((resolve, reject) => {
|
||||
if(!Diff.rootContainer) {
|
||||
Diff.rootContainer = document.createElement("html")
|
||||
}
|
||||
|
||||
Diff.rootContainer.innerHTML = html.replace("<!DOCTYPE html>", "")
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
Diff.childNodes(aRoot.getElementsByTagName("body")[0], Diff.rootContainer.getElementsByTagName("body")[0])
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// childNodes diffs the child nodes of 2 given elements and applies DOM mutations.
|
||||
@ -31,7 +43,7 @@ export class Diff {
|
||||
let aChild = [...aRoot.childNodes]
|
||||
let bChild = [...bRoot.childNodes]
|
||||
let numNodes = Math.max(aChild.length, bChild.length)
|
||||
|
||||
|
||||
for(let i = 0; i < numNodes; i++) {
|
||||
let a = aChild[i]
|
||||
|
||||
@ -69,7 +81,7 @@ export class Diff {
|
||||
let elemB = b as HTMLElement
|
||||
|
||||
let removeAttributes: Attr[] = []
|
||||
|
||||
|
||||
for(let x = 0; x < elemA.attributes.length; x++) {
|
||||
let attrib = elemA.attributes[x]
|
||||
|
||||
@ -119,7 +131,7 @@ export class Diff {
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
elemA.setAttribute(attrib.name, attrib.value)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user