1,6 → 1,6 |
/** |
* @require |
* types.js for #isMethod(), |
* @requires |
* object.js for jsx.object#isMethod(), |
* string.js for #esc(), #escURI() |
* |
* @idl |
24,19 → 24,19 |
* void HTTPRequest(string sURL); |
* // URL=sURL||document.URL, method="GET", async=true, responseHandler=null, |
* // errorHandler=null |
* |
* |
* void HTTPRequest(string sURL, string sMethod); |
* // URL=sURL||document.URL, method=sMethod||"GET", async=true, |
* // responseHandler=null, errorHandler=null |
* |
* |
* void HTTPRequest(string sURL, string sMethod, boolean bAsync); |
* // URL=sURL||document.URL, method=sMethod||"GET", async=bAsync, |
* // URL=sURL||document.URL, method=sMethod||"GET", async=bAsync, |
* |
* void HTTPRequest(string sURL, string sMethod, boolean bAsync, |
* HTTPResponseHandler fResponseHandler); |
* // URL=sURL||document.URL, method=sMethod||"GET", async=bAsync, |
* // responseHandler=fResponseHandler, errorHandler=null |
* |
* // responseHandler=fResponseHandler, errorHandler=null |
* |
* void HTTPRequest(string sURL, string sMethod, boolean bAsync, |
* HTTPResponseHandler fResponseHandler, |
* HTTPResponseHandler fErrorHandler); |
46,12 → 46,38 |
* boolean setRequestType(string sRequestType |
* default="application/x-www-form-urlencoded"); |
* // requestType=sRequestType |
* |
* |
* } |
* |
* @end |
*/ |
|
/** |
* Creates a new HTTPRequest object when called as constructor. |
* Set up response handlers per argument (see below), or |
* {@link HTTPRequest.prototype#setResponseHandler} and |
* {@link HTTPRequest.prototype#setErrorHandler}, then call |
* {@link HTTPRequest.prototype#send} method to send the request. |
* |
* @param sURL : optional string=document.URL |
* Request URL. The default is the URL of the sending resource. |
* @param sMethod : optional string=HTTPRequest.method.GET |
* Request method. Use the <code>HTTPRequest.method.GET</code> |
* (default) and <code>.POST</code> properties to avoid problems |
* caused by case mismatch, and other typos. |
* @param bAsync : optional boolean=true |
* Pass <code>true</code> to make an asynchronous request (default), |
* that is, a request that is processed in the background and does |
* not interrupt user operation. |
* @param fResponseHandler : optional HTTPResponseHandler=null |
* The function to handle the response of a successful request |
* (default: <code>null</code>). |
* @param fErrorHandler : optional HTTPResponseHandler=null |
* The function to handle the response of a request that failed |
* (default: <code>null</code>). |
* @constructor |
* @return undefined |
*/ |
function HTTPRequest(sURL, sMethod, bAsync, fResponseHandler, fErrorHandler) |
{ |
this.setURL(sURL); |
58,13 → 84,18 |
this.setMethod(sMethod); |
this.setAsync(bAsync); |
this.setResponseHandler(fResponseHandler); |
this.setErrorHandler(fErrorHandler); |
// this.setErrorHandler(fErrorHandler); |
this.setData(); |
this.setRequestType(); |
} |
|
HTTPRequest.addProperties({ |
jsx.object.addProperties( |
{ |
method: { |
/** |
* Use the predefined properties to avoid problems |
* caused by case mismatch and other typos. |
*/ |
GET: "GET", |
POST: "POST" |
}, |
74,11 → 105,11 |
LOADING: 1, |
LOADED: 2, |
INTERACTIVE: 3, |
COMPLETED: 4, |
COMPLETED: 4 |
}, |
|
|
status: { |
OK_EXPR: /\b[02]\d\d\b/, |
OK_EXPR: /\b(0|2\d\d)\b/, |
LOCAL_NONE: 0, |
|
CONTINUE: 100, |
129,7 → 160,8 |
GATEWAY_TIMEOUT: 504, |
HTTP_VER_NOT_SUPP: 505 |
} |
}); |
}, |
HTTPRequest); |
|
HTTPRequest.prototype = { |
constructor: HTTPRequest, |
137,17 → 169,16 |
/** |
* Sets the <code>URL</code> property. |
* |
* @argument sURL: string |
* @param sURL : string |
* If not provided or a false-value, the |
* URL of the sending recource is set. |
* @argument bDontEncode: optional boolean |
* @param bDontEncode : optional boolean |
* If <code>true</code>, do not encode the request URL |
* (with <code>escURI()</code> or <code>escape()</code>). |
*/ |
setURL: function(sURL, bDontEncode) |
{ |
if (!bDontEncode) sURL = escURI(sURL); |
this.URL = (sURL || document.URL); |
setURL: function(sURL, bDontEncode) { |
if (!bDontEncode && sURL) sURL = esc(sURL); |
this.URL = (sURL || document.URL); |
}, |
|
/** |
155,13 → 186,12 |
* <code>HTTPRequest.(GET|POST)</code> properties |
* to avoid problems with character case and typos. |
* |
* @argument : optional string |
* @param sMethod : optional string |
* If not provided or a false-value, the value |
* of <code>HTTPRequest.GET</code> is used. |
*/ |
setMethod: function(sMethod) |
{ |
this.method = |
setMethod: function(sMethod) { |
this.method = |
sMethod |
? String(sMethod).toUpperCase() |
: this.constructor.method.GET; |
173,31 → 203,40 |
* response to be fully received in the background, this is the default |
* and recommended). |
* |
* @argument : optional boolean |
* @param bAsync : optional boolean |
* If not provided or a true-value, the request will be asynchronous. |
*/ |
setAsync: function(bAsync) |
{ |
setAsync: function(bAsync) { |
this.async = (typeof bAsync != "undefined" ? !!bAsync : true); |
}, |
|
/** |
* Defines the response handler method to be used for handling |
* successful requests. |
* successful requests. A HTTPRequest object is always initialized |
* with a dummy response handler that does nothing, if you do not |
* specify one. Once initialized, passing a reference to a non-callable |
* object as argument, throws an InvalidArgumentException. |
* |
* @argument : HTTPResponseHandler |
* @param fResponseHandler : HTTPResponseHandler |
* @throws InvalidArgumentException |
*/ |
setResponseHandler: function(fResponseHandler) |
{ |
if (isMethod(fResponseHandler)) |
setResponseHandler: function(fResponseHandler) { |
// initialization |
if (typeof this.responseHandler == "undefined") |
{ |
this.responseHandler = new HTTPResponseHandler(); |
return true; |
} |
else if (jsx.object.isMethod(fResponseHandler)) |
{ |
this.responseHandler = fResponseHandler; |
return (this.responseHandler == this.responseHandler); |
return (this.responseHandler == fResponseHandler); |
} |
else |
{ |
_global.setErrorHandler(); |
eval('throw new Error("Argument is not a method");'); |
eval('throw new Error(' |
+ '"jsx:HTTPRequest::setResponseHandler: Argument is not a method");'); |
_global.clearErrorHandler(); |
return false; |
} |
205,14 → 244,18 |
|
/** |
* Defines the response handler method to be used for handling |
* successful requests. |
* unsuccessful requests. |
* |
* @argument : HTTPResponseHandler |
* @param : HTTPResponseHandler |
*/ |
setErrorHandler: function(fErrorHandler) |
{ |
if (isMethod(fErrorHandler)) |
/* |
setErrorHandler: function(fErrorHandler) { |
if (typeof this.errorHandler == "undefined") |
{ |
this.errorHandler = new HTTPResponseHandler(); |
} |
else if (jsx.object.isMethod(fErrorHandler)) |
{ |
this.errorHandler = fErrorHandler; |
return (this.errorHandler == this.errorHandler); |
} |
219,30 → 262,29 |
else |
{ |
_global.setErrorHandler(); |
eval('throw new Error("Argument is not a method");'); |
eval('throw new Error(' |
+ '"jsx:HTTPRequest::setErrorHandler: Argument is not a method");'); |
_global.clearErrorHandler(); |
return false; |
} |
}, |
|
*/ |
/** |
* Sets the <code>data</code> property. |
* |
* @argument : optional string |
* @param sData : optional string |
* If not provided or a false-value, sets |
* the property to the empty string. |
* @see HTTPRequest#resetData() |
* @see HTTPRequest.prototype#resetData() |
*/ |
setData: function(sData) |
{ |
setData: function(sData) { |
this.data = (sData || ""); |
}, |
|
|
|
/** |
* Resets the <code>data</code> property to the empty string. |
* |
* @see HTTPRequest#setData() |
* @see HTTPRequest.prototype#setData() |
*/ |
resetData: function() |
{ |
253,12 → 295,12 |
* Retrieves the data to send in the request, and optionally the request |
* method, from an (X)HTML form. TODO: select[multiple] elements |
* |
* @argument f: HTMLFormElement |
* @argument : optional boolean |
* @param f : HTMLFormElement |
* @param bUseFormMethod: optional boolean |
* If <code>true</code>, the form's request method becomes the |
* <code>HTTPRequest</code> object's request method. The default |
* is <code>false</code>. |
* @type boolean |
* @return boolean |
*/ |
getDataFromForm: function(f, bUseFormMethod) |
{ |
274,7 → 316,7 |
{ |
var o = es[i]; |
if (o.name) |
{ |
{ |
aData.push(esc(o.name) + "=" + esc(o.value != "" ? o.value : "")); |
} |
} |
292,63 → 334,86 |
* which is what Web browsers, although this media type is currently |
* (June 2006 CE) not registered with IANA, send as default then. |
* |
* @param string sRequestType |
* @param sRequestType : string |
* <code>"application/x-www-form-urlencoded"</code>, if omitted or |
* a false-value (like "", the empty string) |
* a false-value (like "", the empty string). |
*/ |
setRequestType: function(sRequestType) |
{ |
setRequestType: function(sRequestType) { |
this.requestType = sRequestType || "application/x-www-form-urlencoded"; |
}, |
|
send: function( |
/** @type string */ sData, |
/** @type string */ sURL, |
/** @type string */ sMethod, |
/** @type boolean */ bAsync) |
{ |
var result = false, x = null; |
/** |
* @param sData : optional string |
* The data to form the request body. If the request method is "GET", |
* this argument is ignored and <code>null</code> is used instead (no body). |
* If the request method is "POST", and this value is not provided, the |
* value defaults to that of the <code>data</code> property, which is |
* the empty string if not set different previously. |
* @param sURL : optional string |
* The request URL. If not provided, this value defaults to that of the |
* <code>URL</code> property, which is the empty string if not set |
* different previously. |
* @param sMethod : optional string |
* The request method. If not provided, this value defaults to that of |
* the <code>HTTPRequest.method.GET</code> property, which is "GET". |
* @param bAsync : optional boolean |
* The request is asynchronous if <code>true</code> is passed, synchronous |
* if <code>false</code> is passed. If not provided, this value defaults |
* to that of the <code>async</code> property, which is <code>true</code> |
* if not set different previously. |
*/ |
send: function(sData, sURL, sMethod, bAsync) { |
var |
result = false, |
jsx_object = jsx.object, |
x = null; |
|
// Gecko, IE 7, and Opera 8.1 |
if (isMethod(_global.XMLHttpRequest)) |
/* |
* Feature detection based on Jim Ley's XML HTTP Request tutorial |
* at <http://jibbering.com/2002/4/httprequest.html> |
*/ |
|
/* |
* IE 6+ (JScript allows for conditional compilation; an ordinary comment |
* to other script engines). Note that IE 7 supports XMLHttpRequest() but |
* currently not for `file:' URIs, so we don't prefer that wrapper (see |
* <http://xhab.blogspot.com/2006/11/ie7-support-for-xmlhttprequest.html>). |
*/ |
if (jsx_object.isMethod(jsx.global, "ActiveXObject")) |
{ |
// eval() is needed here so that this compiles in ECMAScript < 3 |
// (e.g. IE 4, NS 4) |
eval('try { x = new XMLHttpRequest(); } catch (e) { x = null; }'); |
} |
|
// IE 6 (JScript allows for conditional compilation; |
// a ordinary comment to other script engines) |
if (!x && isMethod(_global.ActiveXObject)) |
{ |
/*@cc_on @*/ |
/*@if (@_jscript_version >= 5) |
try |
{ |
x = new ActiveXObject("Msxml2.XMLHTTP"); |
// MSXML 3.0- |
x = new ActiveXObject("Microsoft.XMLHTTP"); |
} |
catch (e) |
{ |
try |
{ |
x = new ActiveXObject("Microsoft.XMLHTTP"); |
} |
catch (e2) |
{ |
x = null; |
} |
x = null; |
} |
@end @*/ |
} |
|
// IceBrowser |
if (!x && isMethod(window.createRequest)) |
/* Gecko and Opera 8.1+ */ |
if (!x && jsx_object.isMethod(jsx.global, "XMLHttpRequest")) |
{ |
// see above |
/* |
* eval() is needed here so that this compiles in ECMAScript < 3 |
* (e.g. IE 4, NS 4) |
*/ |
eval('try { x = new XMLHttpRequest(); } catch (e) { x = null; }'); |
} |
|
/* IceBrowser */ |
if (!x && typeof window != "undefined" |
&& jsx_object.isMethod(window, "createRequest")) |
{ |
/* see above */ |
eval('try { x = window.createRequest(); } catch (e) { x = null; }'); |
} |
|
if (x && isMethod(x.open)) |
|
if (x) // && jsx_object.isMethod(x.open) |
{ |
if (arguments.length < 2) sURL = this.URL; |
|
358,7 → 423,7 |
bAsync = (arguments.length > 3) ? !!bAsync : this.async; |
|
x.open( |
sMethod, |
sMethod.toUpperCase(), |
sURL |
+ ((bGET && sData) |
? (!/[?&]$/.test(sURL) |
368,46 → 433,61 |
: ""), |
bAsync); |
|
if (isMethod(x.setRequestHeader)) |
{ |
// if (jsx_object.isMethod(x.setRequestHeader)) |
// { |
// see above |
eval('try { x.setRequestHeader("Content-Type", this.requestType); }', |
eval('try { x.setRequestHeader("Content-Type", this.requestType); }' |
+ 'catch (e) {}'); |
} |
// } |
|
if (bAsync) |
{ |
var me = this; |
x.onreadystatechange = function() |
{ |
if (this.constructor.status.OK_EXPR.test(x.status) |
&& isMethod(this.responseHandler)) |
{ |
this.responseHandler(x); |
} |
else if (isMethod(this.errorHandler)) |
{ |
this.errorHandler(x); |
} |
|
if (x.readyState == this.constructor.readyState.COMPLETED) x = null; |
} |
// alert(x.readyState); |
// alert(x.status); |
|
// console.log("readyState = %i, status = %i", x.readyState, x.status); |
// console.log(me.constructor.status.OK_EXPR); |
|
// if (x.readyState > HTTPRequest.readyState.LOADED |
// && me.constructor.status.OK_EXPR.test(x.status)) |
// { |
me.responseHandler(x); |
// } |
// else |
// { |
// me.errorHandler(x); |
// } |
|
if (x.readyState == me.constructor.readyState.COMPLETED) |
{ |
x = null; |
} |
}; |
} |
|
x.send(bGET ? null : (sData || this.data)); |
|
eval('try { x.send(bGET ? null : (sData || this.data)); }' |
+ 'catch (e) { /*this.errorHandler();*/ }'); |
|
if (!bAsync) |
{ |
if (this.constructor.status.OK_EXPR.test(x.status) |
&& isMethod(this.responseHandler)) |
{ |
this.responseHandler(x); |
result = true; |
} |
else if (this.constructor.status.FAILED_EXPR.test(x.status) |
&& isMethod(this.errorHandler)) |
{ |
this.errorHandler(x); |
} |
// if (this.constructor.status.OK_EXPR.test(x.status) |
// && jsx_object.isMethod(this.responseHandler)) |
// { |
this.responseHandler(x); |
|
// Handle stopped servers |
eval('try { if (this.constructor.status.OK_EXPR.test(x.status)) {' |
+ 'result = true;' |
+ '} } catch {}'); |
// } |
// else if (this.constructor.status.FAILED_EXPR.test(x.status) |
// && jsx_object.isMethod(this.errorHandler)) |
// { |
// this.errorHandler(x); |
// } |
|
x = null; |
} |
424,7 → 504,7 |
* |
* Recommended usage: |
* <pre><code> |
* var f = new HTTPResponseHandler( |
* var f = HTTPResponseHandler( |
* new Array( |
* 'statement;', |
* 'statement;' |
431,17 → 511,23 |
* ).join("")); |
* </code></pre> |
* |
* @param sCode |
* @return Function |
* A new <code>HTTPResponseHandler</code> object |
*/ |
function HTTPResponseHandler(sCode) |
{ |
return Function("x", sCode); |
return Function("x", sCode || ""); |
} |
|
/** |
* @param x |
*/ |
function processResponse(x) |
{ |
// ... |
/* ... */ |
} |
|
// var x = new HTTPRequest("", HTTPRequest.GET, processResponse); |
// ... |
/* ... */ |
// x.send(); |