ktec
ktec

Reputation: 2473

How to show an animated spinner while a background task is processing in nested rails model using ajax

My specific example is highly complex, so I will use the example shown by Ryan from Railscasts to discuss this:

http://railscasts.com/episodes/197-nested-model-form-part-2

Background

I have a form, let's say "Survey", which contains an arbitrary number of "Questions".

Senario

Give i am on the "Edit Survey" page.

I would like to add a button to each "Question" field which calls a remote_function, which in turn queue's up a delayed_job to execute some processing on the "Question".

To give feedback to the user, i would like to disable the button, and show an animated spinner, which remains until the delayed_job has processed the "Question".

Hint - I can add methods to the "Question" model to indicate the status of the delayed_job.

So, with best practices in mind, what is the best way to achieve this?

Upvotes: 1

Views: 6490

Answers (4)

Leonel Galán
Leonel Galán

Reputation: 7167

Do the polling and respond with a json similar to this:

{"finished": [1,3,3]}

Then add the polling JavaScript

  var interval = setInterval(function() {
    $.get("test.json", function(data) {
      for(i in data.finished) {
        //Hide spinner with id = data.finished[i]
      }
    })
  }, 5000) //Time in milliseconds

Upvotes: 3

Eddie
Eddie

Reputation: 10148

Simple.

  1. Create a hidden element to show our images
  2. Use CSS to format the layout
  3. Use Javascript to turn the effect on /off

Put the html in your page template

//hidden div that has spinner image
<div id="LoadingDiv" style="display:none;">
        <img src="ajax-loader.gif" alt="" /></div>

Some simple CSS to format the block (this created the translucent background that blocks user interaction)

/*the basics, and works for FF*/
#LoadingDiv{
    margin:0px 0px 0px 0px;
    position:fixed;
    height: 100%;
    z-index:9999;
    padding-top:200px;
    padding-left:50px;
    width:100%;
    clear:none;
    background:url(/img/transbg.png);
    /*background-color:#666666;
    border:1px solid #000000;*/
    }
/*IE will need an 'adjustment'*/
* html #LoadingDiv{
     position: absolute;
     height: expression(document.body.scrollHeight &gt; document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
    }

Then turn it on and off as needed

var ldiv = document.getElementById('LoadingDiv');
ldiv.style.display='block';
/*Do your ajax calls, sorting or laoding, etc.*/
ldiv.style.display = 'none';

If you want more details, or need a translucent pixel to use, see my full article

How to fade window and show translucent progress bar

Upvotes: 1

Mike Sutton
Mike Sutton

Reputation: 4211

First you'll need an animated spinner graphic. Google and there are loads of sites which will generate them for you.

Reference the gif in you layout (or view) with:

    <%= image_tag 'spinner.gif', :id => 'spinner', :style => "display:none;position:absolute;top:300px;left:500px;" %>

(this assumes a fixed position on the page)

Then add the following to your remote_function call:

:before => "Element.show('spinner')",
:after => "Element.hide('spinner')"

Upvotes: 1

Quotidian
Quotidian

Reputation: 2940

Using jQuery you should be able to turn the throbber (yeah... that's the "official" name) on and off using callbacks.

Or, if it's more complex I've used this before:

http://plugins.jquery.com/project/throbber

Upvotes: 0

Related Questions