Skip to content

Commit 8c80098

Browse files
authored
Fix TypeError in saveAndRestoreFocus when restored id resolves to a non-input element (#150)
* fix setSelectionRange is not a function in saveAndRestoreFocus after page morph Signed-off-by: Ednilson Maia <dina@veda.com.br>
1 parent afd144f commit 8c80098

2 files changed

Lines changed: 54 additions & 1 deletion

File tree

src/idiomorph.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,13 @@ var Idiomorph = (function () {
234234
activeElement?.focus();
235235
}
236236
if (activeElement && !activeElement.selectionEnd && selectionEnd) {
237-
activeElement.setSelectionRange(selectionStart, selectionEnd);
237+
try {
238+
activeElement.setSelectionRange(selectionStart, selectionEnd);
239+
} catch {
240+
// the element may not support setSelectionRange: it's no longer an
241+
// input/textarea after the morph, or it's an input type (number,
242+
// email, date, ...) that doesn't support text selection
243+
}
238244
}
239245

240246
return results;

test/restore-focus.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,53 @@ describe("Option to forcibly restore focus after morph", function () {
289289
assertNoFocus();
290290
});
291291

292+
it("does not throw if the saved id resolves to a non-input element after morph", function () {
293+
getWorkArea().innerHTML = `
294+
<div>
295+
<input type="text" id="focused" value="abc">
296+
</div>`;
297+
setFocusAndSelection("focused", "b");
298+
299+
// after the morph nothing input-like has id="focused"; a <div> does
300+
const after = `
301+
<div>
302+
<div id="focused">replaced</div>
303+
</div>`;
304+
(function () {
305+
Idiomorph.morph(getWorkArea(), after, {
306+
morphStyle: "innerHTML",
307+
restoreFocus: true,
308+
});
309+
}).should.not.throw();
310+
311+
getWorkArea().innerHTML.should.equal(after);
312+
assertNoFocus();
313+
});
314+
315+
it("does not throw for input types that reject setSelectionRange", function () {
316+
getWorkArea().innerHTML = `
317+
<div>
318+
<input type="number" id="focused" value="123">
319+
<input type="number" id="other">
320+
</div>`;
321+
// type=number does not support selection, so set focus only
322+
setFocus("focused");
323+
324+
const after = `
325+
<div>
326+
<input type="number" id="other">
327+
<input type="number" id="focused" value="123">
328+
</div>`;
329+
(function () {
330+
Idiomorph.morph(getWorkArea(), after, {
331+
morphStyle: "innerHTML",
332+
restoreFocus: true,
333+
});
334+
}).should.not.throw();
335+
336+
getWorkArea().innerHTML.should.equal(after);
337+
});
338+
292339
it("does not restore selection if selection still set or changed", function () {
293340
getWorkArea().innerHTML = `
294341
<div>

0 commit comments

Comments
 (0)