[jquery] How can I create a "Please Wait, Loading..." animation using jQuery?

I would like to place a "please wait, loading" spinning circle animation on my site. How should I accomplish this using jQuery?

This question is related to jquery animation

The answer is


As far as the actual loading image, check out this site for a bunch of options.

As far as displaying a DIV with this image when a request begins, you have a few choices:

A) Manually show and hide the image:

$('#form').submit(function() {
    $('#wait').show();
    $.post('/whatever.php', function() {
        $('#wait').hide();
    });
    return false;
});

B) Use ajaxStart and ajaxComplete:

$('#wait').ajaxStart(function() {
    $(this).show();
}).ajaxComplete(function() {
    $(this).hide();
});

Using this the element will show/hide for any request. Could be good or bad, depending on the need.

C) Use individual callbacks for a particular request:

$('#form').submit(function() {
    $.ajax({
        url: '/whatever.php',
        beforeSend: function() { $('#wait').show(); },
        complete: function() { $('#wait').hide(); }
    });
    return false;
});

Note that when using ASP.Net MVC, with using (Ajax.BeginForm(..., setting the ajaxStart will not work.

Use the AjaxOptions to overcome this issue:

(Ajax.BeginForm("ActionName", new AjaxOptions { OnBegin = "uiOfProccessingAjaxAction", OnComplete = "uiOfProccessingAjaxActionComplete" }))

Most of the solutions I have seen either expects us to design a loading overlay, keep it hidden and then unhide it when required, or, show a gif or image etc.

I wanted to develop a robust plugin, where with a simply jQuery call I can display the loading screen and tear it down when the task is completed.

Below is the code. It depends on Font awesome and jQuery:

/**
 * Raj: Used basic sources from here: http://jsfiddle.net/eys3d/741/
 **/


(function($){
    // Retain count concept: http://stackoverflow.com/a/2420247/260665
    // Callers should make sure that for every invocation of loadingSpinner method there has to be an equivalent invocation of removeLoadingSpinner
    var retainCount = 0;

    // http://stackoverflow.com/a/13992290/260665 difference between $.fn.extend and $.extend
    $.extend({
        loadingSpinner: function() {
            // add the overlay with loading image to the page
            var over = '<div id="custom-loading-overlay">' +
                '<i id="custom-loading" class="fa fa-spinner fa-spin fa-3x fa-fw" style="font-size:48px; color: #470A68;"></i>'+
                '</div>';
            if (0===retainCount) {
                $(over).appendTo('body');
            }
            retainCount++;
        },
        removeLoadingSpinner: function() {
            retainCount--;
            if (retainCount<=0) {
                $('#custom-loading-overlay').remove();
                retainCount = 0;
            }
        }
    });
}(jQuery)); 

Just put the above in a js file and include it throughout the project.

CSS addition:

#custom-loading-overlay {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
    background: #000;
    opacity: 0.8;
    filter: alpha(opacity=80);
}
#custom-loading {
    width: 50px;
    height: 57px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -28px 0 0 -25px;
}

Invocation:

$.loadingSpinner();
$.removeLoadingSpinner();

Along with what Jonathan and Samir suggested (both excellent answers btw!), jQuery has some built in events that it'll fire for you when making an ajax request.

There's the ajaxStart event

Show a loading message whenever an AJAX request starts (and none is already active).

...and it's brother, the ajaxStop event

Attach a function to be executed whenever all AJAX requests have ended. This is an Ajax Event.

Together, they make a fine way to show a progress message when any ajax activity is happening anywhere on the page.

HTML:

<div id="loading">
  <p><img src="loading.gif" /> Please Wait</p>
</div>

Script:

$(document).ajaxStart(function(){
    $('#loading').show();
 }).ajaxStop(function(){
    $('#loading').hide();
 });

With all due respect to other posts, you have here a very simple solution, using CSS3 and jQuery, without using any further external resources nor files.

