oxjs/source/Ox.UI/js/Core/Ox.Request.js

307 lines
11 KiB
JavaScript
Raw Normal View History

2011-07-29 18:48:43 +00:00
// vim: et:ts=4:sw=4:sts=4:ft=javascript
2011-11-05 16:46:53 +00:00
'use strict';
2011-05-16 08:24:46 +00:00
/*@
Ox.Request <o> Basic request handler object
FIXME: options is not a property, just documenting defaults
options <o> Options object
timeout <n|60000> request timeout
type <s|"POST"> request type, possible values POST, GET, PUT, DELETE
url <s> request url
2011-05-16 08:24:46 +00:00
@*/
2011-04-22 22:03:10 +00:00
2011-05-16 08:24:46 +00:00
Ox.Request = function(options) {
2011-04-22 22:03:10 +00:00
var cache = {},
//dfd = $.Deferred(),
pending = {},
requests = {},
self = {
options: Ox.extend({
2011-04-22 22:03:10 +00:00
timeout: 60000,
type: 'POST',
url: '/api/'
}, options)
};
return {
2011-05-16 08:24:46 +00:00
/*@
cancel <f> cancel pending requests
() -> <u> cancel all requests
(fn) -> <u> cancel all requests where function returns true
(id) -> <u> cancel request by id
2011-05-16 08:24:46 +00:00
@*/
2011-04-22 22:03:10 +00:00
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]];
}
},
2011-05-16 08:24:46 +00:00
/*@
clearCache <f> clear cached results
() -> <u> ...
2011-05-16 08:24:46 +00:00
@*/
clearCache: function(query) {
if (!query) {
cache = {};
} else {
cache = Ox.filter(cache, function(val, key) {
return key.indexOf(query) == -1;
});
}
2011-04-22 22:03:10 +00:00
},
// fixme: remove
2011-08-06 17:41:01 +00:00
_leakCache: function() {
return cache;
},
2011-05-16 08:24:46 +00:00
/*@
options <f> get/set options
() -> <o> get options
(options) -> <o> set options
options <o> Options Object
@*/
2011-04-22 22:03:10 +00:00
options: function(options) {
2011-09-17 11:49:29 +00:00
return Ox.getset(self.options, options, function() {}, this);
2011-04-22 22:03:10 +00:00
},
2011-05-16 08:24:46 +00:00
/*@
requests <f> pending requests
() -> <n> returns number of requests
@*/
2011-04-22 22:03:10 +00:00
requests: function() {
return Ox.len(requests);
},
2011-05-16 08:24:46 +00:00
/*@
send <f> send request
(options) -> <n> returns request id
options <o> Options Object
age <n|-1> cache age
id <n|Ox.uid()> request id
timeout <n|self.options.timeout> overwrite default timeout
type <n|self.options.timeout> overwrite default type
url <n|self.options.timeout> overwrite default url
@*/
2011-04-22 22:03:10 +00:00
send: function(options) {
var options = Ox.extend({
2011-04-22 22:03:10 +00:00
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 > +new Date() - cache[req].time
)) {
var data = cache[req].data;
2011-04-22 22:03:10 +00:00
setTimeout(function() {
callback && callback(data);
2011-04-22 22:03:10 +00:00
}, 0);
} else {
pending[options.id] = true;
$.ajax({
complete: complete,
2011-04-22 22:03:10 +00:00
data: options.data,
//dataType: 'json',
2011-04-22 22:03:10 +00:00
timeout: options.timeout,
type: options.type,
url: options.url
});
}
}
function callback(data) {
if (requests[options.id]) {
delete requests[options.id];
options.callback && options.callback(data);
}
2011-04-22 22:03:10 +00:00
}
/*
2011-04-22 22:03:10 +00:00
function debug(request) {
var $iframe = $('<iframe>')
.css({ // fixme: should go into a class
width: 768,
height: 384
}),
$dialog = Ox.Dialog({
2011-04-22 22:03:10 +00:00
title: 'Application Error',
buttons: [
Ox.Button({
2011-04-22 22:03:10 +00:00
title: 'Close'
})
.bindEvent({
click: function() {
$dialog.close();
}
})
],
content: $iframe,
2011-08-17 11:39:33 +00:00
width: 768,
height: 384
2011-04-22 22:03:10 +00:00
})
.open(),
iframe = $iframe[0].contentDocument || $iframe[0].contentWindow.document;
iframe.open();
iframe.write(request.responseText);
iframe.close();
}
*/
2011-04-22 22:03:10 +00:00
function complete(request) {
var $dialog, data, error;
try {
data = JSON.parse(request.responseText);
} catch (err) {
2011-04-22 22:03:10 +00:00
try {
data = {
status: {
code: request.status,
text: request.statusText
}
};
2011-04-22 22:03:10 +00:00
} catch (err) {
data = {
status: {
code: '500',
text: 'Unknown Error'
}
};
2011-04-22 22:03:10 +00:00
}
}
2011-10-31 17:00:26 +00:00
if (data.status.code == 200 || data.status.code == 404 || data.status.code == 409) {
2011-10-31 16:02:00 +00:00
// we have to include not found and conflict
// so that handlers can handle these cases
cache[req] = {
data: data,
time: Ox.getTime()
};
2011-04-22 22:03:10 +00:00
callback(data);
2011-10-31 16:02:00 +00:00
} else if (data.status.code == 401 || data.status.code == 403) {
// unauthorized or forbidden
$dialog = Ox.Dialog({
buttons: [
Ox.Button({
id: 'close',
title: 'Close'
})
.bindEvent({
click: function() {
$dialog.close();
}
})
],
content: Ox.Element()
.append(
$('<img>')
.attr({src: Ox.UI.PATH + 'png/icon128.png'})
.css({position: 'absolute', left: '16px', top: '16px', width: '64px', height: '64px'})
)
.append(
Ox.Element()
.css({position: 'absolute', left: '96px', top: '16px', width: '256px'})
.html('Sorry, you have made an unauthorized request.')
),
fixedSize: true,
height: 192,
keys: {enter: 'close', escape: 'close'},
title: Ox.toTitleCase(data.status.text),
width: 368
})
.open();
2011-04-22 22:03:10 +00:00
} else {
// 0 (timeout) or 500 (error)
error = data.status.code == 0 ? 'timeout' : 'error';
// on window unload, pending request will time out, so
// in order to keep the dialog from appearing, delay it
setTimeout(function() {
$dialog = Ox.Dialog({
2011-04-22 22:03:10 +00:00
buttons: [
/*
Ox.Button({
2011-04-22 22:03:10 +00:00
id: 'details',
title: 'Details'
})
.bindEvent({
click: function() {
$dialog.close(function() {
debug(request);
});
}
}),
*/
Ox.Button({
2011-04-22 22:03:10 +00:00
id: 'close',
title: 'Close'
})
.bindEvent({
click: function() {
$dialog.close();
}
})
],
2011-08-17 11:39:33 +00:00
content: Ox.Element()
.append(
$('<img>')
.attr({src: Ox.UI.PATH + 'png/icon128.png'})
.css({position: 'absolute', left: '16px', top: '16px', width: '64px', height: '64px'})
)
.append(
Ox.Element()
.css({position: 'absolute', left: '96px', top: '16px', width: '256px'})
.html(
'Sorry, a server ' + error
+ ' occured while handling your request. To help us find out what went wrong, you may want to report this error to an administrator. Otherwise, please try again later.'
)
2011-08-17 11:39:33 +00:00
),
fixedSize: true,
2011-08-17 11:39:33 +00:00
height: 192,
2011-04-22 22:03:10 +00:00
keys: {enter: 'close', escape: 'close'},
title: 'Server ' + Ox.toTitleCase(error),
2011-08-17 11:39:33 +00:00
width: 368
2011-04-22 22:03:10 +00:00
})
.open();
// fixme: change this to Send / Don't Send
}, error == 'timeout' ? 250 : 0);
2011-04-22 22:03:10 +00:00
}
pending[options.id] = false;
}
// return dfd.promise();
return options.id;
}
};
}();