tags:

views:

225

answers:

4

Hi, all I'm new to jQuery and I'm having a bit of a problem manipulating AJAX results with jQuery methods.

I use an AJAX get and execute the find method on the resulting output. But this seems to work only once. Subsequent attempts using the same selector in the find() argument don't work. Different selectors will work, but again, only once.

There seems to be something going on when traversing the AJAX result?

AJAX call...

    $.get('sections.htm', {}, function(data) {
        var $response = $('<div />').html(data);
        showContent("teaser");

        function showContent(nav) {
            loadContent(nav);
            loadSlimboxHack();
            $('#content').fadeIn(400);
        }

Find element ...

    function loadContent(nav) {
        if (nav == 'teaser')
        {
            $('#content').html($response.find('.teaser'));
        }

This works, but if I try showContent(".teaser") again, it fails because it doesn't seem to find anything and so #content is overwritten with nothing.

Take a look at my website to see...

http://www.shadowshapes.com/dev

A: 

From a quick first glance, I think you're having closure issues...

The $response variable isn't captured in the scope of the closure for the event handlers (such as on your click -> fadeout -> showContent). I'm guessing it would be fixed if you passed the $response variable around instead of trying to reference it globally. I.e. taking your example, make it something like this:

$.get('sections.htm', {}, function(data) {
    var $response = $('<div />').html(data);
    showContent("teaser", $response);

    function showContent(nav, $response) {
        loadContent(nav, $response);
        loadSlimboxHack();
        $('#content').fadeIn(400);
    }
...
    function loadContent(nav, $response) {
    if (nav == 'teaser')
    {
        $('#content').html($response.find('.teaser'));
    }
...

That way you're guaranteed that $response will always be there when you go to use it. The other option is to make $response actually global by declaring it outside your $(document).ready.

Alconja
A: 

Thanks, I had actually already tried passing around $response with no luck. I tried it again, and also tried your other suggestion of making $response global. No luck.

The wierd thing is that $response is available within loadContent(). It just seems that once the selector is found it no longer can be "used"? For example, once the page loads the following happens...

        if (nav == 'teaser')
        {
            $('#content').html($response.find('.teaser'));
        }

But then clicking on one of the teaser images will initiate an event...

    $('div.teaser_img').live("click", function() {
        var nav = $(this).attr("id");
        $('#content').fadeOut(400, function() {
            showContent(nav, $response);
        });

Which then kicks off a conditonal inside loadContent()...

                if (nav == projects[i])
                {
                    var tag = '#' + nav;
                    $('#content').html($response.find('div.teaser' + tag));
                    $('#content').append($response.find('div.concept' + tag));
                    break;
                }

So since div.teaser has already been found when loading the page, #content only gets written with div.concept. Any of the other selectors will also work as long as they haven't already been used.

+2  A: 

Your using the contents of $response and appending some of them into other elements. That means they move out of $response and into their new home hence why the selector will only work once.

Look at it this way. If you take your one and only $10 out of your wallet and put it in mine, the next time you look in your wallet it will not be there. Why? Because it is in mine.

redsquare
+2  A: 

@redsquare, Thanks very much! That put me on the right path.

For the uninitiated, append() acts like a 'move' instead of a 'copy' in a single selector context. Apparently its a common mistake among newbies. And its not quite documented? I don't feel so bad now! :)

http://www.nabble.com/Undocumented-move-copy-behavior-of-append%28%29-et-al.-ts21179461s27240.html#a24146606

So I needed to use clone() in addition to append() in this case.

$('#content').append($response.find('div.concept' + tag).clone());

Great! Problem solved!