37

I am trying to make a YouTube-like progress bar. The bar should load at the page startup. I have tried this so far. Here is the code of my script

$({property: 0}).animate({property: 105}, {
    duration: 4000,
    step: function() {
        var _percent = Math.round(this.property);
        $('#progress').css('width',  _percent+"%");
        if(_percent == 105) {
            $("#progress").addClass("done");
        }
    },
    complete: function() {
        alert('complete');
    }
});

I am also including the jsFiddle of the same, http://jsfiddle.net/ajaSB/3/.

In this jsfiddle, the progress bar appears, but when I use the same code in my IDE and run the file no progress bar appears. What am I doing wrong? Or if there is another way to get the bar?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Swagata Barua
  • 385
  • 1
  • 3
  • 9
  • Are you referencing the jQuery files correctly? Check the error logs in the browser. – MarsOne Aug 21 '13 at 06:37
  • yes I doing that correctly – Swagata Barua Aug 21 '13 at 06:40
  • There are also no errors...the page loads but the progress bar do not appear – Swagata Barua Aug 21 '13 at 06:41
  • @SwagataBarua: What MarsOne meant was if you have reference to the jQuery library, *not* your jquery code. jQuery is a Javascript library that you need to reference so that the jQuery functionality is available to use. – awe Aug 21 '13 at 06:42
  • Well can you please throw some light on that. I am still new to jquery. So can you please tell me how can I refer to the jquery library – Swagata Barua Aug 21 '13 at 06:49
  • Are you wrapping your piece of code inside `document.ready`? In `fiddle` you do not necessarily need to do that. – kayen Aug 21 '13 at 06:52
  • You should have this reference. Unless you have downloaded the JQuery library in your root folder and are referencing that File. Ideally you should always try and use a CDN library. http://stackoverflow.com/questions/2145277/what-are-the-advantages-and-disadvantages-of-using-cdncontent-delivery-network – MarsOne Aug 21 '13 at 06:54
  • Well I have done all the things you guys said but still it does not appear. – Swagata Barua Aug 21 '13 at 07:03
  • @Swagata Barua are you see my answer – Padmanathan J Aug 21 '13 at 07:43
  • +1 for doing this yourself, not with the use of some 3rd party JS library. And +1 more for the code simplicity. – Adriano Apr 11 '14 at 11:54

6 Answers6

34

NProgress.js is a very cool and simple library. The Git repository is here. It has an MIT License.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Arthur Yakovlev
  • 8,933
  • 8
  • 32
  • 48
19

Here is example of a complete HTML page including reference to the jQuery library.

Although it will mostly work without, you should wrap your code in a $(document).ready(...) so that you are sure all required resources are loaded before you run the code.

<!DOCTYPE html>
<html>
  <head>
  <title>Progress Test</title>

  <script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>

  <script type="text/javascript">
    $(document).ready(function(){
      $({property: 0}).animate({property: 105}, {
        duration: 4000,
        step: function() {
          var _percent = Math.round(this.property);
          $("#progress").css("width",  _percent+"%");
          if(_percent == 105) {
            $("#progress").addClass("done");
          }
        },
        complete: function() {
          alert("complete");
        }
      });
    });
  </script>

  <link href="css/progressbar.css" rel="stylesheet" type="text/css" />

  </head>
  <body>
    <div id="progress" class="waiting">
  </body>
</html>

Note that this targets version 2 of jQuery, which does not support Internet Explorer 8 and earlier. If you need support for old Internet Explorer versions, you should target jQuery 1.10.2 instead.

If the progress bar does not show, but you do get the alert("complete") after four seconds when the animation should be finished, it is likely that your reference to the CSS is wrong (not pointing to the right place, or misspelled file name).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
awe
  • 21,938
  • 6
  • 78
  • 91
11

Demo : Fiddle

