From b5efaf0bb1d32a842be689e5090d7387e9c268d1 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Wed, 14 Mar 2018 15:13:16 +0100 Subject: [PATCH] Added experimental scripts --- .../Experimental/Diff-onMutationsQueued.ts | 39 ++++ scripts/Experimental/Diff-with-callbacks.ts | 178 ++++++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 scripts/Experimental/Diff-onMutationsQueued.ts create mode 100644 scripts/Experimental/Diff-with-callbacks.ts diff --git a/scripts/Experimental/Diff-onMutationsQueued.ts b/scripts/Experimental/Diff-onMutationsQueued.ts new file mode 100644 index 00000000..9b45c59c --- /dev/null +++ b/scripts/Experimental/Diff-onMutationsQueued.ts @@ -0,0 +1,39 @@ +// let diffStart: number +// let diffMountableCount: number + +// Diff.onStart = () => { +// diffMountableCount = 0 +// } + +// Diff.onMutationsQueued = elem => { +// Diff.mutations.queue(() => { +// // Mountable +// if(elem.classList.contains("mountable")) { +// diffMountableCount++ + +// let now = Date.now() + +// if(diffMountableCount === 1) { +// diffStart = now +// } + +// const mountTime = diffMountableCount * 20 + diffStart + +// if(mountTime > now && mountTime < now + 800) { +// let mount = () => { +// if(Date.now() >= mountTime) { +// elem.classList.add("mounted") +// } else { +// Diff.mutations.queue(mount) +// } +// } + +// Diff.mutations.queue(mount) +// } else { +// elem.classList.add("mounted") +// } +// } else if(elem.classList.contains("lazy")) { +// this.lazyLoadElement(elem) +// } +// }) +// } \ No newline at end of file diff --git a/scripts/Experimental/Diff-with-callbacks.ts b/scripts/Experimental/Diff-with-callbacks.ts new file mode 100644 index 00000000..e3b70011 --- /dev/null +++ b/scripts/Experimental/Diff-with-callbacks.ts @@ -0,0 +1,178 @@ +// import { MutationQueue, CustomMutationQueue } from "./MutationQueue" + +// export class Diff { +// static persistentClasses = new Set() +// static persistentAttributes = new Set() + +// // Reuse container for diffs to avoid memory allocation +// static container: HTMLElement +// static rootContainer: HTMLElement +// static mutations: CustomMutationQueue = new CustomMutationQueue() + +// // Callbacks +// static onStart: () => void +// static onMutationsQueued: (elem: HTMLElement) => void + +// // innerHTML will diff the element with the given HTML string and apply DOM mutations. +// static innerHTML(aRoot: HTMLElement, html: string): Promise { +// return new Promise((resolve, reject) => { +// if(!Diff.container) { +// Diff.container = document.createElement("main") +// } + +// Diff.container.innerHTML = html + +// if(Diff.onStart) { +// Diff.onStart() +// } + +// Diff.childNodes(aRoot, Diff.container) +// this.mutations.wait(resolve) +// }) +// } + +// // root will diff the document root element with the given HTML string and apply DOM mutations. +// static root(aRoot: HTMLElement, html: string) { +// return new Promise((resolve, reject) => { +// if(!Diff.rootContainer) { +// Diff.rootContainer = document.createElement("html") +// } + +// Diff.rootContainer.innerHTML = html.replace("", "") + +// if(Diff.onStart) { +// Diff.onStart() +// } + +// Diff.childNodes(aRoot.getElementsByTagName("body")[0], Diff.rootContainer.getElementsByTagName("body")[0]) +// this.mutations.wait(resolve) +// }) +// } + +// // childNodes diffs the child nodes of 2 given elements and applies DOM mutations. +// static childNodes(aRoot: Node, bRoot: Node) { +// 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] + +// // Remove nodes at the end of a that do not exist in b +// if(i >= bChild.length) { +// this.mutations.queue(() => aRoot.removeChild(a)) +// continue +// } + +// let b = bChild[i] + +// // If a doesn't have that many nodes, simply append at the end of a +// if(i >= aChild.length) { +// this.mutations.queue(() => aRoot.appendChild(b)) + +// if(Diff.onMutationsQueued && b.nodeType === Node.ELEMENT_NODE) { +// Diff.onMutationsQueued(b as HTMLElement) +// } + +// continue +// } + +// // If it's a completely different HTML tag or node type, replace it +// if(a.nodeName !== b.nodeName || a.nodeType !== b.nodeType) { +// this.mutations.queue(() => aRoot.replaceChild(b, a)) + +// if(Diff.onMutationsQueued && b.nodeType === Node.ELEMENT_NODE) { +// Diff.onMutationsQueued(b as HTMLElement) +// } + +// continue +// } + +// // Text node: +// // We don't need to check for b to be a text node as well because +// // we eliminated different node types in the previous condition. +// if(a.nodeType === Node.TEXT_NODE) { +// this.mutations.queue(() => a.textContent = b.textContent) +// continue +// } + +// // HTML element: +// if(a.nodeType === Node.ELEMENT_NODE) { +// let elemA = a as HTMLElement +// let elemB = b as HTMLElement + +// let removeAttributes: Attr[] = [] + +// for(let x = 0; x < elemA.attributes.length; x++) { +// let attrib = elemA.attributes[x] + +// if(attrib.specified) { +// if(!elemB.hasAttribute(attrib.name) && !Diff.persistentAttributes.has(attrib.name)) { +// removeAttributes.push(attrib) +// } +// } +// } + +// this.mutations.queue(() => { +// for(let attr of removeAttributes) { +// elemA.removeAttributeNode(attr) +// } +// }) + +// for(let x = 0; x < elemB.attributes.length; x++) { +// let attrib = elemB.attributes[x] + +// if(!attrib.specified) { +// continue +// } + +// // If the attribute value is exactly the same, skip this attribute. +// if(elemA.getAttribute(attrib.name) === attrib.value) { +// continue +// } + +// if(attrib.name === "class") { +// let classesA = elemA.classList +// let classesB = elemB.classList +// let removeClasses: string[] = [] + +// for(let className of classesA) { +// if(!classesB.contains(className) && !Diff.persistentClasses.has(className)) { +// removeClasses.push(className) +// } +// } + +// this.mutations.queue(() => { +// for(let className of removeClasses) { +// classesA.remove(className) +// } + +// for(let className of classesB) { +// if(!classesA.contains(className)) { +// classesA.add(className) +// } +// } +// }) + +// continue +// } + +// this.mutations.queue(() => elemA.setAttribute(attrib.name, attrib.value)) +// } + +// // Special case: Apply state of input elements +// if(elemA !== document.activeElement && elemA instanceof HTMLInputElement && elemB instanceof HTMLInputElement) { +// this.mutations.queue(() => { +// (elemA as HTMLInputElement).value = (elemB as HTMLInputElement).value +// }) +// } +// } + +// Diff.childNodes(a, b) + +// if(Diff.onMutationsQueued && a.nodeType === Node.ELEMENT_NODE) { +// Diff.onMutationsQueued(a as HTMLElement) +// } +// } +// } +// } \ No newline at end of file