731 lines
23 KiB
JavaScript
731 lines
23 KiB
JavaScript
|
if(!dojo._hasResource["dojo._base.xhr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||
|
dojo._hasResource["dojo._base.xhr"] = true;
|
||
|
dojo.provide("dojo._base.xhr");
|
||
|
dojo.require("dojo._base.Deferred");
|
||
|
dojo.require("dojo._base.json");
|
||
|
dojo.require("dojo._base.lang");
|
||
|
dojo.require("dojo._base.query");
|
||
|
|
||
|
(function(){
|
||
|
var _d = dojo;
|
||
|
function setValue(/*Object*/obj, /*String*/name, /*String*/value){
|
||
|
//summary:
|
||
|
// For the nameed property in object, set the value. If a value
|
||
|
// already exists and it is a string, convert the value to be an
|
||
|
// array of values.
|
||
|
var val = obj[name];
|
||
|
if(_d.isString(val)){
|
||
|
obj[name] = [val, value];
|
||
|
}else if(_d.isArray(val)){
|
||
|
val.push(value);
|
||
|
}else{
|
||
|
obj[name] = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dojo.formToObject = function(/*DOMNode||String*/ formNode){
|
||
|
// summary:
|
||
|
// dojo.formToObject returns the values encoded in an HTML form as
|
||
|
// string properties in an object which it then returns. Disabled form
|
||
|
// elements, buttons, and other non-value form elements are skipped.
|
||
|
// Multi-select elements are returned as an array of string values.
|
||
|
// description:
|
||
|
// This form:
|
||
|
//
|
||
|
// | <form id="test_form">
|
||
|
// | <input type="text" name="blah" value="blah">
|
||
|
// | <input type="text" name="no_value" value="blah" disabled>
|
||
|
// | <input type="button" name="no_value2" value="blah">
|
||
|
// | <select type="select" multiple name="multi" size="5">
|
||
|
// | <option value="blah">blah</option>
|
||
|
// | <option value="thud" selected>thud</option>
|
||
|
// | <option value="thonk" selected>thonk</option>
|
||
|
// | </select>
|
||
|
// | </form>
|
||
|
//
|
||
|
// yields this object structure as the result of a call to
|
||
|
// formToObject():
|
||
|
//
|
||
|
// | {
|
||
|
// | blah: "blah",
|
||
|
// | multi: [
|
||
|
// | "thud",
|
||
|
// | "thonk"
|
||
|
// | ]
|
||
|
// | };
|
||
|
|
||
|
var ret = {};
|
||
|
var iq = "input:not([type=file]):not([type=submit]):not([type=image]):not([type=reset]):not([type=button]), select, textarea";
|
||
|
_d.query(iq, formNode).filter(function(node){
|
||
|
return !node.disabled && node.name;
|
||
|
}).forEach(function(item){
|
||
|
var _in = item.name;
|
||
|
var type = (item.type||"").toLowerCase();
|
||
|
if(type == "radio" || type == "checkbox"){
|
||
|
if(item.checked){ setValue(ret, _in, item.value); }
|
||
|
}else if(item.multiple){
|
||
|
ret[_in] = [];
|
||
|
_d.query("option", item).forEach(function(opt){
|
||
|
if(opt.selected){
|
||
|
setValue(ret, _in, opt.value);
|
||
|
}
|
||
|
});
|
||
|
}else{
|
||
|
setValue(ret, _in, item.value);
|
||
|
if(type == "image"){
|
||
|
ret[_in+".x"] = ret[_in+".y"] = ret[_in].x = ret[_in].y = 0;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
return ret; // Object
|
||
|
}
|
||
|
|
||
|
dojo.objectToQuery = function(/*Object*/ map){
|
||
|
// summary:
|
||
|
// takes a name/value mapping object and returns a string representing
|
||
|
// a URL-encoded version of that object.
|
||
|
// example:
|
||
|
// this object:
|
||
|
//
|
||
|
// | {
|
||
|
// | blah: "blah",
|
||
|
// | multi: [
|
||
|
// | "thud",
|
||
|
// | "thonk"
|
||
|
// | ]
|
||
|
// | };
|
||
|
//
|
||
|
// yields the following query string:
|
||
|
//
|
||
|
// | "blah=blah&multi=thud&multi=thonk"
|
||
|
|
||
|
// FIXME: need to implement encodeAscii!!
|
||
|
var enc = encodeURIComponent;
|
||
|
var pairs = [];
|
||
|
var backstop = {};
|
||
|
for(var name in map){
|
||
|
var value = map[name];
|
||
|
if(value != backstop[name]){
|
||
|
var assign = enc(name) + "=";
|
||
|
if(_d.isArray(value)){
|
||
|
for(var i=0; i < value.length; i++){
|
||
|
pairs.push(assign + enc(value[i]));
|
||
|
}
|
||
|
}else{
|
||
|
pairs.push(assign + enc(value));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return pairs.join("&"); // String
|
||
|
}
|
||
|
|
||
|
dojo.formToQuery = function(/*DOMNode||String*/ formNode){
|
||
|
// summary:
|
||
|
// Returns a URL-encoded string representing the form passed as either a
|
||
|
// node or string ID identifying the form to serialize
|
||
|
return _d.objectToQuery(_d.formToObject(formNode)); // String
|
||
|
}
|
||
|
|
||
|
dojo.formToJson = function(/*DOMNode||String*/ formNode, /*Boolean?*/prettyPrint){
|
||
|
// summary:
|
||
|
// return a serialized JSON string from a form node or string
|
||
|
// ID identifying the form to serialize
|
||
|
return _d.toJson(_d.formToObject(formNode), prettyPrint); // String
|
||
|
}
|
||
|
|
||
|
dojo.queryToObject = function(/*String*/ str){
|
||
|
// summary:
|
||
|
// returns an object representing a de-serialized query section of a
|
||
|
// URL. Query keys with multiple values are returned in an array.
|
||
|
// description:
|
||
|
// This string:
|
||
|
//
|
||
|
// | "foo=bar&foo=baz&thinger=%20spaces%20=blah&zonk=blarg&"
|
||
|
//
|
||
|
// results in this object structure:
|
||
|
//
|
||
|
// | {
|
||
|
// | foo: [ "bar", "baz" ],
|
||
|
// | thinger: " spaces =blah",
|
||
|
// | zonk: "blarg"
|
||
|
// | }
|
||
|
//
|
||
|
// Note that spaces and other urlencoded entities are correctly
|
||
|
// handled.
|
||
|
|
||
|
// FIXME: should we grab the URL string if we're not passed one?
|
||
|
var ret = {};
|
||
|
var qp = str.split("&");
|
||
|
var dec = decodeURIComponent;
|
||
|
_d.forEach(qp, function(item){
|
||
|
if(item.length){
|
||
|
var parts = item.split("=");
|
||
|
var name = dec(parts.shift());
|
||
|
var val = dec(parts.join("="));
|
||
|
if(_d.isString(ret[name])){
|
||
|
ret[name] = [ret[name]];
|
||
|
}
|
||
|
if(_d.isArray(ret[name])){
|
||
|
ret[name].push(val);
|
||
|
}else{
|
||
|
ret[name] = val;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
return ret; // Object
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
from refactor.txt:
|
||
|
|
||
|
all bind() replacement APIs take the following argument structure:
|
||
|
|
||
|
{
|
||
|
url: "blah.html",
|
||
|
|
||
|
// all below are optional, but must be supported in some form by
|
||
|
// every IO API
|
||
|
timeout: 1000, // milliseconds
|
||
|
handleAs: "text", // replaces the always-wrong "mimetype"
|
||
|
content: {
|
||
|
key: "value"
|
||
|
},
|
||
|
|
||
|
// browser-specific, MAY be unsupported
|
||
|
sync: true, // defaults to false
|
||
|
form: dojo.byId("someForm")
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
// need to block async callbacks from snatching this thread as the result
|
||
|
// of an async callback might call another sync XHR, this hangs khtml forever
|
||
|
// must checked by watchInFlight()
|
||
|
|
||
|
dojo._blockAsync = false;
|
||
|
|
||
|
dojo._contentHandlers = {
|
||
|
"text": function(xhr){ return xhr.responseText; },
|
||
|
"json": function(xhr){
|
||
|
if(!dojo.config.usePlainJson){
|
||
|
console.warn("Consider using mimetype:text/json-comment-filtered"
|
||
|
+ " to avoid potential security issues with JSON endpoints"
|
||
|
+ " (use djConfig.usePlainJson=true to turn off this message)");
|
||
|
}
|
||
|
return (xhr.status == 204) ? undefined : _d.fromJson(xhr.responseText);
|
||
|
},
|
||
|
"json-comment-filtered": function(xhr){
|
||
|
// NOTE: we provide the json-comment-filtered option as one solution to
|
||
|
// the "JavaScript Hijacking" issue noted by Fortify and others. It is
|
||
|
// not appropriate for all circumstances.
|
||
|
|
||
|
var value = xhr.responseText;
|
||
|
var cStartIdx = value.indexOf("\/*");
|
||
|
var cEndIdx = value.lastIndexOf("*\/");
|
||
|
if(cStartIdx == -1 || cEndIdx == -1){
|
||
|
throw new Error("JSON was not comment filtered");
|
||
|
}
|
||
|
return (xhr.status == 204) ? undefined :
|
||
|
_d.fromJson(value.substring(cStartIdx+2, cEndIdx));
|
||
|
},
|
||
|
"javascript": function(xhr){
|
||
|
// FIXME: try Moz and IE specific eval variants?
|
||
|
return _d.eval(xhr.responseText);
|
||
|
},
|
||
|
"xml": function(xhr){
|
||
|
var result = xhr.responseXML;
|
||
|
if(_d.isIE && (!result || window.location.protocol == "file:")){
|
||
|
_d.forEach(["MSXML2", "Microsoft", "MSXML", "MSXML3"], function(prefix){
|
||
|
try{
|
||
|
var dom = new ActiveXObject(prefix + ".XMLDOM");
|
||
|
dom.async = false;
|
||
|
dom.loadXML(xhr.responseText);
|
||
|
result = dom;
|
||
|
}catch(e){ /* Not available. Squelch and try next one. */ }
|
||
|
});
|
||
|
}
|
||
|
return result; // DOMDocument
|
||
|
}
|
||
|
};
|
||
|
|
||
|
dojo._contentHandlers["json-comment-optional"] = function(xhr){
|
||
|
var handlers = _d._contentHandlers;
|
||
|
try{
|
||
|
return handlers["json-comment-filtered"](xhr);
|
||
|
}catch(e){
|
||
|
return handlers["json"](xhr);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/*=====
|
||
|
dojo.__IoArgs = function(){
|
||
|
// url: String
|
||
|
// URL to server endpoint.
|
||
|
// content: Object?
|
||
|
// Contains properties with string values. These
|
||
|
// properties will be serialized as name1=value2 and
|
||
|
// passed in the request.
|
||
|
// timeout: Integer?
|
||
|
// Milliseconds to wait for the response. If this time
|
||
|
// passes, the then error callbacks are called.
|
||
|
// form: DOMNode?
|
||
|
// DOM node for a form. Used to extract the form values
|
||
|
// and send to the server.
|
||
|
// preventCache: Boolean?
|
||
|
// Default is false. If true, then a
|
||
|
// "dojo.preventCache" parameter is sent in the request
|
||
|
// with a value that changes with each request
|
||
|
// (timestamp). Useful only with GET-type requests.
|
||
|
// handleAs: String?
|
||
|
// Acceptable values depend on the type of IO
|
||
|
// transport (see specific IO calls for more information).
|
||
|
// load: Function?
|
||
|
// function(response, ioArgs){}. response is an Object, ioArgs
|
||
|
// is of type dojo.__IoCallbackArgs. The load function will be
|
||
|
// called on a successful response.
|
||
|
// error: Function?
|
||
|
// function(response, ioArgs){}. response is an Object, ioArgs
|
||
|
// is of type dojo.__IoCallbackArgs. The error function will
|
||
|
// be called in an error case.
|
||
|
// handle: Function?
|
||
|
// function(response, ioArgs){}. response is an Object, ioArgs
|
||
|
// is of type dojo.__IoCallbackArgs. The handle function will
|
||
|
// be called in either the successful or error case. For
|
||
|
// the load, error and handle functions, the ioArgs object
|
||
|
// will contain the following properties:
|
||
|
this.url = url;
|
||
|
this.content = content;
|
||
|
this.timeout = timeout;
|
||
|
this.form = form;
|
||
|
this.preventCache = preventCache;
|
||
|
this.handleAs = handleAs;
|
||
|
this.load = load;
|
||
|
this.error = error;
|
||
|
this.handle = handle;
|
||
|
}
|
||
|
=====*/
|
||
|
|
||
|
/*=====
|
||
|
dojo.__IoCallbackArgs = function(args, xhr, url, query, handleAs, id, canDelete, json){
|
||
|
// args: Object
|
||
|
// the original object argument to the IO call.
|
||
|
// xhr: XMLHttpRequest
|
||
|
// For XMLHttpRequest calls only, the
|
||
|
// XMLHttpRequest object that was used for the
|
||
|
// request.
|
||
|
// url: String
|
||
|
// The final URL used for the call. Many times it
|
||
|
// will be different than the original args.url
|
||
|
// value.
|
||
|
// query: String
|
||
|
// For non-GET requests, the
|
||
|
// name1=value1&name2=value2 parameters sent up in
|
||
|
// the request.
|
||
|
// handleAs: String
|
||
|
// The final indicator on how the response will be
|
||
|
// handled.
|
||
|
// id: String
|
||
|
// For dojo.io.script calls only, the internal
|
||
|
// script ID used for the request.
|
||
|
// canDelete: Boolean
|
||
|
// For dojo.io.script calls only, indicates
|
||
|
// whether the script tag that represents the
|
||
|
// request can be deleted after callbacks have
|
||
|
// been called. Used internally to know when
|
||
|
// cleanup can happen on JSONP-type requests.
|
||
|
// json: Object
|
||
|
// For dojo.io.script calls only: holds the JSON
|
||
|
// response for JSONP-type requests. Used
|
||
|
// internally to hold on to the JSON responses.
|
||
|
// You should not need to access it directly --
|
||
|
// the same object should be passed to the success
|
||
|
// callbacks directly.
|
||
|
this.args = args;
|
||
|
this.xhr = xhr;
|
||
|
this.url = url;
|
||
|
this.query = query;
|
||
|
this.handleAs = handleAs;
|
||
|
this.id = id;
|
||
|
this.canDelete = canDelete;
|
||
|
this.json = json;
|
||
|
}
|
||
|
=====*/
|
||
|
|
||
|
|
||
|
|
||
|
dojo._ioSetArgs = function(/*dojo.__IoArgs*/args,
|
||
|
/*Function*/canceller,
|
||
|
/*Function*/okHandler,
|
||
|
/*Function*/errHandler){
|
||
|
// summary:
|
||
|
// sets up the Deferred and ioArgs property on the Deferred so it
|
||
|
// can be used in an io call.
|
||
|
// args:
|
||
|
// The args object passed into the public io call. Recognized properties on
|
||
|
// the args object are:
|
||
|
// canceller:
|
||
|
// The canceller function used for the Deferred object. The function
|
||
|
// will receive one argument, the Deferred object that is related to the
|
||
|
// canceller.
|
||
|
// okHandler:
|
||
|
// The first OK callback to be registered with Deferred. It has the opportunity
|
||
|
// to transform the OK response. It will receive one argument -- the Deferred
|
||
|
// object returned from this function.
|
||
|
// errHandler:
|
||
|
// The first error callback to be registered with Deferred. It has the opportunity
|
||
|
// to do cleanup on an error. It will receive two arguments: error (the
|
||
|
// Error object) and dfd, the Deferred object returned from this function.
|
||
|
|
||
|
var ioArgs = {args: args, url: args.url};
|
||
|
|
||
|
//Get values from form if requestd.
|
||
|
var formObject = null;
|
||
|
if(args.form){
|
||
|
var form = _d.byId(args.form);
|
||
|
//IE requires going through getAttributeNode instead of just getAttribute in some form cases,
|
||
|
//so use it for all. See #2844
|
||
|
var actnNode = form.getAttributeNode("action");
|
||
|
ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null);
|
||
|
formObject = _d.formToObject(form);
|
||
|
}
|
||
|
|
||
|
// set up the query params
|
||
|
var miArgs = [{}];
|
||
|
|
||
|
if(formObject){
|
||
|
// potentially over-ride url-provided params w/ form values
|
||
|
miArgs.push(formObject);
|
||
|
}
|
||
|
if(args.content){
|
||
|
// stuff in content over-rides what's set by form
|
||
|
miArgs.push(args.content);
|
||
|
}
|
||
|
if(args.preventCache){
|
||
|
miArgs.push({"dojo.preventCache": new Date().valueOf()});
|
||
|
}
|
||
|
ioArgs.query = _d.objectToQuery(_d.mixin.apply(null, miArgs));
|
||
|
|
||
|
// .. and the real work of getting the deferred in order, etc.
|
||
|
ioArgs.handleAs = args.handleAs || "text";
|
||
|
var d = new _d.Deferred(canceller);
|
||
|
d.addCallbacks(okHandler, function(error){
|
||
|
return errHandler(error, d);
|
||
|
});
|
||
|
|
||
|
//Support specifying load, error and handle callback functions from the args.
|
||
|
//For those callbacks, the "this" object will be the args object.
|
||
|
//The callbacks will get the deferred result value as the
|
||
|
//first argument and the ioArgs object as the second argument.
|
||
|
var ld = args.load;
|
||
|
if(ld && _d.isFunction(ld)){
|
||
|
d.addCallback(function(value){
|
||
|
return ld.call(args, value, ioArgs);
|
||
|
});
|
||
|
}
|
||
|
var err = args.error;
|
||
|
if(err && _d.isFunction(err)){
|
||
|
d.addErrback(function(value){
|
||
|
return err.call(args, value, ioArgs);
|
||
|
});
|
||
|
}
|
||
|
var handle = args.handle;
|
||
|
if(handle && _d.isFunction(handle)){
|
||
|
d.addBoth(function(value){
|
||
|
return handle.call(args, value, ioArgs);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
d.ioArgs = ioArgs;
|
||
|
|
||
|
// FIXME: need to wire up the xhr object's abort method to something
|
||
|
// analagous in the Deferred
|
||
|
return d;
|
||
|
}
|
||
|
|
||
|
var _deferredCancel = function(/*Deferred*/dfd){
|
||
|
//summary: canceller function for dojo._ioSetArgs call.
|
||
|
|
||
|
dfd.canceled = true;
|
||
|
var xhr = dfd.ioArgs.xhr;
|
||
|
var _at = typeof xhr.abort;
|
||
|
if(_at == "function" || _at == "unknown"){
|
||
|
xhr.abort();
|
||
|
}
|
||
|
var err = new Error("xhr cancelled");
|
||
|
err.dojoType = "cancel";
|
||
|
return err;
|
||
|
}
|
||
|
var _deferredOk = function(/*Deferred*/dfd){
|
||
|
//summary: okHandler function for dojo._ioSetArgs call.
|
||
|
|
||
|
return _d._contentHandlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);
|
||
|
}
|
||
|
var _deferError = function(/*Error*/error, /*Deferred*/dfd){
|
||
|
//summary: errHandler function for dojo._ioSetArgs call.
|
||
|
|
||
|
// console.debug("xhr error in:", dfd.ioArgs.xhr);
|
||
|
console.debug(error);
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
var _makeXhrDeferred = function(/*dojo.__XhrArgs*/args){
|
||
|
//summary: makes the Deferred object for this xhr request.
|
||
|
var dfd = _d._ioSetArgs(args, _deferredCancel, _deferredOk, _deferError);
|
||
|
//Pass the args to _xhrObj, to allow xhr iframe proxy interceptions.
|
||
|
dfd.ioArgs.xhr = _d._xhrObj(dfd.ioArgs.args);
|
||
|
return dfd;
|
||
|
}
|
||
|
|
||
|
// avoid setting a timer per request. It degrades performance on IE
|
||
|
// something fierece if we don't use unified loops.
|
||
|
var _inFlightIntvl = null;
|
||
|
var _inFlight = [];
|
||
|
var _watchInFlight = function(){
|
||
|
//summary:
|
||
|
// internal method that checks each inflight XMLHttpRequest to see
|
||
|
// if it has completed or if the timeout situation applies.
|
||
|
|
||
|
var now = (new Date()).getTime();
|
||
|
// make sure sync calls stay thread safe, if this callback is called
|
||
|
// during a sync call and this results in another sync call before the
|
||
|
// first sync call ends the browser hangs
|
||
|
if(!_d._blockAsync){
|
||
|
// we need manual loop because we often modify _inFlight (and therefore 'i') while iterating
|
||
|
// note: the second clause is an assigment on purpose, lint may complain
|
||
|
for(var i = 0, tif; i < _inFlight.length && (tif = _inFlight[i]); i++){
|
||
|
var dfd = tif.dfd;
|
||
|
try{
|
||
|
if(!dfd || dfd.canceled || !tif.validCheck(dfd)){
|
||
|
_inFlight.splice(i--, 1);
|
||
|
}else if(tif.ioCheck(dfd)){
|
||
|
_inFlight.splice(i--, 1);
|
||
|
tif.resHandle(dfd);
|
||
|
}else if(dfd.startTime){
|
||
|
//did we timeout?
|
||
|
if(dfd.startTime + (dfd.ioArgs.args.timeout || 0) < now){
|
||
|
_inFlight.splice(i--, 1);
|
||
|
var err = new Error("timeout exceeded");
|
||
|
err.dojoType = "timeout";
|
||
|
dfd.errback(err);
|
||
|
//Cancel the request so the io module can do appropriate cleanup.
|
||
|
dfd.cancel();
|
||
|
}
|
||
|
}
|
||
|
}catch(e){
|
||
|
// FIXME: make sure we errback! (fixed? remove console.debug?)
|
||
|
console.debug(e);
|
||
|
dfd.errback(new Error("_watchInFlightError!"));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(!_inFlight.length){
|
||
|
clearInterval(_inFlightIntvl);
|
||
|
_inFlightIntvl = null;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
dojo._ioCancelAll = function(){
|
||
|
//summary: Cancels all pending IO requests, regardless of IO type
|
||
|
//(xhr, script, iframe).
|
||
|
try{
|
||
|
_d.forEach(_inFlight, function(i){
|
||
|
i.dfd.cancel();
|
||
|
});
|
||
|
}catch(e){/*squelch*/}
|
||
|
}
|
||
|
|
||
|
//Automatically call cancel all io calls on unload
|
||
|
//in IE for trac issue #2357.
|
||
|
if(_d.isIE){
|
||
|
_d.addOnUnload(_d._ioCancelAll);
|
||
|
}
|
||
|
|
||
|
_d._ioWatch = function(/*Deferred*/dfd,
|
||
|
/*Function*/validCheck,
|
||
|
/*Function*/ioCheck,
|
||
|
/*Function*/resHandle){
|
||
|
//summary: watches the io request represented by dfd to see if it completes.
|
||
|
//dfd:
|
||
|
// The Deferred object to watch.
|
||
|
//validCheck:
|
||
|
// Function used to check if the IO request is still valid. Gets the dfd
|
||
|
// object as its only argument.
|
||
|
//ioCheck:
|
||
|
// Function used to check if basic IO call worked. Gets the dfd
|
||
|
// object as its only argument.
|
||
|
//resHandle:
|
||
|
// Function used to process response. Gets the dfd
|
||
|
// object as its only argument.
|
||
|
if(dfd.ioArgs.args.timeout){
|
||
|
dfd.startTime = (new Date()).getTime();
|
||
|
}
|
||
|
_inFlight.push({dfd: dfd, validCheck: validCheck, ioCheck: ioCheck, resHandle: resHandle});
|
||
|
if(!_inFlightIntvl){
|
||
|
_inFlightIntvl = setInterval(_watchInFlight, 50);
|
||
|
}
|
||
|
_watchInFlight(); // handle sync requests
|
||
|
}
|
||
|
|
||
|
var _defaultContentType = "application/x-www-form-urlencoded";
|
||
|
|
||
|
var _validCheck = function(/*Deferred*/dfd){
|
||
|
return dfd.ioArgs.xhr.readyState; //boolean
|
||
|
}
|
||
|
var _ioCheck = function(/*Deferred*/dfd){
|
||
|
return 4 == dfd.ioArgs.xhr.readyState; //boolean
|
||
|
}
|
||
|
var _resHandle = function(/*Deferred*/dfd){
|
||
|
var xhr = dfd.ioArgs.xhr;
|
||
|
if(_d._isDocumentOk(xhr)){
|
||
|
dfd.callback(dfd);
|
||
|
}else{
|
||
|
var err = new Error("Unable to load " + dfd.ioArgs.url + " status:" + xhr.status);
|
||
|
err.status = xhr.status;
|
||
|
err.responseText = xhr.responseText;
|
||
|
dfd.errback(err);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var _doIt = function(/*String*/type, /*Deferred*/dfd){
|
||
|
// IE 6 is a steaming pile. It won't let you call apply() on the native function (xhr.open).
|
||
|
// workaround for IE6's apply() "issues"
|
||
|
var ioArgs = dfd.ioArgs;
|
||
|
var args = ioArgs.args;
|
||
|
var xhr = ioArgs.xhr;
|
||
|
xhr.open(type, ioArgs.url, args.sync !== true, args.user || undefined, args.password || undefined);
|
||
|
if(args.headers){
|
||
|
for(var hdr in args.headers){
|
||
|
if(hdr.toLowerCase() === "content-type" && !args.contentType){
|
||
|
args.contentType = args.headers[hdr];
|
||
|
}else{
|
||
|
xhr.setRequestHeader(hdr, args.headers[hdr]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// FIXME: is this appropriate for all content types?
|
||
|
xhr.setRequestHeader("Content-Type", args.contentType || _defaultContentType);
|
||
|
if(!args.headers || !args.headers["X-Requested-With"]){
|
||
|
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||
|
}
|
||
|
// FIXME: set other headers here!
|
||
|
try{
|
||
|
xhr.send(ioArgs.query);
|
||
|
}catch(e){
|
||
|
dfd.cancel();
|
||
|
}
|
||
|
_d._ioWatch(dfd, _validCheck, _ioCheck, _resHandle);
|
||
|
xhr = null;
|
||
|
return dfd; //Deferred
|
||
|
}
|
||
|
|
||
|
dojo._ioAddQueryToUrl = function(/*dojo.__IoCallbackArgs*/ioArgs){
|
||
|
//summary: Adds query params discovered by the io deferred construction to the URL.
|
||
|
//Only use this for operations which are fundamentally GET-type operations.
|
||
|
if(ioArgs.query.length){
|
||
|
ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query;
|
||
|
ioArgs.query = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*=====
|
||
|
dojo.declare("dojo.__XhrArgs", dojo.__IoArgs, {
|
||
|
constructor: function(){
|
||
|
// summary:
|
||
|
// In addition to the properties listed for the dojo._IoArgs type,
|
||
|
// the following properties are allowed for dojo.xhr* methods.
|
||
|
// handleAs: String?
|
||
|
// Acceptable values are: text (default), json, json-comment-optional,
|
||
|
// json-comment-filtered, javascript, xml
|
||
|
// sync: Boolean?
|
||
|
// false is default. Indicates whether the request should
|
||
|
// be a synchronous (blocking) request.
|
||
|
// headers: Object?
|
||
|
// Additional HTTP headers to send in the request.
|
||
|
this.handleAs = handleAs;
|
||
|
this.sync = sync;
|
||
|
this.headers = headers;
|
||
|
}
|
||
|
});
|
||
|
=====*/
|
||
|
|
||
|
dojo.xhr = function(/*String*/ method, /*dojo.__XhrArgs*/ args, /*Boolean?*/ hasBody){
|
||
|
// summary:
|
||
|
// Sends an HTTP request with the given method. If the request has an
|
||
|
// HTTP body, then pass true for hasBody. The method argument should be uppercase.
|
||
|
// Also look at dojo.xhrGet(), xhrPost(), xhrPut() and dojo.xhrDelete() for shortcuts
|
||
|
// for those HTTP methods. There are also methods for "raw" PUT and POST methods
|
||
|
// via dojo.rawXhrPut() and dojo.rawXhrPost() respectively.
|
||
|
var dfd = _makeXhrDeferred(args);
|
||
|
if(!hasBody){
|
||
|
_d._ioAddQueryToUrl(dfd.ioArgs);
|
||
|
}
|
||
|
return _doIt(method, dfd); // dojo.Deferred
|
||
|
}
|
||
|
|
||
|
dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){
|
||
|
// summary:
|
||
|
// Sends an HTTP GET request to the server.
|
||
|
return _d.xhr("GET", args); //dojo.Deferred
|
||
|
}
|
||
|
|
||
|
dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){
|
||
|
//summary:
|
||
|
// Sends an HTTP POST request to the server.
|
||
|
return _d.xhr("POST", args, true); // dojo.Deferred
|
||
|
}
|
||
|
|
||
|
dojo.rawXhrPost = function(/*dojo.__XhrArgs*/ args){
|
||
|
// summary:
|
||
|
// Sends an HTTP POST request to the server. In addtion to the properties
|
||
|
// listed for the dojo.__XhrArgs type, the following property is allowed:
|
||
|
// postData:
|
||
|
// String. The raw data to send in the body of the POST request.
|
||
|
var dfd = _makeXhrDeferred(args);
|
||
|
dfd.ioArgs.query = args.postData;
|
||
|
return _doIt("POST", dfd); // dojo.Deferred
|
||
|
}
|
||
|
|
||
|
dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){
|
||
|
// summary:
|
||
|
// Sends an HTTP PUT request to the server.
|
||
|
return _d.xhr("PUT", args, true); // dojo.Deferred
|
||
|
}
|
||
|
|
||
|
dojo.rawXhrPut = function(/*dojo.__XhrArgs*/ args){
|
||
|
// summary:
|
||
|
// Sends an HTTP PUT request to the server. In addtion to the properties
|
||
|
// listed for the dojo.__XhrArgs type, the following property is allowed:
|
||
|
// putData:
|
||
|
// String. The raw data to send in the body of the PUT request.
|
||
|
var dfd = _makeXhrDeferred(args);
|
||
|
var ioArgs = dfd.ioArgs;
|
||
|
if(args.putData){
|
||
|
ioArgs.query = args.putData;
|
||
|
args.putData = null;
|
||
|
}
|
||
|
return _doIt("PUT", dfd); // dojo.Deferred
|
||
|
}
|
||
|
|
||
|
dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){
|
||
|
// summary:
|
||
|
// Sends an HTTP DELETE request to the server.
|
||
|
return _d.xhr("DELETE", args); //dojo.Deferred
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
dojo.wrapForm = function(formNode){
|
||
|
//summary:
|
||
|
// A replacement for FormBind, but not implemented yet.
|
||
|
|
||
|
// FIXME: need to think harder about what extensions to this we might
|
||
|
// want. What should we allow folks to do w/ this? What events to
|
||
|
// set/send?
|
||
|
throw new Error("dojo.wrapForm not yet implemented");
|
||
|
}
|
||
|
*/
|
||
|
})();
|
||
|
|
||
|
}
|