0

Is it better to have multiple handlers for button click events, or is it suitable to combine click handlers with a switch statement? This works in my code, but I was wondering, is there a cooler, more JQuery-istic way to do it?

<html>
    <button id="button1">Button 1</button>
    <button id="button2">Button 2</button>
    <button id="button3">Button 3</button>
</html>

Which is better, this?

$('button').click(function(){
    switch(this.id){
        case "button1": 
            alert("Do what button 1 says");
            break;

        case "button2":
            alert("Do what button 2 says");
            break;

        case "button3":
            alert("Do what button 3 says");
            break;
    }
});

Or this,

$('#button1').click(function(){
    alert("Do what button 1 says")
});

$('#button2').click(function(){
    alert("Do what button 3 says")
});

$('#button3').click(function(){
    alert("Do what button 3 says")
});

...Or is there no difference?

Allan Taylor
  • 1,123
  • 6
  • 4

5 Answers5

2

It all depends on the event handler. If there is shared code between the handlers and only a small part is specific, it might be fine to distinguish between the buttons inside the handler.
If each button handler is totally different though, why put three unrelated functions into one?

You can also create a map of functions:

var handlers = {
    id1: function() {
        // ...
    },
    id2: function() {
        //...
    }
};

and simply call a function with handlers[this.id]().

In the end, you assign an even handler to each element one way or the other, so it's more a matter of how you want to structure your code (which is personal preference more or less).

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • I had tried the map technique, but couldn't get it to work. I didn't know it needed the "()" after the function call. Makes sense now that I see it. Thanks. – Allan Taylor Mar 15 '12 at 19:13
1

Your first approach will look for button elements by button tag and it will attach click e event handler to all the button elements.

Second approach will find each button by there ids and also attach click event handler to each of the button elements.

So basically there is no difference.

If you want to optimize it then you on which can work with only one event handler.

$(document).on('click', 'button', function(){
    switch(this.id){
        case "button1": 
            alert("Do what button 1 says");
            break;

        case "button2":
            alert("Do what button 2 says");
            break;

        case "button3":
            alert("Do what button 3 says");
            break;
    }
});

This way it will attach only one event handler on the document and look for button selector whenever click event is triggered.

Note that instead of document it is always better to attach event on any parent element container which will always be present on the page.

Reference - http://api.jquery.com/on/

ShankarSangoli
  • 69,612
  • 13
  • 93
  • 124
  • Binding click events to the document is not recommended. It's why `.live()` was deprecated in jQuery because that's what it did. You can too much congestion when trying to match up an event with the right event handler and event handling can bog down. Events should either be bound to the actual object itself or to the closest ancestor that is practical. Avoid binding at the top level document or body whenever possible. See [this answer from earlier today](http://stackoverflow.com/questions/9711118/why-not-take-javascript-event-delegation-to-the-extreme/9711252#9711252) for more info. – jfriend00 Mar 15 '12 at 01:16
  • I hear you and I always make sure the event should be attached to the immediate parent which is always available on the page. But if the markup structure is not know it makes sense to attach it on the document. However you have explained it very well in your answer +1 :) – ShankarSangoli Mar 15 '12 at 01:28
0

With all things Javascript, maintainability and readability should factor in. With that said, and with little else to go on, I'd always prefer the latter because you have already encouraged the code to focus on the function of each individual button... and in general with any UI, any given button will have a very specific purpose relative to another.

sethcall
  • 2,837
  • 1
  • 19
  • 22
0

For your example, you could store all messages into an array and add a class .button to your buttons in addition to the id. The idea is to extract the id on click() and take the correct message from the array. Something like:

var alerts = ['Hello', 'There', 'World'],
    $buttons = $('.button');

$buttons.click(function(){
    var n = this.id.match(/\d+/); // Assuming that id is `buttonX`...
    alert(alerts[n-1]);
});
elclanrs
  • 92,861
  • 21
  • 134
  • 171
0

The main difference I see is that option 1 is going to bind a click event to every button on the page (which will probably end up with many empty events) and the second will only attach the events to the targeted buttons.

While I'm no stickler for javascript performance, I'd say the second option is more readable and will lend itself to less maintenance issues.

If the different buttons are performing nearly the same function, albeit with slightly different parameters, then perhaps a good alternative would be to use data- attributes on the button elements and have all buttons performing the same task use the same click event, which would pull the unique parameters off of the actual html element that was clicked. Overly simplistic example:

html:

<button data-effect="slide" ...>slide</button>
<button data-effect="fade" ...>slide</button>

javascript:

$("button[data-effect]".click(function(){
    //do stuff
    var $this = $(this);
    $this.hide($this.attr("data-effect") || "blind")
});
DMac the Destroyer
  • 5,240
  • 6
  • 36
  • 56
  • Why have a button on your UI if you didn't mean for something to happen when you click it? – Allan Taylor Mar 15 '12 at 19:09
  • why have a button click handler fire on a button that it's not intended for? – DMac the Destroyer Mar 15 '12 at 19:13
  • maybe i misunderstand how the click event works. Assuming all buttons have an intended handler, if the click event fires when you click on a button, and the handler processes the correct code based on the button id, then how was it not intended for that button? the only buttons i can think of that don't need a click event are submit buttons. in which case you just need to include the class of buttons, or parent container in the selector. – Allan Taylor Mar 15 '12 at 19:58
  • I think your understanding is correct... the point I'm trying to make is that it's overly broad to assign a specific click event to every button on your page when you're only targeting a subset of the buttons on that page. Either option works just fine, but when thinking about maintenance and modularity, I would rather constrain the firing of an event to the elements for which it's expected than to run the equivalent of a no-op (and potentially, inadvertently doing something worse!) on elements for which it's _not_ intended. What do you think? – DMac the Destroyer Mar 15 '12 at 20:01
  • While I disagree with most of your reasons, I think I've come to agree with your point. Constraining the firing of an event to a specific element means that the process is defined at load time. Whereas determining the correct process only after the event fires happens when it is clicked. I doubt there is any significant advantage in performance either way, but somehow the former just seems more elegant. I really did like the map solution provided by @Felix though. – Allan Taylor Mar 15 '12 at 21:19
  • agree to disagree, but my way is totally better ;) All joking aside, the map solution provided by @Felix is a very good design pattern in general, especially with languages like javascript. Good luck and happy coding – DMac the Destroyer Mar 15 '12 at 21:25