[IMP] blockdom: apply dynamic part of block before inserting it

This commit is contained in:
Géry Debongnie
2022-02-04 10:38:51 +01:00
committed by aab-odoo
parent a402115227
commit f095f9e5aa
+43 -20
View File
@@ -299,12 +299,13 @@ interface BlockCtx {
locations: IndexedLocation[]; locations: IndexedLocation[];
children: Child[]; children: Child[];
cbRefs: number[]; cbRefs: number[];
refList: (() => void)[];
} }
function buildContext(tree: IntermediateTree, ctx?: BlockCtx, fromIdx?: number): BlockCtx { function buildContext(tree: IntermediateTree, ctx?: BlockCtx, fromIdx?: number): BlockCtx {
if (!ctx) { if (!ctx) {
const children = new Array(tree.info.filter((v) => v.type === "child").length); const children = new Array(tree.info.filter((v) => v.type === "child").length);
ctx = { collectors: [], locations: [], children, cbRefs: [], refN: tree.refN }; ctx = { collectors: [], locations: [], children, cbRefs: [], refN: tree.refN, refList: [] };
fromIdx = 0; fromIdx = 0;
} }
if (tree.refN) { if (tree.refN) {
@@ -408,11 +409,12 @@ function updateCtx(ctx: BlockCtx, tree: IntermediateTree) {
break; break;
} }
case "ref": case "ref":
const index = ctx.refList.push(NO_OP) - 1;
ctx.cbRefs.push(info.idx); ctx.cbRefs.push(info.idx);
ctx.locations.push({ ctx.locations.push({
idx: info.idx, idx: info.idx,
refIdx: info.refIdx!, refIdx: info.refIdx!,
setData: setRef, setData: makeRefSetter(index, ctx.refList),
updateData: NO_OP, updateData: NO_OP,
}); });
} }
@@ -426,12 +428,19 @@ function buildBlock(template: HTMLElement, ctx: BlockCtx): BlockType {
let B = createBlockClass(template, ctx); let B = createBlockClass(template, ctx);
if (ctx.cbRefs.length) { if (ctx.cbRefs.length) {
const refs = ctx.cbRefs; const cbRefs = ctx.cbRefs;
const refList = ctx.refList;
B = class extends B { B = class extends B {
mount(parent: HTMLElement, afterNode: Node | null) {
super.mount(parent, afterNode);
for (let cbRef of refList) {
cbRef();
}
}
remove() { remove() {
super.remove(); super.remove();
for (let ref of refs) { for (let cbRef of cbRefs) {
let fn = (this as any).data[ref]; let fn = (this as any).data[cbRef];
fn(null); fn(null);
} }
} }
@@ -476,12 +485,12 @@ function createBlockClass(template: HTMLElement, ctx: BlockCtx): BlockClass {
const nodeInsertBefore = nodeProto.insertBefore; const nodeInsertBefore = nodeProto.insertBefore;
const elementRemove = elementProto.remove; const elementRemove = elementProto.remove;
return class Block { class Block {
el: HTMLElement | undefined; el: HTMLElement | undefined;
refs: Node[] | undefined;
data: any[] | undefined;
parentEl?: HTMLElement | undefined; parentEl?: HTMLElement | undefined;
data: any[] | undefined;
children?: (VNode | undefined)[]; children?: (VNode | undefined)[];
refs: Node[] | undefined;
constructor(data?: any[]) { constructor(data?: any[]) {
this.data = data; this.data = data;
@@ -502,10 +511,24 @@ function createBlockClass(template: HTMLElement, ctx: BlockCtx): BlockClass {
nodeInsertBefore.call(this.parentEl, this.el!, target); nodeInsertBefore.call(this.parentEl, this.el!, target);
} }
toString() {
const div = document.createElement("div");
this.mount(div, null);
return div.innerHTML;
}
mount(parent: HTMLElement, afterNode: Node | null) { mount(parent: HTMLElement, afterNode: Node | null) {
const el = nodeCloneNode.call(template, true); const el = nodeCloneNode.call(template, true) as HTMLElement;
nodeInsertBefore.call(parent, el, afterNode); nodeInsertBefore.call(parent, el, afterNode);
this.el = el;
this.parentEl = parent;
}
patch(other: Block, withBeforeRemove: boolean) {}
}
if (isDynamic) { if (isDynamic) {
Block.prototype.mount = function mount(parent: HTMLElement, afterNode: Node | null) {
const el = nodeCloneNode.call(template, true);
// collecting references // collecting references
const refs: Node[] = new Array(refN); const refs: Node[] = new Array(refN);
this.refs = refs; this.refs = refs;
@@ -524,6 +547,8 @@ function createBlockClass(template: HTMLElement, ctx: BlockCtx): BlockClass {
} }
} }
nodeInsertBefore.call(parent, el, afterNode);
// preparing all children // preparing all children
if (childN) { if (childN) {
const children = this.children; const children = this.children;
@@ -537,11 +562,11 @@ function createBlockClass(template: HTMLElement, ctx: BlockCtx): BlockClass {
} }
} }
} }
}
this.el = el as HTMLElement; this.el = el as HTMLElement;
this.parentEl = parent; this.parentEl = parent;
} };
patch(other: Block, withBeforeRemove: boolean) {
Block.prototype.patch = function patch(other: Block, withBeforeRemove: boolean) {
if (this === other) { if (this === other) {
return; return;
} }
@@ -586,19 +611,17 @@ function createBlockClass(template: HTMLElement, ctx: BlockCtx): BlockClass {
} }
} }
} }
}
toString() {
const div = document.createElement("div");
this.mount(div, null);
return div.innerHTML;
}
}; };
}
return Block;
} }
function setText(this: Text, value: any) { function setText(this: Text, value: any) {
characterDataSetData.call(this, toText(value)); characterDataSetData.call(this, toText(value));
} }
function setRef(this: HTMLElement, fn: any) { function makeRefSetter(index: number, refs: (() => void)[]): Setter<HTMLElement> {
fn(this); return function setRef(this: HTMLElement, fn: any) {
refs[index] = () => fn(this);
};
} }