On pages that take more than a few seconds to complete, its a good idea to show some type of in-progress meter. Things like bulk email processing and large file uploads are good candidates. Often this doesn’t need to be as complicated as a real progress meter, where you show the actual percentage complete. Instead, an “in progress” meter just gives feedback to the user to let them know that something is going on.

I usually place a hidden element on the page, then use JavaScript to make it appear when the form is submitted. Something like:

<p style="visibility:hidden" id="inprogress">
    <img id="inprogress_img" src="progress.gif">
    Please Wait...
</p>

<input type="submit" onclick="document.getElementById('inprogress').style.visibility='visible'">

Note that there is an image used in the in-progress message, this is important. A static “Please Wait” message tells your user they should wait, but without the feedback of the moving image, they could still get the impression something is locked up. You can get some awesome free progress meters from http://www.ajaxload.info.

Of course Internet Explorer throws a wrench into things. IE will stop any animated gifs from animating when the form is submitted. This is a problem in IE6 and 7. This is far worse than having no progress meter, since it appears as if something has locked up. But there is a work around. We just need to kick start the animation after the form submits. We do this by resetting the source of the image with JavaScript. We have to reset the src after the form submits, and the form submits when our function returns. So we make use of the setTimeout function, which executes a line of JavaScript after a specified number of milliseconds. We’ll also throw in an anti-double submit feature similar to what I mentioned in my last post.

<script language="JavaScript">
var submitted = false;
function doSubmit() {
	if (! submitted) {
		submitted = true;
		ProgressImg = document.getElementById('inprogress_img');
		document.getElementById("inprogress").style.visibility = "visible";
		setTimeout("ProgressImg.src = ProgressImg.src",100);
		return true;
		}
	else {
		return false;
		}
	}
</script>

<input type="submit" onclick="return doSubmit()">

If your form is long enough that it needs scroll bars, be sure to place the in-progress message where the user will see it when they click the submit button.