Try the following code. You must run this file into your localhost (local server).

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $( document ).ready(function() {
        $({property: 0}).animate({property: 105}, {
            duration: 4000,
            step: function() {
                var _percent = Math.round(this.property);
                $('#progress').css('width',  _percent+"%");
                if(_percent == 105) {
                    $("#progress").addClass("done");
                }
            },
            complete: function() {
                alert('complete');
            }
        });
    });
</script>
<style>
    #progress {
        position: fixed;
        z-index: 2147483647;
        top: 0;
        left: -6px;
        width: 0%;
        height: 2px;
        background: #b91f1f;
        -moz-border-radius: 1px;
        -webkit-border-radius: 1px;
        border-radius: 1px;
        -moz-transition: width 500ms ease-out,opacity 400ms linear;
        -ms-transition: width 500ms ease-out,opacity 400ms linear;
        -o-transition: width 500ms ease-out,opacity 400ms linear;
        -webkit-transition: width 500ms ease-out,opacity 400ms linear;
        transition: width 500ms ease-out,opacity 400ms linear
    }
    #progress.done {
        opacity: 0
    }
    #progress dd,#progress dt {
        position: absolute;
        top: 0;
        height: 2px;
        -moz-box-shadow: #b91f1f 1px 0 6px 1px;
        -ms-box-shadow: #b91f1f 1px 0 6px 1px;
        -webkit-box-shadow: #b91f1f 1px 0 6px 1px;
        box-shadow: #b91f1f 1px 0 6px 1px;
        -moz-border-radius: 100%;
        -webkit-border-radius: 100%;
        border-radius: 100%
    }
    #progress dd {
        opacity: 1;
        width: 20px;
        right: 0;
        clip: rect(-6px,22px,14px,10px)
    }
    #progress dt {
        opacity: 1;
        width: 180px;
        right: -80px;
        clip: rect(-6px,90px,14px,-6px)
    }
    @-moz-keyframes pulse {
        30% {
            opacity: 1
        }
        60% {
            opacity: 0
        }
        100% {
            opacity: 1
        }
    }
    @-ms-keyframes pulse {
        30% {
            opacity: .6
        }
        60% {
            opacity: 0
        }
        100% {
            opacity: .6
        }
    }
    @-o-keyframes pulse {
        30% {
            opacity: 1
        }
        60% {
            opacity: 0
        }
        100% {
            opacity: 1
        }
    }
    @-webkit-keyframes pulse {
        30% {
            opacity: .6
        }
        60% {
            opacity: 0
        }
        100% {
            opacity: .6
        }
    }
    @keyframes pulse {
        30% {
            opacity: 1
        }
        60% {
            opacity: 0
        }
        100% {
            opacity: 1
        }
    }
    #progress.waiting dd,#progress.waiting dt {
        -moz-animation: pulse 2s ease-out 0s infinite;
        -ms-animation: pulse 2s ease-out 0s infinite;
        -o-animation: pulse 2s ease-out 0s infinite;
        -webkit-animation: pulse 2s ease-out 0s infinite;
        animation: pulse 2s ease-out 0s infinite
    }
</style>
<div id="progress" class="waiting">
    <dt></dt>
    <dd></dd>
</div>

Or:

Just upload this file to your server, and then you execute the file. Definitely it works.

Padmanathan J
  • 4,614
  • 5
  • 37
  • 75
  • 1
    I did not down-vote, though it should be mentioned that this solution only works one time, on a page load...it is not 'ready for ajax integration'. One would need to manually set the 'done' class in their `ajax( { xhr: } );` call. Also, a no-transition style would be needed which should disable animations and transitions so `#progress.css( { width: } )` (i.e. resetting width to 0%) would not cause your hidden loader to display and animate/transition the reset of the loader in general. HTH – Rik May 27 '15 at 23:30
  • @NathanSrivi can u plzz give me a jsfiddle link of your code....just to see how to use it when multiple link is there in page which causes to load page content. thanks – Mou Oct 10 '15 at 15:45
5

