main/view/lib/api.js

152 lines
4.0 KiB
JavaScript
Raw Permalink Normal View History

/* classe API */
function API(target){ this.target = target; }
API.prototype = {
xhr: [], // tableau d'objets pour les requêtes ajax
buffer: null, // Contiendra le buffer pour debugger si erreur de parsage
error: { // error constants
'-1': 'Invalid target format: "METHOD module/method"',
'-2': 'XHR error',
'-3': 'Invalid JSON response',
},
/* transaction avec le serveur (http://{host}/api/)
*
* @param pTarget<String> URI cible, format "HTTP_METHOD uri/uri/uri"
* @param pArgs<Object> Le tableu d'arguments passé en POST (attribut<->postfield) à http://{host}/api/
* @param pHandler<Function> Fonction qui s'éxécutera lors de la réponse (1 argument -> réponse<Object>)
* @param pToken<String> Optionnel, token d'auth pour l'api
*
***************************************************************************************************
*
* @usecase
* 1. api.call(
* 2. "PUT newspaper/article/4"
* 2. { content: "New article content" },
* 3. function(resp){
* 4. alert(resp.error);
* 5. }
* 6. );
*
*/
call: function(pTarget, pArgs, pHandler, pToken=null){
/* (1) Check @pHandler (for dispatching errors)
---------------------------------------------------------*/
/* (1) Check if is a Function */
if( !(pHandler instanceof Function) )
throw new Error("3rd argument must be a function, but is of type '"+typeof(pHandler)+"' !");
/* (2) Check @pTarget
---------------------------------------------------------*/
/* (1) Check format */
if( !/^([A-Z]+) (.+)/i.test(pTarget) ){
pHandler({ error: -1, ErrorDescription: this.error['-1'] });
return false;
}
/* (2) Store locally data */
var lHttpMethod = RegExp.$1;
var lUri = RegExp.$2;
/* (3) Create form data
---------------------------------------------------------*/
/* (1) Create virtual form */
var lForm = new FormData();
/* (2) Add attributes */
for( var key in pArgs ){
// {2.1} If a file -> send as it //
if( pArgs[key] instanceof File )
lForm.append(key, pArgs[key]);
// {2.2} Else -> JSON stringify //
else
lForm.append(key, JSON.stringify(pArgs[key]));
}
/* (4) Create XHR request
---------------------------------------------------------*/
/* (1) Clean ended requests */
for( var i = this.xhr.length-1 ; i >= 0 ; i-- ){
if( this.xhr[i] != null )
break;
this.xhr.pop();
}
/* (2) Push a new entry -> fetch its index */
i = this.xhr.push(null) - 1;
/* (3) Create XHR object */
this.xhr[i] = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHttpRequest');
/* (5) Bind response event
---------------------------------------------------------*/
var self = this; // to access the buffer
this.xhr[i].onreadystatechange = function(i){
/* (1) If request over */
if( this.xhr[i].readyState == 4 ){
/* (2) Update buffer (for debug) */
self.buffer = this.xhr[i].responseText;
/* (3) If request success */
if( [0, 200, 417].indexOf(this.xhr[i].status) > -1 ){
/* (3.1) Create default response (if JSON error) */
var response = {error:-3, ErrorDescription: self.error['-3']};
/* (3.2) Try to parse JSON */
try{ response = JSON.parse(this.xhr[i].responseText); }catch(e){}
/* (3.3) Launch @pHandler with response */
pHandler(response);
/* (4) If request error */
}else
pHandler({ error:-2, ErrorDescription: self.error['-2'] });
/* (5) Notify current xhr instance is done */
this.xhr[i] = null;
}
}.bind(this, i);
/* (6) Finish & send request
---------------------------------------------------------*/
/* (1) Open the XHR */
this.xhr[i].open(lHttpMethod, this.target+lUri, true);
/* (2) Manage optional token */
if( pToken != null )
this.xhr[i].setRequestHeader('Authorization', 'Digest '+pToken);
/* (3) Custom header to notify we're using Ajax */
this.xhr[i].setRequestHeader('X-Requested-With', 'XMLHttpRequest');
/* (4) Make the call */
this.xhr[i].send( lForm );
return true;
}
};