Another rather easy method to avoid all the hassle of re-attaching event 
handlers to ajax-loaded content is to attach the event handlers to the 
container element only once, and then take advantage of Event Bubbling.

Consider the following example

<div id="container">
    <div class="clickme">please click me</div>
</div>

If we attached the event to the inner div using 
$.('.clickme').bind('click',function(){alert('foo');}) we would need to do 
this binding each time we load some new content to the container. We would 
also need to be careful not to reattach to elements that already have the 
listener attached, and so on.

If we instead bind to the container element, we will not need to rebind at 
all. There is only one listener bound, and clicks on all children will 
trigger its event listeners through event bubbling:

$('#container').bind('click',function(event){
        if($(event.target).is('.clickme'))
        {
            alert('foo');
        }
});

Since the event listener is bound to the containing element, there is no 
need to reattach it when content inside it changes (through aja[x|h] or 
otherwise). You can also have several actions bound this way.

Performance-wise this means moving the (totally negligible in this case, 
rarely becomes an issue except for larger javascript applications) 
performance hit from page load (attaching several listeners upon loading the 
DOM) to the event clicks (going through several conditional statements to 
pick the right code to run). IMO this is actually better, since I suspect 
users are generally more acceptant to tiny delays when they take action 
(click an element) than to general delays on page loads.

-- 
Suni


Joel Birch wrote:
> What I said about the handler being attached more than once really
> only applied to the example we were working with. Considering you are
> emptying the content now the previous .test will not exist by the
> time you load the new one. Also, Jörn's advise about using find() is
> good practice and will ensure that the handler is attached only to
> the .test elements it "finds" within the string you just appended.
> You should be ok with something like:
>
> function testHandler() {
> $(".test").change(function(){
> alert(this.options[this.selectedIndex].text);
> });
> }
>
> $(document).ready(function(){
> testHandler();
> $(".trigger.fruits").click(function(){
> $("#content").empty();
> $("#content").append('<select name="fruits" class="test"><option
> value="first">apple</option><option
> value="second">orange</option><option
> value="third">peach</option></select>')
> .find(".test").each(testHandler);
> return false;
> });
> $(".trigger.vegetables").click(function(){
> $("#content").empty();
> $("#content").append('<select name="vegetables"
> class="test"><option value="first">tomato</option><option
> value="second">potatoe</option><option
> value="third">carrot</option></select>')
> .find(".test").each(testHandler);
> return false;
> });
> });
>
> I'm pretty sure that code can be optimised better than this though.
> Also, about the parsing of the HTML - jQuery does do this for you so
> don't worry about that.
>
> Good luck
> Joel.
>
>
> On 24/01/2007, at 12:34 AM, Laurent Goussard wrote:
>
>> If I well understood Joel and Jörn, I am suppose to declare my event
>> handler each time I switch the #content's content, but this will
>> result to increment the alert() number each time the event is
>> declared... What a pity...
>>
>> I cannot really understand why jQuery does not add the content newly
>> loaded to the existing DOM. I mean jQuery should parse and update the
>> DOM foreach .html method used (in append*, load, etc...), shouldn't
>> it ?
>>
>> I can't imagine I'm the only one who wanted to add jQuery events on
>> html content loaded with jQuery. Am I ?
>
>
> _______________________________________________
> jQuery mailing list
> discuss@jquery.com
> http://jquery.com/discuss/ 


_______________________________________________
jQuery mailing list
discuss@jquery.com
http://jquery.com/discuss/

Reply via email to