diff --git a/src/idiomorph.js b/src/idiomorph.js index dd6975c..257c040 100644 --- a/src/idiomorph.js +++ b/src/idiomorph.js @@ -234,7 +234,13 @@ var Idiomorph = (function () { activeElement?.focus(); } if (activeElement && !activeElement.selectionEnd && selectionEnd) { - activeElement.setSelectionRange(selectionStart, selectionEnd); + try { + activeElement.setSelectionRange(selectionStart, selectionEnd); + } catch { + // the element may not support setSelectionRange: it's no longer an + // input/textarea after the morph, or it's an input type (number, + // email, date, ...) that doesn't support text selection + } } return results; diff --git a/test/restore-focus.js b/test/restore-focus.js index 1c4a54a..43eef38 100644 --- a/test/restore-focus.js +++ b/test/restore-focus.js @@ -289,6 +289,53 @@ describe("Option to forcibly restore focus after morph", function () { assertNoFocus(); }); + it("does not throw if the saved id resolves to a non-input element after morph", function () { + getWorkArea().innerHTML = ` +
+ +
`; + setFocusAndSelection("focused", "b"); + + // after the morph nothing input-like has id="focused"; a
does + const after = ` +
+
replaced
+
`; + (function () { + Idiomorph.morph(getWorkArea(), after, { + morphStyle: "innerHTML", + restoreFocus: true, + }); + }).should.not.throw(); + + getWorkArea().innerHTML.should.equal(after); + assertNoFocus(); + }); + + it("does not throw for input types that reject setSelectionRange", function () { + getWorkArea().innerHTML = ` +
+ + +
`; + // type=number does not support selection, so set focus only + setFocus("focused"); + + const after = ` +
+ + +
`; + (function () { + Idiomorph.morph(getWorkArea(), after, { + morphStyle: "innerHTML", + restoreFocus: true, + }); + }).should.not.throw(); + + getWorkArea().innerHTML.should.equal(after); + }); + it("does not restore selection if selection still set or changed", function () { getWorkArea().innerHTML = `