Tuesday, September 13, 2011

(Smart) jQuery Ajax Indicator

Any fool can hook into the jQuery's ajaxStart and ajaxStop functions in order to display an "ajax request in progress" indicator. But what if we want to suppress the display for requests that finish in less than X number of milliseconds? And what if we want to maintain the display actively for Y number of milliseconds (to prevent "bouncing")? Look no further. The markup:

<html>
	<head><!--blah blah--></head>
	<body>
		<div id="notify-container">
			<div class="ui-corner-bl ui-corner-br" id="ajax-loading" style="display: none;">
				Loading...</div>
			</div>
		<div>
		<!--blah blah-->
	</body>
</html>

Throw in some styling:

#notify-container 
{ 
	position: fixed; 
	left: 0; 
	top: 0; 
	width: 100%; 
	height: 0; 
	z-index: 100; 
}
#ajax-loading 
{ 
	position: absolute; 
	display: inline-block; 
	width: 100px; 
	left: 50%; 
	margin-left: -50px; 
	padding: 0.5em 1em 0.6em 1em; 
	font-weight: bold; 
	font-size: 1.1em; 
	text-align: center; 
	background-color: #ffe79c; 
	border: 1px solid #c98400; 
}

Any type of indicator works, really. I prefer a Google-esqe div that slides down from the top of the window, but it could be a spinner gif or an opaqued modal window. Doesn't matter; that's not the relevant part. Here's the magic:

$(document).ready(function () {
	// ajax working indicator
	$('#ajax-loading')
		.ajaxStart(function () {
			var $this = $(this);
			clearTimeout($this.data('waitingToHide'));
			$this.data('waitingToShow', setTimeout(function () { $this.slideDown(); }, 600));
		})
		.ajaxStop(function () {
			var $this = $(this);
			clearTimeout($this.data('waitingToShow'));
			$this.data('waitingToHide', setTimeout(function () { $this.slideUp(); }, 2000));
		});
})

Each call to ajaxStart and ajaxStop introduces the respective show and hide animations via a setTimeout delay. The function handler is saved to the jQuery element's data() store.

The real trick here is that before this happens, the data() store is checked and cleared of any pending animations. In this way, if ajaxStop is called before the show animation, the show animation will be "short-circuited". Similarly, if another call to ajaxStart occurs while the hide animation is pending, the hide animation will be cancelled.

No comments:

Post a Comment