4

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).

Community
  • 1
  • 1
Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • I always find those 'wait' and 'loading' things annoying. The browser has it by default (a spinner in FireFox/Safari and a progress bar in IE). Better consider not adding it? –  Nov 21 '09 at 19:26
  • 2
    On slow systems and connections, especially IE is very hazy in communicating what it is currently doing. A quick symbol somewhere that pops up would remedy the situation. – Pekka Nov 21 '09 at 19:32
  • 1
    Regarding the AJAX point, if you use jQuery, there are global event handlers that do a good job. see a fiddle I've been playing around with jsfiddle.net/e4z9bv6k , and also some v helpful SO posts stackoverflow.com/q/3735877 and stackoverflow.com/q/9043768 an also stackoverflow.com/q/3709597 – Adriano Sep 15 '14 at 08:52
  • +1 for your second point, even in 2014 there are real-life work situations where the page takes for ever to be loaded & in some browser (ie. Chrome) "only" a little loading icon in the top left of the browser shows the page being loaded. Adding a cross-browser custom styling seems legit to me. – Adriano Sep 15 '14 at 08:55

6 Answers6

3

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
  • 528,062
  • 107
  • 651
  • 834
  • 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 Nov 22 '09 at 11:19
  • 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 Nov 22 '09 at 13:05
1

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;
}
Community
  • 1
  • 1
Dan Herbert
  • 99,428
  • 48
  • 189
  • 219
  • 1
    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 Nov 21 '09 at 19:35
  • 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 Nov 21 '09 at 19:44
  • 1
    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 Nov 22 '09 at 11:12
  • 1
    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 Nov 22 '09 at 11:29
1

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
  • 2,567
  • 5
  • 29
  • 34
  • 1
    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 Nov 22 '09 at 11:20
  • 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 Nov 23 '09 at 03:39
  • @Vitaly as pointed out by Pekka, anchor navigation means switching from regular form submission (handled by the browser) to AJAX form submission (handled by you, programmatically). Yes, Gmail & other single page apps do cool stuff by programmatically doing some clientside routing, but it is probably NOT something you want to do if you are not building a single page app in the 1st place. see http://read.humanjavascript.com/ch09-clientside-routing.html – Adriano Sep 15 '14 at 09:06
  • Note that Pekka is looking for a generic solution, so something that'd work on his whole website... – Adriano Sep 15 '14 at 09:08
1

(Yep, I do like old topics)

I'm facing the same situation here. I'm building some pages where the navigation is done through form submitting, and I find convenient to show clearly to the user that something is happening before he gets exited and triggers 15 times the same request - "We don't trust users, do we?"

So I use jQuery along with a nice plug-in maned Impromptu, available there http://trentrichardson.com/Impromptu/index.php

Here is the piece of code:

$(document).ready( function () {

 $("form").submit( function() {
  $.prompt( "<center>Sending request...</center>", {
   overlayspeed: 200,
   buttons:{}
  });

  setTimeout( "jQuery.prompt.close()", 2000 );
 });

});
Randoum
  • 19
  • 1
  • not answering the question. Pekka is looking for a generic solution detecting "cancel" action on browser. – Adriano Sep 15 '14 at 08:59
0

I don't believe it's possible to check whether the user hit the STOP button in a cross-browser fashion, but going to the root of the problem, you can monitor the requests themselves:

When you run your xhr requests, register a function with onreadystatechange. Check if xhr.readyState === XMLHttpRequest.DONE. Check your indicator as to whether the request succeeded (hand wavy, edits welcome). If it did not succeed, then it was interrupted somehow and you should revert your progress indicator.

If this is a common scenario, you can automate this by monkey patching. See this question.

If it was a POST, you should probably also warn the user that cancelling their request doesn't prevent data changes. You could get more sophisticated here and automatically reverse the POST request or tell them what exactly was changed so that they can decide.

Hope that helps!

DylanYoung
  • 2,423
  • 27
  • 30
0

window.onabort seems to be a promising solution but at this time (2020-05-02) it is marked as an experimental technology supported by Chrome and Edge only. Besides, it seems is designed for handling abort of loading existing page or resources rather than next page.

abbr
  • 5,361
  • 6
  • 30
  • 44