Edward Potter
Edward Potter

Reputation: 3820

Super simple JQuery issue has me stumped. Code will not fire off in <head> but will in <body>

Have never seen this before. Something so simple I'm doing wrong.

My JQuery code just stopped working in the head tag, and now will only work in the body.

This will work:

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>

<body>

<div id="foo">
  Click Me
</div>

<script type="application/javascript">
$('#foo').click(function(){
  alert("I got here");
});
</script>

</body>
</html>

And this will not:

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>

<script type="application/javascript">
$('#foo').click(function(){
  alert("I got here");
});
</script>

</head>

<body>

<div id="foo">
  Click Me
</div>

</body>
</html>

A bit confused. I don't see the typo. Advice most appreciated!

Upvotes: 1

Views: 150

Answers (4)

hex494D49
hex494D49

Reputation: 9235

Try this. It happens because the DOM isn't yet loaded.

$(document).ready(function() {
    $('#foo').click(function(){
        alert("I got here");
    });
});

Or without using a specific library (I think it's more self-describing)

window.onload = function(){
    document.getElementById('foo').onclick = function(){
        alert('I got here');
    };
};

HTML file is loaded sequentially, so your code works within the body because it fires after the div has been created, but it doesn't work within the head section because at that moment the div wasn't yet created. That's way is .onload event used - it guaranteed that nothing will be executed until the DOM isn't ready.

Upvotes: 3

T.J. Crowder
T.J. Crowder

Reputation: 1074198

The problem is that your code runs before the element exists, so $("#foo") doesn't find it.

Unless you use the async or defer attributes, the code in your script tags is run when it is encountered in the HTML. So:

<script>/* your code here */</script>
<div id="foo">..</div>

...will not find the #foo element, because it doesn't exist yet.

But if you have

<div id="foo">..</div>
<script>/* your code here */</script>

...the element exists and your code can find it.

You have three choices:

  1. Use event delegation, where you hook the event on document but only respond to it if the event travelled through a #foo element during the bubbling phase. Example:

    $(document).on("click", "#foo", function() {
        // Do something
    });
    

    This works well unless something else will handle the event on a descendant element of document and prevent it bubbling.

  2. Put the script below the elements it refers to in the HTML. This is vastly preferred. Any elements defined in the markup above the script tags will exist as of when your script runs. So the usual advice is put the script just before the closing </body> tag.

  3. If you don't control where the script element goes, use jQuery's ready function.

    $(document).ready(function() {
        // Your code here
    });
    

    or the shortcut:

    $(function() {
        // Your code here
    });
    

Upvotes: 5

chrisweb
chrisweb

Reputation: 1510

You need to execute your script when the dom is ready. If you put the code into head it will get executed before the browser has loaded the dom inside body, therefore jquery can not find foo. If the code is in body after the element with id "foo" then it will have created the element before the javascript code gets executed.

$(document).ready(function() {

    $('body').on('click', '#foo', function(event) {
        alert('Hello World');
    });

});

If you wrap an on ready around your code it will again work. You could also use jQuery on, and tell jquery to listen on the body, this has the advantage that it will still work even if the element foo is loaded by ajax and inserted into the dom after ready got executed.

Here is the jsfiddle: http://jsfiddle.net/6uLHL/

Upvotes: 1

gkaimakas
gkaimakas

Reputation: 582

The comments and answers that tell you to wrap the code in $(document).ready() are correct but fail to mention why this happens.

This behavior occurs because when you try to excecute the script the DOM has not been created in its enterity and therefore the element you are looking for does not exist. When using $(document).ready() you make sure that the scripts run after the DOM is ready

Upvotes: 0

Related Questions