Detect when user clicks link, but aborts
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.
Howe开发者_如何学JAVAver, 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).
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!)
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.
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;
}
(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 );
});
});
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!
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.
精彩评论