_x000D_
_x000D_
$('#submit').click(function(){_x000D_
  $(this).addClass('button_loader').attr("value","");_x000D_
  window.setTimeout(function(){_x000D_
    $('#submit').removeClass('button_loader').attr("value","\u2713");_x000D_
    $('#submit').prop('disabled', true);_x000D_
  }, 3000);_x000D_
});
_x000D_
#submit:focus{_x000D_
  outline:none;_x000D_
  outline-offset: none;_x000D_
}_x000D_
_x000D_
.button {_x000D_
    display: inline-block;_x000D_
    padding: 6px 12px;_x000D_
    margin: 20px 8px;_x000D_
    font-size: 14px;_x000D_
    font-weight: 400;_x000D_
    line-height: 1.42857143;_x000D_
    text-align: center;_x000D_
    white-space: nowrap;_x000D_
    vertical-align: middle;_x000D_
    -ms-touch-action: manipulation;_x000D_
    cursor: pointer;_x000D_
    -webkit-user-select: none;_x000D_
    -moz-user-select: none;_x000D_
    -ms-user-select: none;_x000D_
    background-image: none;_x000D_
    border: 2px solid transparent;_x000D_
    border-radius: 5px;_x000D_
    color: #000;_x000D_
    background-color: #b2b2b2;_x000D_
    border-color: #969696;_x000D_
}_x000D_
_x000D_
.button_loader {_x000D_
  background-color: transparent;_x000D_
  border: 4px solid #f3f3f3;_x000D_
  border-radius: 50%;_x000D_
  border-top: 4px solid #969696;_x000D_
  border-bottom: 4px solid #969696;_x000D_
  width: 35px;_x000D_
  height: 35px;_x000D_
  -webkit-animation: spin 0.8s linear infinite;_x000D_
  animation: spin 0.8s linear infinite;_x000D_
}_x000D_
_x000D_
@-webkit-keyframes spin {_x000D_
  0% { -webkit-transform: rotate(0deg); }_x000D_
  99% { -webkit-transform: rotate(360deg); }_x000D_
}_x000D_
_x000D_
@keyframes spin {_x000D_
  0% { transform: rotate(0deg); }_x000D_
  99% { transform: rotate(360deg); }_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<input id="submit" class="button" type="submit" value="Submit" />
_x000D_
_x000D_
_x000D_


Place this code on your body tag

<div class="loader">
<div class="loader-centered">
    <div class="object square-one"></div>
    <div class="object square-two"></div>
    <div class="object square-three"></div>
</div>
</div>
<div class="container">
<div class="jumbotron">
    <h1 id="loading-text">Loading...</h1>
</div>
</div>

And use this jquery script

<script type="text/javascript">

jQuery(window).load(function() {
//$(".loader-centered").fadeOut();
//in production change 5000 to 400
$(".loader").delay(5000).fadeOut("slow");
$("#loading-text").addClass('text-success').html('page loaded');
});
</script>

See a full example working here.

http://bootdey.com/snippets/view/page-loader


SVG animations are probably a better solution to this problem. You won't need to worry about writing CSS and compared to GIFs, you'll get better resolution and alpha transparency. Some very good SVG loading animations that you can use are here: http://samherbert.net/svg-loaders/

You can also use those animations directly through a service I built: https://svgbox.net/iconset/loaders. It allows you to customize the fill and direct usage (hotlinking) is permitted.

To accomplish what you want to do with jQuery, you probably should have a loading info element hidden and use .show() when you want to show the loader. For eg, this code shows the loader after one second:

_x000D_
_x000D_
setTimeout(function() {
  $("#load").show();
}, 1000)
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>

<div id="load" style="display:none">
    Please wait... 
    <img src="//s.svgbox.net/loaders.svg?fill=maroon&ic=tail-spin" 
         style="width:24px">
</div>
_x000D_
_x000D_
_x000D_


Like Mark H said the blockUI is the way.

Ex.:

<script type="text/javascript" src="javascript/jquery/jquery.blockUI.js"></script>
<script>
// unblock when ajax activity stops
$(document).ajaxStop($.unblockUI); 

$("#downloadButton").click(function() {

    $("#dialog").dialog({
        width:"390px",
        modal:true,
        buttons: {
            "OK, AGUARDO O E-MAIL!":  function() {
                $.blockUI({ message: '<img src="img/ajax-loader.gif" />' });
                send();
            }
        }
    });
});

function send() {
    $.ajax({
        url: "download-enviar.do",          
        type: "POST",
        blablabla
    });
}
</script>

Obs.: I got the ajax-loader.gif on http://www.ajaxload.info/


It is very simple.

HTML

<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

<body>

  <div id="cover"> <span class="glyphicon glyphicon-refresh w3-spin preloader-Icon"></span>Please Wait, Loading…</div>

  <h1>Dom Loaded</h1>
</body>

CSS

#cover {
  position: fixed;
  height: 100%;
  width: 100%;
  top: 0;
  left: 0;
  background: #141526;
  z-index: 9999;
  font-size: 65px;
  text-align: center;
  padding-top: 200px;
  color: #fff;
  font-family:tahoma;
}

