javascript - Why does jQuery or a DOM method such as getElementById not find the element? -


what possible reasons document.getelementbyid, $("#id") or other dom method / jquery selector not finding elements?

example problems include:

jquery silently failing bind event handler, , standard dom method returning null resulting in error:

uncaught typeerror: cannot set property '...' of null

the element trying find wasn’t in dom when script ran.

the position of dom-reliant script can have profound effect upon behavior. browsers parse html documents top bottom. elements added dom , scripts (generally) executed they're encountered. this means order matters. typically, scripts can't find elements appear later in markup because elements have yet added dom.

consider following markup; script #1 fails find <div> while script #2 succeeds:

<script>    console.log("script #1: %o", document.getelementbyid("test")); // null  </script>  <div id="test">test div</div>  <script>    console.log("script #2: %o", document.getelementbyid("test")); // <div id="test" ...  </script>

so, should do? you've got few options:


option 1: move script

move script further down page, before closing body tag. organized in fashion, rest of document parsed before script executed:

<body>    <button id="test">click me</button>    <script>      document.getelementbyid("test").addeventlistener("click", function() {        console.log("clicked: %o", this);      });    </script>  </body><!-- closing body tag -->

note: placing scripts @ bottom considered best practice.


option 2: jquery's ready()

defer script until dom has been parsed, using ready():

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>  <script>    $(document).ready(function() {      $("#test").click(function() {        console.log("clicked: %o", this);      });    });  </script>  <button id="test">click me</button>

note: bind domcontentloaded or window.onload each has caveats. jquery's ready() delivers hybrid solution.


option 3: event delegation

delegated events have advantage can process events descendant elements added document @ later time.

when element raises event (provided it's bubbling event , nothing stops propagation), each parent in element's ancestry receives event well. allows attach handler existing element , sample events bubble descendants... added after handler attached. have check event see whether raised desired element and, if so, run our code.

jquery's on() performs logic us. provide event name, selector desired descendant, , event handler:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>  <script>    $(document).on("click", "#test", function(e) {      console.log("clicked: %o",  this);    });  </script>  <button id="test">click me</button>

note: typically, pattern reserved elements didn't exist @ load-time or avoid attaching large amount of handlers. it's worth pointing out while i've attached handler document (for demonstrative purposes), should select nearest reliable ancestor.


option 4: defer attribute

use defer attribute of <script>.

[defer, boolean attribute,] set indicate browser script meant executed after document has been parsed.

<script src="https://gh-canon.github.io/misc-demos/log-test-click.js" defer></script>  <button id="test">click me</button>

for reference, here's code external script:

document.getelementbyid("test").addeventlistener("click", function(e){    console.log("clicked: %o", this);  }); 

note: defer attribute seems magic bullet but it's important aware of caveats...
1. defer can used external scripts, i.e.: having src attribute.
2. aware of browser support, i.e.: buggy implementation in ie < 10


Comments

Popular posts from this blog

python Tkinter Capturing keyboard events save as one single string -

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

javascript - Z-index in d3.js -