/** * @author alexander.farkas * * @version 2.5.1 * project site: http://plugins.jquery.com/project/AjaxManager */ (function($){ $.manageAjax = (function(){ var cache = {}, queues = {}, presets = {}, activeRequest = {}, allRequests = {}, triggerEndCache = {}, defaults = { queue: true, //clear maxRequests: 1, abortOld: false, preventDoubbleRequests: true, cacheResponse: false, complete: function(){}, error: function(ahr, status){ var opts = this; if(status && status.indexOf('error') != -1){ setTimeout(function(){ var errStr = status +': '; if(ahr.status){ errStr += 'status: '+ ahr.status +' | '; } errStr += 'URL: '+ opts.url; throw new Error(errStr); }, 1); } }, success: function(){}, abort: function(){} } ; function create(name, settings){ var publicMethods = {}; presets[name] = presets[name] || {}; $.extend(true, presets[name], $.ajaxSettings, defaults, settings); if(!allRequests[name]){ allRequests[name] = {}; activeRequest[name] = {}; activeRequest[name].queue = []; queues[name] = []; triggerEndCache[name] = []; } $.each($.manageAjax, function(fnName, fn){ if($.isFunction(fn) && fnName.indexOf('_') !== 0){ publicMethods[fnName] = function(param, param2){ if(param2 && typeof param === 'string'){ param = param2; } fn(name, param); }; } }); return publicMethods; } function complete(opts, args){ if(args[1] == 'success' || args[1] == 'notmodified'){ opts.success.apply(opts, [args[0].successData, args[1]]); if (opts.global) { $.event.trigger("ajaxSuccess", args); } } if(args[1] === 'abort'){ opts.abort.apply(opts, args); if(opts.global){ $.active--; $.event.trigger("ajaxAbort", args); } } opts.complete.apply(opts, args); if (opts.global) { $.event.trigger("ajaxComplete", args); } if (opts.global && ! $.active){ $.event.trigger("ajaxStop"); } //args[0] = null; } function proxy(oldFn, fn){ return function(xhr, s, e){ fn.call(this, xhr, s, e); oldFn.call(this, xhr, s, e); xhr = null; e = null; }; } function callQueueFn(name){ var q = queues[name]; if(q && q.length){ var fn = q.shift(); if(fn){ fn(); } } } function add(name, opts){ if(!presets[name]){ create(name, opts); } opts = $.extend({}, presets[name], opts); //aliases var allR = allRequests[name], activeR = activeRequest[name], queue = queues[name]; var id = opts.type +'_'+ opts.url.replace(/\./g, '_'), triggerStart = true, oldComplete = opts.complete, ajaxFn = function(){ activeR[id] = { xhr: $.ajax(opts), ajaxManagerOpts: opts }; activeR.queue.push(id); return id; } ; if(opts.data){ id += (typeof opts.data == 'string') ? opts.data : $.param(opts.data); } if(opts.preventDoubbleRequests && allRequests[name][id]){ return false; } allR[id] = true; opts.complete = function(xhr, s, e){ var triggerEnd = true; if(opts.abortOld){ $.each(activeR.queue, function(i, activeID){ if(activeID == id){ return false; } abort(name, activeID); return activeID; }); } oldComplete.call(this, xhr, s, e); //stop memory leak if(activeRequest[name][id]){ if(activeRequest[name][id] && activeRequest[name][id].xhr){ activeRequest[name][id].xhr = null; } activeRequest[name][id] = null; } triggerEndCache[name].push({xhr: xhr, status: s}); xhr = null; activeRequest[name].queue = $.grep(activeRequest[name].queue, function(qid){ return (qid !== id); }); allR[id] = false; e = null; delete activeRequest[name][id]; $.each(activeR, function(id, queueRunning){ if(id !== 'queue' || queueRunning.length){ triggerEnd = false; return false; } }); if(triggerEnd){ $.event.trigger(name +'End', [triggerEndCache[name]]); $.each(triggerEndCache[name], function(i, cached){ cached.xhr = null; //memory leak }); triggerEndCache[name] = []; } }; if(cache[id]){ ajaxFn = function(){ activeR.queue.push(id); complete(opts, cache[id]); return id; }; } else if(opts.cacheResponse){ opts.complete = proxy(opts.complete, function(xhr, s){ if( s !== "success" && s !== "notmodified" ){ return false; } cache[id][0].responseXML = xhr.responseXML; cache[id][0].responseText = xhr.responseText; cache[id][1] = s; //stop memory leak xhr = null; return id; //strict }); opts.success = proxy(opts.success, function(data, s){ cache[id] = [{ successData: data, ajaxManagerOpts: opts }, s]; data = null; }); } ajaxFn.ajaxID = id; $.each(activeR, function(id, queueRunning){ if(id !== 'queue' || queueRunning.length){ triggerStart = false; return false; } }); if(triggerStart){ $.event.trigger(name +'Start'); } if(opts.queue){ opts.complete = proxy(opts.complete, function(){ callQueueFn(name); }); if(opts.queue === 'clear'){ queue = clear(name); } queue.push(ajaxFn); if(activeR.queue.length < opts.maxRequests){ callQueueFn(name); } return id; } return ajaxFn(); } function clear(name, shouldAbort){ $.each(queues[name], function(i, fn){ allRequests[name][fn.ajaxID] = false; }); queues[name] = []; if(shouldAbort){ abort(name); } return queues[name]; } function getXHR(name, id){ var ar = activeRequest[name]; if(!ar || !allRequests[name][id]){ return false; } if(ar[id]){ return ar[id].xhr; } var queue = queues[name], xhrFn; $.each(queue, function(i, fn){ if(fn.ajaxID == id){ xhrFn = [fn, i]; return false; } return xhrFn; }); return xhrFn; } function abort(name, id){ var ar = activeRequest[name]; if(!ar){ return false; } function abortID(qid){ if(qid !== 'queue' && ar[qid] && ar[qid].xhr && ar[qid].xhr.abort){ ar[qid].xhr.abort(); complete(ar[qid].ajaxManagerOpts, [ar[qid].xhr, 'abort']); } return null; } if(id){ return abortID(id); } return $.each(ar, abortID); } function unload(){ $.each(presets, function(name){ clear(name, true); }); cache = {}; } return { defaults: defaults, add: add, create: create, cache: cache, abort: abort, clear: clear, getXHR: getXHR, _activeRequest: activeRequest, _complete: complete, _allRequests: allRequests, _unload: unload }; })(); //stop memory leaks $(window).unload($.manageAjax._unload); })(jQuery);