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-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-04-22 22:03:10 +00:00
var data ;
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-10-27 18:50:23 +00:00
var $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.' )
) ,
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-06-19 17:48:32 +00:00
var $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' } )
. html ( 'Sorry, we have encountered an application error 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.' )
) ,
height : 192 ,
2011-04-22 22:03:10 +00:00
keys : { enter : 'close' , escape : 'close' } ,
2011-10-27 18:50:23 +00:00
title : 'Application 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
}
pending [ options . id ] = false ;
}
// return dfd.promise();
return options . id ;
}
} ;
} ( ) ;