···185185 }
186186187187 private visitAttributes([from, to]: PairOfMatchingElements<Element>): void {
188188- const fromAttrs = from.attributes
188188+ if (from.hasAttribute("morphlex-dirty")) {
189189+ from.removeAttribute("morphlex-dirty")
190190+ }
189191190192 // First pass: update/add attributes from reference (iterate forwards)
191193 for (const { name, value } of to.attributes) {
192192- console.log(from, name)
193193- const oldValue = from.getAttribute(name)
194194-195195- // This attribute was only added to trigger attribute morphing.
196196- if (name === "morphlex-dirty") {
197197- from.removeAttribute(name)
198198- continue
199199- }
200200-201194 if (name === "value") {
202195 if (isInputElement(from) && from.value !== value) {
203196 if (!this.options.preserveModified || from.value === from.defaultValue) {
···222215 }
223216 }
224217218218+ const oldValue = from.getAttribute(name)
219219+225220 if (oldValue !== value && (this.options.beforeAttributeUpdated?.(from, name, value) ?? true)) {
226221 from.setAttribute(name, value)
227222 this.options.afterAttributeUpdated?.(from, name, oldValue)
228223 }
229224 }
225225+226226+ const fromAttrs = from.attributes
230227231228 // Second pass: remove excess attributes (iterate backwards for efficiency)
232229 for (let i = fromAttrs.length - 1; i >= 0; i--) {
+5-5
test/morphlex-morphdom.test.ts
···115115116116 morph(from, to)
117117118118- // Input values are no longer updated by morphlex
119119- expect((from as HTMLInputElement).value).toBe("Hello")
118118+ // Input values are updated by default when not modified
119119+ expect((from as HTMLInputElement).value).toBe("World")
120120 })
121121122122 it("should add disabled attribute to input", () => {
···182182183183 morph(from, to)
184184185185- // Selected options are no longer updated by morphlex
185185+ // Selected options are updated by default when not modified
186186 const select = from as HTMLSelectElement
187187- expect(select.value).toBe("1")
188188- expect(select.options[1].selected).toBe(false)
187187+ expect(select.value).toBe("2")
188188+ expect(select.options[1].selected).toBe(true)
189189 })
190190 })
191191
+5-4
test/morphlex.browser.test.ts
···601601602602 morph(select, referenceSelect)
603603604604- // Selected attributes are no longer updated
605605- expect(select.selectedOptions.length).toBe(1)
604604+ // Selected attributes are updated by default when not modified
605605+ expect(select.selectedOptions.length).toBe(2)
606606 expect(select.selectedOptions[0].value).toBe("2")
607607+ expect(select.selectedOptions[1].value).toBe("3")
607608 })
608609609610 it("should handle script tags safely", () => {
···688689 morph(form, referenceForm)
689690690691 const radioB = form.querySelector("#radio-b") as HTMLInputElement
691691- // Checked attribute is removed but not added - radioA loses its checked state
692692+ // Checked attributes are updated by default when not modified
692693 expect(radioA.checked).toBe(false)
693693- expect(radioB.checked).toBe(false)
694694+ expect(radioB.checked).toBe(true)
694695 })
695696696697 it("should handle contenteditable elements", () => {
+40
test/new.browser.test.ts
···11+import { test, expect } from "vitest"
22+import { morph } from "../src/morphlex"
33+44+function parseHTML(html: string): HTMLElement {
55+ const tmp = document.createElement("div")
66+ tmp.innerHTML = html.trim()
77+ return tmp.firstChild as HTMLElement
88+}
99+1010+test("morphing a modified input value with preserveModified enabled", () => {
1111+ const a = parseHTML(`<input type="text" value="a">`) as HTMLInputElement
1212+ const b = parseHTML(`<input type="text" value="b">`) as HTMLInputElement
1313+1414+ a.value = "new"
1515+ morph(a, b, { preserveModified: true })
1616+1717+ expect(a.outerHTML).toBe(`<input type="text" value="b">`)
1818+ expect(a.value).toBe("new")
1919+})
2020+2121+test("morphing a modified input value preserveModified disabled", () => {
2222+ const a = parseHTML(`<input type="text" value="a">`) as HTMLInputElement
2323+ const b = parseHTML(`<input type="text" value="b">`) as HTMLInputElement
2424+2525+ a.value = "new"
2626+ morph(a, b, { preserveModified: false })
2727+2828+ expect(a.outerHTML).toBe(`<input type="text" value="b">`)
2929+ expect(a.value).toBe("b")
3030+})
3131+3232+test("morphing an unmodified input value with preserveModified enabled", () => {
3333+ const a = parseHTML(`<input type="text" value="a">`) as HTMLInputElement
3434+ const b = parseHTML(`<input type="text" value="b">`) as HTMLInputElement
3535+3636+ morph(a, b, { preserveModified: true })
3737+3838+ expect(a.outerHTML).toBe(`<input type="text" value="b">`)
3939+ expect(a.value).toBe("b")
4040+})