JS - JQuery

$(window).on('load', function () {
  $("#cover").fadeOut(1750);
});

jQuery provides event hooks for when AJAX requests start and end. You can hook into these to show your loader.

For example, create the following div:

<div id="spinner">
  <img src="images/spinner.gif" alt="Loading" />
</div>

Set it to display: none in your stylesheets. You can style it whatever way you want to. You can generate a nice loading image at Ajaxload.info, if you want to.

Then, you can use something like the following to make it be shown automatically when sending Ajax requests:

$(document).ready(function () {

    $('#spinner').bind("ajaxSend", function() {
        $(this).show();
    }).bind("ajaxComplete", function() {
        $(this).hide();
    });

});

Simply add this Javascript block to the end of your page before closing your body tag or wherever you see fit.

Now, whenever you send Ajax requests, the #spinner div will be shown. When the request is complete, it'll be hidden again.


You can grab an animated GIF of a spinning circle from Ajaxload - stick that somewhere in your website file heirarchy. Then you just need to add an HTML element with the correct code, and remove it when you're done. This is fairly simple:

function showLoadingImage() {
    $('#yourParentElement').append('<div id="loading-image"><img src="path/to/loading.gif" alt="Loading..." /></div>');
}

function hideLoadingImage() {
    $('#loading-image').remove();
}

You then just need to use these methods in your AJAX call:

$.load(
     'http://example.com/myurl',
     { 'random': 'data': 1: 2, 'dwarfs': 7},
     function (responseText, textStatus, XMLHttpRequest) {
         hideLoadingImage();
     }
);

// this will be run immediately after the AJAX call has been made,
// not when it completes.
showLoadingImage();

This has a few caveats: first of all, if you have two or more places the loading image can be shown, you're going to need to kep track of how many calls are running at once somehow, and only hide when they're all done. This can be done using a simple counter, which should work for almost all cases.

Secondly, this will only hide the loading image on a successful AJAX call. To handle the error states, you'll need to look into $.ajax, which is more complex than $.load, $.get and the like, but a lot more flexible too.


I use CSS3 for animation

