aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-10-01 12:50:29 +0200
committermetamuffin <metamuffin@disroot.org>2023-10-01 12:50:29 +0200
commitc70c5b970a9d656d31358fa164c249096b2dcf29 (patch)
tree4d1221b56b9ee0b9c3688fe1a70889ac44087c83
parent18cc95742b9e43f1739385ce3bb673c7095a66a1 (diff)
downloadjshelper-c70c5b970a9d656d31358fa164c249096b2dcf29.tar
jshelper-c70c5b970a9d656d31358fa164c249096b2dcf29.tar.bz2
jshelper-c70c5b970a9d656d31358fa164c249096b2dcf29.tar.zst
properly restore element order when updating
-rw-r--r--src/element.ts20
-rw-r--r--src/observable.ts4
2 files changed, 15 insertions, 9 deletions
diff --git a/src/element.ts b/src/element.ts
index bee4ddb..354b976 100644
--- a/src/element.ts
+++ b/src/element.ts
@@ -16,7 +16,7 @@ interface Opts<E> {
onchange?: (e: E) => void,
}
-function apply_opts<E extends HTMLElement>(e: E, o: Opts<E>): (() => unknown) | void {
+function apply_opts<E extends HTMLElement>(e: E, o: Opts<E>): (() => void) | void {
if (o.id) e.id = o.id
if (o.for) (e as unknown as HTMLLabelElement).htmlFor = o.for
if (o.type && e instanceof HTMLInputElement) e.type = o.type
@@ -55,7 +55,8 @@ export function e<K extends keyof HTMLElementTagNameMap>(name: K, ...children: E
return el
}
-function e_apply<K extends keyof HTMLElementTagNameMap, C extends EEl<K>>(el: HTMLElementTagNameMap[K], c: C): () => unknown {
+interface RedoParams { before?: HTMLElement }
+function e_apply<K extends keyof HTMLElementTagNameMap, C extends EEl<K>>(el: HTMLElementTagNameMap[K], c: C, redo?: RedoParams): () => RedoParams | void {
if (typeof c == "undefined") {
return () => { }
}
@@ -66,14 +67,19 @@ function e_apply<K extends keyof HTMLElementTagNameMap, C extends EEl<K>>(el: HT
}
}
else if (c instanceof HTMLElement) {
- el.append(c)
- return () => el.removeChild(c)
+ el.insertBefore(c, redo?.before ?? null)
+ return () => {
+ const p = c.nextSibling as (HTMLElement | void);
+ el.removeChild(c)
+ return { before: p ?? undefined }
+ }
}
else if (c instanceof OVar) {
- let undo_last: () => unknown;
+ let undo_last: () => RedoParams | void;
return c.onchangeinit(val => {
- if (undo_last) undo_last()
- undo_last = e_apply(el, val)
+ let redo_param = undefined;
+ if (undo_last) redo_param = undo_last()
+ undo_last = e_apply(el, val, redo_param ?? undefined)
})
}
else return apply_opts(el, c) ?? (() => { })
diff --git a/src/observable.ts b/src/observable.ts
index 3e1308c..f00b845 100644
--- a/src/observable.ts
+++ b/src/observable.ts
@@ -17,11 +17,11 @@ export class OVar<T> {
this.observers.forEach(o => o(v))
}
- onchange(handler: (v: T) => unknown): () => unknown {
+ onchange(handler: (v: T) => unknown): () => void {
this.observers.push(handler)
return () => this.observers = this.observers.filter(o => o != handler)
}
- onchangeinit(handler: (v: T) => unknown): () => unknown {
+ onchangeinit(handler: (v: T) => unknown): () => void {
const abort = this.onchange(handler)
handler(this.value)
return abort