If you want a 'youtube-like' loader for your AJAX application that actually represents legitimate page loading progress, consider the following solution (based on Nathan Srivi's answer):

In your .ajax() method:

$.ajax 
( 
  { 
...
    xhr: function() 
    { 
      var xhr = new window.XMLHttpRequest();

      //Upload progress
      xhr.upload.addEventListener
      (
        "progress",
        function( event)
        {
          if( event.lengthComputable )
          {
            var percentComplete = Math.round( ( ( event.loaded / event.total ) * 100 ) );

            // Do something with upload progress
            $( '#progress' ).css( { 'width':  percentComplete + '%' } );

            if( percentComplete == 100 )
            {
              $( '#progress' ).addClass( 'finished' );
              $( '#progress' ).delay( 500 ).queue
              (
                'fx',
                function( next )
                {
                  $( '#progress' ).addClass( 'notransition' );
                  $( this ).css( { width: '' } );
                  $( this ).removeClass( 'finished' );
                  next();
                }
              );
            }
          }
        },
        false
      );

      //Download progress
      xhr.addEventListener
      (
        "progress",
        function( event )
        {
          if( event.lengthComputable )
          {
            var percentComplete = Math.round( ( ( event.loaded / event.total ) * 100 ) );

            // Do something with upload progress
            $( '#progress' ).css( { 'width':  percentComplete + '%' } );

            if( percentComplete == 100 )
            {
              $( '#progress' ).addClass( 'finished' );
              $( '#progress' ).delay( 500 ).queue
              (
                'fx',
                function( next )
                {
                  $( '#progress' ).addClass( 'notransition' );
                  $( this ).css( { width: '' } );
                  $( this ).removeClass( 'finished' );
                  next();
                }
              );
            }
          }
        },
        false
      );

      return xhr;
    },
...
    success: function( data, textStatus, xhr )
    {
      ...
      // Reset our ajax loading progress bar
      $( '#progress' ).removeClass( 'notransition' );
      ...
    }

Then, in your css; use this:

#progress {
  position: fixed;
  opacity: 1;
  z-index: 2147483647;
  top: 0;
  left: -6px;
  width: 0%;
  height: 2px;
  background: #b91f1f;
  -moz-border-radius: 1px;
  -webkit-border-radius: 1px;
  border-radius: 1px;
  -moz-transition: width 500ms ease-out,opacity 400ms linear;
  -ms-transition: width 500ms ease-out,opacity 400ms linear;
  -o-transition: width 500ms ease-out,opacity 400ms linear;
  -webkit-transition: width 500ms ease-out,opacity 400ms linear;
  transition: width 500ms ease-out,opacity 400ms linear;
}
#progress.finished {
  opacity: 0 !important;
}
#progress.notransition {
  -webkit-transition: none !important;
  -moz-transition: none !important;
  -o-transition: none !important;
  -ms-transition: none !important;
  transition: none !important;
}

#progress dd,#progress dt {
  position: absolute;
  top: 0;
  height: 2px;
  -moz-box-shadow: #b91f1f 1px 0 6px 1px;
  -ms-box-shadow: #b91f1f 1px 0 6px 1px;
  -webkit-box-shadow: #b91f1f 1px 0 6px 1px;
  box-shadow: #b91f1f 1px 0 6px 1px;
  -moz-border-radius: 100%;
  -webkit-border-radius: 100%;
  border-radius: 100%;
}
#progress dd {
  opacity: 1;
  width: 20px;
  right: 0;
  clip: rect(-6px,22px,14px,10px); 
}
#progress dt {
  opacity: 1;
  width: 180px;
  right: -80px;
  clip: rect(-6px,90px,14px,-6px);
}
@-moz-keyframes pulse {
  30% {
    opacity: 1
  }
  60% {
    opacity: 0
  }
  100% {
    opacity: 1
  }
}
@-ms-keyframes pulse {
  30% {
    opacity: .6
  }
  60% {
    opacity: 0
  }
  100% {
    opacity: .6
  }
}
@-o-keyframes pulse {
  30% {
    opacity: 1
  }
  60% {
    opacity: 0
  }
  100% {
    opacity: 1
  }
}
@-webkit-keyframes pulse {
  30% {
    opacity: .6
  }
  60% {
    opacity: 0
  }
  100% {
    opacity: .6
  }
}
@keyframes pulse {
  30% {
    opacity: 1
  }
  60% {
    opacity: 0
  }
  100% {
    opacity: 1
  }
}
#progress.waiting dd,#progress.waiting dt {
  -moz-animation: pulse 2s ease-out 0s infinite;
  -ms-animation: pulse 2s ease-out 0s infinite;
  -o-animation: pulse 2s ease-out 0s infinite;
  -webkit-animation: pulse 2s ease-out 0s infinite;
  animation: pulse 2s ease-out 0s infinite
}
#progress.notransition dd,#progress.notransition dt {
  -moz-animation: none !important;
  -ms-animation: none !important;
  -o-animation:  none !important;
  -webkit-animation:  none !important;
  animation:  none !important;
}

