tags:

views:

27

answers:

2

I am using ajax to insert a series of informational blocks via a loop. The blocks each have a title, and long description in them that is hidden by default. They function like an accordion, only showing one description at a time amongst all of the blocks.

The problem is opening the description on the first block. I would REALLY like to do it with javascript right after the loop that is creating them is done. Is it possible to manipulate elements created ofter an ajax call without using the callback?

<!-- example code-->
<style>
    .placeholder, .long_description{
    display:none;}
</style>
</head><body>
<script>  /* yes, this script is in the body, dont know if it matters */
$(document).ready(function() {
    $(".placeholder").each(function(){  // Use the divs to get the blocks
        var blockname = $(this).html();  // the contents if the div is the ID for the ajax POST
        $.post("/service_app/dyn_block",'form='+blockname, function(data){
            var divname  = '#div_' + blockname;
            $(divname).after(data);
            $(this).setupAccrdFnctly(); //not the actual code
        });
    });

    /* THIS LINE IS THE PROBLEM LINE, is it possible to reference the code ajax inserted */
    /*  Display the long description in the first dyn_block */
    $(".dyn_block").first().find(".long_description").addClass('active').slideDown('fast');
});
</script>
<!-- These lines are generated by PHP -->
<!-- It is POSSIBLE to display the dyn_blocks -->
<!-- here but I would really rather not -->
<div id="div_servicetype" class="placeholder">servicetype</div>     
<div id="div_custtype" class="placeholder">custtype</div>           
<div id="div_custinfo" class="placeholder">custinfo</div>           
<div id="div_businfo" class="placeholder">businfo</div>
</body>
A: 

AJAX by its very nature is "asynchronous". This means execution continues along happily after the asynchronous request has been sent out; the content that you expect to be there won't be there until the AJAX call is complete. So when you try to access the content you won't get anything.

When dealing with asynchronous operations you need to use callbacks since you can never tell when the operation has completed. I'm not sure why you're against using the callback - that's the reason it's there - to help you deal with asynchronous operations.

EDIT

You can have SJAX (Synchronous JAX) if you set the async property to false. So it is possible to do what you suggest, but you will lock up your browser until the request completes.

Vivin Paliath
Correction here, it *is* possible. You can even lockup the browser doing it, which is exactly what `async: false;` does.
Nick Craver
@Nick Craver that is true. Forgot about that. I rarely bother with `async: false`. Will edit to fix.
Vivin Paliath
A: 

The problem is that as AJAX is asynchronus (by default)

$(".dyn_block").first().find(".long_description").addClass('active').slideDown('fast');

will execute before there is any data. So you cannot avoid callbacks.

Instead of polling you could define the following function

var amount = $(".placeholder").size();
function ajaxDone() {
 amount--:
 if(amount == 0) {
    $(".dyn_block").first().find(".long_description").addClass('active').slideDown('fast');
 }
}

If you want to slideDown the first one when all the processing is done.

So the script would look like this

<script>  /* yes, this script is in the body, dont know if it matters */

    var amount = $(".placeholder").size();
    function ajaxDone() {
       amount--:
       if(amount == 0) {
         $(".dyn_block").first().find(".long_description").addClass('active').slideDown('fast');
       }
    }


        $(document).ready(function() {
            $(".placeholder").each(function(){  // Use the divs to get the blocks
                var blockname = $(this).html();  // the contents if the div is the ID for the ajax POST
                $.post("/service_app/dyn_block",'form='+blockname, function(data){
                    var divname  = '#div_' + blockname;
                    $(divname).after(data);
                    $(this).setupAccrdFnctly(); //not the actual code
                });
            });

            /* THIS LINE IS THE PROBLEM LINE, is it possible to reference the code ajax inserted */
            /*  Display the long description in the first dyn_block */

        });
        </script>

EDIT: Regarding you comment about not knowing wether it matters or not to have your javascript on the HTML, check this SO question

As Nick suggested there is a better way to achieve the same thing (instead of using the ajaxDone function)

$(document).ajaxStop(function() { 
    $(".dyn_block").first().find(".long_description").addClass('active').slideDown('fast'); 
    $(this).unbind('ajaxStop'); 
});
Lombo
There's a *much* easier way to do this :) Like this: `$(document).ajaxStop(function() { $(".dyn_block:first .long_description").addClass('active').slideDown('fast'); $(this).unbind('ajaxStop'); });`
Nick Craver
You are right! Thanks for pointing that out, I will edit the answer
Lombo
$(document).ajaxStop worked like a champ! Thank all of you so much!
Cody