1 define("dojo/_base/xhr", [
2 "./kernel", "./sniff", "require", "../io-query", "../dom", "../dom-form", "./Deferred", "./json", "./lang", "./array", "../on"
3 ], function(dojo, has, require, ioq, dom, domForm, deferred, json, lang, array, on){
7 // This modules defines the dojo.xhr* API.
9 has.add("native-xhr", function() {
10 // if true, the environment has a native XHR implementation
11 return typeof XMLHttpRequest !== 'undefined';
14 if(1 && require.getXhr){
15 dojo._xhrObj = require.getXhr;
16 }else if (has("native-xhr")){
17 dojo._xhrObj = function(){
19 // does the work of portably generating a new XMLHTTPRequest object.
21 return new XMLHttpRequest();
23 throw new Error("XMLHTTP not available: "+e);
27 // PROGIDs are in order of decreasing likelihood; this will change in time.
28 for(var XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], progid, i = 0; i < 3;){
30 progid = XMLHTTP_PROGIDS[i++];
31 if (new ActiveXObject(progid)) {
32 // this progid works; therefore, use it from now on
36 // squelch; we're just trying to find a good ActiveX PROGID
37 // if they all fail, then progid ends up as the last attempt and that will signal the error
38 // the first time the client actually tries to exec an xhr
41 dojo._xhrObj= function() {
42 return new ActiveXObject(progid);
46 var cfg = dojo.config;
48 // mix in io-query and dom-form
49 dojo.objectToQuery = ioq.objectToQuery;
50 dojo.queryToObject = ioq.queryToObject;
51 dojo.fieldToObject = domForm.fieldToObject;
52 dojo.formToObject = domForm.toObject;
53 dojo.formToQuery = domForm.toQuery;
54 dojo.formToJson = domForm.toJson;
56 // need to block async callbacks from snatching this thread as the result
57 // of an async callback might call another sync XHR, this hangs khtml forever
58 // must checked by watchInFlight()
60 dojo._blockAsync = false;
62 // MOW: remove dojo._contentHandlers alias in 2.0
63 var handlers = dojo._contentHandlers = dojo.contentHandlers = {
65 // A map of availble XHR transport handle types. Name matches the
66 // `handleAs` attribute passed to XHR calls.
69 // A map of availble XHR transport handle types. Name matches the
70 // `handleAs` attribute passed to XHR calls. Each contentHandler is
71 // called, passing the xhr object for manipulation. The return value
72 // from the contentHandler will be passed to the `load` or `handle`
73 // functions defined in the original xhr call.
76 // Creating a custom content-handler:
77 // | dojo.contentHandlers.makeCaps = function(xhr){
78 // | return xhr.responseText.toUpperCase();
83 // | handleAs:"makeCaps",
84 // | load: function(data){ /* data is a toUpper version of foo.txt */ }
87 "text": function(xhr){
88 // summary: A contentHandler which simply returns the plaintext response data
89 return xhr.responseText;
91 "json": function(xhr){
92 // summary: A contentHandler which returns a JavaScript object created from the response data
93 return json.fromJson(xhr.responseText || null);
95 "json-comment-filtered": function(xhr){
96 // summary: A contentHandler which expects comment-filtered JSON.
98 // A contentHandler which expects comment-filtered JSON.
99 // the json-comment-filtered option was implemented to prevent
100 // "JavaScript Hijacking", but it is less secure than standard JSON. Use
101 // standard JSON instead. JSON prefixing can be used to subvert hijacking.
103 // Will throw a notice suggesting to use application/json mimetype, as
104 // json-commenting can introduce security issues. To decrease the chances of hijacking,
105 // use the standard `json` contentHandler, and prefix your "JSON" with: {}&&
107 // use djConfig.useCommentedJson = true to turn off the notice
108 if(!dojo.config.useCommentedJson){
109 console.warn("Consider using the standard mimetype:application/json."
110 + " json-commenting can introduce security issues. To"
111 + " decrease the chances of hijacking, use the standard the 'json' handler and"
112 + " prefix your json with: {}&&\n"
113 + "Use djConfig.useCommentedJson=true to turn off this message.");
116 var value = xhr.responseText;
117 var cStartIdx = value.indexOf("\/*");
118 var cEndIdx = value.lastIndexOf("*\/");
119 if(cStartIdx == -1 || cEndIdx == -1){
120 throw new Error("JSON was not comment filtered");
122 return json.fromJson(value.substring(cStartIdx+2, cEndIdx));
124 "javascript": function(xhr){
125 // summary: A contentHandler which evaluates the response data, expecting it to be valid JavaScript
127 // FIXME: try Moz and IE specific eval variants?
128 return dojo.eval(xhr.responseText);
130 "xml": function(xhr){
131 // summary: A contentHandler returning an XML Document parsed from the response data
132 var result = xhr.responseXML;
135 if((!result || !result.documentElement)){
136 //WARNING: this branch used by the xml handling in dojo.io.iframe,
137 //so be sure to test dojo.io.iframe if making changes below.
138 var ms = function(n){ return "MSXML" + n + ".DOMDocument"; };
139 var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)];
140 array.some(dp, function(p){
142 var dom = new ActiveXObject(p);
144 dom.loadXML(xhr.responseText);
146 }catch(e){ return false; }
151 return result; // DOMDocument
153 "json-comment-optional": function(xhr){
154 // summary: A contentHandler which checks the presence of comment-filtered JSON and
155 // alternates between the `json` and `json-comment-filtered` contentHandlers.
156 if(xhr.responseText && /^[^{\[]*\/\*/.test(xhr.responseText)){
157 return handlers["json-comment-filtered"](xhr);
159 return handlers["json"](xhr);
165 dojo.__IoArgs = function(){
167 // URL to server endpoint.
169 // Contains properties with string values. These
170 // properties will be serialized as name1=value2 and
171 // passed in the request.
173 // Milliseconds to wait for the response. If this time
174 // passes, the then error callbacks are called.
176 // DOM node for a form. Used to extract the form values
177 // and send to the server.
178 // preventCache: Boolean?
179 // Default is false. If true, then a
180 // "dojo.preventCache" parameter is sent in the request
181 // with a value that changes with each request
182 // (timestamp). Useful only with GET-type requests.
184 // Acceptable values depend on the type of IO
185 // transport (see specific IO calls for more information).
187 // Sets the raw body for an HTTP request. If this is used, then the content
188 // property is ignored. This is mostly useful for HTTP methods that have
189 // a body to their requests, like PUT or POST. This property can be used instead
190 // of postData and putData for dojo.rawXhrPost and dojo.rawXhrPut respectively.
191 // ioPublish: Boolean?
192 // Set this explicitly to false to prevent publishing of topics related to
193 // IO operations. Otherwise, if djConfig.ioPublish is set to true, topics
194 // will be published via dojo.publish for different phases of an IO operation.
195 // See dojo.__IoPublish for a list of topics that are published.
197 // This function will be
198 // called on a successful HTTP response code.
200 // This function will
201 // be called when the request fails due to a network or server error, the url
202 // is invalid, etc. It will also be called if the load or handle callback throws an
203 // exception, unless djConfig.debugAtAllCosts is true. This allows deployed applications
204 // to continue to run even when a logic error happens in the callback, while making
205 // it easier to troubleshoot while in debug mode.
207 // This function will
208 // be called at the end of every request, whether or not an error occurs.
210 this.content = content;
211 this.timeout = timeout;
213 this.preventCache = preventCache;
214 this.handleAs = handleAs;
215 this.ioPublish = ioPublish;
216 this.load = function(response, ioArgs){
217 // ioArgs: dojo.__IoCallbackArgs
218 // Provides additional information about the request.
220 // The response in the format as defined with handleAs.
222 this.error = function(response, ioArgs){
223 // ioArgs: dojo.__IoCallbackArgs
224 // Provides additional information about the request.
226 // The response in the format as defined with handleAs.
228 this.handle = function(loadOrError, response, ioArgs){
229 // loadOrError: String
230 // Provides a string that tells you whether this function
231 // was called because of success (load) or failure (error).
233 // The response in the format as defined with handleAs.
234 // ioArgs: dojo.__IoCallbackArgs
235 // Provides additional information about the request.
241 dojo.__IoCallbackArgs = function(args, xhr, url, query, handleAs, id, canDelete, json){
243 // the original object argument to the IO call.
244 // xhr: XMLHttpRequest
245 // For XMLHttpRequest calls only, the
246 // XMLHttpRequest object that was used for the
249 // The final URL used for the call. Many times it
250 // will be different than the original args.url
253 // For non-GET requests, the
254 // name1=value1&name2=value2 parameters sent up in
257 // The final indicator on how the response will be
260 // For dojo.io.script calls only, the internal
261 // script ID used for the request.
262 // canDelete: Boolean
263 // For dojo.io.script calls only, indicates
264 // whether the script tag that represents the
265 // request can be deleted after callbacks have
266 // been called. Used internally to know when
267 // cleanup can happen on JSONP-type requests.
269 // For dojo.io.script calls only: holds the JSON
270 // response for JSONP-type requests. Used
271 // internally to hold on to the JSON responses.
272 // You should not need to access it directly --
273 // the same object should be passed to the success
274 // callbacks directly.
279 this.handleAs = handleAs;
281 this.canDelete = canDelete;
288 dojo.__IoPublish = function(){
290 // This is a list of IO topics that can be published
291 // if djConfig.ioPublish is set to true. IO topics can be
292 // published for any Input/Output, network operation. So,
293 // dojo.xhr, dojo.io.script and dojo.io.iframe can all
294 // trigger these topics to be published.
296 // "/dojo/io/start" is sent when there are no outstanding IO
297 // requests, and a new IO request is started. No arguments
298 // are passed with this topic.
300 // "/dojo/io/send" is sent whenever a new IO request is started.
301 // It passes the dojo.Deferred for the request with the topic.
303 // "/dojo/io/load" is sent whenever an IO request has loaded
304 // successfully. It passes the response and the dojo.Deferred
305 // for the request with the topic.
307 // "/dojo/io/error" is sent whenever an IO request has errored.
308 // It passes the error and the dojo.Deferred
309 // for the request with the topic.
311 // "/dojo/io/done" is sent whenever an IO request has completed,
312 // either by loading or by erroring. It passes the error and
313 // the dojo.Deferred for the request with the topic.
315 // "/dojo/io/stop" is sent when all outstanding IO requests have
316 // finished. No arguments are passed with this topic.
317 this.start = "/dojo/io/start";
318 this.send = "/dojo/io/send";
319 this.load = "/dojo/io/load";
320 this.error = "/dojo/io/error";
321 this.done = "/dojo/io/done";
322 this.stop = "/dojo/io/stop";
327 dojo._ioSetArgs = function(/*dojo.__IoArgs*/args,
328 /*Function*/canceller,
329 /*Function*/okHandler,
330 /*Function*/errHandler){
332 // sets up the Deferred and ioArgs property on the Deferred so it
333 // can be used in an io call.
335 // The args object passed into the public io call. Recognized properties on
336 // the args object are:
338 // The canceller function used for the Deferred object. The function
339 // will receive one argument, the Deferred object that is related to the
342 // The first OK callback to be registered with Deferred. It has the opportunity
343 // to transform the OK response. It will receive one argument -- the Deferred
344 // object returned from this function.
346 // The first error callback to be registered with Deferred. It has the opportunity
347 // to do cleanup on an error. It will receive two arguments: error (the
348 // Error object) and dfd, the Deferred object returned from this function.
350 var ioArgs = {args: args, url: args.url};
352 //Get values from form if requestd.
353 var formObject = null;
355 var form = dom.byId(args.form);
356 //IE requires going through getAttributeNode instead of just getAttribute in some form cases,
357 //so use it for all. See #2844
358 var actnNode = form.getAttributeNode("action");
359 ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null);
360 formObject = domForm.toObject(form);
363 // set up the query params
367 // potentially over-ride url-provided params w/ form values
368 miArgs.push(formObject);
371 // stuff in content over-rides what's set by form
372 miArgs.push(args.content);
374 if(args.preventCache){
375 miArgs.push({"dojo.preventCache": new Date().valueOf()});
377 ioArgs.query = ioq.objectToQuery(lang.mixin.apply(null, miArgs));
379 // .. and the real work of getting the deferred in order, etc.
380 ioArgs.handleAs = args.handleAs || "text";
381 var d = new deferred(canceller);
382 d.addCallbacks(okHandler, function(error){
383 return errHandler(error, d);
386 //Support specifying load, error and handle callback functions from the args.
387 //For those callbacks, the "this" object will be the args object.
388 //The callbacks will get the deferred result value as the
389 //first argument and the ioArgs object as the second argument.
391 if(ld && lang.isFunction(ld)){
392 d.addCallback(function(value){
393 return ld.call(args, value, ioArgs);
396 var err = args.error;
397 if(err && lang.isFunction(err)){
398 d.addErrback(function(value){
399 return err.call(args, value, ioArgs);
402 var handle = args.handle;
403 if(handle && lang.isFunction(handle)){
404 d.addBoth(function(value){
405 return handle.call(args, value, ioArgs);
409 //Plug in topic publishing, if dojo.publish is loaded.
410 if(cfg.ioPublish && dojo.publish && ioArgs.args.ioPublish !== false){
413 dojo.publish("/dojo/io/load", [d, res]);
417 dojo.publish("/dojo/io/error", [d, res]);
421 d.addBoth(function(res){
422 dojo.publish("/dojo/io/done", [d, res]);
429 // FIXME: need to wire up the xhr object's abort method to something
430 // analagous in the Deferred
434 var _deferredCancel = function(/*Deferred*/dfd){
435 // summary: canceller function for dojo._ioSetArgs call.
438 var xhr = dfd.ioArgs.xhr;
439 var _at = typeof xhr.abort;
440 if(_at == "function" || _at == "object" || _at == "unknown"){
443 var err = dfd.ioArgs.error;
445 err = new Error("xhr cancelled");
446 err.dojoType="cancel";
450 var _deferredOk = function(/*Deferred*/dfd){
451 // summary: okHandler function for dojo._ioSetArgs call.
453 var ret = handlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);
454 return ret === undefined ? null : ret;
456 var _deferError = function(/*Error*/error, /*Deferred*/dfd){
457 // summary: errHandler function for dojo._ioSetArgs call.
459 if(!dfd.ioArgs.args.failOk){
460 console.error(error);
465 // avoid setting a timer per request. It degrades performance on IE
466 // something fierece if we don't use unified loops.
467 var _inFlightIntvl = null;
471 //Use a separate count for knowing if we are starting/stopping io calls.
472 //Cannot use _inFlight.length since it can change at a different time than
473 //when we want to do this kind of test. We only want to decrement the count
474 //after a callback/errback has finished, since the callback/errback should be
475 //considered as part of finishing a request.
477 var _checkPubCount = function(dfd){
480 if(cfg.ioPublish && dojo.publish && (!dfd || dfd && dfd.ioArgs.args.ioPublish !== false)){
481 dojo.publish("/dojo/io/stop");
486 var _watchInFlight = function(){
488 // internal method that checks each inflight XMLHttpRequest to see
489 // if it has completed or if the timeout situation applies.
491 var now = (new Date()).getTime();
492 // make sure sync calls stay thread safe, if this callback is called
493 // during a sync call and this results in another sync call before the
494 // first sync call ends the browser hangs
495 if(!dojo._blockAsync){
496 // we need manual loop because we often modify _inFlight (and therefore 'i') while iterating
497 // note: the second clause is an assigment on purpose, lint may complain
498 for(var i = 0, tif; i < _inFlight.length && (tif = _inFlight[i]); i++){
500 var func = function(){
501 if(!dfd || dfd.canceled || !tif.validCheck(dfd)){
502 _inFlight.splice(i--, 1);
504 }else if(tif.ioCheck(dfd)){
505 _inFlight.splice(i--, 1);
508 }else if(dfd.startTime){
510 if(dfd.startTime + (dfd.ioArgs.args.timeout || 0) < now){
511 _inFlight.splice(i--, 1);
512 var err = new Error("timeout exceeded");
513 err.dojoType = "timeout";
515 //Cancel the request so the io module can do appropriate cleanup.
521 if(dojo.config.debugAtAllCosts){
535 if(!_inFlight.length){
536 clearInterval(_inFlightIntvl);
537 _inFlightIntvl = null;
541 dojo._ioCancelAll = function(){
542 //summary: Cancels all pending IO requests, regardless of IO type
543 //(xhr, script, iframe).
545 array.forEach(_inFlight, function(i){
548 }catch(e){/*squelch*/}
550 }catch(e){/*squelch*/}
553 //Automatically call cancel all io calls on unload
554 //in IE for trac issue #2357.
556 on(window, "unload", dojo._ioCancelAll);
559 dojo._ioNotifyStart = function(/*Deferred*/dfd){
561 // If dojo.publish is available, publish topics
562 // about the start of a request queue and/or the
563 // the beginning of request.
565 // Used by IO transports. An IO transport should
566 // call this method before making the network connection.
567 if(cfg.ioPublish && dojo.publish && dfd.ioArgs.args.ioPublish !== false){
569 dojo.publish("/dojo/io/start");
572 dojo.publish("/dojo/io/send", [dfd]);
576 dojo._ioWatch = function(dfd, validCheck, ioCheck, resHandle){
578 // Watches the io request represented by dfd to see if it completes.
580 // The Deferred object to watch.
581 // validCheck: Function
582 // Function used to check if the IO request is still valid. Gets the dfd
583 // object as its only argument.
585 // Function used to check if basic IO call worked. Gets the dfd
586 // object as its only argument.
587 // resHandle: Function
588 // Function used to process response. Gets the dfd
589 // object as its only argument.
590 var args = dfd.ioArgs.args;
592 dfd.startTime = (new Date()).getTime();
595 _inFlight.push({dfd: dfd, validCheck: validCheck, ioCheck: ioCheck, resHandle: resHandle});
597 _inFlightIntvl = setInterval(_watchInFlight, 50);
599 // handle sync requests
600 //A weakness: async calls in flight
601 //could have their handlers called as part of the
602 //_watchInFlight call, before the sync's callbacks
609 var _defaultContentType = "application/x-www-form-urlencoded";
611 var _validCheck = function(/*Deferred*/dfd){
612 return dfd.ioArgs.xhr.readyState; //boolean
614 var _ioCheck = function(/*Deferred*/dfd){
615 return 4 == dfd.ioArgs.xhr.readyState; //boolean
617 var _resHandle = function(/*Deferred*/dfd){
618 var xhr = dfd.ioArgs.xhr;
619 if(dojo._isDocumentOk(xhr)){
622 var err = new Error("Unable to load " + dfd.ioArgs.url + " status:" + xhr.status);
623 err.status = xhr.status;
624 err.responseText = xhr.responseText;
630 dojo._ioAddQueryToUrl = function(/*dojo.__IoCallbackArgs*/ioArgs){
631 //summary: Adds query params discovered by the io deferred construction to the URL.
632 //Only use this for operations which are fundamentally GET-type operations.
633 if(ioArgs.query.length){
634 ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query;
640 dojo.declare("dojo.__XhrArgs", dojo.__IoArgs, {
641 constructor: function(){
643 // In addition to the properties listed for the dojo._IoArgs type,
644 // the following properties are allowed for dojo.xhr* methods.
646 // Acceptable values are: text (default), json, json-comment-optional,
647 // json-comment-filtered, javascript, xml. See `dojo.contentHandlers`
649 // false is default. Indicates whether the request should
650 // be a synchronous (blocking) request.
652 // Additional HTTP headers to send in the request.
654 // false is default. Indicates whether a request should be
655 // allowed to fail (and therefore no console error message in
656 // the event of a failure)
657 // contentType: String|Boolean
658 // "application/x-www-form-urlencoded" is default. Set to false to
659 // prevent a Content-Type header from being sent, or to a string
660 // to send a different Content-Type.
661 this.handleAs = handleAs;
663 this.headers = headers;
664 this.failOk = failOk;
669 dojo.xhr = function(/*String*/ method, /*dojo.__XhrArgs*/ args, /*Boolean?*/ hasBody){
671 // Sends an HTTP request with the given method.
673 // Sends an HTTP request with the given method.
674 // See also dojo.xhrGet(), xhrPost(), xhrPut() and dojo.xhrDelete() for shortcuts
675 // for those HTTP methods. There are also methods for "raw" PUT and POST methods
676 // via dojo.rawXhrPut() and dojo.rawXhrPost() respectively.
678 // HTTP method to be used, such as GET, POST, PUT, DELETE. Should be uppercase.
680 // If the request has an HTTP body, then pass true for hasBody.
682 //Make the Deferred object for this xhr request.
683 var dfd = dojo._ioSetArgs(args, _deferredCancel, _deferredOk, _deferError);
684 var ioArgs = dfd.ioArgs;
686 //Pass the args to _xhrObj, to allow alternate XHR calls based specific calls, like
687 //the one used for iframe proxies.
688 var xhr = ioArgs.xhr = dojo._xhrObj(ioArgs.args);
689 //If XHR factory fails, cancel the deferred.
695 //Allow for specifying the HTTP body completely.
696 if("postData" in args){
697 ioArgs.query = args.postData;
698 }else if("putData" in args){
699 ioArgs.query = args.putData;
700 }else if("rawBody" in args){
701 ioArgs.query = args.rawBody;
702 }else if((arguments.length > 2 && !hasBody) || "POST|PUT".indexOf(method.toUpperCase()) == -1){
703 //Check for hasBody being passed. If no hasBody,
704 //then only append query string if not a POST or PUT request.
705 dojo._ioAddQueryToUrl(ioArgs);
708 // IE 6 is a steaming pile. It won't let you call apply() on the native function (xhr.open).
709 // workaround for IE6's apply() "issues"
710 xhr.open(method, ioArgs.url, args.sync !== true, args.user || undefined, args.password || undefined);
712 for(var hdr in args.headers){
713 if(hdr.toLowerCase() === "content-type" && !args.contentType){
714 args.contentType = args.headers[hdr];
715 }else if(args.headers[hdr]){
716 //Only add header if it has a value. This allows for instnace, skipping
717 //insertion of X-Requested-With by specifying empty value.
718 xhr.setRequestHeader(hdr, args.headers[hdr]);
722 // FIXME: is this appropriate for all content types?
723 if(args.contentType !== false){
724 xhr.setRequestHeader("Content-Type", args.contentType || _defaultContentType);
726 if(!args.headers || !("X-Requested-With" in args.headers)){
727 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
729 // FIXME: set other headers here!
730 dojo._ioNotifyStart(dfd);
731 if(dojo.config.debugAtAllCosts){
732 xhr.send(ioArgs.query);
735 xhr.send(ioArgs.query);
741 dojo._ioWatch(dfd, _validCheck, _ioCheck, _resHandle);
743 return dfd; // dojo.Deferred
746 dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){
748 // Sends an HTTP GET request to the server.
749 return dojo.xhr("GET", args); // dojo.Deferred
752 dojo.rawXhrPost = dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){
754 // Sends an HTTP POST request to the server. In addtion to the properties
755 // listed for the dojo.__XhrArgs type, the following property is allowed:
757 // String. Send raw data in the body of the POST request.
758 return dojo.xhr("POST", args, true); // dojo.Deferred
761 dojo.rawXhrPut = dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){
763 // Sends an HTTP PUT request to the server. In addtion to the properties
764 // listed for the dojo.__XhrArgs type, the following property is allowed:
766 // String. Send raw data in the body of the PUT request.
767 return dojo.xhr("PUT", args, true); // dojo.Deferred
770 dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){
772 // Sends an HTTP DELETE request to the server.
773 return dojo.xhr("DELETE", args); //dojo.Deferred
777 dojo.wrapForm = function(formNode){
779 // A replacement for FormBind, but not implemented yet.
781 // FIXME: need to think harder about what extensions to this we might
782 // want. What should we allow folks to do w/ this? What events to
784 throw new Error("dojo.wrapForm not yet implemented");
788 dojo._isDocumentOk = function(http){
789 var stat = http.status || 0;
791 (stat >= 200 && stat < 300) || // allow any 2XX response code
792 stat == 304 || // or, get it out of the cache
793 stat == 1223 || // or, Internet Explorer mangled the status code
794 !stat; // or, we're Titanium/browser chrome/chrome extension requesting a local file
795 return stat; // Boolean
798 dojo._getText = function(url){
800 dojo.xhrGet({url:url, sync:true, load:function(text){
806 // Add aliases for static functions to dojo.xhr since dojo.xhr is what's returned from this module
807 lang.mixin(dojo.xhr, {
808 _xhrObj: dojo._xhrObj,
809 fieldToObject: domForm.fieldToObject,
810 formToObject: domForm.toObject,
811 objectToQuery: ioq.objectToQuery,
812 formToQuery: domForm.toQuery,
813 formToJson: domForm.toJson,
814 queryToObject: ioq.queryToObject,
815 contentHandlers: handlers,
816 _ioSetArgs: dojo._ioSetArgs,
817 _ioCancelAll: dojo._ioCancelAll,
818 _ioNotifyStart: dojo._ioNotifyStart,
819 _ioWatch: dojo._ioWatch,
820 _ioAddQueryToUrl: dojo._ioAddQueryToUrl,
821 _isDocumentOk: dojo._isDocumentOk,
822 _getText: dojo._getText,
826 del: dojo.xhrDelete // because "delete" is a reserved word