views:

196

answers:

4

Often times I have elements hooked to added functionality, like:

$('.myfav').autocomplete();
$('.myfav').datepicker();
$('.myfav').click(somefunction);

But when more instances of this class are generated dynamically through some code, the new $('.myfav') are dead and need rewiring, so I do this:

$("#somelink").click(function(){
     //generate 10 new $('.myfav') and append them to the DOM
     //re-wire them again as in the block above
     $('.myfav').autocomplete();
     $('.myfav').datepicker();
     $('.myfav').click(somefunction);
});

What this means is that I end up having 2 identical blocks of code, 1 for the initial page load and one to rewire the new elements that get generated dynamically. This isn't DRY code and isn't very efficient.

Is this really the only way to get this done, or there another best practice? My gut tells me there's gotta be something more efficient than this (also to help DRY the code).

update

Looks like .live works well with .click as explained by cletus.

$('.myfav').live("click", somefunction);

But I tried it with custom-set plugins like .autocomplete and it didn't work. I tried this:

$('.myfav').live("click", autocomplete("somefile.php", {max: 15, mustMatch: true}));

So live doesn't look like it can handle these custom plugins (of course I could be wrong, please update if you know something)

+3  A: 

Use live():

$(".myfav").live("click", somefunction);

This will bind that event handler to elements dynamically created after the live() call.

cletus
I thought of live too, but would it work with plugin binding like `$('.myfav').datepicker();` or `$('.myfav').autocomplete();`What should the syntax look like in this case? `$('.myfav').live("click", autocomplete("somefile.php"));`? and what if I have many options like `$('.myfav').autocomplete("somefile.php", {max: 15, mustMatch: true});` Any further input on the syntax in this last case as an example?
Chris
live() works with event handlers, not plugins like datepicker(). There is no other choice for those than binding when you create/append the elements to the DOM.
cletus
+2  A: 

I think you can use live();, but not how you have written it.

Your current implementation:

$('.myfav').live("click", autocomplete("somefile.php", {max: 15, mustMatch: true}));

This will execute autocomplete immediately, not when jQuery finds a new element with class="myfav"

You should use this syntax:

$('.myfav').live("click", function () {
    $('.myfav').autocomplete("somefile.php", {max: 15, mustMatch: true})
});

You can use all the normal syntax, functions, etc inside the anonymous function.

I think this will work, but I haven't tested it. What it does is send jQuery a function to execute later when the click event fires.

Ryan Doherty
Hmmm, didn't seem to work for me, not sure why.
Chris
I changed it to $('.myfav').autocomplete("somefile.php", {max: 15, mustMatch: true}) inside the anonymous function, I think that was the problem.
Ryan Doherty
+3  A: 

The .live() documentation says ...

.live doesn't support the no-event style callback that liveQuery provides. Only event handlers can be bound with .live.

So I took a look at liveQuery, and I think it will do exactly what you need with something like the following:

$('.myfav').livequery(function() {
  $(this).autocomplete();
  $(this).datepicker();
  $(this).click(somefunction);
});

Seems handy!

No Surprises
Looks promising. Will try it out and get back
Chris
+1  A: 

In cases like this I usually find myself using an init function that does the binding/unbinding, then call that on ajaxComplete or the like. In this case it would probably look like this:

function init()
{
    $('.myfav').unbind('click');
    $('.myfav').autocomplete('disable');
    $('.myfav').datepicker('disable');
    $('.myfav').autocomplete();
    $('.myfav').datepicker();
    $('.myfav').click(somefunction);
}

Of course, depending on the plugin the unbind might look different, I belive jQueryUI uses $('.myfav').draggable('destroy') for instance.

Kristoffer S Hansen