Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery: Any way to "refresh" event handlers?

I have two divs, one that holds some stuff and the other with all possible stuff. Clicking on one of the divs will transfer items to the other div. The code I came up with is:

$("#holder > *").each(function() {
    $(this).click(function(e) {
        $(this).remove();
        $("#bucket").append(this);
    });
});

$("#bucket > *").each(function() {
    $(this).click(function(e) {
        $(this).remove();
        $("#holder").append(this);
        });
});

This one works perfectly, except that the event handlers need to be refreshed once I append or remove elements. What I mean is, if I first click on an element, it gets added to the other div, but if I click on this element again, nothing happens. I can do this manually but is there a better way to achieve this?

like image 540
Legend Avatar asked May 25 '10 21:05

Legend


4 Answers

Try jquery live events .. the $.live(eventname, function) will bind to any current elements that match as well as elements added to the Dom in the future by javascript manipulation.

example:

$("#holder > *").live("click", function(e) { 
        $(this).remove(); 
        $("#bucket").append(this); 
}); 

$("#bucket > *").live("click", function(e) { 
        $(this).remove(); 
        $("#holder").append(this); 
});

Important:

Note that $.live has since been stripped from jQuery (1.9 onwards) and that you should instead use $.on.

I suggest that you refer to this answer for an updated example.

like image 50
John Hartsock Avatar answered Nov 16 '22 11:11

John Hartsock


First, live is deprecated. Second, refreshing isn't what you want. You just need to attach the click handler to the right source, in this case: the document.

When you do

$(document).on('click', <id or class of element>, <function>);

the click handler is attached to the document. When the page is loaded, the click handler is attached to a specific instance of an element. When the page is reloaded, that specific instance is gone so the handler isn't going to register any clicks. But the page remains so attach the click handler to the document. Simple and easy.

like image 23
craned Avatar answered Nov 16 '22 12:11

craned


Here you go, using the more intuitive delegate API:

var holder = $('#holder'),
    bucket = $('#bucket');

holder.delegate('*', 'click', function(e) {
    $(this).remove();
    bucket.append(this);
});

bucket.delegate('*', 'click', function(e) {
    $(this).remove();
    holder.append(this);
});
like image 6
James Avatar answered Nov 16 '22 13:11

James


EDIT: don't use live, it be deprecated!

Take advantage of the fact that events bubble. Using .on():

var  = function( el1, el2 ) {

var things = $('#holder, #bucket');
things.each(function( index ) {
  // for every click on or in this element
  things.eq(index).on('click', '> *', function() {
    // append will remove the element
    // Number( !0 ) => 1, Number( !1 ) => 0
    things.eq( Number(!index) ).append( this );
  });
});

any click on any element (existing at the time of bind or not) will bubble up (assuming you haven't manually captured the event and stopped propagation). Thus, you can use that event delegation to bind only two events, one on each container. Every click that passed the selector test of the 2nd argument (in this case, > *, will remove that element and then append it to the alternate container as accesesed by things.eq( Number(!index) )

like image 2
Dan Heberden Avatar answered Nov 16 '22 13:11

Dan Heberden