2

If the event handler is declared in the markup, it'd be (kind-of) adding presentation logic to HTML.

<button id="btn" onClick="foo()">Click Me!</button>

If the event handler is declared in the script, it'd be (kind-of) hard to look at the code and figure out what button does.

document.getElementById('btn').onclick=foo;

Is there any best-practice for this scenario?


The reason for this question is that I was attaching event handlers on page load via the script. However, I ran into a problem where the DOM element may not be present when the page loads (I'm using KnockoutJS's if binding), and the event is not bound to the handler. To attach the handler as and when the if condition is satisfied would complicate the code further. So now I'm thinking of moving my handlers to the click binding. What might be the potential pitfalls and what best-practices should I follow to avoid them?

2

There's no right or wrong to this, both things are fine. There are a few things to consider which makes one or the other better in one or the other situation.

And actually, there are at least three ways of assigning event handlers:

  1. Using an event handler attribute in HTML, like this:

    <button id="buttonSave" onClick="save()">Save</button>
    
  2. Using a script to set the property, like this:

    <button id="buttonSave">Save</button>
    
    document.getElementById("buttonSave").onclick = save;
    
  3. Modifying the event handlers using addEventListener()

    document.getElementById("buttonSave").addEventListener("onclick", save);
    

Here's the decision path which I use.

  • A lot (>~20) of elements share the same handler -> 2. or 3., because doing it in JavaScript will save bytes, and in page loading traffic is slower than JavaScript.
  • Multiple handlers for a single element needed
    • Handler needs to be added or removed dynamically -> 3. addEventListener()
    • Handler doesn't change -> 1. HTML
  • Single handler sufficient
    • Handler needs to be added or removed dynamically -> 2. JavaScript
    • Handler doesn't change -> 1. HTML

The problem which you describe can actually be solved by moving the JavaScript code which installs the handlers into a JavaScript function which itself is installed as onload handler, so the JavaScript would only run when the DOM is ready for it. There might still be a "race condition" (not in the sense of concurrency but in the sense of sequence) when other JavaScripts run and modify the DOM. To prevent that, I usually do not install multiple onload handlers, but just a single handler which calls all the functions that need to be executed during onload in the required sequence.

  • Cool! This decision path makes sense. But in my case, the DOM elements may pop in and out of existence based on user interaction too, so even the onload approach may not be sufficient. – Fa773N M0nK Jul 8 '15 at 10:45
  • Using a less-than-kosher method might make sense in the case where you are injecting DOM elements into a page dynamically. Whether you define event listeners after appending elements or add bindings in the markup itself, all that matters in the end is that your code is maintainable. Though I would suggest keeping JS in the markup to a minimum... separation of concerns is important. – Jeffrey Sweeney Jul 8 '15 at 13:37
0

If the event handler is declared in the script, it'd be (kind-of) hard to look at the code and figure out what button does.

You answered your own question.

Registering the handler in the JS code separates the markup from the logic which is always a desirable property.

  • 1
    "...separates the markup from the logic which is always a desirable property" Until you look at angular, knockout, react, or pretty much any other modern JS framework. – zzzzBov Jul 8 '15 at 13:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.