Project

General

Profile

« Previous | Next » 

Revision 1263

Added by Dietmar over 14 years ago

updated YUI 2.4.1 to 2.8.0r4

View differences:

connection.js
1 1
/*
2
Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 3
Code licensed under the BSD License:
4 4
http://developer.yahoo.net/yui/license.txt
5
version: 2.4.1
5
version: 2.8.0r4
6 6
*/
7 7
/**
8 8
 * The Connection Manager provides a simplified interface to the XMLHttpRequest
......
131 131
    _default_headers:{},
132 132

  
133 133
 /**
134
  * @description Property modified by setForm() to determine if the data
135
  * should be submitted as an HTML form.
136
  * @property _isFormSubmit
137
  * @private
138
  * @static
139
  * @type boolean
140
  */
141
    _isFormSubmit:false,
142

  
143
 /**
144
  * @description Property modified by setForm() to determine if a file(s)
145
  * upload is expected.
146
  * @property _isFileUpload
147
  * @private
148
  * @static
149
  * @type boolean
150
  */
151
    _isFileUpload:false,
152

  
153
 /**
154
  * @description Property modified by setForm() to set a reference to the HTML
155
  * form node if the desired action is file upload.
156
  * @property _formNode
157
  * @private
158
  * @static
159
  * @type object
160
  */
161
    _formNode:null,
162

  
163
 /**
164
  * @description Property modified by setForm() to set the HTML form data
165
  * for each transaction.
166
  * @property _sFormData
167
  * @private
168
  * @static
169
  * @type string
170
  */
171
    _sFormData:null,
172

  
173
 /**
174 134
  * @description Collection of polling references to the polling mechanism in handleReadyState.
175 135
  * @property _poll
176 136
  * @private
......
209 169
     _transaction_id:0,
210 170

  
211 171
  /**
212
   * @description Tracks the name-value pair of the "clicked" submit button if multiple submit
213
   * buttons are present in an HTML form; and, if YAHOO.util.Event is available.
214
   * @property _submitElementValue
215
   * @private
216
   * @static
217
   * @type string
218
   */
219
	 _submitElementValue:null,
220

  
221
  /**
222
   * @description Determines whether YAHOO.util.Event is available and returns true or false.
223
   * If true, an event listener is bound at the document level to trap click events that
224
   * resolve to a target type of "Submit".  This listener will enable setForm() to determine
225
   * the clicked "Submit" value in a multi-Submit button, HTML form.
226
   * @property _hasSubmitListener
227
   * @private
228
   * @static
229
   */
230
	 _hasSubmitListener:(function()
231
	 {
232
		if(YAHOO.util.Event){
233
			YAHOO.util.Event.addListener(
234
				document,
235
				'click',
236
				function(e){
237
					var obj = YAHOO.util.Event.getTarget(e);
238
					if(obj.type && obj.type.toLowerCase() == 'submit'){
239
						YAHOO.util.Connect._submitElementValue = encodeURIComponent(obj.name) + "=" + encodeURIComponent(obj.value);
240
					}
241
				});
242
			return true;
243
	    }
244
	    return false;
245
	 })(),
246

  
247
  /**
248 172
   * @description Custom event that fires at the start of a transaction
249 173
   * @property startEvent
250 174
   * @private
......
283 207
	failureEvent: new YAHOO.util.CustomEvent('failure'),
284 208

  
285 209
  /**
286
   * @description Custom event that fires when handleTransactionResponse() determines a
287
   * response in the HTTP 4xx/5xx range.
288
   * @property failureEvent
289
   * @private
290
   * @static
291
   * @type CustomEvent
292
   */
293
	uploadEvent: new YAHOO.util.CustomEvent('upload'),
294

  
295
  /**
296 210
   * @description Custom event that fires when a transaction is successfully aborted.
297 211
   * @property abortEvent
298 212
   * @private
......
396 310
   */
397 311
	createXhrObject:function(transactionId)
