24

I'm trying to do something fairly simple, but for the reason of me probably not being good enough to search documentation, I can't get this to work.

I have a functioning inline JS that looks like this:

<A title="Wolfram IP Calc" href="javascript:txt=prompt('Enter%20IP%20address,%20e.g.%2010.20.30.40/29','1.2.3.4/5');%20if(txt)%20window.open('http://www.wolframalpha.com/input/?i='+txt);void(O);">Compute!</A>

For various reasons, I'm trying to seperate the JS, and this is where I hit a snag.

I've created the following test page that gives me the error Uncaught TypeError: Cannot call method 'addEventListener' of null:

<HTML> <HEAD profile="http://www.w3.org/2005/10/profile"> <script type="text/javascript">
var compute = document.getElementById('compute');
compute.addEventListener('click', computeThatThing, false);

function computeThatThing() {
    txt=prompt('Enter%20IP%20address,%20e.g.%2010.20.30.40/29','1.2.3.4/5');
    if(txt) {
        window.open('http://www.wolframalpha.com/input/?i='+txt);
    }
}
</script></HEAD>
<BODY>
<A title="Wolfram IP Calc" id="compute" href="javascript:void(O);">Test</A>
</BODY>
</HTML>

The only thing I've been able to find that points to a problem like that is that addEventListener can't work with <A> but should handle <IMG> (which suits me fine as I'm going to pour this on some images), so I tried adding the following to no avail:

<img id="compute" src="http://products.wolframalpha.com/images/products/products-wa.png" />

Thanks in advance for pointing out what I'm doing wrong. It is probably glaringly obvious, but I have close to zero experience with JS and I have gone mostly by cargo culting when I've needed it until now.

Aamer
  • 743
  • 2
  • 11
  • 24
Jan
  • 813
  • 2
  • 8
  • 17
  • Use Jquery. $(document).ready(function(){ }); – PhillipKregg Mar 24 '12 at 22:31
  • 1
    @PhillipKregg, I feel adding Jquery to my project would add needless complexity and load times. – Jan Mar 25 '12 at 00:46
  • @PhillipKregg This is specifically for a project where everything is contained in one file, including base64 encoded images, so that it has no external dependencies. – Jan Mar 25 '12 at 05:21
  • You can simply paste in the jquery code, you don't need to use an external file to use jquery. – cchiera Mar 27 '15 at 20:44
  • @cchiera That would needlessly add 10'000 lines of code to a project I am trying to keep simple. – Jan Mar 28 '15 at 08:57
  • Possible duplicate of [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) – Makyen Mar 05 '17 at 17:10

2 Answers2

55

Your code is in the <head> => runs before the elements are rendered, so document.getElementById('compute'); returns null, as MDN promise...

element = document.getElementById(id);
element is a reference to an Element object, or null if an element with the specified ID is not in the document.

MDN

Solutions:

  1. Put the scripts in the bottom of the page.
  2. Call the attach code in the load event.
  3. Use jQuery library and it's DOM ready event.

What is the jQuery ready event and why is it needed?
(why no just JavaScript's load event):

While JavaScript provides the load event for executing code when a page is rendered, this event does not get triggered until all assets such as images have been completely received. In most cases, the script can be run as soon as the DOM hierarchy has been fully constructed. The handler passed to .ready() is guaranteed to be executed after the DOM is ready, so this is usually the best place to attach all other event handlers...
...

ready docs

gdoron is supporting Monica
  • 136,782
  • 49
  • 273
  • 342
  • 1
    Thanks `gdoron`! Solution 1 worked right off the bat. I'm honestly surprised that it was this simple and almost intuitive. Now onto breaking my production code! :) – Jan Mar 24 '12 at 22:30
  • i am facing same problem while implimenting morris chart. and i have done all this and still no hope. – Abhinav Oct 26 '16 at 13:14
  • Your answer was refered to me by someone who's learning web development. Being up-voted, it has the weight of being useful, but it's misleading. Please correct it or reference my clarifications to it to prevent this. As a rule of thumb, please make sure what you quote is actually correct and up to date. Thank you. – tao Sep 21 '18 at 22:16
  • @AndreiGheorghiu misleading in which way? if you think there is a mistake here, feel free to suggest an edit to the answer. – gdoron is supporting Monica Sep 22 '18 at 19:27
  • I already explained it in the answer. Since the explanation, for clarity, was longer than your answer, I thought it was better to contain it into an additional answer, which refers yours. In detail, your answer states that `ready` event of jQuery waits for images to load, which is `false`. You also state this using tools denominating a quote, adding emphasis to it and trying to make it look "official". That is detrimental especially to people just starting with web design, like my students. – tao Sep 22 '18 at 19:31
  • I've made a small demo [here](https://jsfiddle.net/websiter/6h5xrqwj/). Placed the results in the js panel. I'll also test and post from Ubuntu, although I doubt there will be major differences (it has little to do with the OS/browser used). You can clearly see `.ready()` fires before `$("img").on('load')` - if the `img` is not cached. – tao Sep 22 '18 at 20:10
  • @AndreiGheorghiu A. The quote in the bottom of my answer was in the official documentation I linked, seems like it was changed a bit since then, the internet isn't static. B. Anyhow, I hope your students have better reading comprehension, I no where said jQuery's ready waits for images and in fact, if you read carefully the official documentation I quoted says exactly the opposite. You wrote all that without REALLY reading my answer at all. – gdoron is supporting Monica Sep 29 '18 at 21:36
  • I read your answer carefully. And so did those who told me they read it on [so] in a highly up-voted answer. Apologies for having to repeat myself: the end result of your answer is that people understand wrongly what is going on with each of the two events. Which means your answer is at least misleading, if not outright wrong, by commonly accepted standards. – tao Sep 29 '18 at 22:18
0

Move script tag at the end of BODY instead of HEAD because in current code when the script is computed html element doesn't exist in document.

Since you don't want to you jquery. Use window.onload or document.onload to execute the entire piece of code that you have in current script tag. window.onload vs document.onload

Shubham Gupta
  • 2,328
  • 1
  • 6
  • 18