Added mutation queues

This commit is contained in:
Eduard Urbach 2017-07-05 21:06:38 +02:00
parent 44803adc2d
commit 4a76c12803
3 changed files with 60 additions and 14 deletions

View File

@ -2,17 +2,26 @@ import { Application } from "./Application"
import { Diff } from "./Diff" import { Diff } from "./Diff"
import { displayLocalDate } from "./DateView" import { displayLocalDate } from "./DateView"
import { findAll, delay } from "./Utils" import { findAll, delay } from "./Utils"
import { MutationQueue } from "./MutationQueue"
import * as actions from "./Actions" import * as actions from "./Actions"
export class AnimeNotifier { export class AnimeNotifier {
app: Application app: Application
visibilityObserver: IntersectionObserver
user: HTMLElement user: HTMLElement
visibilityObserver: IntersectionObserver
imageFound: MutationQueue
imageNotFound: MutationQueue
unmount: MutationQueue
constructor(app: Application) { constructor(app: Application) {
this.app = app this.app = app
this.user = null this.user = null
this.imageFound = new MutationQueue(elem => elem.classList.add("image-found"))
this.imageNotFound = new MutationQueue(elem => elem.classList.add("image-not-found"))
this.unmount = new MutationQueue(elem => elem.classList.remove("mounted"))
if("IntersectionObserver" in window) { if("IntersectionObserver" in window) {
// Enable lazy load // Enable lazy load
this.visibilityObserver = new IntersectionObserver( this.visibilityObserver = new IntersectionObserver(
@ -185,15 +194,15 @@ export class AnimeNotifier {
img.src = img.dataset.src img.src = img.dataset.src
if(img.naturalWidth === 0) { if(img.naturalWidth === 0) {
img.onload = function() { img.onload = () => {
this.classList.add("image-found") this.imageFound.queue(img)
} }
img.onerror = function() { img.onerror = () => {
this.classList.add("image-not-found") this.imageNotFound.queue(img)
} }
} else { } else {
img.classList.add("image-found") this.imageFound.queue(img)
} }
} }
@ -210,7 +219,7 @@ export class AnimeNotifier {
continue continue
} }
element.classList.remove("mounted") this.unmount.queue(element)
} }
} }

View File

@ -1,4 +1,18 @@
export class Diff { export class Diff {
// Reuse container for diffs to avoid memory allocation
static container: HTMLElement
// innerHTML will diff the element with the given HTML string and apply DOM mutations.
static innerHTML(aRoot: HTMLElement, html: string) {
if(!Diff.container) {
Diff.container = document.createElement("main")
}
Diff.container.innerHTML = html
Diff.childNodes(aRoot, Diff.container)
}
// childNodes diffs the child nodes of 2 given elements and applies DOM mutations.
static childNodes(aRoot: Node, bRoot: Node) { static childNodes(aRoot: Node, bRoot: Node) {
let aChild = [...aRoot.childNodes] let aChild = [...aRoot.childNodes]
let bChild = [...bRoot.childNodes] let bChild = [...bRoot.childNodes]
@ -33,6 +47,7 @@ export class Diff {
let elemA = a as HTMLElement let elemA = a as HTMLElement
let elemB = b as HTMLElement let elemB = b as HTMLElement
// Skip iframes
if(elemA.tagName === "IFRAME") { if(elemA.tagName === "IFRAME") {
continue continue
} }
@ -75,11 +90,4 @@ export class Diff {
Diff.childNodes(a, b) Diff.childNodes(a, b)
} }
} }
static innerHTML(aRoot: HTMLElement, html: string) {
let bRoot = document.createElement("main")
bRoot.innerHTML = html
Diff.childNodes(aRoot, bRoot)
}
} }

29
scripts/MutationQueue.ts Normal file
View File

@ -0,0 +1,29 @@
export class MutationQueue {
elements: Array<HTMLElement>
mutation: (elem: HTMLElement) => void
constructor(mutation: (elem: HTMLElement) => void) {
this.mutation = mutation
this.elements = []
}
queue(elem: HTMLElement) {
this.elements.push(elem)
if(this.elements.length === 1) {
window.requestAnimationFrame(() => this.mutateAll())
}
}
mutateAll() {
for(let i = 0; i < this.elements.length; i++) {
this.mutation(this.elements[i])
}
this.clear()
}
clear() {
this.elements.length = 0
}
}