398 312
	{
399
		var obj,http;
313
		var obj,http,i;
400 314
		try
401 315
		{
402 316
			// Instantiates XMLHttpRequest in non-IE browsers and assigns to http.
403 317
			http = new XMLHttpRequest();
404 318
			//  Object literal with http and tId properties
405
			obj = { conn:http, tId:transactionId };
319
			obj = { conn:http, tId:transactionId, xhr: true };
406 320
		}
407 321
		catch(e)
408 322
		{
409
			for(var i=0; i<this._msxml_progid.length; ++i){
323
			for(i=0; i<this._msxml_progid.length; ++i){
410 324
				try
411 325
				{
412 326
					// Instantiates XMLHttpRequest for IE and assign to http
413 327
					http = new ActiveXObject(this._msxml_progid[i]);
414 328
					//  Object literal with conn and tId properties
415
					obj = { conn:http, tId:transactionId };
329
					obj = { conn:http, tId:transactionId, xhr: true };
416 330
					break;
417 331
				}
418
				catch(e){}
332
				catch(e1){}
419 333
			}
420 334
		}
421 335
		finally
......
433 347
   * @static
434 348
   * @return {object}
435 349
   */
436
	getConnectionObject:function(isFileUpload)
350
	getConnectionObject:function(t)
437 351
	{
438
		var o;
439
		var tId = this._transaction_id;
352
		var o, tId = this._transaction_id;
440 353

  
441 354
		try
442 355
		{
443
			if(!isFileUpload){
356
			if(!t){
444 357
				o = this.createXhrObject(tId);
445 358
			}
446 359
			else{
447
				o = {};
448
				o.tId = tId;
449
				o.isUpload = true;
360
				o = {tId:tId};
361
				if(t==='xdr'){
362
					o.conn = this._transport;
363
					o.xdr = true;
364
				}
365
				else if(t==='upload'){
366
					o.upload = true;
367
				}
450 368
			}
451 369

  
452 370
			if(o){
......
454 372
			}
455 373
		}
456 374
		catch(e){}
457
		finally
458
		{
459
			return o;
460
		}
375
		return o;
461 376
	},
462 377

  
463 378
  /**
......
473 388
   */
474 389
	asyncRequest:function(method, uri, callback, postData)
475 390
	{
476
		var o = (this._isFileUpload)?this.getConnectionObject(true):this.getConnectionObject();
477
		var args = (callback && callback.argument)?callback.argument:null;
391
		var o,t,args = (callback && callback.argument)?callback.argument:null;
478 392

  
393
		if(this._isFileUpload){
394
			t = 'upload';
395
		}
396
		else if(callback.xdr){
397
			t = 'xdr';
398
		}
399

  
400
		o = this.getConnectionObject(t);
479 401
		if(!o){
480 402
			return null;
481 403
		}
......
515 437
				uri += ((uri.indexOf('?') == -1)?'?':'&') + "rnd=" + new Date().valueOf().toString();
516 438
			}
517 439

  
518
			o.conn.open(method, uri, true);
519

  
520 440
			// Each transaction will automatically include a custom header of
521 441
			// "X-Requested-With: XMLHttpRequest" to identify the request as
522 442
			// having originated from Connection Manager.
......
528 448

  
529 449
			//If the transaction method is POST and the POST header value is set to true
530 450
			//or a custom value, initalize the Content-Type header to this value.
531
			if((method.toUpperCase() == 'POST' && this._use_default_post_header) && this._isFormSubmit === false){
451
			if((method.toUpperCase() === 'POST' && this._use_default_post_header) && this._isFormSubmit === false){
532 452
				this.initHeader('Content-Type', this._default_post_header);
533 453
			}
534 454

  
455
			if(o.xdr){
456
				this.xdr(o, method, uri, callback, postData);
457
				return o;
458
			}
459

  
460
			o.conn.open(method, uri, true);
535 461
			//Initialize all default and custom HTTP headers,
536 462
			if(this._has_default_headers || this._has_http_headers){
537 463
				this.setHeader(o);
538 464
			}
539 465

  
540 466
			this.handleReadyState(o, callback);
541
			o.conn.send(postData || null);
467
			o.conn.send(postData || '');
542 468

  
543

  
544 469
			// Reset the HTML form data and state properties as
545 470
			// soon as the data are submitted.
546 471
			if(this._isFormSubmit === true){
......
571 496
   */
572 497
	initCustomEvents:function(o, callback)
573 498
	{
499
		var prop;
574 500
		// Enumerate through callback.customevents members and bind/subscribe
575 501
		// events that match in the _customEvents table.
576
		for(var prop in callback.customevents){
502
		for(prop in callback.customevents){
577 503
			if(this._customEvents[prop][0]){
578 504
				// Create the custom event
579 505
				o[this._customEvents[prop][0]] = new YAHOO.util.CustomEvent(this._customEvents[prop][1], (callback.scope)?callback.scope:null);
......
600 526
    handleReadyState:function(o, callback)
601 527

  
602 528
    {
603
		var oConn = this;
604
		var args = (callback && callback.argument)?callback.argument:null;
529
		var oConn = this,
530
			args = (callback && callback.argument)?callback.argument:null;
605 531

  
606 532
		if(callback && callback.timeout){
607 533
			this._timeOut[o.tId] = window.setTimeout(function(){ oConn.abort(o, callback, true); }, callback.timeout);
......
649 575
   */
650 576
    handleTransactionResponse:function(o, callback, isAbort)
651 577
    {
652
		var httpStatus, responseObject;
653
		var args = (callback && callback.argument)?callback.argument:null;
578
		var httpStatus, responseObject,
579
			args = (callback && callback.argument)?callback.argument:null,
580
			xdrS = (o.r && o.r.statusText === 'xdr:success')?true:false,
581
			xdrF = (o.r && o.r.statusText === 'xdr:failure')?true:false,
582
			xdrA = isAbort;
654 583

  
655 584
		try
656 585
		{
657
			if(o.conn.status !== undefined && o.conn.status !== 0){
586
			if((o.conn.status !== undefined && o.conn.status !== 0) || xdrS){
587
				// XDR requests will not have HTTP status defined. The
588
				// statusText property will define the response status
589
				// set by the Flash transport.
658 590
				httpStatus = o.conn.status;
659 591
			}
592
			else if(xdrF && !xdrA){
593
				// Set XDR transaction failure to a status of 0, which
594
				// resolves as an HTTP failure, instead of an exception.
595
				httpStatus = 0;
596
			}
660 597
			else{
661 598
				httpStatus = 13030;
662 599
			}
......
669 606
			httpStatus = 13030;
670 607
		}
671 608

  
672
		if(httpStatus >= 200 && httpStatus < 300 || httpStatus === 1223){
673
			responseObject = this.createResponseObject(o, args);
609
		if((httpStatus >= 200 && httpStatus < 300) || httpStatus === 1223 || xdrS){
610
			responseObject = o.xdr ? o.r : this.createResponseObject(o, args);
674 611
			if(callback && callback.success){
675 612
				if(!callback.scope){
676 613
					callback.success(responseObject);
......
699 636
				case 12031:
700 637
				case 12152: // Connection closed by server.
701 638
				case 13030: // See above comments for variable status.
639
					// XDR transactions will not resolve to this case, since the
640
					// response object is already built in the xdr response.
702 641
					responseObject = this.createExceptionObject(o.tId, args, (isAbort?isAbort:false));
703 642
					if(callback && callback.failure){
704 643
						if(!callback.scope){
......
711 650

  
712 651
					break;
713 652
				default:
714
					responseObject = this.createResponseObject(o, args);
653
					responseObject = (o.xdr) ? o.response : this.createResponseObject(o, args);
715 654
					if(callback && callback.failure){
716 655
						if(!callback.scope){
717 656
							callback.failure(responseObject);
......
749 688
   */
750 689
    createResponseObject:function(o, callbackArg)
751 690
    {
752
		var obj = {};
753
		var headerObj = {};
691
		var obj = {}, headerObj = {},
692
			i, headerStr, header, delimitPos;
754 693

  
755 694
		try
756 695
		{
757
			var headerStr = o.conn.getAllResponseHeaders();
758
			var header = headerStr.split('\n');
759
			for(var i=0; i<header.length; i++){
760
				var delimitPos = header[i].indexOf(':');
696
			headerStr = o.conn.getAllResponseHeaders();
697
			header = headerStr.split('\n');
698
			for(i=0; i<header.length; i++){
699
				delimitPos = header[i].indexOf(':');
761 700
				if(delimitPos != -1){
762
					headerObj[header[i].substring(0,delimitPos)] = header[i].substring(delimitPos+2);
701
					headerObj[header[i].substring(0,delimitPos)] = YAHOO.lang.trim(header[i].substring(delimitPos+2));
763 702
				}
764 703
			}
765 704
		}
......
800 739
   */
801 740
    createExceptionObject:function(tId, callbackArg, isAbort)
802 741
    {
803
		var COMM_CODE = 0;
804
		var COMM_ERROR = 'communication failure';
805
		var ABORT_CODE = -1;
806
		var ABORT_ERROR = 'transaction aborted';
742
		var COMM_CODE = 0,
743
			COMM_ERROR = 'communication failure',
744
			ABORT_CODE = -1,
745
			ABORT_ERROR = 'transaction aborted',
746
			obj = {};
807 747

  
808
		var obj = {};
809

  
810 748
		obj.tId = tId;
811 749
		if(isAbort){
812 750
			obj.status = ABORT_CODE;
......
838 776
	initHeader:function(label, value, isDefault)
839 777
	{
840 778
		var headerObj = (isDefault)?this._default_headers:this._http_headers;
779

  
841 780
		headerObj[label] = value;
842

  
843 781
		if(isDefault){
844 782
			this._has_default_headers = true;
845 783
		}
......
859 797
   */
860 798
	setHeader:function(o)
861 799
	{
800
		var prop;
862 801
		if(this._has_default_headers){
863
			for(var prop in this._default_headers){
802
			for(prop in this._default_headers){
864 803
				if(YAHOO.lang.hasOwnProperty(this._default_headers, prop)){
865 804
					o.conn.setRequestHeader(prop, this._default_headers[prop]);
866 805
				}
......
868 807
		}
869 808

  
870 809
		if(this._has_http_headers){
871
			for(var prop in this._http_headers){
810
			for(prop in this._http_headers){
872 811
				if(YAHOO.lang.hasOwnProperty(this._http_headers, prop)){
873 812
					o.conn.setRequestHeader(prop, this._http_headers[prop]);
874 813
				}
875 814
			}
876
			delete this._http_headers;
877 815

  
878 816
			this._http_headers = {};
879 817
			this._has_http_headers = false;
......
888 826
   * @return {void}
889 827
   */
890 828
	resetDefaultHeaders:function(){
891
		delete this._default_headers;
892 829
		this._default_headers = {};
893 830
		this._has_default_headers = false;
894 831
	},
895 832

  
896 833
  /**
834
   * @description Method to terminate a transaction, if it has not reached readyState 4.
835
   * @method abort
836
   * @public
837
   * @static
838
   * @param {object} o The connection object returned by asyncRequest.
839
   * @param {object} callback  User-defined callback object.
840
   * @param {string} isTimeout boolean to indicate if abort resulted from a callback timeout.
841
   * @return {boolean}
842
   */
843
	abort:function(o, callback, isTimeout)
844
	{
845
		var abortStatus,
846
			args = (callback && callback.argument)?callback.argument:null;
847
			o = o || {};
848

  
849
		if(o.conn){
850
			if(o.xhr){
851
				if(this.isCallInProgress(o)){
852
					// Issue abort request
853
					o.conn.abort();
854

  
855
					window.clearInterval(this._poll[o.tId]);
856
					delete this._poll[o.tId];
857

  
858
					if(isTimeout){
859
						window.clearTimeout(this._timeOut[o.tId]);
860
						delete this._timeOut[o.tId];
861
					}
862

  
863
					abortStatus = true;
864
				}
865
			}
866
			else if(o.xdr){
867
				o.conn.abort(o.tId);
868
				abortStatus = true;
869
			}
870
		}
871
		else if(o.upload){
872
			var frameId = 'yuiIO' + o.tId;
873
			var io = document.getElementById(frameId);
874

  
875
			if(io){
876
				// Remove all listeners on the iframe prior to
877
				// its destruction.
878
				YAHOO.util.Event.removeListener(io, "load");
879
				// Destroy the iframe facilitating the transaction.
880
				document.body.removeChild(io);
881

  
882
				if(isTimeout){
883
					window.clearTimeout(this._timeOut[o.tId]);
884
					delete this._timeOut[o.tId];
885
				}
886

  
887
				abortStatus = true;
888
			}
889
		}
890
		else{
891
			abortStatus = false;
892
		}
893

  
894
		if(abortStatus === true){
895
			// Fire global custom event -- abortEvent
896
			this.abortEvent.fire(o, args);
897

  
898
			if(o.abortEvent){
899
				// Fire transaction custom event -- abortEvent
900
				o.abortEvent.fire(o, args);
901
			}
902

  
903
			this.handleTransactionResponse(o, callback, true);
904
		}
905

  
906
		return abortStatus;
907
	},
908

  
909
  /**
910
   * @description Determines if the transaction is still being processed.
911
   * @method isCallInProgress
912
   * @public
913
   * @static
914
   * @param {object} o The connection object returned by asyncRequest
915
   * @return {boolean}
916
   */
917
	isCallInProgress:function(o)
918
	{
919
		o = o || {};
920
		// if the XHR object assigned to the transaction has not been dereferenced,
921
		// then check its readyState status.  Otherwise, return false.
922
		if(o.xhr && o.conn){
923
			return o.conn.readyState !== 4 && o.conn.readyState !== 0;
924
		}
925
		else if(o.xdr && o.conn){
926
			return o.conn.isCallInProgress(o.tId);
927
		}
928
		else if(o.upload === true){
929
			return document.getElementById('yuiIO' + o.tId)?true:false;
930
		}
931
		else{
932
			return false;
933
		}
934
	},
935

  
936
  /**
937
   * @description Dereference the XHR instance and the connection object after the transaction is completed.
938
   * @method releaseObject
939
   * @private
940
   * @static
941
   * @param {object} o The connection object
942
   * @return {void}
943
   */
944
	releaseObject:function(o)
945
	{
946
		if(o && o.conn){
947
			//dereference the XHR instance.
948
			o.conn = null;
949

  
950

  
951
			//dereference the connection object.
952
			o = null;
953
		}
954
	}
955
};
956

  
957
/**
958
  * @for Connect
959
  */
960
(function() {
961
	var YCM = YAHOO.util.Connect, _fn = {};
962

  
963
   /**
964
    * @description This method creates and instantiates the Flash transport.
965
    * @method _swf
966
    * @private
967
    * @static
968
    * @param {string} URI to connection.swf.
969
    * @return {void}
970
    */
971
	function _swf(uri) {
972
		var o = '<object id="YUIConnectionSwf" type="application/x-shockwave-flash" data="' +
973
		        uri + '" width="0" height="0">' +
974
		     	'<param name="movie" value="' + uri + '">' +
975
                '<param name="allowScriptAccess" value="always">' +
976
		    	'</object>',
977
		    c = document.createElement('div');
978

  
979
		document.body.appendChild(c);
980
		c.innerHTML = o;
981
	}
982

  
983
   /**
984
    * @description This method calls the public method on the
985
    * Flash transport to start the XDR transaction.  It is analogous
986
    * to Connection Manager's asyncRequest method.
987
    * @method xdr
988
    * @private
989
    * @static
990
    * @param {object} The transaction object.
991
    * @param {string} HTTP request method.
992
    * @param {string} URI for the transaction.
993
    * @param {object} The transaction's callback object.
994
    * @param {object} The JSON object used as HTTP POST data.
995
    * @return {void}
996
    */
997
	function _xdr(o, m, u, c, d) {
998
		_fn[parseInt(o.tId)] = { 'o':o, 'c':c };
999
		if (d) {
1000
			c.method = m;
1001
			c.data = d;
1002
		}
1003

  
1004
		o.conn.send(u, c, o.tId);
1005
	}
1006

  
1007
   /**
1008
    * @description This method instantiates the Flash transport and
1009
    * establishes a static reference to it, used for all XDR requests.
1010
    * @method transport
1011
    * @public
1012
    * @static
1013
    * @param {string} URI to connection.swf.
1014
    * @return {void}
1015
    */
1016
	function _init(uri) {
1017
		_swf(uri);
1018
		YCM._transport = document.getElementById('YUIConnectionSwf');
1019
	}
1020

  
1021
	function _xdrReady() {
1022
		YCM.xdrReadyEvent.fire();
1023
	}
1024

  
1025
   /**
1026
    * @description This method fires the global and transaction start
1027
    * events.
1028
    * @method _xdrStart
1029
    * @private
1030
    * @static
1031
    * @param {object} The transaction object.
1032
    * @param {string} The transaction's callback object.
1033
    * @return {void}
1034
    */
1035
	function _xdrStart(o, cb) {
1036
		if (o) {
1037
			// Fire global custom event -- startEvent
1038
			YCM.startEvent.fire(o, cb.argument);
1039

  
1040
			if(o.startEvent){
1041
				// Fire transaction custom event -- startEvent
1042
				o.startEvent.fire(o, cb.argument);
1043
			}
1044
		}
1045
	}
1046

  
1047
   /**
1048
    * @description This method is the initial response handler
1049
    * for XDR transactions.  The Flash transport calls this
1050
    * function and sends the response payload.
1051
    * @method handleXdrResponse
1052
    * @private
1053
    * @static
1054
    * @param {object} The response object sent from the Flash transport.
1055
    * @return {void}
1056
    */
1057
	function _handleXdrResponse(r) {
1058
		var o = _fn[r.tId].o,
1059
			cb = _fn[r.tId].c;
1060

  
1061
		if (r.statusText === 'xdr:start') {
1062
			_xdrStart(o, cb);
1063
			return;
1064
		}
1065

  
1066
		r.responseText = decodeURI(r.responseText);
1067
		o.r = r;
1068
		if (cb.argument) {
1069
			o.r.argument = cb.argument;
1070
		}
1071

  
1072
		this.handleTransactionResponse(o, cb, r.statusText === 'xdr:abort' ? true : false);
1073
		delete _fn[r.tId];
1074
	}
1075

  
1076
	// Bind the functions to Connection Manager as static fields.
1077
	YCM.xdr = _xdr;
1078
	YCM.swf = _swf;
1079
	YCM.transport = _init;
1080
	YCM.xdrReadyEvent = new YAHOO.util.CustomEvent('xdrReady');
1081
	YCM.xdrReady = _xdrReady;
1082
	YCM.handleXdrResponse = _handleXdrResponse;
1083
})();
1084

  
1085
/**
1086
  * @for Connect
1087
  */
1088
(function(){
1089
	var YCM = YAHOO.util.Connect,
1090
		YE = YAHOO.util.Event;
1091
   /**
1092
	* @description Property modified by setForm() to determine if the data
1093
	* should be submitted as an HTML form.
1094
	* @property _isFormSubmit
1095
	* @private
1096
	* @static
1097
	* @type boolean
1098
	*/
1099
	YCM._isFormSubmit = false;
1100

  
1101
   /**
1102
	* @description Property modified by setForm() to determine if a file(s)
1103
	* upload is expected.
1104
	* @property _isFileUpload
1105
	* @private
1106
	* @static
1107
	* @type boolean
1108
	*/
1109
	YCM._isFileUpload = false;
1110

  
1111
   /**
1112
	* @description Property modified by setForm() to set a reference to the HTML
1113
	* form node if the desired action is file upload.
1114
	* @property _formNode
1115
	* @private
1116
	* @static
1117
	* @type object
1118
	*/
1119
	YCM._formNode = null;
1120

  
1121
   /**
1122
	* @description Property modified by setForm() to set the HTML form data
1123
	* for each transaction.
1124
	* @property _sFormData
1125
	* @private
1126
	* @static
1127
	* @type string
1128
	*/
1129
	YCM._sFormData = null;
1130

  
1131
   /**
1132
	* @description Tracks the name-value pair of the "clicked" submit button if multiple submit
1133
	* buttons are present in an HTML form; and, if YAHOO.util.Event is available.
1134
	* @property _submitElementValue
1135
	* @private
1136
	* @static
1137
	* @type string
1138
	*/
1139
	YCM._submitElementValue = null;
1140

  
1141
   /**
1142
    * @description Custom event that fires when handleTransactionResponse() determines a
1143
    * response in the HTTP 4xx/5xx range.
1144
    * @property failureEvent
1145
    * @private
1146
    * @static
1147
    * @type CustomEvent
1148
    */
1149
	YCM.uploadEvent = new YAHOO.util.CustomEvent('upload'),
1150

  
1151
   /**
1152
	* @description Determines whether YAHOO.util.Event is available and returns true or false.
1153
	* If true, an event listener is bound at the document level to trap click events that
1154
	* resolve to a target type of "Submit".  This listener will enable setForm() to determine
1155
	* the clicked "Submit" value in a multi-Submit button, HTML form.
1156
	* @property _hasSubmitListener
1157
	* @private
1158
	* @static
1159
	*/
1160
	YCM._hasSubmitListener = function() {
1161
		if(YE){
1162
			YE.addListener(
1163
				document,
1164
				'click',
1165
				function(e){
1166
					var obj = YE.getTarget(e),
1167
						name = obj.nodeName.toLowerCase();
1168

  
1169
					if((name === 'input' || name === 'button') && (obj.type && obj.type.toLowerCase() == 'submit')){
1170
						YCM._submitElementValue = encodeURIComponent(obj.name) + "=" + encodeURIComponent(obj.value);
1171
					}
1172
				});
1173
			return true;
1174
		}
1175
		return false;
1176
	}();
1177

  
1178
  /**
897 1179
   * @description This method assembles the form label and value pairs and
898 1180
   * constructs an encoded string.
899 1181
   * asyncRequest() will automatically initialize the transaction with a
......
906 1188
   * @param {boolean} optional enable file upload over SSL in IE only.
907 1189
   * @return {string} string of the HTML form field name and value pairs..
908 1190
   */
909
	setForm:function(formId, isUpload, secureUri)
1191
	function _setForm(formId, isUpload, secureUri)
910 1192
	{
911
		// reset the HTML form data and state properties
1193
		var oForm, oElement, oName, oValue, oDisabled,
1194
			hasSubmit = false,
1195
			data = [], item = 0,
1196
			i,len,j,jlen,opt;
1197

  
912 1198
		this.resetFormState();
913 1199

  
914
		var oForm;
915 1200
		if(typeof formId == 'string'){
916 1201
			// Determine if the argument is a form id or a form name.
917
			// Note form name usage is deprecated, but supported
918
			// here for backward compatibility.
1202
			// Note form name usage is deprecated by supported
1203
			// here for legacy reasons.
919 1204
			oForm = (document.getElementById(formId) || document.forms[formId]);
920 1205
		}
921 1206
		else if(typeof formId == 'object'){
......
935 1220
		if(isUpload){
936 1221

  
937 1222
			// Create iframe in preparation for file upload.
938
			var io = this.createFrame(secureUri?secureUri:null);
1223
			this.createFrame(secureUri?secureUri:null);
1224

  
939 1225
			// Set form reference and file upload properties to true.
940 1226
			this._isFormSubmit = true;
941 1227
			this._isFileUpload = true;
942 1228
			this._formNode = oForm;
943 1229

  
944 1230
			return;
945

  
946 1231
		}
947 1232

  
948
		var oElement, oName, oValue, oDisabled;
949
		var hasSubmit = false;
950

  
951 1233
		// Iterate over the form elements collection to construct the
952 1234
		// label-value pairs.
953
		for (var i=0; i<oForm.elements.length; i++){
954
			oElement = oForm.elements[i];
1235
		for (i=0,len=oForm.elements.length; i<len; ++i){
1236
			oElement  = oForm.elements[i];
955 1237
			oDisabled = oElement.disabled;
956
			oName = oElement.name;
957
			oValue = oElement.value;
1238
			oName     = oElement.name;
958 1239

  
959 1240
			// Do not submit fields that are disabled or
960 1241
			// do not have a name attribute value.
961 1242
			if(!oDisabled && oName)
962 1243
			{
1244
				oName  = encodeURIComponent(oName)+'=';
1245
				oValue = encodeURIComponent(oElement.value);
1246

  
963 1247
				switch(oElement.type)
964 1248
				{
1249
					// Safari, Opera, FF all default opt.value from .text if
1250
					// value attribute not specified in markup
965 1251
					case 'select-one':
1252
						if (oElement.selectedIndex > -1) {
1253
							opt = oElement.options[oElement.selectedIndex];
1254
							data[item++] = oName + encodeURIComponent(
1255
								(opt.attributes.value && opt.attributes.value.specified) ? opt.value : opt.text);
1256
						}
1257
						break;
966 1258
					case 'select-multiple':
967
						for(var j=0; j<oElement.options.length; j++){
968
							if(oElement.options[j].selected){
969
								if(window.ActiveXObject){
970
									this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oElement.options[j].attributes['value'].specified?oElement.options[j].value:oElement.options[j].text) + '&';
1259
						if (oElement.selectedIndex > -1) {
1260
							for(j=oElement.selectedIndex, jlen=oElement.options.length; j<jlen; ++j){
1261
								opt = oElement.options[j];
1262
								if (opt.selected) {
1263
									data[item++] = oName + encodeURIComponent(
1264
										(opt.attributes.value && opt.attributes.value.specified) ? opt.value : opt.text);
971 1265
								}
972
								else{
973
									this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oElement.options[j].hasAttribute('value')?oElement.options[j].value:oElement.options[j].text) + '&';
974
								}
975 1266
							}
976 1267
						}
977 1268
						break;
978 1269
					case 'radio':
979 1270
					case 'checkbox':
980 1271
						if(oElement.checked){
981
							this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
1272
							data[item++] = oName + oValue;
982 1273
						}
983 1274
						break;
984 1275
					case 'file':
......
993 1284
					case 'submit':
994 1285
						if(hasSubmit === false){
995 1286
							if(this._hasSubmitListener && this._submitElementValue){
996
								this._sFormData += this._submitElementValue + '&';
1287
								data[item++] = this._submitElementValue;
997 1288
							}
998
							else{
999
								this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
1000
							}
1001

  
1002 1289
							hasSubmit = true;
1003 1290
						}
1004 1291
						break;
1005 1292
					default:
1006
						this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
1293
						data[item++] = oName + oValue;
1007 1294
				}
1008 1295
			}
1009 1296
		}
1010 1297

  
1011 1298
		this._isFormSubmit = true;
1012
		this._sFormData = this._sFormData.substr(0, this._sFormData.length - 1);
1299
		this._sFormData = data.join('&');
1013 1300

  
1014 1301

  
1015 1302
		this.initHeader('Content-Type', this._default_form_header);
1016 1303

  
1017 1304
		return this._sFormData;
1018
	},
1305
	}
1019 1306

  
1020
  /**
1021
   * @description Resets HTML form properties when an HTML form or HTML form
1022
   * with file upload transaction is sent.
1023
   * @method resetFormState
1024
   * @private
1025
   * @static
1026
   * @return {void}
1027
   */
1028
	resetFormState:function(){
1307
   /**
1308
    * @description Resets HTML form properties when an HTML form or HTML form
1309
    * with file upload transaction is sent.
1310
    * @method resetFormState
1311
    * @private
1312
    * @static
1313
    * @return {void}
1314
    */
1315
	function _resetFormState(){
1029 1316
		this._isFormSubmit = false;
1030 1317
		this._isFileUpload = false;
1031 1318
		this._formNode = null;
1032 1319
		this._sFormData = "";
1033
	},
1320
	}
1034 1321

  
1035
  /**
1036
   * @description Creates an iframe to be used for form file uploads.  It is remove from the
1037
   * document upon completion of the upload transaction.
1038
   * @method createFrame
1039
   * @private
1040
   * @static
1041
   * @param {string} optional qualified path of iframe resource for SSL in IE.
1042
   * @return {void}
1043
   */
1044
	createFrame:function(secureUri){
1045 1322

  
1323
   /**
1324
    * @description Creates an iframe to be used for form file uploads.  It is remove from the
1325
    * document upon completion of the upload transaction.
1326
    * @method createFrame
1327
    * @private
1328
    * @static
1329
    * @param {string} optional qualified path of iframe resource for SSL in IE.
1330
    * @return {void}
1331
    */
1332
	function _createFrame(secureUri){
1333

  
1046 1334
		// IE does not allow the setting of id and name attributes as object
1047 1335
		// properties via createElement().  A different iframe creation
1048 1336
		// pattern is required for IE.
1049
		var frameId = 'yuiIO' + this._transaction_id;
1050
		var io;
1051
		if(window.ActiveXObject){
1337
		var frameId = 'yuiIO' + this._transaction_id,
1338
			io;
1339
		if(YAHOO.env.ua.ie){
1052 1340
			io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
1053 1341

  
1054 1342
			// IE will throw a security exception in an SSL environment if the
......
1056 1344
			if(typeof secureUri == 'boolean'){
1057 1345
				io.src = 'javascript:false';
1058 1346
			}
1059
			else if(typeof secureURI == 'string'){
1060
				// Deprecated
1061
				io.src = secureUri;
1062
			}
1063 1347
		}
1064 1348
		else{
1065 1349
			io = document.createElement('iframe');
......
1072 1356
		io.style.left = '-1000px';
1073 1357

  
1074 1358
		document.body.appendChild(io);
1075
	},
1359
	}
1076 1360

  
1077
  /**
1078
   * @description Parses the POST data and creates hidden form elements
1079
   * for each key-value, and appends them to the HTML form object.
1080
   * @method appendPostData
1081
   * @private
1082
   * @static
1083
   * @param {string} postData The HTTP POST data
1084
   * @return {array} formElements Collection of hidden fields.
1085
   */
1086
	appendPostData:function(postData)
1087
	{
1088
		var formElements = [];
1089
		var postMessage = postData.split('&');
1090
		for(var i=0; i < postMessage.length; i++){
1091
			var delimitPos = postMessage[i].indexOf('=');
1361
   /**
1362
    * @description Parses the POST data and creates hidden form elements
1363
    * for each key-value, and appends them to the HTML form object.
1364
    * @method appendPostData
1365
    * @private
1366
    * @static
1367
    * @param {string} postData The HTTP POST data
1368
    * @return {array} formElements Collection of hidden fields.
1369
    */
1370
	function _appendPostData(postData){
1371
		var formElements = [],
1372
			postMessage = postData.split('&'),
1373
			i, delimitPos;
1374

  
1375
		for(i=0; i < postMessage.length; i++){
1376
			delimitPos = postMessage[i].indexOf('=');
1092 1377
			if(delimitPos != -1){
1093 1378
				formElements[i] = document.createElement('input');
1094 1379
				formElements[i].type = 'hidden';
1095
				formElements[i].name = postMessage[i].substring(0,delimitPos);
1096
				formElements[i].value = postMessage[i].substring(delimitPos+1);
1380
				formElements[i].name = decodeURIComponent(postMessage[i].substring(0,delimitPos));
1381
				formElements[i].value = decodeURIComponent(postMessage[i].substring(delimitPos+1));
1097 1382
				this._formNode.appendChild(formElements[i]);
1098 1383
			}
1099 1384
		}
1100 1385

  
1101 1386
		return formElements;
1102
	},
1387
	}
1103 1388

  
1104
  /**
1105
   * @description Uploads HTML form, inclusive of files/attachments, using the
1106
   * iframe created in createFrame to facilitate the transaction.
1107
   * @method uploadFile
1108
   * @private
1109
   * @static
1110
   * @param {int} id The transaction id.
1111
   * @param {object} callback User-defined callback object.
1112
   * @param {string} uri Fully qualified path of resource.
1113
   * @param {string} postData POST data to be submitted in addition to HTML form.
1114
   * @return {void}
1115
   */
1116
	uploadFile:function(o, callback, uri, postData){
1117

  
1389
   /**
1390
    * @description Uploads HTML form, inclusive of files/attachments, using the
1391
    * iframe created in createFrame to facilitate the transaction.
1392
    * @method uploadFile
1393
    * @private
1394
    * @static
1395
    * @param {int} id The transaction id.
1396
    * @param {object} callback User-defined callback object.
1397
    * @param {string} uri Fully qualified path of resource.
1398
    * @param {string} postData POST data to be submitted in addition to HTML form.
1399
    * @return {void}
1400
    */
1401
	function _uploadFile(o, callback, uri, postData){
1118 1402
		// Each iframe has an id prefix of "yuiIO" followed
1119 1403
		// by the unique transaction id.
1120
		var oConn = this;
1121
		var frameId = 'yuiIO' + o.tId;
1122
		var uploadEncoding = 'multipart/form-data';
1123
		var io = document.getElementById(frameId);
1124
		var args = (callback && callback.argument)?callback.argument:null;
1404
		var frameId = 'yuiIO' + o.tId,
1405
		    uploadEncoding = 'multipart/form-data',
1406
		    io = document.getElementById(frameId),
1407
		    ie8 = (document.documentMode && document.documentMode === 8) ? true : false,
1408
		    oConn = this,
1409
			args = (callback && callback.argument)?callback.argument:null,
1410
            oElements,i,prop,obj, rawFormAttributes, uploadCallback;
1125 1411

  
1126 1412
		// Track original HTML form attribute values.
1127
		var rawFormAttributes =
1128
		{
1413
		rawFormAttributes = {
1129 1414
			action:this._formNode.getAttribute('action'),
1130 1415
			method:this._formNode.getAttribute('method'),
1131 1416
			target:this._formNode.getAttribute('target')
......
1137 1422
		this._formNode.setAttribute('method', 'POST');
1138 1423
		this._formNode.setAttribute('target', frameId);
1139 1424

  
1140
		if(this._formNode.encoding){
1425
		if(YAHOO.env.ua.ie && !ie8){
1141 1426
			// IE does not respect property enctype for HTML forms.
1142 1427
			// Instead it uses the property - "encoding".
1143 1428
			this._formNode.setAttribute('encoding', uploadEncoding);
......
1147 1432
		}
1148 1433

  
1149 1434
		if(postData){
1150
			var oElements = this.appendPostData(postData);
1435
			oElements = this.appendPostData(postData);
1151 1436
		}
1152 1437

  
1153 1438
		// Start file upload.
......
1169 1454

  
1170 1455
		// Remove HTML elements created by appendPostData
1171 1456
		if(oElements && oElements.length > 0){
1172
			for(var i=0; i < oElements.length; i++){
1457
			for(i=0; i < oElements.length; i++){
1173 1458
				this._formNode.removeChild(oElements[i]);
1174 1459
			}
1175 1460
		}
1176 1461

  
1177 1462
		// Restore HTML form attributes to their original
1178 1463
		// values prior to file upload.
1179
		for(var prop in rawFormAttributes){
1464
		for(prop in rawFormAttributes){
1180 1465
			if(YAHOO.lang.hasOwnProperty(rawFormAttributes, prop)){
1181 1466
				if(rawFormAttributes[prop]){
1182 1467
					this._formNode.setAttribute(prop, rawFormAttributes[prop]);
......
1193 1478
		// Create the upload callback handler that fires when the iframe
1194 1479
		// receives the load event.  Subsequently, the event handler is detached
1195 1480
		// and the iframe removed from the document.
1196
		var uploadCallback = function()
1197
		{
1481
		uploadCallback = function() {
1198 1482
			if(callback && callback.timeout){
1199 1483
				window.clearTimeout(oConn._timeOut[o.tId]);
1200 1484
				delete oConn._timeOut[o.tId];
......
1208 1492
				o.completeEvent.fire(o, args);
1209 1493
			}
1210 1494

  
1211
			var obj = {};
1212
			obj.tId = o.tId;
1213
			obj.argument = callback.argument;
1495
			obj = {
1496
			    tId : o.tId,
1497
			    argument : callback.argument
1498
            };
1214 1499

  
1215 1500
			try
1216 1501
			{
......
1238 1523
				o.uploadEvent.fire(obj);
1239 1524
			}
1240 1525

  
1241
			YAHOO.util.Event.removeListener(io, "load", uploadCallback);
1526
			YE.removeListener(io, "load", uploadCallback);
1242 1527

  
1243 1528
			setTimeout(
1244 1529
				function(){
......
1248 1533
		};
1249 1534

  
1250 1535
		// Bind the onload handler to the iframe to detect the file upload response.
1251
		YAHOO.util.Event.addListener(io, "load", uploadCallback);
1252
	},
1536
		YE.addListener(io, "load", uploadCallback);
1537
	}
1253 1538

  
1254
  /**
1255
   * @description Method to terminate a transaction, if it has not reached readyState 4.
1256
   * @method abort
1257
   * @public
1258
   * @static
1259
   * @param {object} o The connection object returned by asyncRequest.
1260
   * @param {object} callback  User-defined callback object.
1261
   * @param {string} isTimeout boolean to indicate if abort resulted from a callback timeout.
1262
   * @return {boolean}
1263
   */
1264
	abort:function(o, callback, isTimeout)
1265
	{
1266
		var abortStatus;
1267
		var args = (callback && callback.argument)?callback.argument:null;
1539
	YCM.setForm = _setForm;
1540
	YCM.resetFormState = _resetFormState;
1541
	YCM.createFrame = _createFrame;
1542
	YCM.appendPostData = _appendPostData;
1543
	YCM.uploadFile = _uploadFile;
1544
})();
1268 1545

  
1269

  
1270
		if(o && o.conn){
1271
			if(this.isCallInProgress(o)){
1272
				// Issue abort request
1273
				o.conn.abort();
1274

  
1275
				window.clearInterval(this._poll[o.tId]);
1276
				delete this._poll[o.tId];
1277

  
1278
				if(isTimeout){
1279
					window.clearTimeout(this._timeOut[o.tId]);
1280
					delete this._timeOut[o.tId];
1281
				}
1282

  
1283
				abortStatus = true;
1284
			}
1285
		}
1286
		else if(o && o.isUpload === true){
1287
			var frameId = 'yuiIO' + o.tId;
1288
			var io = document.getElementById(frameId);
1289

  
1290
			if(io){
1291
				// Remove all listeners on the iframe prior to
1292
				// its destruction.
1293
				YAHOO.util.Event.removeListener(io, "load");
1294
				// Destroy the iframe facilitating the transaction.
1295
				document.body.removeChild(io);
1296

  
1297
				if(isTimeout){
1298
					window.clearTimeout(this._timeOut[o.tId]);
1299
					delete this._timeOut[o.tId];
1300
				}
1301

  
1302
				abortStatus = true;
1303
			}
1304
		}
1305
		else{
1306
			abortStatus = false;
1307
		}
1308

  
1309
		if(abortStatus === true){
1310
			// Fire global custom event -- abortEvent
1311
			this.abortEvent.fire(o, args);
1312

  
1313
			if(o.abortEvent){
1314
				// Fire transaction custom event -- abortEvent
1315
				o.abortEvent.fire(o, args);
1316
			}
1317

  
1318
			this.handleTransactionResponse(o, callback, true);
1319
		}
1320

  
1321
		return abortStatus;
1322
	},
1323

  
1324
  /**
1325
   * @description Determines if the transaction is still being processed.
1326
   * @method isCallInProgress
1327
   * @public
1328
   * @static
1329
   * @param {object} o The connection object returned by asyncRequest
1330
   * @return {boolean}
1331
   */
1332
	isCallInProgress:function(o)
1333
	{
1334
		// if the XHR object assigned to the transaction has not been dereferenced,
1335
		// then check its readyState status.  Otherwise, return false.
1336
		if(o && o.conn){
1337
			return o.conn.readyState !== 4 && o.conn.readyState !== 0;
1338
		}
1339
		else if(o && o.isUpload === true){
1340
			var frameId = 'yuiIO' + o.tId;
1341
			return document.getElementById(frameId)?true:false;
1342
		}
1343
		else{
1344
			return false;
1345
		}
1346
	},
1347

  
1348
  /**
1349
   * @description Dereference the XHR instance and the connection object after the transaction is completed.
1350
   * @method releaseObject
1351
   * @private
1352
   * @static
1353
   * @param {object} o The connection object
1354
   * @return {void}
1355
   */
1356
	releaseObject:function(o)
1357
	{
1358
		if(o && o.conn){
1359
			//dereference the XHR instance.
1360
			o.conn = null;
1361

  
1362

  
1363
			//dereference the connection object.
1364
			o = null;
1365
		}
1366
	}
1367
};
1368

  
1369
YAHOO.register("connection", YAHOO.util.Connect, {version: "2.4.1", build: "742"});
1546
YAHOO.register("connection", YAHOO.util.Connect, {version: "2.8.0r4", build: "2449"});

Also available in: Unified diff