5

This question is so basic, I'm certain in must be a duplicate of something, even though I've looked for something similar.

My question is basically: Where is the best place to initially register event handlers for HTML elements?

The easiest way to register an event handler is obviously to just do it inline:

<div id = "mybutton" onclick = "doSomething()">Click me</div>

But this goes against the overwhelming march towards separation of logic and content in modern web development. So, in 2012, all logic/behavior is supposed to be done in pure Javascript code. That's great, and it leads to more maintainable code. But you still need some initial hook that hooks up your HTML elements with your Javascript code.

Usually, I just do something like:

<body onload = "registerAllEventHandlers()">

But... that's still "cheating", isn't it - because we're still using inline Javascript here. But what other options do we have? We can't do it in a <script> tag in the <head> section, because at that point we can't access the DOM since the page hasn't loaded yet:

<head>
<script type = "text/javascript">
    var myButton = document.getElementById("mybutton"); // myButton is null!
</script>
</head>

Do we place a <script> tag at the bottom of the page or something? Like:

<html>
<body>
...
...
<script type = "text/javascript">
   registerAllEventHandlers();
</script>
</body>
</html>

What is the best practice here?

Community
  • 1
  • 1
Channel72
  • 24,139
  • 32
  • 108
  • 180

4 Answers4

2

You can use window.onload:

<script type = "text/javascript">
  window.onload = registerAllEventHandlers;
</script>

Or if you use :

$(registerAllEventHandlers);

Using onload works because it registers onload event immediately but fires it when DOM is ready.

ComFreek
  • 29,044
  • 18
  • 104
  • 156
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • -1: The `window.onload` event is not equivalent to using jQuery's `ready` event: `window.onload` will fire when the page has finished loading, including all external resources (images, CSS etc.) while jQuery's `ready` event will fire after the HTML has finished loading but before external resources. Using `window.onload` is a bad idea, because in many cases (many images, slow connection, etc.) the JavaScript events won't be registered for a long time. – georgebrock May 27 '12 at 16:29
  • @slebetman: Can you elaborate on why it's stupid to attach JS event handlers before images (etc.) are loaded and to understand the differences between two different techniques? On a site that's meant to be about learning and sharing information a comment saying “that's stupid” isn't very constructive. – georgebrock May 27 '12 at 16:46
0

I had a similar answer to this but was about JavaScript in general. But the idea is still the same - load scripts before closing the body.

Take advantage of libraries that abstract the window.onload and the DOM ready event. That way, you can load the scripts as soon as the DOM is ready.

Community
  • 1
  • 1
Joseph
  • 117,725
  • 30
  • 181
  • 234
0

You should register your event handlers as soon as the DOM is ready. Detecting this across all browsers hasn't always been easy, although with the notable exception of IE 8 (and earlier) most widely used browsers now support the DOMContentLoaded event (thanks to gengkev for pointing that out in the comments).

This is essentially equivalent to calling your registerAllEventHandlers function at the end of your body, but it has the advantage that you don't need to add any JavaScript to your HTML.

It is significantly better than using window.onload because that isn't executed until all of the page's assets (images, CSS etc.) have loaded.

If you're using one of the major JavaScript frameworks, then you can very easily detect when the DOM is ready, even in older versions of IE. With jQuery you would use the ready event:

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

Or the shorthand:

jQuery(function() { … });

With Prototype you would use the dom:loaded event:

document.observe("dom:loaded", function() {
    // Your initialisation code here
});
Community
  • 1
  • 1
georgebrock
  • 28,393
  • 13
  • 77
  • 72
0

Personally, I have no problems with adding onlclick="doSomething();" to elements. No logic, just a function call.

All logic is where it should be: in the function defined in the HEAD or a separate file.

Tell me what the difference is when you add href="somepage.html" or even href="somepage.html#someanchor" to an A tag.

Matthew
  • 8,183
  • 10
  • 37
  • 65
  • I rarely find I have just one link that needs some behaviour; often it's a whole group of similar links. When that behaviour changes or is no longer required, I find it much more convenient to change or remove a single `.js` file that defines the behaviour and attaches it to the relevant links, rather than changing or removing many `onclick` attributes on many links. – georgebrock May 27 '12 at 16:24
  • @georgebrock You could say the same if you wanted to rename/re-structure your HTML files - you would still have to go to every `A` tag and change the `href` attribute. Anyway, in your case, no need to change the function name, just re-write the function. If the behavior of the onclick is changing then maybe it's worth changing the function name to something else. You make a good point though. – Matthew May 27 '12 at 16:33
  • Once a website is on the public web, changing the `href` attributes is going to be a headache anyway, because [cool URIs don't change](http://www.w3.org/Provider/Style/URI) (and when they do have to change, they should 301 to the new locations). But I digress. Since you can write your JavaScript so that there's a single point of change and clear separation of concerns, why not do so? – georgebrock May 27 '12 at 16:40
  • You can still have a single point of change with inline onclicks if all you are changing is the code in your function. As to why not separate event handlers: readability of the HTML - you can't tell what buttons (for example) will do solely by looking at the HTML since the behavior is defined in a separate file. – Matthew May 27 '12 at 16:49
  • Perhaps we're just coming from different development styles: I would always want a link to point to a real URL, and a button to submit a real form. If I added a link or button didn't work without JavaScript then I would add it to the page using JavaScript. – georgebrock May 27 '12 at 16:54