views:

194

answers:

4

I have been adding new elements via jQuery in some of my projects, and I have stumbled across a bit of a cumbersome issue.

Consider the following:

$('span.claim').click(function() {
    $(this).parent().html('<span class="unclaim">Unclaim</span>'):
});

$('span.unclaim').click(function() {
    $(this).parent().html('<span class="claim">Claim</span>'):
});

And the following markup...

<ul>
    <li><span class="claim">Claim</span></li>
    <li><span class="unclaim">Unclaim</span></li>
    <li><span class="claim">Claim</span></li>
    <li><span class="unclaim">Unclaim</span></li>
</ul>

Unfortunately, after the initial event is fired, no subsequent events are handled.

I realize I could completely restructure and use the .bind() function, but because of the complexity of my project this isn't really all that feasible.

How would I go about re-binding the events after the new elements are created without ditching my anonymous functions, or is it even possible?

+1  A: 

You probably want to look at jQuery live events: http://docs.jquery.com/Events/live

Paddy
+1 - I did not know about the live, that is very, very handy.
sberry2A
That's exactly what I needed. Thanks!
Skudd
+1  A: 

Option 1:

$('a.claim').click(function() {
    $(this).html('Unclaim').addClass('unclaim').removeClass('claim');
});

$('a.unclaim').click(function() {
    $(this).html('Claim').addClass('claim').removeClass('unclaim');
});

Option 2:

function bindClaim(){
$('a.claim').unbind('click').click(function() {
    $(this).parent().html('<span class="unclaim">Unclaim</span>');
    bindUnclaim();
});
}

function bindUnclaim(){
$('a.unclaim').unbind('click').click(function() {
    $(this).parent().html('<span class="claim">Claim</span>');
    bindClaim();
});
}

bindClaim();
bindUnclaim();

Option 3 (recommended):

http://docs.jquery.com/Events/live instead of bind.

thephpdeveloper
+1 for giving several options.
sberry2A
A: 

There is most likely a far more "jquery-ic" solution, but this would work.

initClicks = function() {
    $('span.claim').click(function() {
        $(this).parent().html('<span class="unclaim">Unclaim</span>');
        initClicks();
    });
    $('span.unclaim').click(function() {
        $(this).parent().html('<span class="claim">Claim</span>');
        initClicks();
    });
}
initClicks();
sberry2A
+1  A: 

No need for .live() or re-binding this one. You only need one method:

$('.claim,.unclaim').click(function() {
    var claimed = $(this).hasClass('claim') ? 'Unclaim' : 'Claim';
    $(this).text(claimed).attr('class', claimed.toLowerCase());
});
David
That's not really a viable solution because of the complexity of the actual events. The example given was only intended to be a simple example; much more is actually happening in each event.
Skudd
It's still a good idea to keep the event simple and apply methods depending on the target (event delegation)
David