What are the possible reasons for document.getElementById
, $("#id")
or any other DOM method / jQuery selector not finding the elements?
Example problems include:
- jQuery silently failing to bind an event handler
- jQuery "getter" methods (
.val()
,.html()
,.text()
) returningundefined
- A standard DOM method returning
null
resulting in any of several errors:
Uncaught TypeError: Cannot set property '...' of null
Uncaught TypeError: Cannot read property '...' of null
The most common forms are:
Uncaught TypeError: Cannot set property 'onclick' of null
Uncaught TypeError: Cannot read property 'addEventListener' of null
Uncaught TypeError: Cannot read property 'style' of null
Answer
The element you were trying to find wasn’t in the DOM when your script ran.
The position of your DOM-reliant script can have a profound effect upon its behavior. Browsers parse HTML documents from top to bottom. Elements are added to the DOM and scripts are (generally) executed as they're encountered. This means that order matters. Typically, scripts can't find elements which appear later in the markup because those elements have yet to be added to the DOM.
Consider the following markup; script #1 fails to find the So, what should you do? You've got a few options: Move your script further down the page, just before the closing body tag. Organized in this fashion, the rest of the document is parsed before your script is executed: Note: Placing scripts at the bottom is generally considered a best practice. Defer your script until the DOM has been completely parsed, using Note: You could simply bind to Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. When an element raises an event (provided that it's a bubbling event and nothing stops its propagation), each parent in that element's ancestry receives the event as well. That allows us to attach a handler to an existing element and sample events as they bubble up from its descendants... even those added after the handler is attached. All we have to do is check the event to see whether it was raised by the desired element and, if so, run our code. jQuery's Note: Typically, this pattern is reserved for elements which didn't exist at load-time or to avoid attaching a large amount of handlers. It's also worth pointing out that while I've attached a handler to Use the [ For reference, here's the code from that external script: Note: The
ready()
:DOMContentLoaded
or window.onload
but each has its caveats. jQuery's ready()
delivers a hybrid solution.
on()
performs that logic for us. We simply provide an event name, a selector for the desired descendant, and an event handler:document
(for demonstrative purposes), you should select the nearest reliable ancestor.defer
attribute of .
defer
, a Boolean attribute,] is set to indicate to a browser that the script is meant to be executed after the document has been parsed.document.getElementById("test").addEventListener("click", function(e){
console.log("clicked: %o", this);
});defer
attribute certainly seems like a magic bullet but it's important to be aware of the caveats...
1. defer
can only be used for external scripts, i.e.: those having a src
attribute.
2. be aware of browser support, i.e.: buggy implementation in IE < 10
No comments:
Post a Comment