And now you should have a loader that works for each AJAX operation...and really works to represent the true percentage of how much of the response has been received, instead of just playing a fancy animation when you first load the main page.

To make it operational on the initial page load (i.e. its not actually displaying legitimate progress), use the method that Nathan Srivi mentions in a document.ready function above and beyond what I already mentioned:

$( document ).ready(function() {
    $({property: 0}).animate({property: 105}, {
        duration: 4000,
        step: function() {
            var _percent = Math.round(this.property);
            $('#progress').css('width',  _percent+"%");
            if(_percent == 105) {
                $("#progress").addClass("done");
            }
        },
        complete: function() {
            alert('complete');
        }
    });
});

Lastly,

You will need to ensure that 'Content-Length' headers are being sent to the browser in order for a loader of this design to work correctly...otherwise the event.lengthComputable member resolves to false...and no progress bar will load.

HTH, feel free to edit inconsistencies.

Rik
  • 676
  • 7
  • 11
  • can u plzz post a demo version of your code which i can run and see how it works. – Mou Aug 04 '15 at 14:52
  • how to send 'Content-Length' headers are being sent to the browser ? – Mou Aug 04 '15 at 14:53
  • Good stuff! How are the `dd` and `dt` tags supposed to be formatted in `#progress`? I don't believe they are doing anything necessary. – Tim Aug 19 '15 at 14:12
  • @Tim the `#progress dt` and `#progress dd` and similar css styles, respectively, control the style and format of the dd and dt tags. They are part of the pulse effect. If you mean to ask how the html looks: `
    `
    – Rik Oct 09 '15 at 21:30
  • @Mou The 'Content-Length' headers are typically sent automatically by the web server. When using a technology such as Node.js, you might need to send the 'length' of your response and manually set the Content-Length header, though if using a reverse proxy the web server being used might do this for you (though I have to send the header when using reverse-proxy via nginx.) I use the above loader over at mmogp.com – Rik Oct 09 '15 at 21:36
1

Code from TalkersCode.com and tutorial here http://talkerscode.com/webtricks/display-progress-bar-while-page-loads-using-jquery.php

function check_element(ele)
{
 var all = document.getElementsByTagName("*");
 var totalele=all.length;
 var per_inc=100/all.length;

 if($(ele).on())
 {
  var prog_width=per_inc+Number(document.getElementById("progress_width").value);
  document.getElementById("progress_width").value=prog_width;
  $("#bar1").animate({width:prog_width+"%"},10,function(){
  if(document.getElementById("bar1").style.width=="100%")
  {
    $(".progress").fadeOut("slow");
  }         
  });
 }

 else   
 {
  set_ele(ele);
 }
}
naresh
  • 41
  • 1
0

You can get the plugin for the progress bar
I have published it on GitHub

https://github.com/shashibeit/progressbar

you will need to include in your project and call the below functions

Progress.start(); Progress.go(20); Progress.go(30); Progress.go(80); Progress.go(100); Progress.complete();

Shashikant
  • 137
  • 1
  • 2
  • 10