Monday, March 7, 2011

Lazy binding functions to multiple events with jQuery

Here's the scenario: I have a set of buttons that I want to bind to corresponding functions when clicked. The ids of these buttons are the same as the names of their corresponding functions. I could do this:

$("#kick").click(kick);
$("#push").click(push);
$("#shove").click(shove);

But I'm lazy and would like to do this more lazily (as is my nature). As the buttons are all contained in a block element, I'd like to do something like this:

$("#button_holder > span").each(function () {
    var doThis = this.id;
    $(this).click(doThis);
});

Except that doesn't work. Any suggestions?

From stackoverflow
  • $("#button_holder > span").each(function () {
        var doThis = this.id;
        $(this).click(function(doThis){
          alert(doThis);
        });
    });
    
    robbiebow : I don't think that works; it binds an anonymous function to the event.
  • <input type="submit" id="kick" value="Kick Me">
    <input type="submit" id="push" value="Push Me">
    
    <script type="text/javascript>
    $(function() {
        $("input[type=submit]").each(function () {
            var doThis = this.id;
            $(this).click(doThis);
        });
    });
    </script>
    
    robbiebow : This gives me the same end result, just that the way the elements to bind to are selected has changed, as far as I can see.
  • I guess I don't see the point of this. You need to create each function individually anyway and this sort of programming is difficult for others to grok usually. Maybe if you have dozens of buttons and it's throw-away code, I could understand but .. probably not...

    Why not just bind all to a single function and make the determination based on this.id at event time??

    robbiebow : I find it more readable and more reusable to say "children spans of this div will all have their own functions, and the functions' names will be the same as the spans' ids". It's a matter of aesthetics, IMO.
  • its very simple ! you try to pass none-function to the click method.

    var doThis = this.id;
    $(this).click(doThis);
    

    you need to pass a function :

     $(this).click(function(doThis){
          alert(doThis);
    

    });

    or :

    function myFunc(){};
    $(this).click(myFunc);
    
  • Like the other answerers, I'm not sure that this is "true" laziness (as in the programmer's virtue), but only you know your implementation details.

    If you really want to do something like this, you can use an object to store your particular functions and then use the string to look them up:

    var myFunction = {
         kick:  kick,
         push:  push,
         shove: shove
    };
    
    $("#button_holder > span").each(function () {
        var doThis = this.id;
        $(this).click(myFunction[doThis]);
    });
    

    Or as anonymous functions:

    var myFunction = {
         kick:  function() { /*do kick  */ },
         push:  function() { /*do push  */ },
         shove: function() { /*do shove */ }
    };
    
    $("#button_holder > span").each(function () {
        var doThis = this.id;
        $(this).click(myFunction[doThis]);
    });
    
    robbiebow : Thanks for the ideas, both of which work for me. I consider this to be proper laziness as it reduces the amount of repetition / work I need to do to add new buttons with associated events, but sure, it's arguable. Thanks again.

0 comments:

Post a Comment