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?
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
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')"
Simple.
- Create a hidden element to show our images
- Use CSS to format the layout
- 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 > 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
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
精彩评论