2010-02-17 00:53:05 -05:00
|
|
|
/**!
|
|
|
|
* project-site: http://plugins.jquery.com/project/AjaxManager
|
|
|
|
* repository: http://github.com/aFarkas/Ajaxmanager
|
|
|
|
* @author Alexander Farkas
|
|
|
|
* @version 3.0
|
|
|
|
* Copyright 2010, Alexander Farkas
|
|
|
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
|
|
|
*/
|
|
|
|
|
|
|
|
(function($){
|
|
|
|
|
|
|
|
//this can be deleted if jQuery 1.4.2 is out
|
|
|
|
$.support.ajax = !!(window.XMLHttpRequest);
|
|
|
|
if(window.ActiveXObject){
|
|
|
|
try{
|
|
|
|
new ActiveXObject("Microsoft.XMLHTTP");
|
|
|
|
$.support.ajax = true;
|
|
|
|
} catch(e){
|
|
|
|
if(window.XMLHttpRequest){
|
|
|
|
$.ajaxSetup({xhr: function(){
|
|
|
|
return new XMLHttpRequest();
|
|
|
|
}});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var managed = {},
|
|
|
|
cache = {}
|
|
|
|
;
|
|
|
|
$.manageAjax = (function(){
|
|
|
|
function create(name, opts){
|
|
|
|
managed[name] = new $.manageAjax._manager(name, opts);
|
|
|
|
return managed[name];
|
|
|
|
}
|
|
|
|
|
|
|
|
var publicFns = {
|
|
|
|
create: create
|
|
|
|
};
|
|
|
|
|
|
|
|
return publicFns;
|
|
|
|
})();
|
|
|
|
|
|
|
|
$.manageAjax._manager = function(name, opts){
|
|
|
|
this.requests = {};
|
|
|
|
this.inProgress = 0;
|
|
|
|
this.name = name;
|
|
|
|
this.qName = name;
|
|
|
|
|
|
|
|
this.opts = $.extend({}, $.ajaxSettings, $.manageAjax.defaults, opts);
|
|
|
|
if(opts.queue && opts.queue !== true && typeof opts.queue === 'string' && opts.queue !== 'clear'){
|
|
|
|
this.qName = opts.queue;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
$.manageAjax._manager.prototype = {
|
|
|
|
add: function(o){
|
|
|
|
o = $.extend({}, this.opts, o);
|
|
|
|
|
|
|
|
var origCom = o.complete,
|
|
|
|
origSuc = o.success,
|
|
|
|
beforeSend = o.beforeSend,
|
|
|
|
origError = o.error,
|
|
|
|
strData = (typeof o.data == 'string') ? o.data : $.param(o.data || {}),
|
|
|
|
xhrID = o.type + o.url + strData,
|
|
|
|
that = this,
|
|
|
|
ajaxFn = this._createAjax(xhrID, o, origSuc, origCom)
|
|
|
|
;
|
|
|
|
if(this.requests[xhrID] && o.preventDoubbleRequests){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ajaxFn.xhrID = xhrID;
|
|
|
|
o.xhrID = xhrID;
|
|
|
|
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['add', o, o.queue, this.opts, this.requests[xhrID], this.qName]);
|
2010-02-17 00:53:05 -05:00
|
|
|
o.beforeSend = function(xhr, opts){
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['o.beforeSend', xhr, opts]);
|
2010-02-17 00:53:05 -05:00
|
|
|
var ret = beforeSend.call(this, xhr, opts);
|
|
|
|
if(ret === false){
|
|
|
|
that._removeXHR(xhrID);
|
|
|
|
}
|
|
|
|
xhr = null;
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
o.complete = function(xhr, status){
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['o.complete', xhr, status, o]);
|
2010-02-17 00:53:05 -05:00
|
|
|
that._complete.call(that, this, origCom, xhr, status, xhrID, o);
|
|
|
|
xhr = null;
|
|
|
|
};
|
|
|
|
|
|
|
|
o.success = function(data, status, xhr){
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['o.success', data, status]);
|
2010-02-17 00:53:05 -05:00
|
|
|
that._success.call(that, this, origSuc, data, status, xhr, o);
|
|
|
|
xhr = null;
|
|
|
|
};
|
|
|
|
|
|
|
|
//always add some error callback
|
|
|
|
o.error = function(ahr, status, errorStr){
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['o.error', errorStr, status]);
|
2010-02-17 00:53:05 -05:00
|
|
|
ahr = (ahr || {});
|
|
|
|
var httpStatus = ahr.status,
|
|
|
|
content = ahr.responseXML || ahr.responseText
|
|
|
|
;
|
|
|
|
if(origError) {
|
|
|
|
origError.call(this, ahr, status, errorStr, o);
|
|
|
|
} else {
|
|
|
|
setTimeout(function(){
|
|
|
|
throw status + ':: status: ' + httpStatus + ' | URL: ' + o.url + ' | data: '+ strData + ' | thrown: '+ errorStr + ' | response: '+ content;
|
|
|
|
}, 0);
|
|
|
|
}
|
|
|
|
ahr = null;
|
|
|
|
};
|
|
|
|
|
|
|
|
if(o.queue === 'clear'){
|
|
|
|
$(document).clearQueue(this.qName);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(o.queue){
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['Queueing', o.queue, this.qName]);
|
2010-02-17 00:53:05 -05:00
|
|
|
$.queue(document, this.qName, ajaxFn);
|
|
|
|
if(this.inProgress < o.maxRequests){
|
|
|
|
$.dequeue(document, this.qName);
|
|
|
|
}
|
|
|
|
return xhrID;
|
|
|
|
}
|
|
|
|
return ajaxFn();
|
|
|
|
},
|
|
|
|
_createAjax: function(id, o, origSuc, origCom){
|
|
|
|
var that = this;
|
|
|
|
return function(){
|
|
|
|
if(o.beforeCreate.call(o.context || that, id, o) === false){return;}
|
|
|
|
that.inProgress++;
|
|
|
|
if(o.cacheResponse && cache[id]){
|
|
|
|
that.requests[id] = {};
|
|
|
|
setTimeout(function(){
|
|
|
|
that._complete.call(that, o.context || o, origCom, {}, 'success', id, o);
|
|
|
|
that._success.call(that, o.context || o, origSuc, cache[id], 'success', {}, o);
|
|
|
|
}, 0);
|
|
|
|
} else {
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['create_ajax', o, o.complete, o.error, o.success]);
|
2010-02-17 00:53:05 -05:00
|
|
|
that.requests[id] = $.ajax(o);
|
|
|
|
}
|
|
|
|
if(that.inProgress === 1){
|
|
|
|
$.event.trigger(that.name +'AjaxStart');
|
|
|
|
}
|
|
|
|
return id;
|
|
|
|
};
|
|
|
|
},
|
|
|
|
_removeXHR: function(xhrID){
|
|
|
|
if(this.opts.queue){
|
|
|
|
$.dequeue(document, this.qName);
|
|
|
|
}
|
|
|
|
this.inProgress--;
|
|
|
|
this.requests[xhrID] = null;
|
|
|
|
delete this.requests[xhrID];
|
|
|
|
},
|
|
|
|
_isAbort: function(xhr, o){
|
|
|
|
var ret = !!( o.abortIsNoSuccess && ( !xhr || xhr.readyState === 0 || this.lastAbort === o.xhrID ) );
|
|
|
|
xhr = null;
|
|
|
|
return ret;
|
|
|
|
},
|
|
|
|
_complete: function(context, origFn, xhr, status, xhrID, o){
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['complete', o]);
|
2010-02-17 00:53:05 -05:00
|
|
|
if(this._isAbort(xhr, o)){
|
|
|
|
status = 'abort';
|
|
|
|
o.abort.call(context, xhr, status, o);
|
|
|
|
}
|
|
|
|
origFn.call(context, xhr, status, o);
|
|
|
|
$.event.trigger(this.name +'AjaxComplete', [xhr, status, o]);
|
|
|
|
|
|
|
|
if(o.domCompleteTrigger){
|
|
|
|
$(o.domCompleteTrigger).trigger(this.name +'DOMComplete', [xhr, status, o]);
|
|
|
|
}
|
|
|
|
|
|
|
|
this._removeXHR(xhrID);
|
|
|
|
if(!this.inProgress){
|
|
|
|
$.event.trigger(this.name +'AjaxStop');
|
|
|
|
}
|
|
|
|
xhr = null;
|
|
|
|
},
|
|
|
|
_success: function(context, origFn, data, status, xhr, o){
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['_success', data, status]);
|
2010-02-17 00:53:05 -05:00
|
|
|
var that = this;
|
|
|
|
if(this._isAbort(xhr, o)){
|
|
|
|
xhr = null;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(o.abortOld){
|
|
|
|
$.each(this.requests, function(name){
|
|
|
|
if(name === o.xhrID){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
that.abort(name);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if(o.cacheResponse && !cache[o.xhrID]){
|
|
|
|
cache[o.xhrID] = data;
|
|
|
|
}
|
|
|
|
origFn.call(context, data, status, xhr, o);
|
|
|
|
$.event.trigger(this.name +'AjaxSuccess', [xhr, o, data]);
|
|
|
|
if(o.domSuccessTrigger){
|
|
|
|
$(o.domSuccessTrigger).trigger(this.name +'DOMSuccess', [data, o]);
|
|
|
|
}
|
|
|
|
xhr = null;
|
|
|
|
},
|
|
|
|
getData: function(id){
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['getData', id]);
|
2010-02-17 00:53:05 -05:00
|
|
|
if( id ){
|
|
|
|
var ret = this.requests[id];
|
|
|
|
if(!ret && this.opts.queue) {
|
|
|
|
ret = $.grep($(document).queue(this.qName), function(fn, i){
|
|
|
|
return (fn.xhrID === id);
|
|
|
|
})[0];
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
requests: this.requests,
|
|
|
|
queue: (this.opts.queue) ? $(document).queue(this.qName) : [],
|
|
|
|
inProgress: this.inProgress
|
|
|
|
};
|
|
|
|
},
|
|
|
|
abort: function(id){
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['abort', id]);
|
2010-02-17 00:53:05 -05:00
|
|
|
var xhr;
|
|
|
|
if(id){
|
|
|
|
xhr = this.getData(id);
|
|
|
|
|
|
|
|
if(xhr && xhr.abort){
|
|
|
|
this.lastAbort = id;
|
|
|
|
xhr.abort();
|
|
|
|
this.lastAbort = false;
|
|
|
|
} else {
|
|
|
|
$(document).queue(
|
|
|
|
this.qName, $.grep($(document).queue(this.qName), function(fn, i){
|
|
|
|
return (fn !== xhr);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
xhr = null;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var that = this,
|
|
|
|
ids = []
|
|
|
|
;
|
|
|
|
$.each(this.requests, function(id){
|
|
|
|
ids.push(id);
|
|
|
|
});
|
|
|
|
$.each(ids, function(i, id){
|
|
|
|
that.abort(id);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
clear: function(shouldAbort){
|
2010-06-08 11:19:07 -04:00
|
|
|
// NEWSBLUR.log(['clear', shouldAbort]);
|
2010-02-17 00:53:05 -05:00
|
|
|
$(document).clearQueue(this.qName);
|
|
|
|
if(shouldAbort){
|
|
|
|
this.abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
$.manageAjax._manager.prototype.getXHR = $.manageAjax._manager.prototype.getData;
|
|
|
|
$.manageAjax.defaults = {
|
|
|
|
complete: $.noop,
|
|
|
|
success: $.noop,
|
|
|
|
beforeSend: $.noop,
|
|
|
|
beforeCreate: $.noop,
|
|
|
|
abort: $.noop,
|
|
|
|
abortIsNoSuccess: true,
|
|
|
|
maxRequests: 1,
|
|
|
|
cacheResponse: false,
|
|
|
|
domCompleteTrigger: false,
|
|
|
|
domSuccessTrigger: false,
|
|
|
|
preventDoubbleRequests: true,
|
|
|
|
queue: false // true, false, clear
|
|
|
|
};
|
|
|
|
|
|
|
|
$.each($.manageAjax._manager.prototype, function(n, fn){
|
|
|
|
if(n.indexOf('_') === 0 || !$.isFunction(fn)){return;}
|
|
|
|
$.manageAjax[n] = function(name, o){
|
|
|
|
if(!managed[name]){
|
|
|
|
if(n === 'add'){
|
|
|
|
$.manageAjax.create(name, o);
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
|
|
managed[name][n].apply(managed[name], args);
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
})(jQuery);
|