views:

219

answers:

3

I am working on a Web CMS. When the user clicks on a link to move to a different page, or submits a form, I want a "please wait" animated GIF to show up in the top right corner to symbolize that loading is in progress.

However, the user can cancel loading of the new page in their browser, for example by pressing the "cancel" button or ESC. In that case, they will stay on the current page as the browser stops loading the next page.

How can I detect this in Javascript, and hide the "wait" icon again?

Edit: To address the "you shouldn't do that, the browser already has it" comments. I have two specific reasons for introducing a custom solution.

  • I have AJAX buttons on the page. I need an activity indicator for them so the user isn't confused whether the click registered or not.

  • On slow connections with a lot of lag, some browsers' progress bar will move extremely slowly. I am in a real-life work situation when it takes ages until the throbber shows any kind of activity in IE6/7. This gives the impression that nothing is happening and the app is reacting very slowly, and that annoys me. I want an indicator that is constantly moving (like Safari's, for example).

+1  A: 

This won't work for submit buttons. Once the user clicks "submit", the request has been posted to the server. Once that happens, the action has been performed. The best you could do in that case is stop the user from seeing the response of their action, however the action would still be performed.

Also, the only way to stop the user from navigating to another page once another request has been started would be to redirect the user back to the page they came from. In general, cancelling out of the request is just a plain Bad Idea™

For forms, another option would be to use AJAX for all form submissions. AJAX requests can be cancelled, so you could use this to your advantage, although it makes things more complicated and harder to deal with.

If you still want to go through with this, knowing the implications though, you can easily do this with a JavaScript framework like jQuery, YUI, Dojo, MooTools, ExtJS, or Closure.

Here is an example of how to do this in jQuery. As I mentioned, you can't stop a request once it has started without refreshing the page the user is on (to stop the current page load) so I have omitted that part from this example.

$().ready(function() { 
    function showLoading(){  
        $loadingOverlay = $('<div id="loadingOverlay"></div>'); 
        $loadingAnimation = $('<div id="loadingAnimation">Loading...</div>'); 
        $("body").prepend($loadingAnimation).prepend($loadingOverlay); 
    } 

    $("a[href]").click(showLoading); 
    $("form").submit(showLoading); 
});

To add an animated gif in the loading box, replace the text "Loading..." with an <img /> tag pointing to the loading gif of your choice. A live demo of this can be seen here: http://jsbin.com/opadi

You'll need this CSS to go with the code above:

#loadingOverlay {
    position: absolute; 
    top: 0px; 
    left: 0px; 
    height: 100%; 
    width: 100%; 
    z-index: 1000; 
    background: #000;
    filter:alpha(opacity=50);
    -moz-opacity:0.5;
    -khtml-opacity: 0.5;    
    opacity: 0.5;
}
#loadingAnimation {
    position: absolute; 
    top: 30%; 
    left: 50%;
    z-index: 1001;
}
Dan Herbert
My focus is not so much on whether the action was performed or not - that is in the responsibility of the user. I only want to correctly hide the symbol again if the action has been cancelled, and no page change has occurred. I am looking for an event I can hook up to, or a reliable workaround.
Pekka
That sounds like a bad idea from a usability standpoint. You should never have a "cancel button" that doesn't actually cancel anything. What you're doing is effectively just creating a cancel button that has no function except to hide the cancel button, but not the action the user would expect to get cancelled.
Dan Herbert
No you don't understand, I want to detect when the user has cancelled loading of the next page using the browser's built in cancel button or escape key. The user's workflow is not altered.
Pekka
But thanks Dan, for the extensive examples. Switching form submission and/or navigation to AJAX would have too many implications in a complex system, so it's not an option for me. I have clarified my question to highlight that I'm not trying to cancel the request programmatically.
Pekka
+1  A: 

I think you should check so called "Anchor Navigation". There's a good tutorial here:

http://yensdesign.com/2008/11/creating-ajax-websites-based-on-anchor-navigation/

Basically, you will refer user to the same URL but with anchor in the end (http://localhost/home#somepage?param1=val1) and load the data using AJAX. Javascript will catch anchor change and can show "loading" icon and provide additional stuff like "cancel loading". In this case you will have your browser history in place, so you can say "back" in the browser or history.go(-1) in the javascript.

Vitaly
Switching to AJAX submission is not really an option, it's too much hassle as it's a complex system. But thanks for the idea.
Pekka
If you want to implement that feature, you have to use javascript anyway. Also, I believe this will not be for every page, so it shouldn't be thta hard. Not GMail, which uses this anchor navigation :) Actually, you can check the following: open GMail, close internet connection and switch between "Inbox" and "Sent" - you will see that "Page is not loading", but not 404 error!
Vitaly
+3  A: 

Sorry, I don't think there's any way to do this, no. I mean you can spot an escape keypress for what that's worth, but there's no general way to detect a cancel of the next page loading. Other than just guessing that if you're still around a number of seconds after a submit/click then either it's been cancelled or your server's slow. Or doing the whole navigation and submission stuff with AJAX in the same page, which would avoid the problem simply by breaking the browser's own stop button; probably not a good idea.

(I don't it's really a great idea to add a wait throbber of your own though anyway; the browser has a perfectly good one of its own!)

bobince
I agree, breaking the stop button is no good. Hmm, it would be too bad if this couldn't be done. As to the throbber, see my edit in my question above.
Pekka
When the progress bar is slow, is that because you're doing a large form submission? If so it shouldn't be that difficult to break it out into an AJAX form submission with its own throbber followed by a fast navigation.
bobince