Uncaught TypeError: Cannot read property 'nodeType' of null when calling .focus() on an empty jQuery selection
0 reputation · 15 May 2024, 16:13 UTC
0 reputation · 15 May 2024, 16:13 UTC
In a dynamic interface, a focus-management script moves keyboard focus to a target element after content is injected or removed. When the selector matches nothing, calling .focus() on the empty jQuery object raises Uncaught TypeError: Cannot read property 'nodeType' of null, halting the rest of the script.
This is a concern for accessibility: if the exception fires mid-flow, subsequent focus moves never happen, and keyboard or screen-reader users can be left with focus stranded on removed or hidden content. The documented guidance is to guard with .length before invoking .focus(), but the behavior differs from most jQuery methods, which silently no-op on empty selections.
Assuming jQuery 3.x, with behavior to be verified against the exact version and across browsers (some may fail silently rather than throw):
.focus() call intentional API design, or an inconsistency with jQuery's usual empty-set no-op convention?.length guard sufficient, or should the fallback explicitly redirect focus to a known landmark?.focus() calls, or should callers treat the exception as the stable contract?35275 reputation · 15 May 2024, 19:15 UTC
Calling $(selector).focus() on a jQuery object that contains no matched elements normally returns the empty set and does nothing. The TypeError: Cannot read property 'nodeType' of null you see is not an intentional jQuery API change. It originates from the focus‑dispatch path – either from a native focus() call that receives a null target or from a focus event handler that dereferences a removed element.
event.target or document.activeElement when the element has already been detached, yielding null and causing the nodeType lookup to fail.jQuery.fn.focus itself does not throw on an empty set; it simply returns the set. The error therefore must come from the surrounding focus‑management logic.var $target = $(selector);
if ($target.length) {
$target.focus();
}
This prevents the exception and keeps the rest of the script running.display:none or aria-hidden="true" element can still match the selector but should not receive focus.
if ($target.is(':visible') && !$target.is(':disabled')) {
$target.focus();
}
var $fallback = $('#dialog-main');
if ($target.length && $target.is(':visible')) {
$target.focus();
} else {
$fallback.attr('tabindex', '-1').focus();
}
$(document).on('focus', '.dynamic', handler), make sure handler checks that event.target is still in the DOM before accessing properties.$.append or MutationObserver) to avoid race conditions where the element is removed before the focus call executes.There is no public roadmap indicating that jQuery will change .focus() to silently ignore all edge cases. The current stable contract is: .focus() will throw if the underlying element is null or if a focus handler dereferences a removed node. Defensive guarding is the recommended practice.
Could you share the stack trace of the error? If it points to a custom focus handler rather than to the native focus() call, the fix may involve updating that handler to check for null before accessing properties.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.