Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
if(!dojo._hasResource["dojo._base.xhr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2
dojo._hasResource["dojo._base.xhr"] = true;
3
dojo.provide("dojo._base.xhr");
4
dojo.require("dojo._base.Deferred");
5
dojo.require("dojo._base.json");
6
dojo.require("dojo._base.lang");
7
dojo.require("dojo._base.query");
8
 
9
(function(){
10
	var _d = dojo;
11
	function setValue(/*Object*/obj, /*String*/name, /*String*/value){
12
		//summary:
13
		//		For the nameed property in object, set the value. If a value
14
		//		already exists and it is a string, convert the value to be an
15
		//		array of values.
16
		var val = obj[name];
17
		if(_d.isString(val)){
18
			obj[name] = [val, value];
19
		}else if(_d.isArray(val)){
20
			val.push(value);
21
		}else{
22
			obj[name] = value;
23
		}
24
	}
25
 
26
	dojo.formToObject = function(/*DOMNode||String*/ formNode){
27
		// summary:
28
		//		dojo.formToObject returns the values encoded in an HTML form as
29
		//		string properties in an object which it then returns. Disabled form
30
		//		elements, buttons, and other non-value form elements are skipped.
31
		//		Multi-select elements are returned as an array of string values.
32
		// description:
33
		//		This form:
34
		//
35
		//			<form id="test_form">
36
		//				<input type="text" name="blah" value="blah">
37
		//				<input type="text" name="no_value" value="blah" disabled>
38
		//				<input type="button" name="no_value2" value="blah">
39
		//				<select type="select" multiple name="multi" size="5">
40
		//					<option value="blah">blah</option>
41
		//					<option value="thud" selected>thud</option>
42
		//					<option value="thonk" selected>thonk</option>
43
		//				</select>
44
		//			</form>
45
		//
46
		//		yields this object structure as the result of a call to
47
		//		formToObject():
48
		//
49
		//			{
50
		//				blah: "blah",
51
		//				multi: [
52
		//					"thud",
53
		//					"thonk"
54
		//				]
55
		//			};
56
 
57
		var ret = {};
58
		var iq = "input:not([type=file]):not([type=submit]):not([type=image]):not([type=reset]):not([type=button]), select, textarea";
59
		_d.query(iq, formNode).filter(function(node){
60
			return (!node.disabled);
61
		}).forEach(function(item){
62
			var _in = item.name;
63
			var type = (item.type||"").toLowerCase();
64
			if(type == "radio" || type == "checkbox"){
65
				if(item.checked){ setValue(ret, _in, item.value); }
66
			}else if(item.multiple){
67
				ret[_in] = [];
68
				_d.query("option", item).forEach(function(opt){
69
					if(opt.selected){
70
						setValue(ret, _in, opt.value);
71
					}
72
				});
73
			}else{
74
				setValue(ret, _in, item.value);
75
				if(type == "image"){
76
					ret[_in+".x"] = ret[_in+".y"] = ret[_in].x = ret[_in].y = 0;
77
				}
78
			}
79
		});
80
		return ret; // Object
81
	}
82
 
83
	dojo.objectToQuery = function(/*Object*/ map){
84
		//	summary:
85
		//		takes a key/value mapping object and returns a string representing
86
		//		a URL-encoded version of that object.
87
		//	example:
88
		//		this object:
89
		//
90
		//		|	{
91
		//		|		blah: "blah",
92
		//		|		multi: [
93
		//		|			"thud",
94
		//		|			"thonk"
95
		//		|		]
96
		//		|	};
97
		//
98
		//	yeilds the following query string:
99
		//
100
		//	|	"blah=blah&multi=thud&multi=thonk"
101
 
102
 
103
		// FIXME: need to implement encodeAscii!!
104
		var ec = encodeURIComponent;
105
		var ret = "";
106
		var backstop = {};
107
		for(var x in map){
108
			if(map[x] != backstop[x]){
109
				if(_d.isArray(map[x])){
110
					for(var y=0; y<map[x].length; y++){
111
						ret += ec(x) + "=" + ec(map[x][y]) + "&";
112
					}
113
				}else{
114
					ret += ec(x) + "=" + ec(map[x]) + "&";
115
				}
116
			}
117
		}
118
		if(ret.length && ret.charAt(ret.length-1) == "&"){
119
			ret = ret.substr(0, ret.length-1);
120
		}
121
		return ret; // String
122
	}
123
 
124
	dojo.formToQuery = function(/*DOMNode||String*/ formNode){
125
		// summary:
126
		//		return URL-encoded string representing the form passed as either a
127
		//		node or string ID identifying the form to serialize
128
		return _d.objectToQuery(_d.formToObject(formNode)); // String
129
	}
130
 
131
	dojo.formToJson = function(/*DOMNode||String*/ formNode, /*Boolean?*/prettyPrint){
132
		// summary:
133
		//		return a serialized JSON string from a form node or string
134
		//		ID identifying the form to serialize
135
		return _d.toJson(_d.formToObject(formNode), prettyPrint); // String
136
	}
137
 
138
	dojo.queryToObject = function(/*String*/ str){
139
		// summary:
140
		//		returns an object representing a de-serialized query section of a
141
		//		URL. Query keys with multiple values are returned in an array.
142
		// description:
143
		//		This string:
144
		//
145
		//			"foo=bar&foo=baz&thinger=%20spaces%20=blah&zonk=blarg&"
146
		//
147
		//		returns this object structure:
148
		//
149
		//			{
150
		//				foo: [ "bar", "baz" ],
151
		//				thinger: " spaces =blah",
152
		//				zonk: "blarg"
153
		//			}
154
		//
155
		//		Note that spaces and other urlencoded entities are correctly
156
		//		handled.
157
 
158
		// FIXME: should we grab the URL string if we're not passed one?
159
		var ret = {};
160
		var qp = str.split("&");
161
		var dc = decodeURIComponent;
162
		_d.forEach(qp, function(item){
163
			if(item.length){
164
				var parts = item.split("=");
165
				var name = dc(parts.shift());
166
				var val = dc(parts.join("="));
167
				if(_d.isString(ret[name])){
168
					ret[name] = [ret[name]];
169
				}
170
				if(_d.isArray(ret[name])){
171
					ret[name].push(val);
172
				}else{
173
					ret[name] = val;
174
				}
175
			}
176
		});
177
		return ret; // Object
178
	}
179
 
180
	/*
181
		from refactor.txt:
182
 
183
		all bind() replacement APIs take the following argument structure:
184
 
185
			{
186
				url: "blah.html",
187
 
188
				// all below are optional, but must be supported in some form by
189
				// every IO API
190
				timeout: 1000, // milliseconds
191
				handleAs: "text", // replaces the always-wrong "mimetype"
192
				content: {
193
					key: "value"
194
				},
195
 
196
				// browser-specific, MAY be unsupported
197
				sync: true, // defaults to false
198
				form: dojo.byId("someForm")
199
			}
200
	*/
201
 
202
	// need to block async callbacks from snatching this thread as the result
203
	// of an async callback might call another sync XHR, this hangs khtml forever
204
	// must checked by watchInFlight()
205
 
206
	dojo._blockAsync = false;
207
 
208
	dojo._contentHandlers = {
209
		"text": function(xhr){ return xhr.responseText; },
210
		"json": function(xhr){
211
			if(!djConfig.usePlainJson){
212
				console.debug("Consider using mimetype:text/json-comment-filtered"
213
					+ " to avoid potential security issues with JSON endpoints"
214
					+ " (use djConfig.usePlainJson=true to turn off this message)");
215
			}
216
			return _d.fromJson(xhr.responseText);
217
		},
218
		"json-comment-filtered": function(xhr){
219
			// NOTE: we provide the json-comment-filtered option as one solution to
220
			// the "JavaScript Hijacking" issue noted by Fortify and others. It is
221
			// not appropriate for all circumstances.
222
 
223
			var value = xhr.responseText;
224
			var cStartIdx = value.indexOf("\/*");
225
			var cEndIdx = value.lastIndexOf("*\/");
226
			if(cStartIdx == -1 || cEndIdx == -1){
227
				throw new Error("JSON was not comment filtered");
228
			}
229
			return _d.fromJson(value.substring(cStartIdx+2, cEndIdx));
230
		},
231
		"javascript": function(xhr){
232
			// FIXME: try Moz and IE specific eval variants?
233
			return _d.eval(xhr.responseText);
234
		},
235
		"xml": function(xhr){
236
			if(_d.isIE && !xhr.responseXML){
237
				_d.forEach(["MSXML2", "Microsoft", "MSXML", "MSXML3"], function(i){
238
					try{
239
						var doc = new ActiveXObject(prefixes[i]+".XMLDOM");
240
						doc.async = false;
241
						doc.loadXML(xhr.responseText);
242
						return doc;	//	DOMDocument
243
					}catch(e){ /* squelch */ };
244
				});
245
			}else{
246
				return xhr.responseXML;
247
			}
248
		}
249
	};
250
 
251
	dojo._contentHandlers["json-comment-optional"] = function(xhr){
252
		var handlers = _d._contentHandlers;
253
		try{
254
			return handlers["json-comment-filtered"](xhr);
255
		}catch(e){
256
			return handlers["json"](xhr);
257
		}
258
	};
259
 
260
	/*=====
261
	dojo.__ioArgs = function(kwArgs){
262
		//	url: String
263
		//		URL to server endpoint.
264
		//	content: Object?
265
		//		Contains properties with string values. These
266
		//		properties will be serialized as name1=value2 and
267
		//		passed in the request.
268
		//	timeout: Integer?
269
		//		Milliseconds to wait for the response. If this time
270
		//		passes, the then error callbacks are called.
271
		//	form: DOMNode?
272
		//		DOM node for a form. Used to extract the form values
273
		//		and send to the server.
274
		//	preventCache: Boolean?
275
		//		Default is false. If true, then a
276
		//		"dojo.preventCache" parameter is sent in the request
277
		//		with a value that changes with each request
278
		//		(timestamp). Useful only with GET-type requests.
279
		//	handleAs: String?
280
		//		Acceptable values depend on the type of IO
281
		//		transport (see specific IO calls for more information).
282
		//	load: Function?
283
		//		function(response, ioArgs){}. response is an Object, ioArgs
284
		//		is of type dojo.__ioCallbackArgs. The load function will be
285
		//		called on a successful response.
286
		//	error: Function?
287
		//		function(response, ioArgs){}. response is an Object, ioArgs
288
		//		is of type dojo.__ioCallbackArgs. The error function will
289
		//		be called in an error case.
290
		//	handle: Function
291
		//		function(response, ioArgs){}. response is an Object, ioArgs
292
		//		is of type dojo.__ioCallbackArgs. The handle function will
293
		//		be called in either the successful or error case.  For
294
		//		the load, error and handle functions, the ioArgs object
295
		//		will contain the following properties:
296
	}
297
	=====*/
298
 
299
	/*=====
300
	dojo.__ioCallbackArgs = function(kwArgs){
301
		//	args: Object
302
		//		the original object argument to the IO call.
303
		//	xhr: XMLHttpRequest
304
		//		For XMLHttpRequest calls only, the
305
		//		XMLHttpRequest object that was used for the
306
		//		request.
307
		//	url: String
308
		//		The final URL used for the call. Many times it
309
		//		will be different than the original args.url
310
		//		value.
311
		//	query: String
312
		//		For non-GET requests, the
313
		//		name1=value1&name2=value2 parameters sent up in
314
		//		the request.
315
		//	handleAs: String
316
		//		The final indicator on how the response will be
317
		//		handled.
318
		//	id: String
319
		//		For dojo.io.script calls only, the internal
320
		//		script ID used for the request.
321
		//	canDelete: Boolean
322
		//		For dojo.io.script calls only, indicates
323
		//		whether the script tag that represents the
324
		//		request can be deleted after callbacks have
325
		//		been called. Used internally to know when
326
		//		cleanup can happen on JSONP-type requests.
327
		//	json: Object
328
		//		For dojo.io.script calls only: holds the JSON
329
		//		response for JSONP-type requests. Used
330
		//		internally to hold on to the JSON responses.
331
		//		You should not need to access it directly --
332
		//		the same object should be passed to the success
333
		//		callbacks directly.
334
	}
335
	=====*/
336
 
337
 
338
 
339
	dojo._ioSetArgs = function(/*dojo.__ioArgs*/args,
340
			/*Function*/canceller,
341
			/*Function*/okHandler,
342
			/*Function*/errHandler){
343
		//	summary:
344
		//		sets up the Deferred and ioArgs property on the Deferred so it
345
		//		can be used in an io call.
346
		//	args:
347
		//		The args object passed into the public io call. Recognized properties on
348
		//		the args object are:
349
		//	canceller:
350
		//		The canceller function used for the Deferred object. The function
351
		//		will receive one argument, the Deferred object that is related to the
352
		//		canceller.
353
		//	okHandler:
354
		//		The first OK callback to be registered with Deferred. It has the opportunity
355
		//		to transform the OK response. It will receive one argument -- the Deferred
356
		//		object returned from this function.
357
		//	errHandler:
358
		//		The first error callback to be registered with Deferred. It has the opportunity
359
		//		to do cleanup on an error. It will receive two arguments: error (the
360
		//		Error object) and dfd, the Deferred object returned from this function.
361
 
362
		var ioArgs = {args: args, url: args.url};
363
 
364
		//Get values from form if requestd.
365
		var formObject = null;
366
		if(args.form){
367
			var form = _d.byId(args.form);
368
			//IE requires going through getAttributeNode instead of just getAttribute in some form cases,
369
			//so use it for all.  See #2844
370
			var actnNode = form.getAttributeNode("action");
371
			ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null);
372
			formObject = _d.formToObject(form);
373
		}
374
 
375
		// set up the query params
376
		var miArgs = [{}];
377
 
378
		if(formObject){
379
			// potentially over-ride url-provided params w/ form values
380
			miArgs.push(formObject);
381
		}
382
		if(args.content){
383
			// stuff in content over-rides what's set by form
384
			miArgs.push(args.content);
385
		}
386
		if(args.preventCache){
387
			miArgs.push({"dojo.preventCache": new Date().valueOf()});
388
		}
389
		ioArgs.query = _d.objectToQuery(_d.mixin.apply(null, miArgs));
390
 
391
		// .. and the real work of getting the deferred in order, etc.
392
		ioArgs.handleAs = args.handleAs || "text";
393
		var d = new _d.Deferred(canceller);
394
		d.addCallbacks(okHandler, function(error){
395
			return errHandler(error, d);
396
		});
397
 
398
		//Support specifying load, error and handle callback functions from the args.
399
		//For those callbacks, the "this" object will be the args object.
400
		//The callbacks will get the deferred result value as the
401
		//first argument and the ioArgs object as the second argument.
402
		var ld = args.load;
403
		if(ld && _d.isFunction(ld)){
404
			d.addCallback(function(value){
405
				return ld.call(args, value, ioArgs);
406
			});
407
		}
408
		var err = args.error;
409
		if(err && _d.isFunction(err)){
410
			d.addErrback(function(value){
411
				return err.call(args, value, ioArgs);
412
			});
413
		}
414
		var handle = args.handle;
415
		if(handle && _d.isFunction(handle)){
416
			d.addBoth(function(value){
417
				return handle.call(args, value, ioArgs);
418
			});
419
		}
420
 
421
		d.ioArgs = ioArgs;
422
 
423
		// FIXME: need to wire up the xhr object's abort method to something
424
		// analagous in the Deferred
425
		return d;
426
	}
427
 
428
	var _deferredCancel = function(/*Deferred*/dfd){
429
		//summary: canceller function for dojo._ioSetArgs call.
430
 
431
		dfd.canceled = true;
432
		var xhr = dfd.ioArgs.xhr;
433
		var _at = (typeof xhr.abort);
434
		if((_at == "function")||(_at == "unknown")){
435
			xhr.abort();
436
		}
437
		var err = new Error("xhr cancelled");
438
		err.dojoType = "cancel";
439
		return err;
440
	}
441
	var _deferredOk = function(/*Deferred*/dfd){
442
		//summary: okHandler function for dojo._ioSetArgs call.
443
 
444
		return _d._contentHandlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);
445
	}
446
	var _deferError = function(/*Error*/error, /*Deferred*/dfd){
447
		//summary: errHandler function for dojo._ioSetArgs call.
448
 
449
		// console.debug("xhr error in:", dfd.ioArgs.xhr);
450
		console.debug(error);
451
		return error;
452
	}
453
 
454
	var _makeXhrDeferred = function(/*dojo.__xhrArgs*/args){
455
		//summary: makes the Deferred object for this xhr request.
456
		var dfd = _d._ioSetArgs(args, _deferredCancel, _deferredOk, _deferError);
457
		//Pass the args to _xhrObj, to allow xhr iframe proxy interceptions.
458
		dfd.ioArgs.xhr = _d._xhrObj(dfd.ioArgs.args);
459
		return dfd;
460
	}
461
 
462
	// avoid setting a timer per request. It degrades performance on IE
463
	// something fierece if we don't use unified loops.
464
	var _inFlightIntvl = null;
465
	var _inFlight = [];
466
	var _watchInFlight = function(){
467
		//summary:
468
		//		internal method that checks each inflight XMLHttpRequest to see
469
		//		if it has completed or if the timeout situation applies.
470
 
471
		var now = (new Date()).getTime();
472
		// make sure sync calls stay thread safe, if this callback is called
473
		// during a sync call and this results in another sync call before the
474
		// first sync call ends the browser hangs
475
		if(!_d._blockAsync){
476
			// we need manual loop because we often modify _inFlight (and therefore 'i') while iterating
477
			// note: the second clause is an assigment on purpose, lint may complain
478
			for(var i=0, tif; (i<_inFlight.length)&&(tif=_inFlight[i]); i++){
479
				var dfd = tif.dfd;
480
				try{
481
					if(!dfd || dfd.canceled || !tif.validCheck(dfd)){
482
						_inFlight.splice(i--, 1);
483
					}else if(tif.ioCheck(dfd)){
484
						_inFlight.splice(i--, 1);
485
						tif.resHandle(dfd);
486
					}else if(dfd.startTime){
487
						//did we timeout?
488
						if(dfd.startTime + (dfd.ioArgs.args.timeout||0) < now){
489
							_inFlight.splice(i--, 1);
490
							var err = new Error("timeout exceeded");
491
							err.dojoType = "timeout";
492
							dfd.errback(err);
493
							//Cancel the request so the io module can do appropriate cleanup.
494
							dfd.cancel();
495
						}
496
					}
497
				}catch(e){
498
					// FIXME: make sure we errback!
499
					console.debug(e);
500
					dfd.errback(new Error("_watchInFlightError!"));
501
				}
502
			}
503
		}
504
 
505
		if(!_inFlight.length){
506
			clearInterval(_inFlightIntvl);
507
			_inFlightIntvl = null;
508
			return;
509
		}
510
 
511
	}
512
 
513
	dojo._ioCancelAll = function(){
514
		//summary: Cancels all pending IO requests, regardless of IO type
515
		//(xhr, script, iframe).
516
		try{
517
			_d.forEach(_inFlight, function(i){
518
				i.dfd.cancel();
519
			});
520
		}catch(e){/*squelch*/}
521
	}
522
 
523
	//Automatically call cancel all io calls on unload
524
	//in IE for trac issue #2357.
525
	if(_d.isIE){
526
		_d.addOnUnload(_d._ioCancelAll);
527
	}
528
 
529
	_d._ioWatch = function(/*Deferred*/dfd,
530
		/*Function*/validCheck,
531
		/*Function*/ioCheck,
532
		/*Function*/resHandle){
533
		//summary: watches the io request represented by dfd to see if it completes.
534
		//dfd:
535
		//		The Deferred object to watch.
536
		//validCheck:
537
		//		Function used to check if the IO request is still valid. Gets the dfd
538
		//		object as its only argument.
539
		//ioCheck:
540
		//		Function used to check if basic IO call worked. Gets the dfd
541
		//		object as its only argument.
542
		//resHandle:
543
		//		Function used to process response. Gets the dfd
544
		//		object as its only argument.
545
		if(dfd.ioArgs.args.timeout){
546
			dfd.startTime = (new Date()).getTime();
547
		}
548
		_inFlight.push({dfd: dfd, validCheck: validCheck, ioCheck: ioCheck, resHandle: resHandle});
549
		if(!_inFlightIntvl){
550
			_inFlightIntvl = setInterval(_watchInFlight, 50);
551
		}
552
		_watchInFlight(); // handle sync requests
553
	}
554
 
555
	var _defaultContentType = "application/x-www-form-urlencoded";
556
 
557
	var _validCheck = function(/*Deferred*/dfd){
558
		return dfd.ioArgs.xhr.readyState; //boolean
559
	}
560
	var _ioCheck = function(/*Deferred*/dfd){
561
		return 4 == dfd.ioArgs.xhr.readyState; //boolean
562
	}
563
	var _resHandle = function(/*Deferred*/dfd){
564
		if(_d._isDocumentOk(dfd.ioArgs.xhr)){
565
			dfd.callback(dfd);
566
		}else{
567
			dfd.errback(new Error("bad http response code:" + dfd.ioArgs.xhr.status));
568
		}
569
	}
570
 
571
	var _doIt = function(/*String*/type, /*Deferred*/dfd){
572
		// IE 6 is a steaming pile. It won't let you call apply() on the native function (xhr.open).
573
		// workaround for IE6's apply() "issues"
574
		var ioArgs = dfd.ioArgs;
575
		var args = ioArgs.args;
576
		ioArgs.xhr.open(type, ioArgs.url, args.sync !== true, args.user || undefined, args.password || undefined);
577
		if(args.headers){
578
			for(var hdr in args.headers){
579
				if(hdr.toLowerCase() === "content-type" && !args.contentType){
580
					args.contentType = args.headers[hdr];
581
				}else{
582
					ioArgs.xhr.setRequestHeader(hdr, args.headers[hdr]);
583
				}
584
			}
585
		}
586
		// FIXME: is this appropriate for all content types?
587
		ioArgs.xhr.setRequestHeader("Content-Type", (args.contentType||_defaultContentType));
588
		// FIXME: set other headers here!
589
		try{
590
			ioArgs.xhr.send(ioArgs.query);
591
		}catch(e){
592
			dfd.cancel();
593
		}
594
		_d._ioWatch(dfd, _validCheck, _ioCheck, _resHandle);
595
		return dfd; //Deferred
596
	}
597
 
598
	dojo._ioAddQueryToUrl = function(/*dojo.__ioCallbackArgs*/ioArgs){
599
		//summary: Adds query params discovered by the io deferred construction to the URL.
600
		//Only use this for operations which are fundamentally GET-type operations.
601
		if(ioArgs.query.length){
602
			ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query;
603
			ioArgs.query = null;
604
		}
605
	}
606
 
607
	/*=====
608
	dojo.__xhrArgs = function(kwArgs){
609
		//	summary:
610
		//		In addition to the properties listed for the dojo.__ioArgs type,
611
		//		the following properties are allowed for dojo.xhr* methods.
612
		//	handleAs:
613
		//		String. Acceptable values are:
614
		//			"text" (default)
615
		//			"json"
616
		//			"json-comment-optional"
617
		//			"json-comment-filtered"
618
		//			"javascript"
619
		//			"xml"
620
		//	sync:
621
		//		Boolean. false is default. Indicates whether the request should
622
		//		be a synchronous (blocking) request.
623
		//	headers:
624
		//		Object. Additional HTTP headers to send in the request.
625
	}
626
	=====*/
627
 
628
	dojo.xhrGet = function(/*dojo.__xhrArgs*/ args){
629
		//	summary:
630
		//		Sends an HTTP GET request to the server.
631
		var dfd = _makeXhrDeferred(args);
632
		_d._ioAddQueryToUrl(dfd.ioArgs);
633
		return _doIt("GET", dfd); // dojo.Deferred
634
	}
635
 
636
	dojo.xhrPost = function(/*dojo.__xhrArgs*/ args){
637
		//summary:
638
		//		Sends an HTTP POST request to the server.
639
		return _doIt("POST", _makeXhrDeferred(args)); // dojo.Deferred
640
	}
641
 
642
	dojo.rawXhrPost = function(/*dojo.__xhrArgs*/ args){
643
		//	summary:
644
		//		Sends an HTTP POST request to the server. In addtion to the properties
645
		//		listed for the dojo.__xhrArgs type, the following property is allowed:
646
		//	postData:
647
		//		String. The raw data to send in the body of the POST request.
648
		var dfd = _makeXhrDeferred(args);
649
		dfd.ioArgs.query = args.postData;
650
		return _doIt("POST", dfd); // dojo.Deferred
651
	}
652
 
653
	dojo.xhrPut = function(/*dojo.__xhrArgs*/ args){
654
		//	summary:
655
		//		Sends an HTTP PUT request to the server.
656
		return _doIt("PUT", _makeXhrDeferred(args)); // dojo.Deferred
657
	}
658
 
659
	dojo.rawXhrPut = function(/*dojo.__xhrArgs*/ args){
660
		//	summary:
661
		//		Sends an HTTP PUT request to the server. In addtion to the properties
662
		//		listed for the dojo.__xhrArgs type, the following property is allowed:
663
		//	putData:
664
		//		String. The raw data to send in the body of the PUT request.
665
		var dfd = _makeXhrDeferred(args);
666
		var ioArgs = dfd.ioArgs;
667
		if(args["putData"]){
668
			ioArgs.query = args.putData;
669
			args.putData = null;
670
		}
671
		return _doIt("PUT", dfd); // dojo.Deferred
672
	}
673
 
674
	dojo.xhrDelete = function(/*dojo.__xhrArgs*/ args){
675
		//	summary:
676
		//		Sends an HTTP DELETE request to the server.
677
		var dfd = _makeXhrDeferred(args);
678
		_d._ioAddQueryToUrl(dfd.ioArgs);
679
		return _doIt("DELETE", dfd); // dojo.Deferred
680
	}
681
 
682
	/*
683
	dojo.wrapForm = function(formNode){
684
		//summary:
685
		//		A replacement for FormBind, but not implemented yet.
686
 
687
		// FIXME: need to think harder about what extensions to this we might
688
		// want. What should we allow folks to do w/ this? What events to
689
		// set/send?
690
		throw new Error("dojo.wrapForm not yet implemented");
691
	}
692
	*/
693
})();
694
 
695
}