patternjavascriptMinor
Display progress bar to show async request status using jQuery
Viewed 0 times
showbarasyncrequeststatusprogressjqueryusingdisplay
Problem
Instead of using the ProgressBar plugin, this script displays the progress bar for async requests on the page. Could anyone provide any feedback on this, especially if there will be any issues like cross browser compatibility, etc?
Loading...
//displays progress bar
$('.overlay').ajaxStart(function () {
$(this).css({ height: $(document).height(), width: $(document).width() }).show();
$(this).find(".progress").css({ top: $(window).height() / 2, left: $(window).width() / 2 });
}).ajaxStop(function () {
$(this).hide();
});
.overlay
{
position: fixed !important;
position: absolute; /*ie6*/
width: 100%;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background-color: #000;
filter: alpha(opacity=20);
opacity: 0.2;
-moz-opacity: 0.2;
-khtml-opacity: 0.2;
-webkit-opacity: 0.2;
z-index: 10004;
display: none;
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=20); /*ie6*/
}
.overlay .progress
{
position: absolute;
z-index: 10005;
background: #fff;
color: #000;
}Solution
Realizing that you are trying to make reusable code, I figured I would share my methodology, as I believe it will extend your structure here.
I like to wrap everything into an object with functions appropriate to AJAX, and I added in your
And then it is called with an example of something like this:
This is obviously super generic, but should do the trick. A quick explanation:
And a few small tweaks I made to your existing jQuery code to optimize:
This function should give you a good starting point, and you can modify as needed if you need additional parameters. The only additional parameter I advise against is the use of
Hope this helped.
I like to wrap everything into an object with functions appropriate to AJAX, and I added in your
.overlay components:var ajax = {
showProgressBar:function($overlay){
var $doc = $(document),
$win = $(window);
$overlay
.css({
height:$doc.height(),
width:$doc.width(),
display:'block'
})
.find('.progress')
.css({
top:($win.height() / 2),
left:($win.width() / 2)
});
},
hideProgressBar:function($overlay){
$overlay.hide();
},
abortActive:function(){
var self = this;
if(($.active > 0) && (self.active !== undefined)){
self.active.abort();
}
},
clearActive:function(){
this.active = undefined;
},
send:function($type,$url,$data,$success,$error,$abort){
var self = this,
$overlay = $('.overlay'),
$beforeSend = ($abort ? function(){
self.abortActive();
self.showProgressBar($overlay);
} : function(){
self.showProgressBar($overlay);
}),
$complete = ($abort ? function(){
self.clearActive();
self.hideProgressBar($overlay);
} : function(){
self.hideProgressBar($overlay);
}),
curFunc = $.ajax({
type:$type,
url:$url,
data:$data,
beforeSend:$beforeSend
}).success($success).error($error).complete($complete);
this.active = ($abort ? curFunc : self.active);
}
};And then it is called with an example of something like this:
ajax.send(
'POST',
'requires/submitSomething.php',
{
id:$someId,
type:$someType
},
function(data){
alert('Successful! The response message was: '+data.message);
},
function(data){
alert('Error! The response message was: '+data.message);
},
false
);This is obviously super generic, but should do the trick. A quick explanation:
- the
beforeSendsetting will fire a callback function prior to sending the AJAX, which is where you want to load your progress gif
- the
completesetting will fire a callback function once everything else completes, including thesuccess/errorfunctions, so it is where you want to hide the progress gif
- in the
success/errorfunctions, you can include the response data and manipulate as you wish
- the use of
thisin thesendfunction refers to the object parent, hence able to see the other functions rather than referring to them by name
- the ajax call is assigned to a variable to allow for aborting the call mid-stream before starting another (if another action overrides it, for example) ... the reason for the use of
thisrather thanselfis because we need to assign it to the object rather than just reference the existing objects within it
- the function creation is based on the boolean you pass in for
$abort, to determine if your AJAX call should stop all current AJAX calls or have it run in parallel (depending on your usage)
And a few small tweaks I made to your existing jQuery code to optimize:
- cached
$(document),$(window), and$('.overlay')as they are used more than once in the functions
- consolidated your
.show()function into the previous CSS statement (as the default is to basically perform a.css({display:'block'})statement ... if you have overridden this with a custom function, you can return as needed)
- chained the calls to
$('.overlay')and$('.progress'), as they were both based on$(this)
This function should give you a good starting point, and you can modify as needed if you need additional parameters. The only additional parameter I advise against is the use of
dataType; for some reason, everyone using json likes to include dataType in their AJAX call (which is an intelligent guess, not a true marker) instead of doing it right. Don't be "that guy", put your appropriate header declaration in the files you are loading via AJAX and it will be bulletproof.Hope this helped.
Code Snippets
var ajax = {
showProgressBar:function($overlay){
var $doc = $(document),
$win = $(window);
$overlay
.css({
height:$doc.height(),
width:$doc.width(),
display:'block'
})
.find('.progress')
.css({
top:($win.height() / 2),
left:($win.width() / 2)
});
},
hideProgressBar:function($overlay){
$overlay.hide();
},
abortActive:function(){
var self = this;
if(($.active > 0) && (self.active !== undefined)){
self.active.abort();
}
},
clearActive:function(){
this.active = undefined;
},
send:function($type,$url,$data,$success,$error,$abort){
var self = this,
$overlay = $('.overlay'),
$beforeSend = ($abort ? function(){
self.abortActive();
self.showProgressBar($overlay);
} : function(){
self.showProgressBar($overlay);
}),
$complete = ($abort ? function(){
self.clearActive();
self.hideProgressBar($overlay);
} : function(){
self.hideProgressBar($overlay);
}),
curFunc = $.ajax({
type:$type,
url:$url,
data:$data,
beforeSend:$beforeSend
}).success($success).error($error).complete($complete);
this.active = ($abort ? curFunc : self.active);
}
};ajax.send(
'POST',
'requires/submitSomething.php',
{
id:$someId,
type:$someType
},
function(data){
alert('Successful! The response message was: '+data.message);
},
function(data){
alert('Error! The response message was: '+data.message);
},
false
);Context
StackExchange Code Review Q#25379, answer score: 6
Revisions (0)
No revisions yet.