Showing posts with label scriptaculous. Show all posts
Showing posts with label scriptaculous. Show all posts

Sunday, February 1, 2009

Scriptaculous and AJAX

I started with a task which seemed to be typical when script.aculo.us is used with Prototype Ajax.Request. The old content nicely disappears with one of scriptaculous effects, AJAX request is sent and when result is available it appears with another effect. Let's use Effect.SlideUp and Effect.SlideDown for these effects, and <div id='main_div'> for the content. Straight-forward solution looks like this:
new Effect.SlideUp('main_div', {
      afterFinish: function () {
        new Ajax.Request(url, {
            method:'get',
            onSuccess: function(transport){
              $('main_div').innerHTML=transport.responseText;
              new Effect.SlideDown('main_div');
            }
          })
      }
    });
Failure handling is omitted for brevity. This solution works, but has a significant problem: the request is sent only after the slide up effect is finished, so the user waits more than necessary. I wanted to send the AJAX request immediately, so the response might be ready when the slide up is finished. But it's impossible to know which will finish first.
My next try was to start slide up and immediately send the request, like this:
    new Effect.SlideUp('main_div');
    new Ajax.Request(url,
    {
        method:'get',
        onSuccess: function(transport){
             $('main_div').innerHTML=transport.responseText;
             new Effect.SlideDown('main_div', {queue: 'end'});
        }
    });
Unfortunately, it did not work correctly. If the response comes before the slide up vanished the main_div, it will be replaced with the new content for a moment, then disappear and come nicely with the slide down effect. So the problem here is that replacing the content and slide down must start only when both slide up and the AJAX are finished. I ended up with the following:
    var hideEffectComplete=false;
    var ajaxResult=null;
    new Effect.SlideUp('main_div', {
        afterFinish: function () {
            complete=true;
            if (ajaxResult != null) {
                $('main_div').innerHTML=ajaxResult;
                new Effect.SlideDown('main_div');
            }
        }
    });
    new Ajax.Request(url,
    {
        method:'get',
        onSuccess: function(transport){
          ajaxResult=transport.responseText;
          if (hideEffectComplete) {
             $('main_div').innerHTML=ajaxResult;
             new Effect.SlideDown('main_div');
          }
        }
    });
It works better, but it's long, ugly and redundant. Also it makes problems when a user makes a few actions fast, things are just messed up. Does anybody have a better idea how to synchronize AJAX and script.aculo.us?