tangled
alpha
login
or
join now
yippee.fun
/
morphlex
0
fork
atom
Precise DOM morphing
morphing
typescript
dom
0
fork
atom
overview
issues
pulls
pipelines
Rename `preserveModified` to `preserveChanges`
joel.drapper.me
4 months ago
0cde519c
4b34329d
+42
-44
2 changed files
expand all
collapse all
unified
split
src
morphlex.ts
test
new
inputs.browser.test.ts
+10
-12
src/morphlex.ts
···
19
19
* This prevents user-entered data from being overwritten.
20
20
* @default false
21
21
*/
22
22
-
preserveModified?: boolean
22
22
+
preserveChanges?: boolean
23
23
24
24
/**
25
25
* Called before a node is visited during morphing.
···
107
107
* @param options Optional configuration for the morphing behavior.
108
108
* @example
109
109
* ```ts
110
110
-
* morphDocument(document, "<html>...</html>", { preserveModified: true })
110
110
+
* morphDocument(document, "<html>...</html>", { preserveChanges: true })
111
111
* ```
112
112
*/
113
113
export function morphDocument(from: Document, to: Document | string, options?: Options): void {
···
375
375
for (const { name, value } of to.attributes) {
376
376
if (name === "value") {
377
377
if (isInputElement(from) && from.value !== value) {
378
378
-
if (!this.#options.preserveModified || from.value === from.defaultValue) {
378
378
+
if (!this.#options.preserveChanges || from.value === from.defaultValue) {
379
379
from.value = value
380
380
}
381
381
}
···
383
383
384
384
if (name === "selected") {
385
385
if (isOptionElement(from) && !from.selected) {
386
386
-
if (!this.#options.preserveModified || from.selected === from.defaultSelected) {
386
386
+
if (!this.#options.preserveChanges || from.selected === from.defaultSelected) {
387
387
from.selected = true
388
388
}
389
389
}
···
391
391
392
392
if (name === "checked") {
393
393
if (isInputElement(from) && !from.checked) {
394
394
-
if (!this.#options.preserveModified || from.checked === from.defaultChecked) {
394
394
+
if (!this.#options.preserveChanges || from.checked === from.defaultChecked) {
395
395
from.checked = true
396
396
}
397
397
}
···
414
414
if (!to.hasAttribute(name)) {
415
415
if (name === "selected") {
416
416
if (isOptionElement(from) && from.selected) {
417
417
-
if (!this.#options.preserveModified || from.selected === from.defaultSelected) {
417
417
+
if (!this.#options.preserveChanges || from.selected === from.defaultSelected) {
418
418
from.selected = false
419
419
}
420
420
}
···
422
422
423
423
if (name === "checked") {
424
424
if (isInputElement(from) && from.checked) {
425
425
-
if (!this.#options.preserveModified || from.checked === from.defaultChecked) {
425
425
+
if (!this.#options.preserveChanges || from.checked === from.defaultChecked) {
426
426
from.checked = false
427
427
}
428
428
}
···
445
445
from.textContent = newTextContent
446
446
}
447
447
448
448
-
if (this.#options.preserveModified && isModified) return
448
448
+
if (this.#options.preserveChanges && isModified) return
449
449
450
450
from.value = from.defaultValue
451
451
}
···
640
640
// Find LIS - these nodes don't need to move
641
641
const lisIndices = this.#longestIncreasingSubsequence(sequence)
642
642
const shouldNotMove = new Set<number>()
643
643
-
for (const idx of lisIndices) {
644
644
-
shouldNotMove.add(sequence[idx]!)
643
643
+
for (const i of lisIndices) {
644
644
+
shouldNotMove.add(sequence[i]!)
645
645
}
646
646
647
647
-
// Process nodes in forward order to maintain proper positioning
648
647
let insertionPoint: ChildNode | null = parent.firstChild
649
648
for (let i = 0; i < toChildNodes.length; i++) {
650
649
const node = toChildNodes[i]!
651
650
const match = matches[i]
652
651
if (match) {
653
652
const matchIndex = fromIndex.get(match)!
654
654
-
// Only move if not in LIS
655
653
if (!shouldNotMove.has(matchIndex)) {
656
654
moveBefore(parent, match, insertionPoint)
657
655
}
+32
-32
test/new/inputs.browser.test.ts
···
3
3
import { dom } from "./utils"
4
4
5
5
describe("text input", () => {
6
6
-
test("morphing a modified value with preserveModified enabled", () => {
6
6
+
test("morphing a modified value with preserveChanges enabled", () => {
7
7
const a = dom(`<input type="text" value="a">`) as HTMLInputElement
8
8
const b = dom(`<input type="text" value="b">`) as HTMLInputElement
9
9
10
10
a.value = "c"
11
11
-
morph(a, b, { preserveModified: true })
11
11
+
morph(a, b, { preserveChanges: true })
12
12
13
13
expect(a.outerHTML).toBe(`<input type="text" value="b">`)
14
14
expect(a.value).toBe("c")
15
15
})
16
16
17
17
-
test("morphing a modified value preserveModified disabled", () => {
17
17
+
test("morphing a modified value preserveChanges disabled", () => {
18
18
const a = dom(`<input type="text" value="a">`) as HTMLInputElement
19
19
const b = dom(`<input type="text" value="b">`) as HTMLInputElement
20
20
21
21
a.value = "c"
22
22
-
morph(a, b, { preserveModified: false })
22
22
+
morph(a, b, { preserveChanges: false })
23
23
24
24
expect(a.outerHTML).toBe(`<input type="text" value="b">`)
25
25
expect(a.value).toBe("b")
26
26
})
27
27
28
28
-
test("morphing an unmodified value with preserveModified enabled", () => {
28
28
+
test("morphing an unmodified value with preserveChanges enabled", () => {
29
29
const a = dom(`<input type="text" value="a">`) as HTMLInputElement
30
30
const b = dom(`<input type="text" value="b">`) as HTMLInputElement
31
31
32
32
-
morph(a, b, { preserveModified: true })
32
32
+
morph(a, b, { preserveChanges: true })
33
33
34
34
expect(a.outerHTML).toBe(`<input type="text" value="b">`)
35
35
expect(a.value).toBe("b")
···
37
37
})
38
38
39
39
describe("checkbox", () => {
40
40
-
test("morphing a modified checkbox checked with preserveModified enabled", () => {
40
40
+
test("morphing a modified checkbox checked with preserveChanges enabled", () => {
41
41
const a = dom(`<input type="checkbox">`) as HTMLInputElement
42
42
const b = dom(`<input type="checkbox" checked>`) as HTMLInputElement
43
43
44
44
a.checked = true
45
45
-
morph(a, b, { preserveModified: true })
45
45
+
morph(a, b, { preserveChanges: true })
46
46
47
47
expect(a.hasAttribute("checked")).toBe(true)
48
48
expect(a.checked).toBe(true)
49
49
})
50
50
51
51
-
test("morphing a modified checkbox checked with preserveModified disabled", () => {
51
51
+
test("morphing a modified checkbox checked with preserveChanges disabled", () => {
52
52
const a = dom(`<input type="checkbox">`) as HTMLInputElement
53
53
const b = dom(`<input type="checkbox" checked>`) as HTMLInputElement
54
54
55
55
a.checked = true
56
56
-
morph(a, b, { preserveModified: false })
56
56
+
morph(a, b, { preserveChanges: false })
57
57
58
58
expect(a.hasAttribute("checked")).toBe(true)
59
59
expect(a.checked).toBe(true)
60
60
})
61
61
62
62
-
test("morphing an unmodified checkbox with preserveModified enabled", () => {
62
62
+
test("morphing an unmodified checkbox with preserveChanges enabled", () => {
63
63
const a = dom(`<input type="checkbox">`) as HTMLInputElement
64
64
const b = dom(`<input type="checkbox" checked>`) as HTMLInputElement
65
65
66
66
-
morph(a, b, { preserveModified: true })
66
66
+
morph(a, b, { preserveChanges: true })
67
67
68
68
expect(a.hasAttribute("checked")).toBe(true)
69
69
expect(a.checked).toBe(true)
70
70
})
71
71
72
72
-
test("morphing a modified checkbox unchecked with preserveModified enabled", () => {
72
72
+
test("morphing a modified checkbox unchecked with preserveChanges enabled", () => {
73
73
const a = dom(`<input type="checkbox" checked>`) as HTMLInputElement
74
74
const b = dom(`<input type="checkbox">`) as HTMLInputElement
75
75
76
76
a.checked = false
77
77
-
morph(a, b, { preserveModified: true })
77
77
+
morph(a, b, { preserveChanges: true })
78
78
79
79
expect(a.hasAttribute("checked")).toBe(false)
80
80
expect(a.checked).toBe(false)
81
81
})
82
82
83
83
-
test("morphing a modified checkbox unchecked with preserveModified disabled", () => {
83
83
+
test("morphing a modified checkbox unchecked with preserveChanges disabled", () => {
84
84
const a = dom(`<input type="checkbox" checked>`) as HTMLInputElement
85
85
const b = dom(`<input type="checkbox">`) as HTMLInputElement
86
86
87
87
a.checked = false
88
88
-
morph(a, b, { preserveModified: false })
88
88
+
morph(a, b, { preserveChanges: false })
89
89
90
90
expect(a.hasAttribute("checked")).toBe(false)
91
91
expect(a.checked).toBe(false)
···
93
93
})
94
94
95
95
describe("select", () => {
96
96
-
test("morphing a modified select option with preserveModified enabled", () => {
96
96
+
test("morphing a modified select option with preserveChanges enabled", () => {
97
97
const a = dom(`<select><option value="a">A</option><option value="b">B</option></select>`) as HTMLSelectElement
98
98
const b = dom(`<select><option value="a">A</option><option value="b" selected>B</option></select>`) as HTMLSelectElement
99
99
100
100
a.value = "b"
101
101
-
morph(a, b, { preserveModified: true })
101
101
+
morph(a, b, { preserveChanges: true })
102
102
103
103
expect(a.options[1].hasAttribute("selected")).toBe(true)
104
104
expect(a.value).toBe("b")
105
105
expect(a.options[1].selected).toBe(true)
106
106
})
107
107
108
108
-
test("morphing a modified select option with preserveModified disabled", () => {
108
108
+
test("morphing a modified select option with preserveChanges disabled", () => {
109
109
const a = dom(`<select><option value="a">A</option><option value="b">B</option></select>`) as HTMLSelectElement
110
110
const b = dom(`<select><option value="a">A</option><option value="b" selected>B</option></select>`) as HTMLSelectElement
111
111
112
112
a.value = "b"
113
113
-
morph(a, b, { preserveModified: false })
113
113
+
morph(a, b, { preserveChanges: false })
114
114
115
115
expect(a.options[1].hasAttribute("selected")).toBe(true)
116
116
expect(a.value).toBe("b")
117
117
expect(a.options[1].selected).toBe(true)
118
118
})
119
119
120
120
-
test("morphing an unmodified select option with preserveModified enabled", () => {
120
120
+
test("morphing an unmodified select option with preserveChanges enabled", () => {
121
121
const a = dom(`<select><option value="a">A</option><option value="b">B</option></select>`) as HTMLSelectElement
122
122
const b = dom(`<select><option value="a">A</option><option value="b" selected>B</option></select>`) as HTMLSelectElement
123
123
124
124
-
morph(a, b, { preserveModified: true })
124
124
+
morph(a, b, { preserveChanges: true })
125
125
126
126
expect(a.options[1].hasAttribute("selected")).toBe(true)
127
127
expect(a.value).toBe("b")
128
128
expect(a.options[1].selected).toBe(true)
129
129
})
130
130
131
131
-
test("morphing a modified select option back to default with preserveModified enabled", () => {
131
131
+
test("morphing a modified select option back to default with preserveChanges enabled", () => {
132
132
const a = dom(`<select><option value="a">A</option><option value="b" selected>B</option></select>`) as HTMLSelectElement
133
133
const b = dom(`<select><option value="a">A</option><option value="b">B</option></select>`) as HTMLSelectElement
134
134
135
135
a.value = "a"
136
136
-
morph(a, b, { preserveModified: true })
136
136
+
morph(a, b, { preserveChanges: true })
137
137
138
138
expect(a.options[1].hasAttribute("selected")).toBe(false)
139
139
expect(a.value).toBe("a")
140
140
expect(a.options[0].selected).toBe(true)
141
141
})
142
142
143
143
-
test("morphing a modified select option back to default with preserveModified disabled", () => {
143
143
+
test("morphing a modified select option back to default with preserveChanges disabled", () => {
144
144
const a = dom(`<select><option value="a">A</option><option value="b" selected>B</option></select>`) as HTMLSelectElement
145
145
const b = dom(`<select><option value="a">A</option><option value="b">B</option></select>`) as HTMLSelectElement
146
146
147
147
a.value = "a"
148
148
-
morph(a, b, { preserveModified: false })
148
148
+
morph(a, b, { preserveChanges: false })
149
149
150
150
expect(a.options[1].hasAttribute("selected")).toBe(false)
151
151
expect(a.value).toBe("a")
···
154
154
})
155
155
156
156
describe("textarea", () => {
157
157
-
test("morphing a modified textarea value with preserveModified enabled", () => {
157
157
+
test("morphing a modified textarea value with preserveChanges enabled", () => {
158
158
const a = dom(`<textarea>a</textarea>`) as HTMLTextAreaElement
159
159
const b = dom(`<textarea>b</textarea>`) as HTMLTextAreaElement
160
160
161
161
a.value = "c"
162
162
-
morph(a, b, { preserveModified: true })
162
162
+
morph(a, b, { preserveChanges: true })
163
163
164
164
expect(a.textContent).toBe("b")
165
165
expect(a.value).toBe("c")
166
166
})
167
167
168
168
-
test("morphing a modified textarea value with preserveModified disabled", () => {
168
168
+
test("morphing a modified textarea value with preserveChanges disabled", () => {
169
169
const a = dom(`<textarea>a</textarea>`) as HTMLTextAreaElement
170
170
const b = dom(`<textarea>b</textarea>`) as HTMLTextAreaElement
171
171
172
172
a.value = "c"
173
173
-
morph(a, b, { preserveModified: false })
173
173
+
morph(a, b, { preserveChanges: false })
174
174
175
175
expect(a.textContent).toBe("b")
176
176
expect(a.value).toBe("b")
177
177
})
178
178
179
179
-
test("morphing an unmodified textarea value with preserveModified enabled", () => {
179
179
+
test("morphing an unmodified textarea value with preserveChanges enabled", () => {
180
180
const a = dom(`<textarea>a</textarea>`) as HTMLTextAreaElement
181
181
const b = dom(`<textarea>b</textarea>`) as HTMLTextAreaElement
182
182
183
183
-
morph(a, b, { preserveModified: true })
183
183
+
morph(a, b, { preserveChanges: true })
184
184
185
185
expect(a.textContent).toBe("b")
186
186
expect(a.value).toBe("b")