2

I'm having issues showing my ajax spinner. Right now I am testing this on my localhost:3000/test with the following code:

I click a link to get the loader to show (Ruby on Rails code):

<li><%= link_to "New Test", new_test_path, :remote => true %></li>

I have the div the loader should appear inside:

<div id="generate-add-form">
  <div class="ajax-loader"></div>
</div>

Then my functions to make it appear:

jQuery( function($) {

$('#generate-add-form').ajaxStart( function() {
    $(this).children('.ajax-loader').show();
});

$('#generate-add-form').ajaxStop( function() {
    $(this).children('.ajax-loader').hide();
});

});

Last is my css (some stuff commented out to see if its needed or not):

.ajax-loader {
 display:    none;
 /*position:   fixed;*/
 z-index:    1000;
 /*top:        -13em;
 left:       6em;*/
 background:url('ajax-loader.gif') 50% 50% no-repeat;
}
body.loading {
 overflow: hidden;
}
body.loading .ajax-loader {
 display: block;
}

How come when I click the link it doesn't show?


EDIT:

<li><%= link_to "Test", new_test_path, :class => "add-link", :remote => true %></li>
<li><%= link_to "Study Guide", new_study_guide_path, :class => "add-link", :remote => true %></li>

$('#generate-add-form').children('.ajax-loader').hide();
  $('.add-link').click( function() {
    $('#generate-add-form').children('.ajax-loader').show();
});

I hide the spinner first and then show it again on click. What about in between when switching to another link?

LearningRoR
  • 26,582
  • 22
  • 85
  • 150

2 Answers2

4

Ok, so first, you want to hide something and show your ajax loader. First, give an id or an unique class to your link so you can target it:

<%= link_to "New Test", new_test_path, :remote => true, :id => 'you_link_id' %>

Then add some javascript to handle the click on the link:

$('#your_link_id').click(function(){
  $('#generate-add-form').children('.ajax-loader').show();
  $('#id_of_the_stuff_you_want_to_hide').hide();
});

In the controller action that will respond to new_test_path, add this at the end:

respond_to do |format|
  format.js
end

Here, you are making your controller action respond to your javascript request (that's what remote does). You could also add format.html to respond to html requests. You'll probably want to do this if you also want serve your page to people with javascript disabled (1 to 2% of all users).

Then, create your view with the name your_action.js.erb. Notice the js instead of the usual html. Inside, you can then hide your ajax spinner and show whatever you want. You can even render partials defined in that page.

$('#generate-add-form').children('.ajax-loader').hide();
$('#id_of_the_stuff_you_now_want_to_show').show();
$("#div_containing_your_partial").html('<%= escape_javascript(render 'name_of_your_partial') %>');

If you want, clone this repository I made some time ago that shows just how to do this.

And finally, when you get this working, you'll probably want to look at ways to make showing and hiding stuff in a prettier way. Try using fadeIn instead of show and fadeOut instead of hide for example.

Also, one final detail. In jQuery, functions don't get called sequentially. They are all called at the same time. So if you want to make something appear only after something disappears, you have to use of callbacks. Here's an example:

# without a callback, both actions take place at the same time
$("#id").hide();
$("#id2").show();

# with a callback, show will only be called after hide ends
$("#id").hide(function(){
  $("#id2").show();
});

EDIT: To do what you want, you have to remove the :remote => true part of your link and basically program what Rails already does automatically for you. Use these links to guide yourself:

And then this is probably what you're looking for:

But this is all rather complicated, specially for a Railsbeginner :/

Community
  • 1
  • 1
Ashitaka
  • 19,028
  • 6
  • 54
  • 69
  • In my updated section of my question, am I on the right track? – LearningRoR Jun 17 '12 at 15:23
  • 1
    Remove your ajaxStart and ajaxStop functions. Also, on the success of the ajax event, you probably want to _hide_ the ajax-loader, not show it. You show it with the click event. But wait, I'm sorry, I suddenly realized that you may not even need this. I'm going to edit my answer. – Ashitaka Jun 17 '12 at 16:05
  • 1
    I also added just now a way to make your javascript do things in a prettier way. Did you get this to work? If you have any trouble I can still edit my answer to make something clearer. – Ashitaka Jun 18 '12 at 02:31
  • I do have one last question. I can get the throbber (spinner) to show on the first clicked link but not when switching to another link. Check out my edit if its not to much trouble to ask. – LearningRoR Jun 19 '12 at 02:38
  • I'm not sure of what you're asking. You click the first link and the spinner is shown. Then you get a response back and the spinner is hidden. When you click a second link, this doesn't happen? – Ashitaka Jun 19 '12 at 16:36
  • Right now if I was to click the test form, it shows the spinner. But if I'm already on the test form and click the study guide link to see that form, it will not show the spinner before the study guide form appears. I want it to show the spinner when going to the test form to the study guide form and vice versa. – LearningRoR Jun 19 '12 at 19:27
  • 1
    So basically what you want to do, is interrupt your request. You click on a link and before you get the response back, you click the other link and you only want that second form to appear. That is rather complicated :/ see my edited answer. – Ashitaka Jun 20 '12 at 00:01
1

Try to set non-zero height for .ajax-loader.

dimuch
  • 12,728
  • 2
  • 39
  • 23
  • I put `height: 10px;` and nothing happened. – LearningRoR Jun 16 '12 at 12:51
  • Check please if css is correct and the spinner will be visible after show() - just comment out display:none. – dimuch Jun 16 '12 at 13:03
  • Oh ok that did it. With the `height` and the comment out of `display:none`. Thank you. – LearningRoR Jun 16 '12 at 13:17
  • Wait this actually display on the page forever. Sorry if I wasn't clear enough. What I meant is, I want to click the link and the spinner shows and after the ajax request is done it hides. – LearningRoR Jun 16 '12 at 13:27
  • 1
    That's OK, now set `display:none` again, everything should work. To make sure it works add `sleep 2` to rails controller that responds to ajax call. – dimuch Jun 16 '12 at 13:39
  • Ok so it does displays and I have it at the position I want it to be. Right now without clicking any of the links, it has the spinner showing. Now I when I click one link it shows that content, but when I click another I want it to show the spinner in between the request to show the content of the next link. How would I do this? Also, I am not familiar with `sleep 2`. How would I place that in my controller if its needed? – LearningRoR Jun 16 '12 at 13:58
  • `.ajaxStart()` does not provide any info which element triggered the event. Perhaps it will be better to bind spinner displaying to click event. Cannot say more without knowing your markup. Regarding the `sleep`, it just emulates network delay, you can put it in the beginning of the method (test#new). – dimuch Jun 16 '12 at 15:12
  • 1
    It's because if you use $().hide() it writes a style attribute on the selected element. If you have display: none in your css it won't be affected then. So you either use .hide() or you use .css('display', 'none') – Todd Baur Jun 16 '12 at 16:30