(function($) {
 $.ajaxUnqueued = $.ajax;

 // a dummy request object to allow aborting of requests
 function Request(s) {
   this._s = s;
 };

 Request.abort = function() {
   this._aborted = true;
   if (this._xhr) {
     this._xhr.abort();
   };
 };

 // the queue manager
 // it handles the wrapping and sending of requests
 var queue = function() {
   var _queue = [];

   function push(data) {
     _queue[_queue.length] = new Request(data);
     update();
   };

   function update() {
     // handle requests as long as there are some and there are no more
     // then 4 concurrent requests at once
     while (_queue.length > 0 && jQuery.active < 4) {
       var request = _queue.shift();
       // only do the request if it's not aborted yet
       if (request._aborted != true) {
         // wrap the original complete function so the update function
         // gets called when a request is complete
         var __old_complete = request._s.complete;
         request._s.complete = function(res, status) {
           update();
           if (__old_complete != null)
             return __old_complete(res, status);
         }
         // use the original function to do the actual request
         request._xhr = $.ajaxUnqueued(request._s);
       };
     };
   };

   // public functions of queue
   return {
     push: push,
     update: update
   };
 }();

 // the new ajax function for jQuery. It wraps the original function which
 // is still available as ajaxUnqueued.
 $.ajax = function(s) {
   s = jQuery.extend({}, {queue: true}, s);
   if (s.queue == true) {
     return queue.push(s);
   } else {
     return $.ajaxUnqueued(s);
   };
 };
})(jQuery);