32 Comments

  1. Ikesacolick says:

    Good solution. Thank You.

    One small issue. To get this to work, you need to set the id=’inprogress_img’ in the img tag as in:

    img id=”inprogress_img” src=”progress.gif”

  2. Ryan Stille says:

    Good call, I missed that in my example. Its been updated now.

  3. gesmith says:

    Thanks for this very good solution. No thanks to IE and all of it’s headaches. :X

  4. Andrew Violette says:

    Perfect. Worked like a charm!

  5. Stephen Scotti says:

    I’m wanting to do something like this also, but instead of submitting a form I’m using a

  6. aearly says:

    Nice solution! Glad you found a way around this problem.

  7. Andrisi says:

    Nice, but how (where) do I hide the progress image?

  8. MJJ says:

    Hi can i know how to hide the progress image when the processing is over? Thanks!

  9. Muthu says:

    Thanks ! Can you let me know, if there is a way to keep the position of the image dyanmic? next to cursor/ mouse pointer ?

  10. Gary says:

    With the ajaxload noted above this was the perfect solution for what I was trying to do.  Thanks much!

  11. Tolenca says:

    Thanks…thanks…thanks a lot

  12. Mike says:

    Hi,

    Love this post! Trying to implement, but don't see…
    1) Where you submit the form, and
    2) Where you check if submit successful, and
    3) Then reset to "hidden".

    Can you help me with this.

    I'm a rookie, so go easy on me… 🙂

    Thanks Mike

  13. manfred says:

    Thanks a lot!!!! It works flawlessly and you saved me HOURS!!!
    Manfred

  14. dickintw says:

    Thanks! This did the job for me but it took a lot of trial and error to get it to work. In my version of the doSubmit() function, I was also changing the class name on another element:

    document.getElementById('other-big-eye-catching-box').className = 'pleasewait-now';

    The progress bar never became visible until I put this line after the setTimeout() call.

    (Tested in FF3.6.3 and IE 8.0.7600).

  15. dickintw says:

    Thanks! This did the job for me but it took some trial and error to get it to work. In my version of the doSubmit() function, I was also changing the class name on another element:

    document.getElementById('other-big-eye-catching-box').className = 'pleasewait-now';

    The progress bar never became visible until I put this line after the setTimeout() call.

    (Tested in FF3.6.3 and IE 8.0.7600).

  16. Adam says:

    Fantastic stuff – thanks a million – one question, and it may be a CSS thing, but because I want my loading box to be say 200px high, how do I have it so that it won't take up that room on the page before the page has been submitted and the loader initiated.

    I've tried 'display:none' but then it doesn't display the loader once the page has been submitted.

    This is the bit I'm referring to:

    <p style="visibility:hidden" id="inprogress">
        <img id="inprogress_img" src="progress.gif">
        Please Wait…
    </p>

  17. Ryan says:

    Adam I would think display:none would work, but to turn it on you'll have to use style.display='block' instead of style.visibility='visible'.

  18. Adam says:

    Thanks Ryan for that – I've tried changing it on this line:

            document.getElementById("inprogress").style.visibility = "visible";

    to

    document.getElementById("inprogress").style.display= "block";

    but it doesn't appear then – just leaves space for it.

    Any ideas? Cheers

  19. Ryan says:

    So a space for it does appear?  But its just a blank white space?  Sounds like you still have visibility:hidden still set on some element.

  20. Adam says:

    but when I take visibility: hidden off the inprogress element the loader appears as soon as I navigate to the page.

  21. Ryan says:

    If you have display:none set on the outer element it shouldn't display at all.  You shouldn't need to have visibility:hidden on there also.

    If you do decide to have visibility:hidden on there, then of course you also need to reset that at the same time you reset the 'display' attribute.


    document.getElementById("inprogress").style.visibility = "visible";
    document.getElementById("inprogress").style.display = "block";

  22. Adam says:

    You're a star!!!

    thanks very much.

  23. Kirk says:

    Thank you! The web is such a great place because of people like you!

  24. Sebastian says:

    You save me…. I was two days trying to solve this issue. Thanks a lot!

  25. John says:

    Thank you for this solution!!

  26. Dan says:

    Outstanding! Thanks for the post.

    IE still broken on version 9, but this fixed it.

    I used a simpler version – only a hidden image tag on the page.

    function appear()
    {
    ProgressImg = document.getElementById(‘processing’);
    ProgressImg.style.visibility = ‘visible’;
    setTimeout(“ProgressImg.src = ProgressImg.src”,100);
    }
    So the only extra line needed for IE compared to my original was the setTimeout()

  27. amod says:

    Hi thanks for cool sol. i want to set its display time to until its browser close. how can i achieve?

  28. Brij says:

    I am still getting the non animated icon/image when I click on the submit button.

    Below given is the code
    if (! submitted) {
    alert(“test”);
    submitted = true;
    ProgressImg = document.getElementById(‘inprogress_img’);
    ProgressImg.style.display = “block”;
    setTimeOut(“ProgressImg.src = ‘C:\\130.gif'”,1000);
    return true;
    }
    else {
    return false;
    }

  29. brij says:

    I am still getting the non animated icon/image when I click on the submit button.

    Below given is the code
    if (! submitted) {
    alert(“test”);
    submitted = true;
    ProgressImg = document.getElementById(‘inprogress_img’);
    ProgressImg.style.display = “block”;
    setTimeOut(“ProgressImg.src = ‘C:\\130.gif’”,1000);
    return true;
    }
    else {
    return false;
    }

    Can someone help?
    Regards

  30. Crimson Kate says:

    Excellent!! Really, really helpful. Works perfectly. Thank you so much for sharing this. 🙂

  31. justin says:

    i got error

    Uncaught TypeError: Cannot read property ‘style’ of null

    Please help me

  32. PEDRO FERREIRA says:

    Thank you for the excellent, elegant, and light solution.
    Salute from Rio!