if( _.isUndefined(self.fluorine) )
{
throw new Error('[ERROR] Should include fluorine.utils first.')
}
if( _.isUndefined(self.fluorine) )
{
throw new Error('[ERROR] Should include fluorine.utils first.')
}
Basic IO context provide file CRUD operations.
Provide following features:
Data constructor of this context. Context constructor should be able to receive anything, while contexted functions can has type constrains.
self.fluorine.IO = function(a)
{
return new self.fluorine.IO.o(a)
}
Inner implement of this context.
self.fluorine.IO.o = function(a){ self.fluorine.Context.o.call(this, a) }
Statics functions.
_.extend( self.fluorine.IO.o,
{
__genAjaxSuccess: function(proc)
{
return function(data, textStatus, jqXHR)
{
Resume execition after receiving.
proc.run(data)
}
}
Will throw error while ajax request got failed.
:: URL -> Query -> ( XHR -> TextStatus -> Error ) -> IO ()
,__genAjaxError: function(url, qry)
{
return function(jqXHR, textStatus, errorThrown)
{ var msg = "ERROR: IO error in request: "+qry+" on "+url
console.error(msg, errorThrown)
throw new Error(msg);
}
}
Default Ajax request function handling binary formats.
DataType:: ArrayBuffer | Blob :: Process a -> URL -> Query -> DataType -> Request
,__binaryAjax: function( proc, url, query, type)
{ var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = type;
request.addEventListener
( 'load'
, function()
{ self.fluorine.IO.o.
__genAjaxSuccess(proc)(request.response, request.statusText, request)
}
)
request.addEventListener
( 'error'
, function(event)
{ self.fluorine.IO.o.
__genAjaxError(url)(request, request.statusText, event)
}
)
return request
}
Make XMLHttpRequest chainable. Effects hidden, and not to provide this feature yet.
:: IO r -> IO r
,__wrapRequest: function(io)
{
var fnames =
[ 'addEventListener'
, 'open', 'setRequestHeader'
, 'send', 'abort'
]
var anames =
[ 'timeout'
, 'upload'
, 'withCredentials'
]
_.each
( fnames
, function(fname)
{
Append new request functions in that IO context.
io[fname] = _.bind( function()
{ var args = arguments
this.__process.next
( _.bind(function(req)
{
Lazy execute/set request and pass it out.
req[fname].apply(req, args)
this.__process.run(req)
}, this)
, 'IO::'+fname
)
}, io)
}
)
_.each
( anames
, function(aname)
{
Append new setter functions in that IO context. Return the attr value if the passed attr is undefined.
io[aname] = _.bind( function(attr)
{
( _.bind(function(req)
{
if( ! _.isUndefined(attr) )
{
req[aname] = attr
this.__process.run(req)
}
else // Return value.
{
this.__process.run(req[aname])
}
}, this)
, 'IO::'+aname
)
}, io)
}
)
}
}
)
Extends basic the context.
_.extend( self.fluorine.IO.o.prototype, self.fluorine.Context.o.prototype )
Extends our new functions. Depend on jQuery.ajax, may be decoupled in near future.
self.fluorine.IO.o.prototype = _.extend
( self.fluorine.IO.o.prototype
,
{
get: function(url)
{
this.__process.next
( _.bind(function()
{
var process = this.__process
var request = new XMLHttpRequest()
request.open('GET', url, true)
request.responseType = 'text'
request.addEventListener
( 'load'
, function()
{ self.fluorine.IO.o.
__genAjaxSuccess(process)(request.response, request.statusText, request)
}
)
request.addEventListener
( 'error'
, function(event)
{ self.fluorine.IO.o.
__genAjaxError(url)(request, request.statusText, event)
}
)
request.send()
}, this)
, 'IO::get')
return this
}
,getBinary: function(url)
{
this.__process.next
( _.bind(function()
{
var process = this.__process
var request = new XMLHttpRequest()
request.open('GET', url, true)
request.responseType = 'arraybuffer'
request.addEventListener
( 'load'
, function()
{ self.fluorine.IO.o.
__genAjaxSuccess(process)(request.response, request.statusText, request)
}
)
request.addEventListener
( 'error'
, function(event)
{ self.fluorine.IO.o.
__genAjaxError(url)(request, request.statusText, event)
}
)
request.send()
}, this)
, 'IO::getBinary')
return this
}
,getBinaryFile: function(url)
{
this.__process.next
( _.bind(function()
{
var process = this.__process
var request = new XMLHttpRequest()
request.open('GET', url, true)
request.responseType = 'blob'
request.addEventListener
( 'load'
, function()
{ self.fluorine.IO.o.
__genAjaxSuccess(process)(request.response, request.statusText, request)
}
)
request.addEventListener
( 'error'
, function(event)
{ self.fluorine.IO.o.
__genAjaxError(url)(request, request.statusText, event)
}
)
request.send()
}, this)
, 'IO::getBinaryFile')
return this
}
Post previous IO handling result to URL. Will automatically convert data as FormData. Key/Value paris will automatically transform to form data.
:: ( NotBinary r ) => IO r -> URL -> IO ()
,post: function(url)
{
this.__process.next
( _.bind(function(data)
{
var process = this.__process
var request = new XMLHttpRequest()
request.open('POST', url, true)
var formData = new FormData()
if( _.isObject(data))
{
_.chain(data).keys(data).each(function(k){formData.append(k, data[k]) })
}
else
{
formData.append(data,"") // Like jQuery
}
request.addEventListener
( 'load'
, function()
{ self.fluorine.IO.o.
__genAjaxSuccess(process)(request.response, request.statusText, request)
}
)
request.addEventListener
( 'error'
, function(event)
{ self.fluorine.IO.o.
__genAjaxError(url)(request, request.statusText, event)
}
)
request.send(formData)
}, this)
, 'IO:post')
return this
}
,postBinary: function(url)
{
this.__process.next
( _.bind(function(data)
{
var process = this.__process
var request = new XMLHttpRequest()
request.open('POST', url, true)
request.addEventListener
( 'load'
, function()
{ self.fluorine.IO.o.
__genAjaxSuccess(process)(request.response, request.statusText, request)
}
)
request.addEventListener
( 'error'
, function(event)
{ self.fluorine.IO.o.
__genAjaxError(url)(request, request.statusText, event)
}
)
request.send(data)
}, this)
, 'IO:postBinary')
return this
}
Put previous IO handling result to URL. Will automatically convert data as FormData. Key/Value paris will automatically transform to form data.
:: ( NotBinary r ) => IO r -> URL -> IO ()
,put: function(url)
{
this.__process.next
( _.bind(function(data)
{
var process = this.__process
var request = new XMLHttpRequest()
request.open('PUT', url, true)
var formData = new FormData()
if( _.isObject(data))
{
_.chain(data).keys(data).each(function(k){formData.append(k, data[k]) })
}
else
{
formData.append(data,"") // Like jQuery
}
request.addEventListener
( 'load'
, function()
{ self.fluorine.IO.o.
__genAjaxSuccess(process)(request.response, request.statusText, request)
}
)
request.addEventListener
( 'error'
, function(event)
{ self.fluorine.IO.o.
__genAjaxError(url)(request, request.statusText, event)
}
)
request.send(formData)
}, this)
, 'IO:put')
return this
}
,putBinary: function(url)
{
this.__process.next
( _.bind(function(data)
{
var process = this.__process
var request = new XMLHttpRequest()
request.open('PUT', url, true)
request.addEventListener
( 'load'
, function()
{ self.fluorine.IO.o.
__genAjaxSuccess(process)(request.response, request.statusText, request)
}
)
request.addEventListener
( 'error'
, function(event)
{ self.fluorine.IO.o.
__genAjaxError(url)(request, request.statusText, event)
}
)
request.send(data)
}, this)
, 'IO:put')
return this
}
,delete: function(url)
{
this.__process.next
( _.bind(function()
{
var process = this.__process
var request = new XMLHttpRequest()
request.open('DELETE', url, true)
request.addEventListener
( 'load'
, function()
{ self.fluorine.IO.o.
__genAjaxSuccess(process)(request.response, request.statusText, request)
}
)
request.addEventListener
( 'error'
, function(event)
{ self.fluorine.IO.o.
__genAjaxError(url)(request, request.statusText, event)
}
)
request.send()
}, this)
, 'IO:delete')
return this
}
Do your dirty works here to elimate the gap between ideal and reality.
:: IO a -> ( a -> IO b ) -> IO b
,unsafe: function(fn)
{
return self.fluorine.IO.o._(fn)
}
}
)
self.fluorine.registerInfect('IO', self.fluorine.IO)