_x000D_
_x000D_
/************ CSS3 *************/_x000D_
.icon-spin {_x000D_
  font-size: 1.5em;_x000D_
  display: inline-block;_x000D_
  animation: spin1 2s infinite linear;_x000D_
}_x000D_
_x000D_
@keyframes spin1{_x000D_
    0%{transform:rotate(0deg)}_x000D_
    100%{transform:rotate(359deg)}_x000D_
}_x000D_
_x000D_
/************** CSS3 cross-platform ******************/_x000D_
_x000D_
.icon-spin-cross-platform {_x000D_
  font-size: 1.5em;_x000D_
  display: inline-block;_x000D_
  -moz-animation: spin 2s infinite linear;_x000D_
  -o-animation: spin 2s infinite linear;_x000D_
  -webkit-animation: spin 2s infinite linear;_x000D_
  animation: spin2 2s infinite linear;_x000D_
}_x000D_
_x000D_
@keyframes spin2{_x000D_
    0%{transform:rotate(0deg)}_x000D_
    100%{transform:rotate(359deg)}_x000D_
}_x000D_
@-moz-keyframes spin2{_x000D_
    0%{-moz-transform:rotate(0deg)}_x000D_
    100%{-moz-transform:rotate(359deg)}_x000D_
}_x000D_
@-webkit-keyframes spin2{_x000D_
    0%{-webkit-transform:rotate(0deg)}_x000D_
    100%{-webkit-transform:rotate(359deg)}_x000D_
}_x000D_
@-o-keyframes spin2{_x000D_
    0%{-o-transform:rotate(0deg)}_x000D_
    100%{-o-transform:rotate(359deg)}_x000D_
}_x000D_
@-ms-keyframes spin2{_x000D_
    0%{-ms-transform:rotate(0deg)}_x000D_
    100%{-ms-transform:rotate(359deg)}_x000D_
}
_x000D_
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>_x000D_
_x000D_
_x000D_
<div class="row">_x000D_
  <div class="col-md-6">_x000D_
    Default CSS3_x000D_
    <span class="glyphicon glyphicon-repeat icon-spin"></span>_x000D_
  </div>_x000D_
  <div class="col-md-6">_x000D_
    Cross-Platform CSS3_x000D_
    <span class="glyphicon glyphicon-repeat icon-spin-cross-platform"></span>_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Per https://www.w3schools.com/howto/howto_css_loader.asp, this is a 2-step process with no JS:

1.Add this HTML where you want the spinner: <div class="loader"></div>

2.Add this CSS to make the actual spinner:

.loader {
    border: 16px solid #f3f3f3; /* Light grey */
    border-top: 16px solid #3498db; /* Blue */
    border-radius: 50%;
    width: 120px;
    height: 120px;
    animation: spin 2s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

Jonathon's excellent solution breaks in IE8 (the animation does not show at all). To fix this, change the CSS to:

.modal {
display:    none;
position:   fixed;
z-index:    1000;
top:        0;
left:       0;
height:     100%;
width:      100%;
background: rgba( 255, 255, 255, .8 ) 
            url('http://i.stack.imgur.com/FhHRx.gif') 
            50% 50% 
            no-repeat;
opacity: 0.80;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity = 80);
filter: alpha(opacity = 80)};

If you are using Turbolinks With Rails this is my solution:

This is the CoffeeScript

$(window).on 'page:fetch', ->
  $('body').append("<div class='modal'></div>")
  $('body').addClass("loading")

$(window).on 'page:change', ->
  $('body').removeClass("loading")

This is the SASS CSS based on the first excellent answer from Jonathan Sampson

# loader.css.scss

.modal {
    display:    none;
    position:   fixed;
    z-index:    1000;
    top:        0;
    left:       0;
    height:     100%;
    width:      100%;
    background: rgba( 255, 255, 255, 0.4)
            asset-url('ajax-loader.gif', image)
            50% 50% 
            no-repeat;
}
body.loading {
    overflow: hidden;   
}

body.loading .modal {
    display: block;
}

This would make the buttons disappear, then an animation of "loading" would appear in their place and finally just display a success message.

$(function(){
    $('#submit').click(function(){
        $('#submit').hide();
        $("#form .buttons").append('<img src="assets/img/loading.gif" alt="Loading..." id="loading" />');
        $.post("sendmail.php",
                {emailFrom: nameVal, subject: subjectVal, message: messageVal},
                function(data){
                    jQuery("#form").slideUp("normal", function() {                 
                        $("#form").before('<h1>Success</h1><p>Your email was sent.</p>');
                    });
                }
        );
    });
});