Ox.Request = function(options) { /*** Ox.Request Basic request handler Options timeout Methods cancel() cancel request clearCache() clear cache options() get or set options requests() return number of active requests send() send request ***/ var cache = {}, //dfd = $.Deferred(), pending = {}, requests = {}, self = { options: $.extend({ timeout: 60000, type: 'POST', url: '/api/' }, options) }; return { cancel: function() { if (arguments.length == 0) { // cancel all requests requests = {}; } else if (Ox.isFunction(arguments[0])) { // cancel with function Ox.forEach(requests, function(req, id) { if (arguments[0](req)) { delete requests[id]; } }); } else { // cancel by id delete requests[arguments[0]]; } }, clearCache: function() { cache = {}; }, options: function(options) { return Ox.getset(self.options, options, $.noop(), this); }, requests: function() { return Ox.len(requests); }, send: function(options) { var options = $.extend({ age: -1, callback: null, id: Ox.uid(), timeout: self.options.timeout, type: self.options.type, url: self.options.url }, options), req = JSON.stringify({ url: options.url, data: options.data }); if (pending[options.id]) { setTimeout(function() { Ox.Request.send(options); }, 0); } else { requests[options.id] = { url: options.url, data: options.data }; if (cache[req] && (options.age == -1 || options.age > Ox.getTime() - cache[req].time)) { setTimeout(function() { callback && callback(cache[req].data); }, 0); } else { pending[options.id] = true; $.ajax({ data: options.data, dataType: 'json', error: error, success: success, timeout: options.timeout, type: options.type, url: options.url }); } } function callback(data) { delete requests[options.id]; //Ox.len(requests) == 0 && $body.trigger('requestStop'); options.callback && options.callback(data); } function debug(request) { var $iframe = $('