Recipe 8.13. Creating an Ajax Progress Indicator


Problem

Contributed by: Diego Scataglini

Although Ajax makes web applications more responsive, some operations just take time. Users hate nothing more than an application that appears to be dead while it's sitting there, thinking. To make your application feel more responsive, you want to provide a progress indicator that appears and disappears whenever an Ajax request starts and stops.

Solution

For this recipe, create an empty Rails application. Next, create a basic HTML file for your application's layout. Make sure to load the prototype, effects, and application JavaScript files:

app/views/layout/application.rhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head>   <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>   <title>Rails Cookbook</title>    <%= javascript_include_tag 'prototype' %>   <%= javascript_include_tag 'effects' %>   <%= javascript_include_tag 'application' %>  </head> <body>   <%= yield %> </body> </html>

Add the following to your application.js file:

public/javascripts/application.js:

Ajax.Responders.register({  onCreate: function(){    if($('ajax_busy') && Ajax.activeRequestCount > 0){        Effect.Appear('ajax_busy', {duration: 0.5, queue: 'end'});    }  },  onComplete: function(){    if($('ajax_busy') && Ajax.activeRequestCount == 0){      Effect.Fade('ajax_busy', {duration: 0.5, queue: 'end'});    }  } });

Now find or create an animated GIF like browsers use to indicate a page is loading. Name this file myspinner.gif and save it in the public/images folder. Now create a helper that outputs the HTML for the progress indicator. This helper lets you re-use the same HTML in all of your views.

app/helpers/application_helper.rb:

def show_spinner   content_tag "div", "Working... " + image_tag("myspinner.gif"),                :id => "ajax_busy", :style => "display:none;" end

Add a style for the ajax_busy div tag:

public/stylesheets/display.css:

#ajax_busy {position: absolute;             top: 0; right: 0;             width: 120px;             background-color: #900;             color: #fff;             padding: 4px;}

To test the progress indicator, create a controller with two actions: one to simulate a long-running task and one from which to call it using Ajax:

$ ruby script/generate controller Home index myajax_call             

Next, add the following code to the generated controller file:

app/controllers/home_controller.rb:

class HomeController < ApplicationController   def index   end   def myajax_call     sleep 3 # sleep for 3 seconds     render :update do |page|        page.alert('I am done sleeping.')     end   end end

Create a view for the index action from which to test the Ajax call:

app/views/home/index.rhtml:

<%= show_spinner %> <%= link_to_remote "Test Spinner", :url => {:action => "myajax_call"} %>

You're done. Start the development server to test your application:

$ ruby script/server -d             

Finally, point your browser to http://localhost:3000/home, and click on the Test Spinner link to see the progress indicator in action.

Discussion

The solution uses the Ajax.Responders object to register a couple of event handlers. Because the Prototype JavaScript library raises events with Ajax.Responders.dispatch, any events generated by Prototype are sent to every registered responder stored in Ajax.Responders.responders. This hook provides a handy way to create a global progress indicator.




Rails Cookbook
Rails Cookbook (Cookbooks (OReilly))
ISBN: 0596527314
EAN: 2147483647
Year: 2007
Pages: 250
Authors: Rob Orsini

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net