Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

StackOverflow Point

StackOverflow Point Navigation

  • Web Stories
  • Badges
  • Tags
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Web Stories
  • Badges
  • Tags
Home/ Questions/Q 185601
Alex Hales
  • 0
Alex HalesTeacher
Asked: June 10, 20222022-06-10T02:16:39+00:00 2022-06-10T02:16:39+00:00

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

  • 0

[ad_1]

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 on 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 that 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 <div> while script #2 succeeds:

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

So, what should you do? You’ve got a few options:


Option 1: Move your script

Given what we’ve seen in the example above, an intuitive solution might be to simply move your script down the markup, past the elements you’d like to access. In fact, for a long time, placing scripts at the bottom of the page was considered a best practice for a variety of reasons. Organized in this fashion, the rest of the document would be parsed before executing your script:

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

While this makes sense and is a solid option for legacy browsers, it’s limited and there are more flexible, modern approaches available.


Option 2: The defer attribute

While we did say that scripts are, “(generally) executed as they’re encountered,” modern browsers allow you to specify a different behavior. If you’re linking an external script, you can make use of the defer attribute.

[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, but before firing DOMContentLoaded.

This means that you can place a script tagged with defer anywhere, even the <head>, and it should have access to the fully realized DOM.

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

Just keep in mind…

  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

Option 3: Modules

Depending upon your requirements, you may be able to utilize JavaScript modules. Among other important distinctions from standard scripts (noted here), modules are deferred automatically and are not limited to external sources.

Set your script’s type to module, e.g.:

<script type="module">
  document.getElementById("test").addEventListener("click", function(e) {
    console.log("clicked: ", this);
  });
</script>
<button id="test">click me</button>

Option 4: Defer with event handling

Add a listener to an event that fires after your document has been parsed.

DOMContentLoaded event

DOMContentLoaded fires after the DOM has been completely constructed from the initial parse, without waiting for things like stylesheets or images to load.

<script>
  document.addEventListener("DOMContentLoaded", function(e){
    document.getElementById("test").addEventListener("click", function(e) {
      console.log("clicked:", this);
    });
  });
</script>
<button id="test">click me</button>

Window: load event

The load event fires after DOMContentLoaded and additional resources like stylesheets and images have been loaded. For that reason, it fires later than desired for our purposes. Still, if you’re considering older browsers like IE8, the support is nearly universal. Granted, you may want a polyfill for addEventListener().

<script>
  window.addEventListener("load", function(e){
    document.getElementById("test").addEventListener("click", function(e) {
      console.log("clicked:", this);
    });
  });
</script>
<button id="test">click me</button>

jQuery’s ready()

DOMContentLoaded and window:load each have their caveats. jQuery’s ready() delivers a hybrid solution, using DOMContentLoaded when possible, failing over to window:load when necessary, and firing its callback immediately if the DOM is already complete.

You can pass your ready handler directly to jQuery as $(handler), e.g.:

<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<script>
  $(function() {
    $("#test").click(function() {
      console.log("clicked:", this);
    });
  });
</script>
<button id="test">click me</button>

Option 5: Event Delegation

Delegate the event handling to an ancestor of the target element.

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, all the way up to window, 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 from descendants added after the handler was 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.

Typically, this pattern is reserved for elements that don’t exist at load time or to avoid attaching a large number of duplicate handlers. For efficiency, select the nearest reliable ancestor of the target element rather than attaching it to the document.

Native JavaScript

<div id="ancestor"><!-- nearest ancestor available to our script -->
  <script>
    document.getElementById("ancestor").addEventListener("click", function(e) {
      if (e.target.id === "descendant") {
        console.log("clicked:", e.target);
      }
    });
  </script>
  <button id="descendant">click me</button>
</div>

jQuery’s on()

jQuery makes this functionality available through on(). Given an event name, a selector for the desired descendant, and an event handler, it will resolve your delegated event handling and manage your this context:

<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<div id="ancestor"><!-- nearest ancestor available to our script -->
  <script>
    $("#ancestor").on("click", "#descendant", function(e) {
      console.log("clicked:", this);
    });
  </script>
  <button id="descendant">click me</button>
</div>

[ad_2]

  • 0 0 Answers
  • 4 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report
Leave an answer

Leave an answer
Cancel reply

Browse

Sidebar

Ask A Question

Related Questions

  • xcode - Can you build dynamic libraries for iOS and ...

    • 0 Answers
  • bash - How to check if a process id (PID) ...

    • 396 Answers
  • database - Oracle: Changing VARCHAR2 column to CLOB

    • 370 Answers
  • What's the difference between HEAD, working tree and index, in ...

    • 361 Answers
  • Amazon EC2 Free tier - how many instances can I ...

    • 0 Answers

Stats

  • Questions : 43k

Subscribe

Login

Forgot Password?

Footer

Follow

© 2022 Stackoverflow Point. All Rights Reserved.

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.