After careful consideration, I have determined that utilizing $.Deferred is the most effective approach to tackle this particular issue. Rather than delving into its technical intricacies, I will focus on outlining its advantages and providing a solution.
If you are seeking further information, I recommend referring to the documentation available at:
http://api.jquery.com/category/deferred-object/
I personally found these resources to be immensely helpful for getting started with $.Deferred:
http://www.html5rocks.com/en/tutorials/async/deferred/
The crux of the matter involves combining CSS3 animations with asynchronous ajax requests while ensuring synchronicity through callbacks. This entails scenarios where elements need to fade in and out seamlessly during ajax transitions. The beauty of using $.Deferred lies in its ability to orchestrate these events in a more refined manner. Instead of waiting for each animation to conclude before proceeding to the next step, $.Deferred enables you to synchronize actions such as fading out, triggering an ajax request, and then fading back in upon completion of both processes.
To witness this concept in action, feel free to explore this functioning fiddle:
http://jsfiddle.net/SB987/1/
For a detailed breakdown of the JavaScript components, refer to the annotated code snippet below.
//Upon clicking the anchor, the loadContent function is invoked
$('a').on('click', function(){
var url = $(this).data('url');
var target = $(this).data('target');
loadContent(url, target);
});
//Utilize a CSS transform to slide out the existing element
var slideOut = function($el, $target){
//Instantiate a deferred object
var deferred = new $.Deferred();
//Initiate sliding out of the element (note the CSS transition) (please consider using transforms for broader browser support)
$el.css({"-webkit-transform":"translateX(100%)"}).on('transitionend webkitTransitionEnd', function(e){
//Once the transition concludes, resolve the deferred object and return $target
deferred.resolve($target);
});
//Return the promise from the deferred object
return deferred.promise();
};
//Insert the retrieved element from the Ajax request and slide it in
var slideIn = function(el, $target){
var $el = $(el);
$target.empty().append($el).css({height : "auto"});
//Address a peculiar bug wherein CSS transition fails outside setTimeout (any insights?)
setTimeout(function(){
$el.removeClass('content2');
}, 0);
};
//Perform an ajax request and retrieve HTML data
//Note that ajax requests also yield promises along with deferred objects; here, I am encapsulating it for clarity
var getData = function(url){
var deferred = new $.Deferred();
//var htmlData = "asdfasfasdf";
$.ajax({
url: url,
method : "POST",
data : { 'html': htmlData},
success: function (returnhtml) {
//Resolve the deferred object and pass the response
deferred.resolve(returnhtml);
},
error: function (xhr, ajaxOptions, thrownError) {
//You can reject a deferred object and execute alternative callbacks, but I'll leave that exploration to you
deferred.reject(thrownError);
}
});
//Return the promise from the deferred object
return deferred.promise();
}
var loadContent = function(url, target){
$el = $('.content');
$target = $(target);
//Execute slideOut and getData functions
var slidePromise = slideOut($el, $target);
var dataPromise = getData(url);
//Since we are returning promises from deferred objects in the aforementioned functions, the following code executes only after resolving those objects
$.when(slidePromise, dataPromise).done(function(slidePromise, dataPromise) {
//Following the completion of the ajax request and slideOut animation, proceed by sliding in the new content while passing the target element and response content
slideIn(dataPromise, slidePromise );
});
};