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
2011-09-05 23:34:29 +00:00
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 = {
2011-09-17 18:36:09 +00:00
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
2011-09-05 23:34:29 +00:00
( 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
2011-09-05 23:34:29 +00:00
( ) - > < u > ...
2011-05-16 08:24:46 +00:00
@ * /
2011-09-19 13:34:17 +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
} ,
2011-11-08 10:27:49 +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 ) {
2011-09-17 18:36:09 +00:00
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
} ;
2011-10-07 19:29:04 +00:00
if ( cache [ req ] && (
options . age == - 1
|| options . age > + new Date ( ) - cache [ req ] . time
) ) {
2011-10-29 12:32:55 +00:00
var data = cache [ req ] . data ;
2011-04-22 22:03:10 +00:00
setTimeout ( function ( ) {
2011-10-29 12:32:55 +00:00
callback && callback ( data ) ;
2011-04-22 22:03:10 +00:00
} , 0 ) ;
} else {
pending [ options . id ] = true ;
$ . ajax ( {
2011-10-27 18:50:23 +00:00
complete : complete ,
2011-04-22 22:03:10 +00:00
data : options . data ,
2011-10-27 18:50:23 +00:00
//dataType: 'json',
2011-04-22 22:03:10 +00:00
timeout : options . timeout ,
type : options . type ,
url : options . url
} ) ;
}
}
function callback ( data ) {
2011-10-07 19:29:04 +00:00
if ( requests [ options . id ] ) {
delete requests [ options . id ] ;
options . callback && options . callback ( data ) ;
}
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
} ) ,
2011-06-19 17:48:32 +00:00
$dialog = Ox . Dialog ( {
2011-04-22 22:03:10 +00:00
title : 'Application Error' ,
buttons : [
2011-06-19 17:48:32 +00:00
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-10-27 18:50:23 +00:00
function complete ( request ) {
2011-11-08 10:27:49 +00:00
var $dialog , data , error ;
2011-10-27 18:50:23 +00:00
try {
data = JSON . parse ( request . responseText ) ;
} catch ( err ) {
2011-04-22 22:03:10 +00:00
try {
2011-10-27 18:50:23 +00:00
data = {
status : {
code : request . status ,
text : request . statusText
}
} ;
2011-04-22 22:03:10 +00:00
} catch ( err ) {
2011-10-27 18:50:23 +00:00
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
2011-10-27 18:50:23 +00:00
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
2011-11-08 10:27:49 +00:00
$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 {
2011-10-27 18:50:23 +00:00
// 0 (timeout) or 500 (error)
2011-11-08 10:27:49 +00:00
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 : [
2011-06-19 17:48:32 +00:00
Ox . Button ( {
2011-04-22 22:03:10 +00:00
id : 'details' ,
title : 'Details'
} )
. bindEvent ( {
click : function ( ) {
$dialog . close ( function ( ) {
debug ( request ) ;
} ) ;
}
} ) ,
2011-06-19 17:48:32 +00:00
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' } )
2011-11-08 10:27:49 +00:00
. 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
) ,
2011-11-08 10:27:49 +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' } ,
2011-11-08 10:27:49 +00:00
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
2011-11-08 10:27:49 +00:00
} , error == 'timeout' ? 250 : 0 ) ;
2011-04-22 22:03:10 +00:00
}
pending [ options . id ] = false ;
}
// return dfd.promise();
return options . id ;
}
} ;
} ( ) ;