0

I usually don't have a problem using JQuery, but sometimes when I write standalone Javascript I feel like a complete idiot, like today. (I'm doing this simply because one I'm bored and two I'm trying to understand Javascript more itself.)

Here's the JQuery...

$(document).ready(function() {
  $(".call").on('click', function() {
   if ( $(".code").val() === "" ) {
      alert("Function denied!");
    } else {
      alert("Function accepted!");
    }
  });
});

And here is about 30 minutes of toying around without getting it working, until I put it right before the closing </body> tag.

Can someone explain why it has to be done this way and not in the head tags?

var code = document.querySelector('.code'),
    call = document.querySelector('.call');

document.addEventListener('DOMContentLoaded', function() {
  call.addEventListener('click', function() {
    if ( code.value === "" ) {
      alert("Function denied!");
    } else {
      alert("Function accepted!");
    }
  });
});
user2864740
  • 54,112
  • 10
  • 112
  • 187
Michael Schwartz
  • 6,962
  • 12
  • 69
  • 126
  • 4
    Because the elements have to exists in the DOM, so the script has to come after the elements it's trying to use – adeneo Apr 03 '14 at 03:48
  • 2
    See [Why does jQuery or a DOM method such as `getElementById` not find the element?](http://stackoverflow.com/questions/14028959/why-does-jquery-or-a-dom-method-such-as-getelementbyid-not-find-the-element) – Felix Kling Apr 03 '14 at 03:49
  • 2
    Put the variable declarations inside the event listener function, and then it will work just like jQuery. – Barmar Apr 03 '14 at 03:49

2 Answers2

1

You are trying to query DOM for .code and .call before those elements are available. If you move your code to the end of the body, the script gets executed after the elements' html has been interpreted into DOM so you don't see the issue.

A better way to deal with it would be moving the querySelector into the DOMContentLoaded callback:

document.addEventListener('DOMContentLoaded', function() {
  var code = document.querySelector('.code'),
      call = document.querySelector('.call');
  call.addEventListener('click', function() {
    if ( code.value === "" ) {
      alert("Function denied!");
    } else {
      alert("Function accepted!");
    }
  });
});

Stylistics aside, the code above should work regardless of its placement.

Oleg
  • 22,838
  • 4
  • 55
  • 82
0

Although you have an event listener set to run when the document has loaded, you rely on two variables code and call that were initialized at run time, ie before the document was fully loaded. Putting your code at the bottom of the body tag ensures the query returns the expected result in your case. Try putting the variable declarations inside the the event listener.

As a side note, you might be using querySelector wrong. To be clear, querySelector will return the first instance of an element that matches. querySelectorAll will return all instances of elements that match the query. I only point this out because you are using classes in this example, not ID's.

lampwins
  • 870
  • 8
  • 25