Project

General

Profile

« Previous | Next » 

Revision 1289

Added by kweitzel over 14 years ago

Branch 2.8.1 merged back into Trunk

View differences:

connection-debug.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
......
400 314
   */
401 315
	createXhrObject:function(transactionId)
402 316
	{
403
		var obj,http;
317
		var obj,http,i;
404 318
		try
405 319
		{
406 320
			// Instantiates XMLHttpRequest in non-IE browsers and assigns to http.
407 321
			http = new XMLHttpRequest();
408 322
			//  Object literal with http and tId properties
409
			obj = { conn:http, tId:transactionId };
323
			obj = { conn:http, tId:transactionId, xhr: true };
410 324
			YAHOO.log('XHR object created for transaction ' + transactionId, 'info', 'Connection');
411 325
		}
412 326
		catch(e)
413 327
		{
414
			for(var i=0; i<this._msxml_progid.length; ++i){
328
			for(i=0; i<this._msxml_progid.length; ++i){
415 329
				try
416 330
				{
417 331
					// Instantiates XMLHttpRequest for IE and assign to http
418 332
					http = new ActiveXObject(this._msxml_progid[i]);
419 333
					//  Object literal with conn and tId properties
420
					obj = { conn:http, tId:transactionId };
334
					obj = { conn:http, tId:transactionId, xhr: true };
421 335
					YAHOO.log('ActiveX XHR object created for transaction ' + transactionId, 'info', 'Connection');
422 336
					break;
423 337
				}
424
				catch(e){}
338
				catch(e1){}
425 339
			}
426 340
		}
427 341
		finally
......
439 353
   * @static
440 354
   * @return {object}
441 355
   */
442
	getConnectionObject:function(isFileUpload)
356
	getConnectionObject:function(t)
443 357
	{
444
		var o;
445
		var tId = this._transaction_id;
358
		var o, tId = this._transaction_id;
446 359

  
447 360
		try
448 361
		{
449
			if(!isFileUpload){
362
			if(!t){
450 363
				o = this.createXhrObject(tId);
451 364
			}
452 365
			else{
453
				o = {};
454
				o.tId = tId;
455
				o.isUpload = true;
366
				o = {tId:tId};
367
				if(t==='xdr'){
368
					o.conn = this._transport;
369
					o.xdr = true;
370
				}
371
				else if(t==='upload'){
372
					o.upload = true;
373
				}
456 374
			}
457 375

  
458 376
			if(o){
......
460 378
			}
461 379
		}
462 380
		catch(e){}
463
		finally
464
		{
465
			return o;
466
		}
381
		return o;
467 382
	},
468 383

  
469 384
  /**
......
479 394
   */
480 395
	asyncRequest:function(method, uri, callback, postData)
481 396
	{
482
		var o = (this._isFileUpload)?this.getConnectionObject(true):this.getConnectionObject();
483
		var args = (callback && callback.argument)?callback.argument:null;
397
		var o,t,args = (callback && callback.argument)?callback.argument:null;
484 398

  
399
		if(this._isFileUpload){
400
			t = 'upload';
401
		}
402
		else if(callback.xdr){
403
			t = 'xdr';
404
		}
405

  
406
		o = this.getConnectionObject(t);
485 407
		if(!o){
486 408
			YAHOO.log('Unable to create connection object.', 'error', 'Connection');
487 409
			return null;
......
522 444
				uri += ((uri.indexOf('?') == -1)?'?':'&') + "rnd=" + new Date().valueOf().toString();
523 445
			}
524 446

  
525
			o.conn.open(method, uri, true);
526

  
527 447
			// Each transaction will automatically include a custom header of
528 448
			// "X-Requested-With: XMLHttpRequest" to identify the request as
529 449
			// having originated from Connection Manager.
......
536 456

  
537 457
			//If the transaction method is POST and the POST header value is set to true
538 458
			//or a custom value, initalize the Content-Type header to this value.
539
			if((method.toUpperCase() == 'POST' && this._use_default_post_header) && this._isFormSubmit === false){
459
			if((method.toUpperCase() === 'POST' && this._use_default_post_header) && this._isFormSubmit === false){
540 460
				this.initHeader('Content-Type', this._default_post_header);
541 461
				YAHOO.log('Initialize header Content-Type to application/x-www-form-urlencoded; UTF-8 for POST transaction.', 'info', 'Connection');
542 462
			}
543 463

  
464
			if(o.xdr){
465
				this.xdr(o, method, uri, callback, postData);
466
				return o;
467
			}
468

  
469
			o.conn.open(method, uri, true);
544 470
			//Initialize all default and custom HTTP headers,
545 471
			if(this._has_default_headers || this._has_http_headers){
546 472
				this.setHeader(o);
547 473
			}
548 474

  
549 475
			this.handleReadyState(o, callback);
550
			o.conn.send(postData || null);
476
			o.conn.send(postData || '');
551 477
			YAHOO.log('Transaction ' + o.tId + ' sent.', 'info', 'Connection');
552 478

  
553

  
554 479
			// Reset the HTML form data and state properties as
555 480
			// soon as the data are submitted.
556 481
			if(this._isFormSubmit === true){
......
581 506
   */
582 507
	initCustomEvents:function(o, callback)
583 508
	{
509
		var prop;
584 510
		// Enumerate through callback.customevents members and bind/subscribe
585 511
		// events that match in the _customEvents table.
586
		for(var prop in callback.customevents){
512
		for(prop in callback.customevents){
587 513
			if(this._customEvents[prop][0]){
588 514
				// Create the custom event
589 515
				o[this._customEvents[prop][0]] = new YAHOO.util.CustomEvent(this._customEvents[prop][1], (callback.scope)?callback.scope:null);
......
612 538
    handleReadyState:function(o, callback)
613 539

  
614 540
    {
615
		var oConn = this;
616
		var args = (callback && callback.argument)?callback.argument:null;
541
		var oConn = this,
542
			args = (callback && callback.argument)?callback.argument:null;
617 543

  
618 544
		if(callback && callback.timeout){
619 545
			this._timeOut[o.tId] = window.setTimeout(function(){ oConn.abort(o, callback, true); }, callback.timeout);
......
661 587
   */
662 588
    handleTransactionResponse:function(o, callback, isAbort)
663 589
    {
664
		var httpStatus, responseObject;
665
		var args = (callback && callback.argument)?callback.argument:null;
590
		var httpStatus, responseObject,
591
			args = (callback && callback.argument)?callback.argument:null,
592
			xdrS = (o.r && o.r.statusText === 'xdr:success')?true:false,
593
			xdrF = (o.r && o.r.statusText === 'xdr:failure')?true:false,
594
			xdrA = isAbort;
666 595

  
667 596
		try
668 597
		{
669
			if(o.conn.status !== undefined && o.conn.status !== 0){
598
			if((o.conn.status !== undefined && o.conn.status !== 0) || xdrS){
599
				// XDR requests will not have HTTP status defined. The
600
				// statusText property will define the response status
601
				// set by the Flash transport.
670 602
				httpStatus = o.conn.status;
671 603
			}
604
			else if(xdrF && !xdrA){
605
				// Set XDR transaction failure to a status of 0, which
606
				// resolves as an HTTP failure, instead of an exception.
607
				httpStatus = 0;
608
			}
672 609
			else{
673 610
				httpStatus = 13030;
674 611
			}
......
681 618
			httpStatus = 13030;
682 619
		}
683 620

  
684
		if(httpStatus >= 200 && httpStatus < 300 || httpStatus === 1223){
685
			responseObject = this.createResponseObject(o, args);
621
		if((httpStatus >= 200 && httpStatus < 300) || httpStatus === 1223 || xdrS){
622
			responseObject = o.xdr ? o.r : this.createResponseObject(o, args);
686 623
			if(callback && callback.success){
687 624
				if(!callback.scope){
688 625
					callback.success(responseObject);
......
713 650
				case 12031:
714 651
				case 12152: // Connection closed by server.
715 652
				case 13030: // See above comments for variable status.
653
					// XDR transactions will not resolve to this case, since the
654
					// response object is already built in the xdr response.
716 655
					responseObject = this.createExceptionObject(o.tId, args, (isAbort?isAbort:false));
717 656
					if(callback && callback.failure){
718 657
						if(!callback.scope){
......
727 666

  
728 667
					break;
729 668
				default:
730
					responseObject = this.createResponseObject(o, args);
669
					responseObject = (o.xdr) ? o.response : this.createResponseObject(o, args);
731 670
					if(callback && callback.failure){
732 671
						if(!callback.scope){
733 672
							callback.failure(responseObject);
......
767 706
   */
768 707
    createResponseObject:function(o, callbackArg)
769 708
    {
770
		var obj = {};
771
		var headerObj = {};
709
		var obj = {}, headerObj = {},
710
			i, headerStr, header, delimitPos;
772 711

  
773 712
		try
774 713
		{
775
			var headerStr = o.conn.getAllResponseHeaders();
776
			var header = headerStr.split('\n');
777
			for(var i=0; i<header.length; i++){
778
				var delimitPos = header[i].indexOf(':');
714
			headerStr = o.conn.getAllResponseHeaders();
715
			header = headerStr.split('\n');
716
			for(i=0; i<header.length; i++){
717
				delimitPos = header[i].indexOf(':');
779 718
				if(delimitPos != -1){
780
					headerObj[header[i].substring(0,delimitPos)] = header[i].substring(delimitPos+2);
719
					headerObj[header[i].substring(0,delimitPos)] = YAHOO.lang.trim(header[i].substring(delimitPos+2));
781 720
				}
782 721
			}
783 722
		}
......
818 757
   */
819 758
    createExceptionObject:function(tId, callbackArg, isAbort)
820 759
    {
821
		var COMM_CODE = 0;
822
		var COMM_ERROR = 'communication failure';
823
		var ABORT_CODE = -1;
824
		var ABORT_ERROR = 'transaction aborted';
760
		var COMM_CODE = 0,
761
			COMM_ERROR = 'communication failure',
762
			ABORT_CODE = -1,
763
			ABORT_ERROR = 'transaction aborted',
764
			obj = {};
825 765

  
826
		var obj = {};
827

  
828 766
		obj.tId = tId;
829 767
		if(isAbort){
830 768
			obj.status = ABORT_CODE;
......
856 794
	initHeader:function(label, value, isDefault)
857 795
	{
858 796
		var headerObj = (isDefault)?this._default_headers:this._http_headers;
797

  
859 798
		headerObj[label] = value;
860

  
861 799
		if(isDefault){
862 800
			this._has_default_headers = true;
863 801
		}
......
877 815
   */
878 816
	setHeader:function(o)
879 817
	{
818
		var prop;
880 819
		if(this._has_default_headers){
881
			for(var prop in this._default_headers){
820
			for(prop in this._default_headers){
882 821
				if(YAHOO.lang.hasOwnProperty(this._default_headers, prop)){
883 822
					o.conn.setRequestHeader(prop, this._default_headers[prop]);
884 823
					YAHOO.log('Default HTTP header ' + prop + ' set with value of ' + this._default_headers[prop], 'info', 'Connection');
......
887 826
		}
888 827

  
889 828
		if(this._has_http_headers){
890
			for(var prop in this._http_headers){
829
			for(prop in this._http_headers){
891 830
				if(YAHOO.lang.hasOwnProperty(this._http_headers, prop)){
892 831
					o.conn.setRequestHeader(prop, this._http_headers[prop]);
893 832
					YAHOO.log('HTTP header ' + prop + ' set with value of ' + this._http_headers[prop], 'info', 'Connection');
894 833
				}
895 834
			}
896
			delete this._http_headers;
897 835

  
898 836
			this._http_headers = {};
899 837
			this._has_http_headers = false;
......
908 846
   * @return {void}
909 847
   */
910 848
	resetDefaultHeaders:function(){
911
		delete this._default_headers;
912 849
		this._default_headers = {};
913 850
		this._has_default_headers = false;
914 851
	},
915 852

  
916 853
  /**
854
   * @description Method to terminate a transaction, if it has not reached readyState 4.
855
   * @method abort
856
   * @public
857
   * @static
858
   * @param {object} o The connection object returned by asyncRequest.
859
   * @param {object} callback  User-defined callback object.
860
   * @param {string} isTimeout boolean to indicate if abort resulted from a callback timeout.
861
   * @return {boolean}
862
   */
863
	abort:function(o, callback, isTimeout)
864
	{
865
		var abortStatus,
866
			args = (callback && callback.argument)?callback.argument:null;
867
			o = o || {};
868

  
869
		if(o.conn){
870
			if(o.xhr){
871
				if(this.isCallInProgress(o)){
872
					// Issue abort request
873
					o.conn.abort();
874

  
875
					window.clearInterval(this._poll[o.tId]);
876
					delete this._poll[o.tId];
877

  
878
					if(isTimeout){
879
						window.clearTimeout(this._timeOut[o.tId]);
880
						delete this._timeOut[o.tId];
881
					}
882

  
883
					abortStatus = true;
884
				}
885
			}
886
			else if(o.xdr){
887
				o.conn.abort(o.tId);
888
				abortStatus = true;
889
			}
890
		}
891
		else if(o.upload){
892
			var frameId = 'yuiIO' + o.tId;
893
			var io = document.getElementById(frameId);
894

  
895
			if(io){
896
				// Remove all listeners on the iframe prior to
897
				// its destruction.
898
				YAHOO.util.Event.removeListener(io, "load");
899
				// Destroy the iframe facilitating the transaction.
900
				document.body.removeChild(io);
901
				YAHOO.log('File upload iframe destroyed. Id is:' + frameId, 'info', 'Connection');
902

  
903
				if(isTimeout){
904
					window.clearTimeout(this._timeOut[o.tId]);
905
					delete this._timeOut[o.tId];
906
				}
907

  
908
				abortStatus = true;
909
			}
910
		}
911
		else{
912
			abortStatus = false;
913
		}
914

  
915
		if(abortStatus === true){
916
			// Fire global custom event -- abortEvent
917
			this.abortEvent.fire(o, args);
918

  
919
			if(o.abortEvent){
920
				// Fire transaction custom event -- abortEvent
921
				o.abortEvent.fire(o, args);
922
			}
923

  
924
			this.handleTransactionResponse(o, callback, true);
925
			YAHOO.log('Transaction ' + o.tId + ' aborted.', 'info', 'Connection');
926
		}
927

  
928
		return abortStatus;
929
	},
930

  
931
  /**
932
   * @description Determines if the transaction is still being processed.
933
   * @method isCallInProgress
934
   * @public
935
   * @static
936
   * @param {object} o The connection object returned by asyncRequest
937
   * @return {boolean}
938
   */
939
	isCallInProgress:function(o)
940
	{
941
		o = o || {};
942
		// if the XHR object assigned to the transaction has not been dereferenced,
943
		// then check its readyState status.  Otherwise, return false.
944
		if(o.xhr && o.conn){
945
			return o.conn.readyState !== 4 && o.conn.readyState !== 0;
946
		}
947
		else if(o.xdr && o.conn){
948
			return o.conn.isCallInProgress(o.tId);
949
		}
950
		else if(o.upload === true){
951
			return document.getElementById('yuiIO' + o.tId)?true:false;
952
		}
953
		else{
954
			return false;
955
		}
956
	},
957

  
958
  /**
959
   * @description Dereference the XHR instance and the connection object after the transaction is completed.
960
   * @method releaseObject
961
   * @private
962
   * @static
963
   * @param {object} o The connection object
964
   * @return {void}
965
   */
966
	releaseObject:function(o)
967
	{
968
		if(o && o.conn){
969
			//dereference the XHR instance.
970
			o.conn = null;
971

  
972
			YAHOO.log('Connection object for transaction ' + o.tId + ' destroyed.', 'info', 'Connection');
973

  
974
			//dereference the connection object.
975
			o = null;
976
		}
977
	}
978
};
979

  
980
/**
981
  * @for Connect
982
  */
983
(function() {
984
	var YCM = YAHOO.util.Connect, _fn = {};
985

  
986
   /**
987
    * @description This method creates and instantiates the Flash transport.
988
    * @method _swf
989
    * @private
990
    * @static
991
    * @param {string} URI to connection.swf.
992
    * @return {void}
993
    */
994
	function _swf(uri) {
995
		var o = '<object id="YUIConnectionSwf" type="application/x-shockwave-flash" data="' +
996
		        uri + '" width="0" height="0">' +
997
		     	'<param name="movie" value="' + uri + '">' +
998
                '<param name="allowScriptAccess" value="always">' +
999
		    	'</object>',
1000
		    c = document.createElement('div');
1001

  
1002
		document.body.appendChild(c);
1003
		c.innerHTML = o;
1004
	}
1005

  
1006
   /**
1007
    * @description This method calls the public method on the
1008
    * Flash transport to start the XDR transaction.  It is analogous
1009
    * to Connection Manager's asyncRequest method.
1010
    * @method xdr
1011
    * @private
1012
    * @static
1013
    * @param {object} The transaction object.
1014
    * @param {string} HTTP request method.
1015
    * @param {string} URI for the transaction.
1016
    * @param {object} The transaction's callback object.
1017
    * @param {object} The JSON object used as HTTP POST data.
1018
    * @return {void}
1019
    */
1020
	function _xdr(o, m, u, c, d) {
1021
		_fn[parseInt(o.tId)] = { 'o':o, 'c':c };
1022
		if (d) {
1023
			c.method = m;
1024
			c.data = d;
1025
		}
1026

  
1027
		o.conn.send(u, c, o.tId);
1028
	}
1029

  
1030
   /**
1031
    * @description This method instantiates the Flash transport and
1032
    * establishes a static reference to it, used for all XDR requests.
1033
    * @method transport
1034
    * @public
1035
    * @static
1036
    * @param {string} URI to connection.swf.
1037
    * @return {void}
1038
    */
1039
	function _init(uri) {
1040
		_swf(uri);
1041
		YCM._transport = document.getElementById('YUIConnectionSwf');
1042
	}
1043

  
1044
	function _xdrReady() {
1045
		YCM.xdrReadyEvent.fire();
1046
	}
1047

  
1048
   /**
1049
    * @description This method fires the global and transaction start
1050
    * events.
1051
    * @method _xdrStart
1052
    * @private
1053
    * @static
1054
    * @param {object} The transaction object.
1055
    * @param {string} The transaction's callback object.
1056
    * @return {void}
1057
    */
1058
	function _xdrStart(o, cb) {
1059
		if (o) {
1060
			// Fire global custom event -- startEvent
1061
			YCM.startEvent.fire(o, cb.argument);
1062

  
1063
			if(o.startEvent){
1064
				// Fire transaction custom event -- startEvent
1065
				o.startEvent.fire(o, cb.argument);
1066
			}
1067
		}
1068
	}
1069

  
1070
   /**
1071
    * @description This method is the initial response handler
1072
    * for XDR transactions.  The Flash transport calls this
1073
    * function and sends the response payload.
1074
    * @method handleXdrResponse
1075
    * @private
1076
    * @static
1077
    * @param {object} The response object sent from the Flash transport.
1078
    * @return {void}
1079
    */
1080
	function _handleXdrResponse(r) {
1081
		var o = _fn[r.tId].o,
1082
			cb = _fn[r.tId].c;
1083

  
1084
		if (r.statusText === 'xdr:start') {
1085
			_xdrStart(o, cb);
1086
			return;
1087
		}
1088

  
1089
		r.responseText = decodeURI(r.responseText);
1090
		o.r = r;
1091
		if (cb.argument) {
1092
			o.r.argument = cb.argument;
1093
		}
1094

  
1095
		this.handleTransactionResponse(o, cb, r.statusText === 'xdr:abort' ? true : false);
1096
		delete _fn[r.tId];
1097
	}
1098

  
1099
	// Bind the functions to Connection Manager as static fields.
1100
	YCM.xdr = _xdr;
1101
	YCM.swf = _swf;
1102
	YCM.transport = _init;
1103
	YCM.xdrReadyEvent = new YAHOO.util.CustomEvent('xdrReady');
1104
	YCM.xdrReady = _xdrReady;
1105
	YCM.handleXdrResponse = _handleXdrResponse;
1106
})();
1107

  
1108
/**
1109
  * @for Connect
1110
  */
1111
(function(){
1112
	var YCM = YAHOO.util.Connect,
1113
		YE = YAHOO.util.Event;
1114
   /**
1115
	* @description Property modified by setForm() to determine if the data
1116
	* should be submitted as an HTML form.
1117
	* @property _isFormSubmit
1118
	* @private
1119
	* @static
1120
	* @type boolean
1121
	*/
1122
	YCM._isFormSubmit = false;
1123

  
1124
   /**
1125
	* @description Property modified by setForm() to determine if a file(s)
1126
	* upload is expected.
1127
	* @property _isFileUpload
1128
	* @private
1129
	* @static
1130
	* @type boolean
1131
	*/
1132
	YCM._isFileUpload = false;
1133

  
1134
   /**
1135
	* @description Property modified by setForm() to set a reference to the HTML
1136
	* form node if the desired action is file upload.
1137
	* @property _formNode
1138
	* @private
1139
	* @static
1140
	* @type object
1141
	*/
1142
	YCM._formNode = null;
1143

  
1144
   /**
1145
	* @description Property modified by setForm() to set the HTML form data
1146
	* for each transaction.
1147
	* @property _sFormData
1148
	* @private
1149
	* @static
1150
	* @type string
1151
	*/
1152
	YCM._sFormData = null;
1153

  
1154
   /**
1155
	* @description Tracks the name-value pair of the "clicked" submit button if multiple submit
1156
	* buttons are present in an HTML form; and, if YAHOO.util.Event is available.
1157
	* @property _submitElementValue
1158
	* @private
1159
	* @static
1160
	* @type string
1161
	*/
1162
	YCM._submitElementValue = null;
1163

  
1164
   /**
1165
    * @description Custom event that fires when handleTransactionResponse() determines a
1166
    * response in the HTTP 4xx/5xx range.
1167
    * @property failureEvent
1168
    * @private
1169
    * @static
1170
    * @type CustomEvent
1171
    */
1172
	YCM.uploadEvent = new YAHOO.util.CustomEvent('upload'),
1173

  
1174
   /**
1175
	* @description Determines whether YAHOO.util.Event is available and returns true or false.
1176
	* If true, an event listener is bound at the document level to trap click events that
1177
	* resolve to a target type of "Submit".  This listener will enable setForm() to determine
1178
	* the clicked "Submit" value in a multi-Submit button, HTML form.
1179
	* @property _hasSubmitListener
1180
	* @private
1181
	* @static
1182
	*/
1183
	YCM._hasSubmitListener = function() {
1184
		if(YE){
1185
			YE.addListener(
1186
				document,
1187
				'click',
1188
				function(e){
1189
					var obj = YE.getTarget(e),
1190
						name = obj.nodeName.toLowerCase();
1191

  
1192
					if((name === 'input' || name === 'button') && (obj.type && obj.type.toLowerCase() == 'submit')){
1193
						YCM._submitElementValue = encodeURIComponent(obj.name) + "=" + encodeURIComponent(obj.value);
1194
					}
1195
				});
1196
			return true;
1197
		}
1198
		return false;
1199
	}();
1200

  
1201
  /**
917 1202
   * @description This method assembles the form label and value pairs and
918 1203
   * constructs an encoded string.
919 1204
   * asyncRequest() will automatically initialize the transaction with a
......
926 1211
   * @param {boolean} optional enable file upload over SSL in IE only.
927 1212
   * @return {string} string of the HTML form field name and value pairs..
928 1213
   */
929
	setForm:function(formId, isUpload, secureUri)
1214
	function _setForm(formId, isUpload, secureUri)
930 1215
	{
931
		// reset the HTML form data and state properties
1216
		var oForm, oElement, oName, oValue, oDisabled,
1217
			hasSubmit = false,
1218
			data = [], item = 0,
1219
			i,len,j,jlen,opt;
1220

  
932 1221
		this.resetFormState();
933 1222

  
934
		var oForm;
935 1223
		if(typeof formId == 'string'){
936 1224
			// Determine if the argument is a form id or a form name.
937
			// Note form name usage is deprecated, but supported
938
			// here for backward compatibility.
1225
			// Note form name usage is deprecated by supported
1226
			// here for legacy reasons.
939 1227
			oForm = (document.getElementById(formId) || document.forms[formId]);
940 1228
		}
941 1229
		else if(typeof formId == 'object'){
......
956 1244
		if(isUpload){
957 1245

  
958 1246
			// Create iframe in preparation for file upload.
959
			var io = this.createFrame(secureUri?secureUri:null);
1247
			this.createFrame(secureUri?secureUri:null);
1248

  
960 1249
			// Set form reference and file upload properties to true.
961 1250
			this._isFormSubmit = true;
962 1251
			this._isFileUpload = true;
963 1252
			this._formNode = oForm;
964 1253

  
965 1254
			return;
966

  
967 1255
		}
968 1256

  
969
		var oElement, oName, oValue, oDisabled;
970
		var hasSubmit = false;
971

  
972 1257
		// Iterate over the form elements collection to construct the
973 1258
		// label-value pairs.
974
		for (var i=0; i<oForm.elements.length; i++){
975
			oElement = oForm.elements[i];
1259
		for (i=0,len=oForm.elements.length; i<len; ++i){
1260
			oElement  = oForm.elements[i];
976 1261
			oDisabled = oElement.disabled;
977
			oName = oElement.name;
978
			oValue = oElement.value;
1262
			oName     = oElement.name;
979 1263

  
980 1264
			// Do not submit fields that are disabled or
981 1265
			// do not have a name attribute value.
982 1266
			if(!oDisabled && oName)
983 1267
			{
1268
				oName  = encodeURIComponent(oName)+'=';
1269
				oValue = encodeURIComponent(oElement.value);
1270

  
984 1271
				switch(oElement.type)
985 1272
				{
1273
					// Safari, Opera, FF all default opt.value from .text if
1274
					// value attribute not specified in markup
986 1275
					case 'select-one':
1276
						if (oElement.selectedIndex > -1) {
1277
							opt = oElement.options[oElement.selectedIndex];
1278
							data[item++] = oName + encodeURIComponent(
1279
								(opt.attributes.value && opt.attributes.value.specified) ? opt.value : opt.text);
1280
						}
1281
						break;
987 1282
					case 'select-multiple':
988
						for(var j=0; j<oElement.options.length; j++){
989
							if(oElement.options[j].selected){
990
								if(window.ActiveXObject){
991
									this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oElement.options[j].attributes['value'].specified?oElement.options[j].value:oElement.options[j].text) + '&';
1283
						if (oElement.selectedIndex > -1) {
1284
							for(j=oElement.selectedIndex, jlen=oElement.options.length; j<jlen; ++j){
1285
								opt = oElement.options[j];
1286
								if (opt.selected) {
1287
									data[item++] = oName + encodeURIComponent(
1288
										(opt.attributes.value && opt.attributes.value.specified) ? opt.value : opt.text);
992 1289
								}
993
								else{
994
									this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oElement.options[j].hasAttribute('value')?oElement.options[j].value:oElement.options[j].text) + '&';
995
								}
996 1290
							}
997 1291
						}
998 1292
						break;
999 1293
					case 'radio':
1000 1294
					case 'checkbox':
1001 1295
						if(oElement.checked){
1002
							this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
1296
							data[item++] = oName + oValue;
1003 1297
						}
1004 1298
						break;
1005 1299
					case 'file':
......
1014 1308
					case 'submit':
1015 1309
						if(hasSubmit === false){
1016 1310
							if(this._hasSubmitListener && this._submitElementValue){
1017
								this._sFormData += this._submitElementValue + '&';
1311
								data[item++] = this._submitElementValue;
1018 1312
							}
1019
							else{
1020
								this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
1021
							}
1022

  
1023 1313
							hasSubmit = true;
1024 1314
						}
1025 1315
						break;
1026 1316
					default:
1027
						this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&';
1317
						data[item++] = oName + oValue;
1028 1318
				}
1029 1319
			}
1030 1320
		}
1031 1321

  
1032 1322
		this._isFormSubmit = true;
1033
		this._sFormData = this._sFormData.substr(0, this._sFormData.length - 1);
1323
		this._sFormData = data.join('&');
1034 1324

  
1035 1325
		YAHOO.log('Form initialized for transaction. HTML form POST message is: ' + this._sFormData, 'info', 'Connection');
1036 1326

  
......
1038 1328
		YAHOO.log('Initialize header Content-Type to application/x-www-form-urlencoded for setForm() transaction.', 'info', 'Connection');
1039 1329

  
1040 1330
		return this._sFormData;
1041
	},
1331
	}
1042 1332

  
1043
  /**
1044
   * @description Resets HTML form properties when an HTML form or HTML form
1045
   * with file upload transaction is sent.
1046
   * @method resetFormState
1047
   * @private
1048
   * @static
1049
   * @return {void}
1050
   */
1051
	resetFormState:function(){
1333
   /**
1334
    * @description Resets HTML form properties when an HTML form or HTML form
1335
    * with file upload transaction is sent.
1336
    * @method resetFormState
1337
    * @private
1338
    * @static
1339
    * @return {void}
1340
    */
1341
	function _resetFormState(){
1052 1342
		this._isFormSubmit = false;
1053 1343
		this._isFileUpload = false;
1054 1344
		this._formNode = null;
1055 1345
		this._sFormData = "";
1056
	},
1346
	}
1057 1347

  
1058
  /**
1059
   * @description Creates an iframe to be used for form file uploads.  It is remove from the
1060
   * document upon completion of the upload transaction.
1061
   * @method createFrame
1062
   * @private
1063
   * @static
1064
   * @param {string} optional qualified path of iframe resource for SSL in IE.
1065
   * @return {void}
1066
   */
1067
	createFrame:function(secureUri){
1068 1348

  
1349
   /**
1350
    * @description Creates an iframe to be used for form file uploads.  It is remove from the
1351
    * document upon completion of the upload transaction.
1352
    * @method createFrame
1353
    * @private
1354
    * @static
1355
    * @param {string} optional qualified path of iframe resource for SSL in IE.
1356
    * @return {void}
1357
    */
1358
	function _createFrame(secureUri){
1359

  
1069 1360
		// IE does not allow the setting of id and name attributes as object
1070 1361
		// properties via createElement().  A different iframe creation
1071 1362
		// pattern is required for IE.
1072
		var frameId = 'yuiIO' + this._transaction_id;
1073
		var io;
1074
		if(window.ActiveXObject){
1363
		var frameId = 'yuiIO' + this._transaction_id,
1364
			io;
1365
		if(YAHOO.env.ua.ie){
1075 1366
			io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
1076 1367

  
1077 1368
			// IE will throw a security exception in an SSL environment if the
......
1079 1370
			if(typeof secureUri == 'boolean'){
1080 1371
				io.src = 'javascript:false';
1081 1372
			}
1082
			else if(typeof secureURI == 'string'){
1083
				// Deprecated
1084
				io.src = secureUri;
1085
			}
1086 1373
		}
1087 1374
		else{
1088 1375
			io = document.createElement('iframe');
......
1096 1383

  
1097 1384
		document.body.appendChild(io);
1098 1385
		YAHOO.log('File upload iframe created. Id is:' + frameId, 'info', 'Connection');
1099
	},
1386
	}
1100 1387

  
1101
  /**
1102
   * @description Parses the POST data and creates hidden form elements
1103
   * for each key-value, and appends them to the HTML form object.
1104
   * @method appendPostData
1105
   * @private
1106
   * @static
1107
   * @param {string} postData The HTTP POST data
1108
   * @return {array} formElements Collection of hidden fields.
1109
   */
1110
	appendPostData:function(postData)
1111
	{
1112
		var formElements = [];
1113
		var postMessage = postData.split('&');
1114
		for(var i=0; i < postMessage.length; i++){
1115
			var delimitPos = postMessage[i].indexOf('=');
1388
   /**
1389
    * @description Parses the POST data and creates hidden form elements
1390
    * for each key-value, and appends them to the HTML form object.
1391
    * @method appendPostData
1392
    * @private
1393
    * @static
1394
    * @param {string} postData The HTTP POST data
1395
    * @return {array} formElements Collection of hidden fields.
1396
    */
1397
	function _appendPostData(postData){
1398
		var formElements = [],
1399
			postMessage = postData.split('&'),
1400
			i, delimitPos;
1401

  
1402
		for(i=0; i < postMessage.length; i++){
1403
			delimitPos = postMessage[i].indexOf('=');
1116 1404
			if(delimitPos != -1){
1117 1405
				formElements[i] = document.createElement('input');
1118 1406
				formElements[i].type = 'hidden';
1119
				formElements[i].name = postMessage[i].substring(0,delimitPos);
1120
				formElements[i].value = postMessage[i].substring(delimitPos+1);
1407
				formElements[i].name = decodeURIComponent(postMessage[i].substring(0,delimitPos));
1408
				formElements[i].value = decodeURIComponent(postMessage[i].substring(delimitPos+1));
1121 1409
				this._formNode.appendChild(formElements[i]);
1122 1410
			}
1123 1411
		}
1124 1412

  
1125 1413
		return formElements;
1126
	},
1414
	}
1127 1415

  
1128
  /**
1129
   * @description Uploads HTML form, inclusive of files/attachments, using the
1130
   * iframe created in createFrame to facilitate the transaction.
1131
   * @method uploadFile
1132
   * @private
1133
   * @static
1134
   * @param {int} id The transaction id.
1135
   * @param {object} callback User-defined callback object.
1136
   * @param {string} uri Fully qualified path of resource.
1137
   * @param {string} postData POST data to be submitted in addition to HTML form.
1138
   * @return {void}
1139
   */
1140
	uploadFile:function(o, callback, uri, postData){
1141

  
1416
   /**
1417
    * @description Uploads HTML form, inclusive of files/attachments, using the
1418
    * iframe created in createFrame to facilitate the transaction.
1419
    * @method uploadFile
1420
    * @private
1421
    * @static
1422
    * @param {int} id The transaction id.
1423
    * @param {object} callback User-defined callback object.
1424
    * @param {string} uri Fully qualified path of resource.
1425
    * @param {string} postData POST data to be submitted in addition to HTML form.
1426
    * @return {void}
1427
    */
1428
	function _uploadFile(o, callback, uri, postData){
1142 1429
		// Each iframe has an id prefix of "yuiIO" followed
1143 1430
		// by the unique transaction id.
1144
		var oConn = this;
1145
		var frameId = 'yuiIO' + o.tId;
1146
		var uploadEncoding = 'multipart/form-data';
1147
		var io = document.getElementById(frameId);
1148
		var args = (callback && callback.argument)?callback.argument:null;
1431
		var frameId = 'yuiIO' + o.tId,
1432
		    uploadEncoding = 'multipart/form-data',
1433
		    io = document.getElementById(frameId),
1434
		    ie8 = (document.documentMode && document.documentMode === 8) ? true : false,
1435
		    oConn = this,
1436
			args = (callback && callback.argument)?callback.argument:null,
1437
            oElements,i,prop,obj, rawFormAttributes, uploadCallback;
1149 1438

  
1150 1439
		// Track original HTML form attribute values.
1151
		var rawFormAttributes =
1152
		{
1440
		rawFormAttributes = {
1153 1441
			action:this._formNode.getAttribute('action'),
1154 1442
			method:this._formNode.getAttribute('method'),
1155 1443
			target:this._formNode.getAttribute('target')
......
1161 1449
		this._formNode.setAttribute('method', 'POST');
1162 1450
		this._formNode.setAttribute('target', frameId);
1163 1451

  
1164
		if(this._formNode.encoding){
1452
		if(YAHOO.env.ua.ie && !ie8){
1165 1453
			// IE does not respect property enctype for HTML forms.
1166 1454
			// Instead it uses the property - "encoding".
1167 1455
			this._formNode.setAttribute('encoding', uploadEncoding);
......
1171 1459
		}
1172 1460

  
1173 1461
		if(postData){
1174
			var oElements = this.appendPostData(postData);
1462
			oElements = this.appendPostData(postData);
1175 1463
		}
1176 1464

  
1177 1465
		// Start file upload.
......
1193 1481

  
1194 1482
		// Remove HTML elements created by appendPostData
1195 1483
		if(oElements && oElements.length > 0){
1196
			for(var i=0; i < oElements.length; i++){
1484
			for(i=0; i < oElements.length; i++){
1197 1485
				this._formNode.removeChild(oElements[i]);
1198 1486
			}
1199 1487
		}
1200 1488

  
1201 1489
		// Restore HTML form attributes to their original
1202 1490
		// values prior to file upload.
1203
		for(var prop in rawFormAttributes){
1491
		for(prop in rawFormAttributes){
1204 1492
			if(YAHOO.lang.hasOwnProperty(rawFormAttributes, prop)){
1205 1493
				if(rawFormAttributes[prop]){
1206 1494
					this._formNode.setAttribute(prop, rawFormAttributes[prop]);
......
1217 1505
		// Create the upload callback handler that fires when the iframe
1218 1506
		// receives the load event.  Subsequently, the event handler is detached
1219 1507
		// and the iframe removed from the document.
1220
		var uploadCallback = function()
1221
		{
1508
		uploadCallback = function() {
1222 1509
			if(callback && callback.timeout){
1223 1510
				window.clearTimeout(oConn._timeOut[o.tId]);
1224 1511
				delete oConn._timeOut[o.tId];
......
1232 1519
				o.completeEvent.fire(o, args);
1233 1520
			}
1234 1521

  
1235
			var obj = {};
1236
			obj.tId = o.tId;
1237
			obj.argument = callback.argument;
1522
			obj = {
1523
			    tId : o.tId,
1524
			    argument : callback.argument
1525
            };
1238 1526

  
1239 1527
			try
1240 1528
			{
......
1264 1552
				o.uploadEvent.fire(obj);
1265 1553
			}
1266 1554

  
1267
			YAHOO.util.Event.removeListener(io, "load", uploadCallback);
1555
			YE.removeListener(io, "load", uploadCallback);
1268 1556

  
1269 1557
			setTimeout(
1270 1558
				function(){
......
1275 1563
		};
1276 1564

  
1277 1565
		// Bind the onload handler to the iframe to detect the file upload response.
1278
		YAHOO.util.Event.addListener(io, "load", uploadCallback);
1279
	},
1566
		YE.addListener(io, "load", uploadCallback);
1567
	}
1280 1568

  
1281
  /**
1282
   * @description Method to terminate a transaction, if it has not reached readyState 4.
1283
   * @method abort
1284
   * @public
1285
   * @static
1286
   * @param {object} o The connection object returned by asyncRequest.
1287
   * @param {object} callback  User-defined callback object.
1288
   * @param {string} isTimeout boolean to indicate if abort resulted from a callback timeout.
1289
   * @return {boolean}
1290
   */
1291
	abort:function(o, callback, isTimeout)
1292
	{
1293
		var abortStatus;
1294
		var args = (callback && callback.argument)?callback.argument:null;
1569
	YCM.setForm = _setForm;
1570
	YCM.resetFormState = _resetFormState;
1571
	YCM.createFrame = _createFrame;
1572
	YCM.appendPostData = _appendPostData;
1573
	YCM.uploadFile = _uploadFile;
1574
})();
1295 1575

  
1296

  
1297
		if(o && o.conn){
1298
			if(this.isCallInProgress(o)){
1299
				// Issue abort request
1300
				o.conn.abort();
1301

  
1302
				window.clearInterval(this._poll[o.tId]);
1303
				delete this._poll[o.tId];
1304

  
1305
				if(isTimeout){
1306
					window.clearTimeout(this._timeOut[o.tId]);
1307
					delete this._timeOut[o.tId];
1308
				}
1309

  
1310
				abortStatus = true;
1311
			}
1312
		}
1313
		else if(o && o.isUpload === true){
1314
			var frameId = 'yuiIO' + o.tId;
1315
			var io = document.getElementById(frameId);
1316

  
1317
			if(io){
1318
				// Remove all listeners on the iframe prior to
1319
				// its destruction.
1320
				YAHOO.util.Event.removeListener(io, "load");
1321
				// Destroy the iframe facilitating the transaction.
1322
				document.body.removeChild(io);
1323
				YAHOO.log('File upload iframe destroyed. Id is:' + frameId, 'info', 'Connection');
1324

  
1325
				if(isTimeout){
1326
					window.clearTimeout(this._timeOut[o.tId]);
1327
					delete this._timeOut[o.tId];
1328
				}
1329

  
1330
				abortStatus = true;
1331
			}
1332
		}
1333
		else{
1334
			abortStatus = false;
1335
		}
1336

  
1337
		if(abortStatus === true){
1338
			// Fire global custom event -- abortEvent
1339
			this.abortEvent.fire(o, args);
1340

  
1341
			if(o.abortEvent){
1342
				// Fire transaction custom event -- abortEvent
1343
				o.abortEvent.fire(o, args);
1344
			}
1345

  
1346
			this.handleTransactionResponse(o, callback, true);
1347
			YAHOO.log('Transaction ' + o.tId + ' aborted.', 'info', 'Connection');
1348
		}
1349

  
1350
		return abortStatus;
1351
	},
1352

  
1353
  /**
1354
   * @description Determines if the transaction is still being processed.
1355
   * @method isCallInProgress
1356
   * @public
1357
   * @static
1358
   * @param {object} o The connection object returned by asyncRequest
1359
   * @return {boolean}
1360
   */
1361
	isCallInProgress:function(o)
1362
	{
1363
		// if the XHR object assigned to the transaction has not been dereferenced,
1364
		// then check its readyState status.  Otherwise, return false.
1365
		if(o && o.conn){
1366
			return o.conn.readyState !== 4 && o.conn.readyState !== 0;
1367
		}
1368
		else if(o && o.isUpload === true){
1369
			var frameId = 'yuiIO' + o.tId;
1370
			return document.getElementById(frameId)?true:false;
1371
		}
1372
		else{
1373
			return false;
1374
		}
1375
	},
1376

  
1377
  /**
1378
   * @description Dereference the XHR instance and the connection object after the transaction is completed.
1379
   * @method releaseObject
1380
   * @private
1381
   * @static
1382
   * @param {object} o The connection object
1383
   * @return {void}
1384
   */
1385
	releaseObject:function(o)
1386
	{
1387
		if(o && o.conn){
1388
			//dereference the XHR instance.
1389
			o.conn = null;
1390

  
1391
			YAHOO.log('Connection object for transaction ' + o.tId + ' destroyed.', 'info', 'Connection');
1392

  
1393
			//dereference the connection object.
1394
			o = null;
1395
		}
1396
	}
1397
};
1398

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

Also available in: Unified diff