Dynamic Binding

One of the Projects I’ve been working on quite a bit lately has me working with Faceboxes, and I really think they are great! One of the latest uses I have found for them is to replace the ugly JavaScript confirmation box. I have actually been using Faceboxes for a while but in the past have just used them to load a new HTML page. Obviously, this is not practical just to ask for confirmation of an action, so I have started just passing some text or basic HTML rather than a URL.

Ugly JavaScript confirmation box:

Javascript Confirm

Instead, you can have a friendly looking and customised box which is a lot more user friendly:

Facebox Confirm

The problem that I have now encountered is that the buttons which appear in the Facebox require some JavaScript of their own to control them. This is a problem because you can’t just enter some JavaScript into a string which is contained in other JavaScript code. I can’t do this:

      $("input[name='delete-reminder']").click(function(){        $.facebox('Are you sure you want to delete the following reminder?< br / >' +                   '< script language="javascript" type="text/javascript" >' +                   '  $(document).ready(function(){' +                   '    $("input#confirm-delete").click(function(){' +                   '      $.facebox.close()' +                   '      $.post("includes/member-your-reminders-include.php",' +                   '             {ajax: 1, remove: 1, reminder_id: $(this).attr("rel")},' +                   '             function(data){ $("#container").html(data) })' +                   '    })' +                   '  })' +                   '< /script >' +                   '< div align="center" >' +                   '  < input class="save-sml-black" type="button" value="yes" id="confirm-delete" rel="' + $(this).attr('rel') + '" / >' +                   '  < input class="save-sml-black" type="button" value="no" id="cancel-delete" / >' +                   '< /div >')      })

…because, as soon as the web browser encounters the line containing the closing < / script > tag, it thinks the the JavaScript is finished and stops processing the code as JavaScript.

I’m sure that I could probably find a way to encode the script tags so that this problem doesn’t occur but I think there is a much easier way to go. The JavaScript to handle the delete button can go in the JavaScript of the page itself and it doesn’t matter whether the delete button exists at the time that the page is loaded or not. There are two ways to go about this.

The first solution I came up with is one provided by the Facebox itself. It is quite simple in it’s implementation. You simply need to utilise the reveal functionality of the Facebox by binding the delete button to it like this:

     $(document).bind('reveal.facebox', function(){        $('input#confirm-delete').click(function(){          $.facebox.close()          $.post("includes/member-your-reminders-include.php",                 {ajax: 1, remove: 1, reminder_id: $(this).attr("rel")},                       function(data){ $("#container").html(data) })        })      })

Then, every time the Facebox is activated, the delete button will be created and the delete action will be bound to it.

The other solution is to utilise jQuery’s live() function. This function allows any handler to be dynamically bound to an object as the object is created:

        $('input#confirm-delete').live('click', function(){          $.facebox.close()          $.post("includes/member-your-reminders-include.php",                 {ajax: 1, remove: 1, reminder_id: $(this).attr("rel")},                       function(data){ $("#container").html(data) })        })

The implementation for this is even simpler than using Facebox’s reveal function and can be used in many more ways than just the example I have given.

If you have a page where objects are removed and created regularly it can be difficult to keep track of whether a button has it’s appropriate action bound to it but use of the live() function takes all of the guess work out. Imagine a scenario where you have a list of items which is restricted in length. The user removes an item from the list and an AJAX call is triggered to get the next item to display in it’s place. If you were using the bind() function to bind edit and delete buttons to each item, you would need to make sure that, each time a new item was displayed, all of the necessary actions were bound to the correct controls. However, with your click events bound using the live() function you don’t need to worry about it.

I was worried about possible performance implications with using live() instead of bind() but a quick Google search on the topic turned up this article which compares bind(), live() and a couple of other options and seems to show that, on the whole, it compares favourably. I know this is hardly a scientifically sound experiment but everything that I have read seems to indicate that live() is more efficient than bind() so I am satisfied that it’s OK to use.

However, I still only use it where it’s required because, with dynamic binding of events, it is possible that you could end up with a control bound to an event that it shouldn’t be. I think this is something to be careful of when using the live() function.

About Jared

Jared has over 10 years experience developing applications for the web. He can often be found in a dimly light room with the music blasting hacking away at a project to the early hours of the morning.

Speak Your Mind

*