Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('yui2-connectioncore', function(Y) { Y.use('yui2-connection'); }, '3.3.0' ,{"requires": ["yui2-yahoo", "yui2-event"]});
2
YUI.add('yui2-connection', function(Y) {
3
    var YAHOO    = Y.YUI2;
4
    /*
5
Copyright (c) 2011, Yahoo! Inc. All rights reserved.
6
Code licensed under the BSD License:
7
http://developer.yahoo.com/yui/license.html
8
version: 2.9.0
9
*/
10
/**
11
 * The Connection Manager provides a simplified interface to the XMLHttpRequest
12
 * object.  It handles cross-browser instantiantion of XMLHttpRequest, negotiates the
13
 * interactive states and server response, returning the results to a pre-defined
14
 * callback you create.
15
 *
16
 * @namespace YAHOO.util
17
 * @module connection
18
 * @requires yahoo
19
 * @requires event
20
 */
21
 
22
/**
23
 * The Connection Manager singleton provides methods for creating and managing
24
 * asynchronous transactions.
25
 *
26
 * @class YAHOO.util.Connect
27
 */
28
 
29
YAHOO.util.Connect =
30
{
31
  /**
32
   * @description Array of MSFT ActiveX ids for XMLHttpRequest.
33
   * @property _msxml_progid
34
   * @private
35
   * @static
36
   * @type array
37
   */
38
    _msxml_progid:[
39
        'Microsoft.XMLHTTP',
40
        'MSXML2.XMLHTTP.3.0',
41
        'MSXML2.XMLHTTP'
42
        ],
43
 
44
  /**
45
   * @description Object literal of HTTP header(s)
46
   * @property _http_header
47
   * @private
48
   * @static
49
   * @type object
50
   */
51
    _http_headers:{},
52
 
53
  /**
54
   * @description Determines if HTTP headers are set.
55
   * @property _has_http_headers
56
   * @private
57
   * @static
58
   * @type boolean
59
   */
60
    _has_http_headers:false,
61
 
62
 /**
63
  * @description Determines if a default header of
64
  * Content-Type of 'application/x-www-form-urlencoded'
65
  * will be added to any client HTTP headers sent for POST
66
  * transactions.
67
  * @property _use_default_post_header
68
  * @private
69
  * @static
70
  * @type boolean
71
  */
72
    _use_default_post_header:true,
73
 
74
 /**
75
  * @description The default header used for POST transactions.
76
  * @property _default_post_header
77
  * @private
78
  * @static
79
  * @type boolean
80
  */
81
    _default_post_header:'application/x-www-form-urlencoded; charset=UTF-8',
82
 
83
 /**
84
  * @description The default header used for transactions involving the
85
  * use of HTML forms.
86
  * @property _default_form_header
87
  * @private
88
  * @static
89
  * @type boolean
90
  */
91
    _default_form_header:'application/x-www-form-urlencoded',
92
 
93
 /**
94
  * @description Determines if a default header of
95
  * 'X-Requested-With: XMLHttpRequest'
96
  * will be added to each transaction.
97
  * @property _use_default_xhr_header
98
  * @private
99
  * @static
100
  * @type boolean
101
  */
102
    _use_default_xhr_header:true,
103
 
104
 /**
105
  * @description The default header value for the label
106
  * "X-Requested-With".  This is sent with each
107
  * transaction, by default, to identify the
108
  * request as being made by YUI Connection Manager.
109
  * @property _default_xhr_header
110
  * @private
111
  * @static
112
  * @type boolean
113
  */
114
    _default_xhr_header:'XMLHttpRequest',
115
 
116
 /**
117
  * @description Determines if custom, default headers
118
  * are set for each transaction.
119
  * @property _has_default_header
120
  * @private
121
  * @static
122
  * @type boolean
123
  */
124
    _has_default_headers:true,
125
 
126
 /**
127
   * @description Property modified by setForm() to determine if the data
128
   * should be submitted as an HTML form.
129
   * @property _isFormSubmit
130
   * @private
131
   * @static
132
   * @type boolean
133
   */
134
	_isFormSubmit:false,
135
 
136
 /**
137
  * @description Determines if custom, default headers
138
  * are set for each transaction.
139
  * @property _has_default_header
140
  * @private
141
  * @static
142
  * @type boolean
143
  */
144
    _default_headers:{},
145
 
146
 /**
147
  * @description Collection of polling references to the polling mechanism in handleReadyState.
148
  * @property _poll
149
  * @private
150
  * @static
151
  * @type object
152
  */
153
    _poll:{},
154
 
155
 /**
156
  * @description Queue of timeout values for each transaction callback with a defined timeout value.
157
  * @property _timeOut
158
  * @private
159
  * @static
160
  * @type object
161
  */
162
    _timeOut:{},
163
 
164
  /**
165
   * @description The polling frequency, in milliseconds, for HandleReadyState.
166
   * when attempting to determine a transaction's XHR readyState.
167
   * The default is 50 milliseconds.
168
   * @property _polling_interval
169
   * @private
170
   * @static
171
   * @type int
172
   */
173
     _polling_interval:50,
174
 
175
  /**
176
   * @description A transaction counter that increments the transaction id for each transaction.
177
   * @property _transaction_id
178
   * @private
179
   * @static
180
   * @type int
181
   */
182
     _transaction_id:0,
183
 
184
  /**
185
   * @description Custom event that fires at the start of a transaction
186
   * @property startEvent
187
   * @private
188
   * @static
189
   * @type CustomEvent
190
   */
191
    startEvent: new YAHOO.util.CustomEvent('start'),
192
 
193
  /**
194
   * @description Custom event that fires when a transaction response has completed.
195
   * @property completeEvent
196
   * @private
197
   * @static
198
   * @type CustomEvent
199
   */
200
    completeEvent: new YAHOO.util.CustomEvent('complete'),
201
 
202
  /**
203
   * @description Custom event that fires when handleTransactionResponse() determines a
204
   * response in the HTTP 2xx range.
205
   * @property successEvent
206
   * @private
207
   * @static
208
   * @type CustomEvent
209
   */
210
    successEvent: new YAHOO.util.CustomEvent('success'),
211
 
212
  /**
213
   * @description Custom event that fires when handleTransactionResponse() determines a
214
   * response in the HTTP 4xx/5xx range.
215
   * @property failureEvent
216
   * @private
217
   * @static
218
   * @type CustomEvent
219
   */
220
    failureEvent: new YAHOO.util.CustomEvent('failure'),
221
 
222
  /**
223
   * @description Custom event that fires when a transaction is successfully aborted.
224
   * @property abortEvent
225
   * @private
226
   * @static
227
   * @type CustomEvent
228
   */
229
    abortEvent: new YAHOO.util.CustomEvent('abort'),
230
 
231
  /**
232
   * @description A reference table that maps callback custom events members to its specific
233
   * event name.
234
   * @property _customEvents
235
   * @private
236
   * @static
237
   * @type object
238
   */
239
    _customEvents:
240
    {
241
        onStart:['startEvent', 'start'],
242
        onComplete:['completeEvent', 'complete'],
243
        onSuccess:['successEvent', 'success'],
244
        onFailure:['failureEvent', 'failure'],
245
        onUpload:['uploadEvent', 'upload'],
246
        onAbort:['abortEvent', 'abort']
247
    },
248
 
249
  /**
250
   * @description Member to add an ActiveX id to the existing xml_progid array.
251
   * In the event(unlikely) a new ActiveX id is introduced, it can be added
252
   * without internal code modifications.
253
   * @method setProgId
254
   * @public
255
   * @static
256
   * @param {string} id The ActiveX id to be added to initialize the XHR object.
257
   * @return void
258
   */
259
    setProgId:function(id)
260
    {
261
        this._msxml_progid.unshift(id);
262
        YAHOO.log('ActiveX Program Id  ' + id + ' added to _msxml_progid.', 'info', 'Connection');
263
    },
264
 
265
  /**
266
   * @description Member to override the default POST header.
267
   * @method setDefaultPostHeader
268
   * @public
269
   * @static
270
   * @param {boolean} b Set and use default header - true or false .
271
   * @return void
272
   */
273
    setDefaultPostHeader:function(b)
274
    {
275
        if(typeof b == 'string'){
276
            this._default_post_header = b;
277
			this._use_default_post_header = true;
278
 
279
            YAHOO.log('Default POST header set to  ' + b, 'info', 'Connection');
280
        }
281
        else if(typeof b == 'boolean'){
282
            this._use_default_post_header = b;
283
        }
284
    },
285
 
286
  /**
287
   * @description Member to override the default transaction header..
288
   * @method setDefaultXhrHeader
289
   * @public
290
   * @static
291
   * @param {boolean} b Set and use default header - true or false .
292
   * @return void
293
   */
294
    setDefaultXhrHeader:function(b)
295
    {
296
        if(typeof b == 'string'){
297
            this._default_xhr_header = b;
298
            YAHOO.log('Default XHR header set to  ' + b, 'info', 'Connection');
299
        }
300
        else{
301
            this._use_default_xhr_header = b;
302
        }
303
    },
304
 
305
  /**
306
   * @description Member to modify the default polling interval.
307
   * @method setPollingInterval
308
   * @public
309
   * @static
310
   * @param {int} i The polling interval in milliseconds.
311
   * @return void
312
   */
313
    setPollingInterval:function(i)
314
    {
315
        if(typeof i == 'number' && isFinite(i)){
316
            this._polling_interval = i;
317
            YAHOO.log('Default polling interval set to ' + i +'ms', 'info', 'Connection');
318
        }
319
    },
320
 
321
  /**
322
   * @description Instantiates a XMLHttpRequest object and returns an object with two properties:
323
   * the XMLHttpRequest instance and the transaction id.
324
   * @method createXhrObject
325
   * @private
326
   * @static
327
   * @param {int} transactionId Property containing the transaction id for this transaction.
328
   * @return object
329
   */
330
    createXhrObject:function(transactionId)
331
    {
332
        var obj,http,i;
333
        try
334
        {
335
            // Instantiates XMLHttpRequest in non-IE browsers and assigns to http.
336
            http = new XMLHttpRequest();
337
            //  Object literal with http and tId properties
338
            obj = { conn:http, tId:transactionId, xhr: true };
339
            YAHOO.log('XHR object created for transaction ' + transactionId, 'info', 'Connection');
340
        }
341
        catch(e)
342
        {
343
            for(i=0; i<this._msxml_progid.length; ++i){
344
                try
345
                {
346
                    // Instantiates XMLHttpRequest for IE and assign to http
347
                    http = new ActiveXObject(this._msxml_progid[i]);
348
                    //  Object literal with conn and tId properties
349
                    obj = { conn:http, tId:transactionId, xhr: true };
350
                    YAHOO.log('ActiveX XHR object created for transaction ' + transactionId, 'info', 'Connection');
351
                    break;
352
                }
353
                catch(e1){}
354
            }
355
        }
356
        finally
357
        {
358
            return obj;
359
        }
360
    },
361
 
362
  /**
363
   * @description This method is called by asyncRequest to create a
364
   * valid connection object for the transaction.  It also passes a
365
   * transaction id and increments the transaction id counter.
366
   * @method getConnectionObject
367
   * @private
368
   * @static
369
   * @return {object}
370
   */
371
    getConnectionObject:function(t)
372
    {
373
        var o, tId = this._transaction_id;
374
 
375
        try
376
        {
377
            if(!t){
378
                o = this.createXhrObject(tId);
379
            }
380
            else{
381
                o = {tId:tId};
382
                if(t==='xdr'){
383
                    o.conn = this._transport;
384
                    o.xdr = true;
385
                }
386
                else if(t==='upload'){
387
                    o.upload = true;
388
                }
389
            }
390
 
391
            if(o){
392
                this._transaction_id++;
393
            }
394
        }
395
        catch(e){}
396
        return o;
397
    },
398
 
399
  /**
400
   * @description Method for initiating an asynchronous request via the XHR object.
401
   * @method asyncRequest
402
   * @public
403
   * @static
404
   * @param {string} method HTTP transaction method
405
   * @param {string} uri Fully qualified path of resource
406
   * @param {callback} callback User-defined callback function or object
407
   * @param {string} postData POST body
408
   * @return {object} Returns the connection object
409
   */
410
    asyncRequest:function(method, uri, callback, postData)
411
    {
412
        var args = callback&&callback.argument?callback.argument:null,
413
            YCM = this,
414
            o, t;
415
 
416
        if(this._isFileUpload){
417
            t = 'upload';
418
        }
419
        else if(callback && callback.xdr){
420
            t = 'xdr';
421
        }
422
 
423
        o = this.getConnectionObject(t);
424
        if(!o){
425
            YAHOO.log('Unable to create connection object.', 'error', 'Connection');
426
            return null;
427
        }
428
        else{
429
 
430
            // Intialize any transaction-specific custom events, if provided.
431
            if(callback && callback.customevents){
432
                this.initCustomEvents(o, callback);
433
            }
434
 
435
            if(this._isFormSubmit){
436
                if(this._isFileUpload){
437
                    window.setTimeout(function(){YCM.uploadFile(o, callback, uri, postData);}, 10);
438
                    return o;
439
                }
440
 
441
                // If the specified HTTP method is GET, setForm() will return an
442
                // encoded string that is concatenated to the uri to
443
                // create a querystring.
444
                if(method.toUpperCase() == 'GET'){
445
                    if(this._sFormData.length !== 0){
446
                        // If the URI already contains a querystring, append an ampersand
447
                        // and then concatenate _sFormData to the URI.
448
                        uri += ((uri.indexOf('?') == -1)?'?':'&') + this._sFormData;
449
                    }
450
                }
451
                else if(method.toUpperCase() == 'POST'){
452
                    // If POST data exist in addition to the HTML form data,
453
                    // it will be concatenated to the form data.
454
                    postData = postData?this._sFormData + "&" + postData:this._sFormData;
455
                }
456
            }
457
 
458
            if(method.toUpperCase() == 'GET' && (callback && callback.cache === false)){
459
                // If callback.cache is defined and set to false, a
460
                // timestamp value will be added to the querystring.
461
                uri += ((uri.indexOf('?') == -1)?'?':'&') + "rnd=" + new Date().valueOf().toString();
462
            }
463
 
464
            // Each transaction will automatically include a custom header of
465
            // "X-Requested-With: XMLHttpRequest" to identify the request as
466
            // having originated from Connection Manager.
467
            if(this._use_default_xhr_header){
468
                if(!this._default_headers['X-Requested-With']){
469
                    this.initHeader('X-Requested-With', this._default_xhr_header, true);
470
                    YAHOO.log('Initialize transaction header X-Request-Header to XMLHttpRequest.', 'info', 'Connection');
471
                }
472
            }
473
 
474
            //If the transaction method is POST and the POST header value is set to true
475
            //or a custom value, initalize the Content-Type header to this value.
476
            if((method.toUpperCase() === 'POST' && this._use_default_post_header) && this._isFormSubmit === false){
477
                this.initHeader('Content-Type', this._default_post_header);
478
                YAHOO.log('Initialize header Content-Type to application/x-www-form-urlencoded; UTF-8 for POST transaction.', 'info', 'Connection');
479
            }
480
 
481
            if(o.xdr){
482
                this.xdr(o, method, uri, callback, postData);
483
                return o;
484
            }
485
 
486
            o.conn.open(method, uri, true);
487
            //Initialize all default and custom HTTP headers,
488
            if(this._has_default_headers || this._has_http_headers){
489
                this.setHeader(o);
490
            }
491
 
492
            this.handleReadyState(o, callback);
493
            o.conn.send(postData || '');
494
            YAHOO.log('Transaction ' + o.tId + ' sent.', 'info', 'Connection');
495
 
496
            // Reset the HTML form data and state properties as
497
            // soon as the data are submitted.
498
            if(this._isFormSubmit === true){
499
                this.resetFormState();
500
            }
501
 
502
            // Fire global custom event -- startEvent
503
            this.startEvent.fire(o, args);
504
 
505
            if(o.startEvent){
506
                // Fire transaction custom event -- startEvent
507
                o.startEvent.fire(o, args);
508
            }
509
 
510
            return o;
511
        }
512
    },
513
 
514
  /**
515
   * @description This method creates and subscribes custom events,
516
   * specific to each transaction
517
   * @method initCustomEvents
518
   * @private
519
   * @static
520
   * @param {object} o The connection object
521
   * @param {callback} callback The user-defined callback object
522
   * @return {void}
523
   */
524
    initCustomEvents:function(o, callback)
525
    {
526
        var prop;
527
        // Enumerate through callback.customevents members and bind/subscribe
528
        // events that match in the _customEvents table.
529
        for(prop in callback.customevents){
530
            if(this._customEvents[prop][0]){
531
                // Create the custom event
532
                o[this._customEvents[prop][0]] = new YAHOO.util.CustomEvent(this._customEvents[prop][1], (callback.scope)?callback.scope:null);
533
                YAHOO.log('Transaction-specific Custom Event ' + o[this._customEvents[prop][1]] + ' created.', 'info', 'Connection');
534
 
535
                // Subscribe the custom event
536
                o[this._customEvents[prop][0]].subscribe(callback.customevents[prop]);
537
                YAHOO.log('Transaction-specific Custom Event ' + o[this._customEvents[prop][1]] + ' subscribed.', 'info', 'Connection');
538
            }
539
        }
540
    },
541
 
542
  /**
543
   * @description This method serves as a timer that polls the XHR object's readyState
544
   * property during a transaction, instead of binding a callback to the
545
   * onreadystatechange event.  Upon readyState 4, handleTransactionResponse
546
   * will process the response, and the timer will be cleared.
547
   * @method handleReadyState
548
   * @private
549
   * @static
550
   * @param {object} o The connection object
551
   * @param {callback} callback The user-defined callback object
552
   * @return {void}
553
   */
554
 
555
    handleReadyState:function(o, callback)
556
 
557
    {
558
        var oConn = this,
559
            args = (callback && callback.argument)?callback.argument:null;
560
 
561
        if(callback && callback.timeout){
562
            this._timeOut[o.tId] = window.setTimeout(function(){ oConn.abort(o, callback, true); }, callback.timeout);
563
        }
564
 
565
        this._poll[o.tId] = window.setInterval(
566
            function(){
567
                if(o.conn && o.conn.readyState === 4){
568
 
569
                    // Clear the polling interval for the transaction
570
                    // and remove the reference from _poll.
571
                    window.clearInterval(oConn._poll[o.tId]);
572
                    delete oConn._poll[o.tId];
573
 
574
                    if(callback && callback.timeout){
575
                        window.clearTimeout(oConn._timeOut[o.tId]);
576
                        delete oConn._timeOut[o.tId];
577
                    }
578
 
579
                    // Fire global custom event -- completeEvent
580
                    oConn.completeEvent.fire(o, args);
581
 
582
                    if(o.completeEvent){
583
                        // Fire transaction custom event -- completeEvent
584
                        o.completeEvent.fire(o, args);
585
                    }
586
 
587
                    oConn.handleTransactionResponse(o, callback);
588
                }
589
            }
590
        ,this._polling_interval);
591
    },
592
 
593
  /**
594
   * @description This method attempts to interpret the server response and
595
   * determine whether the transaction was successful, or if an error or
596
   * exception was encountered.
597
   * @method handleTransactionResponse
598
   * @private
599
   * @static
600
   * @param {object} o The connection object
601
   * @param {object} callback The user-defined callback object
602
   * @param {boolean} isAbort Determines if the transaction was terminated via abort().
603
   * @return {void}
604
   */
605
    handleTransactionResponse:function(o, callback, isAbort)
606
    {
607
        var httpStatus, responseObject,
608
            args = (callback && callback.argument)?callback.argument:null,
609
            xdrS = (o.r && o.r.statusText === 'xdr:success')?true:false,
610
            xdrF = (o.r && o.r.statusText === 'xdr:failure')?true:false,
611
            xdrA = isAbort;
612
 
613
        try
614
        {
615
            if((o.conn.status !== undefined && o.conn.status !== 0) || xdrS){
616
                // XDR requests will not have HTTP status defined. The
617
                // statusText property will define the response status
618
                // set by the Flash transport.
619
                httpStatus = o.conn.status;
620
            }
621
            else if(xdrF && !xdrA){
622
                // Set XDR transaction failure to a status of 0, which
623
                // resolves as an HTTP failure, instead of an exception.
624
                httpStatus = 0;
625
            }
626
            else{
627
                httpStatus = 13030;
628
            }
629
        }
630
        catch(e){
631
 
632
             // 13030 is a custom code to indicate the condition -- in Mozilla/FF --
633
             // when the XHR object's status and statusText properties are
634
             // unavailable, and a query attempt throws an exception.
635
            httpStatus = 13030;
636
        }
637
 
638
        if((httpStatus >= 200 && httpStatus < 300) || httpStatus === 1223 || xdrS){
639
            responseObject = o.xdr ? o.r : this.createResponseObject(o, args);
640
            if(callback && callback.success){
641
                if(!callback.scope){
642
                    callback.success(responseObject);
643
                    YAHOO.log('Success callback. HTTP code is ' + httpStatus, 'info', 'Connection');
644
                }
645
                else{
646
                    // If a scope property is defined, the callback will be fired from
647
                    // the context of the object.
648
                    callback.success.apply(callback.scope, [responseObject]);
649
                    YAHOO.log('Success callback with scope. HTTP code is ' + httpStatus, 'info', 'Connection');
650
                }
651
            }
652
 
653
            // Fire global custom event -- successEvent
654
            this.successEvent.fire(responseObject);
655
 
656
            if(o.successEvent){
657
                // Fire transaction custom event -- successEvent
658
                o.successEvent.fire(responseObject);
659
            }
660
        }
661
        else{
662
            switch(httpStatus){
663
                // The following cases are wininet.dll error codes that may be encountered.
664
                case 12002: // Server timeout
665
                case 12029: // 12029 to 12031 correspond to dropped connections.
666
                case 12030:
667
                case 12031:
668
                case 12152: // Connection closed by server.
669
                case 13030: // See above comments for variable status.
670
                    // XDR transactions will not resolve to this case, since the
671
                    // response object is already built in the xdr response.
672
                    responseObject = this.createExceptionObject(o.tId, args, (isAbort?isAbort:false));
673
                    if(callback && callback.failure){
674
                        if(!callback.scope){
675
                            callback.failure(responseObject);
676
                            YAHOO.log('Failure callback. Exception detected. Status code is ' + httpStatus, 'warn', 'Connection');
677
                        }
678
                        else{
679
                            callback.failure.apply(callback.scope, [responseObject]);
680
                            YAHOO.log('Failure callback with scope. Exception detected. Status code is ' + httpStatus, 'warn', 'Connection');
681
                        }
682
                    }
683
 
684
                    break;
685
                default:
686
                    responseObject = (o.xdr) ? o.response : this.createResponseObject(o, args);
687
                    if(callback && callback.failure){
688
                        if(!callback.scope){
689
                            callback.failure(responseObject);
690
                            YAHOO.log('Failure callback. HTTP status code is ' + httpStatus, 'warn', 'Connection');
691
                        }
692
                        else{
693
                            callback.failure.apply(callback.scope, [responseObject]);
694
                            YAHOO.log('Failure callback with scope. HTTP status code is ' + httpStatus, 'warn', 'Connection');
695
                        }
696
                    }
697
            }
698
 
699
            // Fire global custom event -- failureEvent
700
            this.failureEvent.fire(responseObject);
701
 
702
            if(o.failureEvent){
703
                // Fire transaction custom event -- failureEvent
704
                o.failureEvent.fire(responseObject);
705
            }
706
 
707
        }
708
 
709
        this.releaseObject(o);
710
        responseObject = null;
711
    },
712
 
713
  /**
714
   * @description This method evaluates the server response, creates and returns the results via
715
   * its properties.  Success and failure cases will differ in the response
716
   * object's property values.
717
   * @method createResponseObject
718
   * @private
719
   * @static
720
   * @param {object} o The connection object
721
   * @param {callbackArg} callbackArg The user-defined argument or arguments to be passed to the callback
722
   * @return {object}
723
   */
724
    createResponseObject:function(o, callbackArg)
725
    {
726
        var obj = {}, headerObj = {},
727
            i, headerStr, header, delimitPos;
728
 
729
        try
730
        {
731
            headerStr = o.conn.getAllResponseHeaders();
732
            header = headerStr.split('\n');
733
            for(i=0; i<header.length; i++){
734
                delimitPos = header[i].indexOf(':');
735
                if(delimitPos != -1){
736
                    headerObj[header[i].substring(0,delimitPos)] = YAHOO.lang.trim(header[i].substring(delimitPos+2));
737
                }
738
            }
739
        }
740
        catch(e){}
741
 
742
        obj.tId = o.tId;
743
        // Normalize IE's response to HTTP 204 when Win error 1223.
744
        obj.status = (o.conn.status == 1223)?204:o.conn.status;
745
        // Normalize IE's statusText to "No Content" instead of "Unknown".
746
        obj.statusText = (o.conn.status == 1223)?"No Content":o.conn.statusText;
747
        obj.getResponseHeader = headerObj;
748
        obj.getAllResponseHeaders = headerStr;
749
        obj.responseText = o.conn.responseText;
750
        obj.responseXML = o.conn.responseXML;
751
 
752
        if(callbackArg){
753
            obj.argument = callbackArg;
754
        }
755
 
756
        return obj;
757
    },
758
 
759
  /**
760
   * @description If a transaction cannot be completed due to dropped or closed connections,
761
   * there may be not be enough information to build a full response object.
762
   * The failure callback will be fired and this specific condition can be identified
763
   * by a status property value of 0.
764
   *
765
   * If an abort was successful, the status property will report a value of -1.
766
   *
767
   * @method createExceptionObject
768
   * @private
769
   * @static
770
   * @param {int} tId The Transaction Id
771
   * @param {callbackArg} callbackArg The user-defined argument or arguments to be passed to the callback
772
   * @param {boolean} isAbort Determines if the exception case is caused by a transaction abort
773
   * @return {object}
774
   */
775
    createExceptionObject:function(tId, callbackArg, isAbort)
776
    {
777
        var COMM_CODE = 0,
778
            COMM_ERROR = 'communication failure',
779
            ABORT_CODE = -1,
780
            ABORT_ERROR = 'transaction aborted',
781
            obj = {};
782
 
783
        obj.tId = tId;
784
        if(isAbort){
785
            obj.status = ABORT_CODE;
786
            obj.statusText = ABORT_ERROR;
787
        }
788
        else{
789
            obj.status = COMM_CODE;
790
            obj.statusText = COMM_ERROR;
791
        }
792
 
793
        if(callbackArg){
794
            obj.argument = callbackArg;
795
        }
796
 
797
        return obj;
798
    },
799
 
800
  /**
801
   * @description Method that initializes the custom HTTP headers for the each transaction.
802
   * @method initHeader
803
   * @public
804
   * @static
805
   * @param {string} label The HTTP header label
806
   * @param {string} value The HTTP header value
807
   * @param {string} isDefault Determines if the specific header is a default header
808
   * automatically sent with each transaction.
809
   * @return {void}
810
   */
811
    initHeader:function(label, value, isDefault)
812
    {
813
        var headerObj = (isDefault)?this._default_headers:this._http_headers;
814
 
815
        headerObj[label] = value;
816
        if(isDefault){
817
            this._has_default_headers = true;
818
        }
819
        else{
820
            this._has_http_headers = true;
821
        }
822
    },
823
 
824
 
825
  /**
826
   * @description Accessor that sets the HTTP headers for each transaction.
827
   * @method setHeader
828
   * @private
829
   * @static
830
   * @param {object} o The connection object for the transaction.
831
   * @return {void}
832
   */
833
    setHeader:function(o)
834
    {
835
        var prop;
836
        if(this._has_default_headers){
837
            for(prop in this._default_headers){
838
                if(YAHOO.lang.hasOwnProperty(this._default_headers, prop)){
839
                    o.conn.setRequestHeader(prop, this._default_headers[prop]);
840
                    YAHOO.log('Default HTTP header ' + prop + ' set with value of ' + this._default_headers[prop], 'info', 'Connection');
841
                }
842
            }
843
        }
844
 
845
        if(this._has_http_headers){
846
            for(prop in this._http_headers){
847
                if(YAHOO.lang.hasOwnProperty(this._http_headers, prop)){
848
                    o.conn.setRequestHeader(prop, this._http_headers[prop]);
849
                    YAHOO.log('HTTP header ' + prop + ' set with value of ' + this._http_headers[prop], 'info', 'Connection');
850
                }
851
            }
852
 
853
            this._http_headers = {};
854
            this._has_http_headers = false;
855
        }
856
    },
857
 
858
  /**
859
   * @description Resets the default HTTP headers object
860
   * @method resetDefaultHeaders
861
   * @public
862
   * @static
863
   * @return {void}
864
   */
865
    resetDefaultHeaders:function(){
866
        this._default_headers = {};
867
        this._has_default_headers = false;
868
    },
869
 
870
  /**
871
   * @description Method to terminate a transaction, if it has not reached readyState 4.
872
   * @method abort
873
   * @public
874
   * @static
875
   * @param {object} o The connection object returned by asyncRequest.
876
   * @param {object} callback  User-defined callback object.
877
   * @param {string} isTimeout boolean to indicate if abort resulted from a callback timeout.
878
   * @return {boolean}
879
   */
880
    abort:function(o, callback, isTimeout)
881
    {
882
        var abortStatus,
883
            args = (callback && callback.argument)?callback.argument:null;
884
            o = o || {};
885
 
886
        if(o.conn){
887
            if(o.xhr){
888
                if(this.isCallInProgress(o)){
889
                    // Issue abort request
890
                    o.conn.abort();
891
 
892
                    window.clearInterval(this._poll[o.tId]);
893
                    delete this._poll[o.tId];
894
 
895
                    if(isTimeout){
896
                        window.clearTimeout(this._timeOut[o.tId]);
897
                        delete this._timeOut[o.tId];
898
                    }
899
 
900
                    abortStatus = true;
901
                }
902
            }
903
            else if(o.xdr){
904
                o.conn.abort(o.tId);
905
                abortStatus = true;
906
            }
907
        }
908
        else if(o.upload){
909
            var frameId = 'yuiIO' + o.tId;
910
            var io = document.getElementById(frameId);
911
 
912
            if(io){
913
                // Remove all listeners on the iframe prior to
914
                // its destruction.
915
                YAHOO.util.Event.removeListener(io, "load");
916
                // Destroy the iframe facilitating the transaction.
917
                document.body.removeChild(io);
918
                YAHOO.log('File upload iframe destroyed. Id is:' + frameId, 'info', 'Connection');
919
 
920
                if(isTimeout){
921
                    window.clearTimeout(this._timeOut[o.tId]);
922
                    delete this._timeOut[o.tId];
923
                }
924
 
925
                abortStatus = true;
926
            }
927
        }
928
        else{
929
            abortStatus = false;
930
        }
931
 
932
        if(abortStatus === true){
933
            // Fire global custom event -- abortEvent
934
            this.abortEvent.fire(o, args);
935
 
936
            if(o.abortEvent){
937
                // Fire transaction custom event -- abortEvent
938
                o.abortEvent.fire(o, args);
939
            }
940
 
941
            this.handleTransactionResponse(o, callback, true);
942
            YAHOO.log('Transaction ' + o.tId + ' aborted.', 'info', 'Connection');
943
        }
944
 
945
        return abortStatus;
946
    },
947
 
948
  /**
949
   * @description Determines if the transaction is still being processed.
950
   * @method isCallInProgress
951
   * @public
952
   * @static
953
   * @param {object} o The connection object returned by asyncRequest
954
   * @return {boolean}
955
   */
956
    isCallInProgress:function(o)
957
    {
958
        o = o || {};
959
        // if the XHR object assigned to the transaction has not been dereferenced,
960
        // then check its readyState status.  Otherwise, return false.
961
        if(o.xhr && o.conn){
962
            return o.conn.readyState !== 4 && o.conn.readyState !== 0;
963
        }
964
        else if(o.xdr && o.conn){
965
            return o.conn.isCallInProgress(o.tId);
966
        }
967
        else if(o.upload === true){
968
            return document.getElementById('yuiIO' + o.tId)?true:false;
969
        }
970
        else{
971
            return false;
972
        }
973
    },
974
 
975
  /**
976
   * @description Dereference the XHR instance and the connection object after the transaction is completed.
977
   * @method releaseObject
978
   * @private
979
   * @static
980
   * @param {object} o The connection object
981
   * @return {void}
982
   */
983
    releaseObject:function(o)
984
    {
985
        if(o && o.conn){
986
            //dereference the XHR instance.
987
            o.conn = null;
988
 
989
            YAHOO.log('Connection object for transaction ' + o.tId + ' destroyed.', 'info', 'Connection');
990
 
991
            //dereference the connection object.
992
            o = null;
993
        }
994
    }
995
};
996
 
997
/**
998
  * @for YAHOO.util.Connect
999
  */
1000
(function() {
1001
	var YCM = YAHOO.util.Connect, _fn = {};
1002
 
1003
   /**
1004
    * @description This method creates and instantiates the Flash transport.
1005
    * @method _swf
1006
    * @private
1007
    * @static
1008
    * @param {string} URI to connection.swf.
1009
    * @return {void}
1010
    */
1011
	function _swf(uri) {
1012
		var o = '<object id="YUIConnectionSwf" type="application/x-shockwave-flash" data="' +
1013
				uri + '" width="0" height="0">' +
1014
				'<param name="movie" value="' + uri + '">' +
1015
				'<param name="allowScriptAccess" value="always">' +
1016
				'</object>',
1017
		    c = document.createElement('div');
1018
 
1019
		document.body.appendChild(c);
1020
		c.innerHTML = o;
1021
	}
1022
 
1023
   /**
1024
    * @description This method calls the public method on the
1025
    * Flash transport to start the XDR transaction.  It is analogous
1026
    * to Connection Manager's asyncRequest method.
1027
    * @method xdr
1028
    * @private
1029
    * @static
1030
    * @param {object} The transaction object.
1031
    * @param {string} HTTP request method.
1032
    * @param {string} URI for the transaction.
1033
    * @param {object} The transaction's callback object.
1034
    * @param {object} The JSON object used as HTTP POST data.
1035
    * @return {void}
1036
    */
1037
	function _xdr(o, m, u, c, d) {
1038
		_fn[parseInt(o.tId)] = { 'o':o, 'c':c };
1039
		if (d) {
1040
			c.method = m;
1041
			c.data = d;
1042
		}
1043
 
1044
		o.conn.send(u, c, o.tId);
1045
	}
1046
 
1047
   /**
1048
    * @description This method instantiates the Flash transport and
1049
    * establishes a static reference to it, used for all XDR requests.
1050
    * @method transport
1051
    * @public
1052
    * @static
1053
    * @param {string} URI to connection.swf.
1054
    * @return {void}
1055
    */
1056
	function _init(uri) {
1057
		_swf(uri);
1058
		YCM._transport = document.getElementById('YUIConnectionSwf');
1059
	}
1060
 
1061
	function _xdrReady() {
1062
		YCM.xdrReadyEvent.fire();
1063
	}
1064
 
1065
   /**
1066
    * @description This method fires the global and transaction start
1067
    * events.
1068
    * @method _xdrStart
1069
    * @private
1070
    * @static
1071
    * @param {object} The transaction object.
1072
    * @param {string} The transaction's callback object.
1073
    * @return {void}
1074
    */
1075
	function _xdrStart(o, cb) {
1076
		if (o) {
1077
			// Fire global custom event -- startEvent
1078
			YCM.startEvent.fire(o, cb.argument);
1079
 
1080
			if(o.startEvent){
1081
				// Fire transaction custom event -- startEvent
1082
				o.startEvent.fire(o, cb.argument);
1083
			}
1084
		}
1085
	}
1086
 
1087
   /**
1088
    * @description This method is the initial response handler
1089
    * for XDR transactions.  The Flash transport calls this
1090
    * function and sends the response payload.
1091
    * @method handleXdrResponse
1092
    * @private
1093
    * @static
1094
    * @param {object} The response object sent from the Flash transport.
1095
    * @return {void}
1096
    */
1097
	function _handleXdrResponse(r) {
1098
		var o = _fn[r.tId].o,
1099
			cb = _fn[r.tId].c;
1100
 
1101
		if (r.statusText === 'xdr:start') {
1102
			_xdrStart(o, cb);
1103
			return;
1104
		}
1105
 
1106
		r.responseText = decodeURI(r.responseText);
1107
		o.r = r;
1108
		if (cb.argument) {
1109
			o.r.argument = cb.argument;
1110
		}
1111
 
1112
		this.handleTransactionResponse(o, cb, r.statusText === 'xdr:abort' ? true : false);
1113
		delete _fn[r.tId];
1114
	}
1115
 
1116
	// Bind the functions to Connection Manager as static fields.
1117
	YCM.xdr = _xdr;
1118
	YCM.swf = _swf;
1119
	YCM.transport = _init;
1120
	YCM.xdrReadyEvent = new YAHOO.util.CustomEvent('xdrReady');
1121
	YCM.xdrReady = _xdrReady;
1122
	YCM.handleXdrResponse = _handleXdrResponse;
1123
})();
1124
 
1125
/**
1126
  * @for YAHOO.util.Connect
1127
  */
1128
(function(){
1129
	var YCM = YAHOO.util.Connect,
1130
		YE = YAHOO.util.Event,
1131
		dM = document.documentMode ? document.documentMode : false;
1132
 
1133
   /**
1134
	* @description Property modified by setForm() to determine if a file(s)
1135
	* upload is expected.
1136
	* @property _isFileUpload
1137
	* @private
1138
	* @static
1139
	* @type boolean
1140
	*/
1141
	YCM._isFileUpload = false;
1142
 
1143
   /**
1144
	* @description Property modified by setForm() to set a reference to the HTML
1145
	* form node if the desired action is file upload.
1146
	* @property _formNode
1147
	* @private
1148
	* @static
1149
	* @type object
1150
	*/
1151
	YCM._formNode = null;
1152
 
1153
   /**
1154
	* @description Property modified by setForm() to set the HTML form data
1155
	* for each transaction.
1156
	* @property _sFormData
1157
	* @private
1158
	* @static
1159
	* @type string
1160
	*/
1161
	YCM._sFormData = null;
1162
 
1163
   /**
1164
	* @description Tracks the name-value pair of the "clicked" submit button if multiple submit
1165
	* buttons are present in an HTML form; and, if YAHOO.util.Event is available.
1166
	* @property _submitElementValue
1167
	* @private
1168
	* @static
1169
	* @type string
1170
	*/
1171
	YCM._submitElementValue = null;
1172
 
1173
   /**
1174
    * @description Custom event that fires when handleTransactionResponse() determines a
1175
    * response in the HTTP 4xx/5xx range.
1176
    * @property failureEvent
1177
    * @private
1178
    * @static
1179
    * @type CustomEvent
1180
    */
1181
	YCM.uploadEvent = new YAHOO.util.CustomEvent('upload');
1182
 
1183
   /**
1184
	* @description Determines whether YAHOO.util.Event is available and returns true or false.
1185
	* If true, an event listener is bound at the document level to trap click events that
1186
	* resolve to a target type of "Submit".  This listener will enable setForm() to determine
1187
	* the clicked "Submit" value in a multi-Submit button, HTML form.
1188
	* @property _hasSubmitListener
1189
	* @private
1190
	* @static
1191
	*/
1192
	YCM._hasSubmitListener = function() {
1193
		if(YE){
1194
			YE.addListener(
1195
				document,
1196
				'click',
1197
				function(e){
1198
					var obj = YE.getTarget(e),
1199
						name = obj.nodeName.toLowerCase();
1200
 
1201
					if((name === 'input' || name === 'button') && (obj.type && obj.type.toLowerCase() == 'submit')){
1202
						YCM._submitElementValue = encodeURIComponent(obj.name) + "=" + encodeURIComponent(obj.value);
1203
					}
1204
				});
1205
			return true;
1206
		}
1207
		return false;
1208
	}();
1209
 
1210
  /**
1211
   * @description This method assembles the form label and value pairs and
1212
   * constructs an encoded string.
1213
   * asyncRequest() will automatically initialize the transaction with a
1214
   * a HTTP header Content-Type of application/x-www-form-urlencoded.
1215
   * @method setForm
1216
   * @public
1217
   * @static
1218
   * @param {string || object} form id or name attribute, or form object.
1219
   * @param {boolean} optional enable file upload.
1220
   * @param {boolean} optional enable file upload over SSL in IE only.
1221
   * @return {string} string of the HTML form field name and value pairs..
1222
   */
1223
	function _setForm(formId, isUpload, secureUri)
1224
	{
1225
		var oForm, oElement, oName, oValue, oDisabled,
1226
			hasSubmit = false,
1227
			data = [], item = 0,
1228
			i,len,j,jlen,opt;
1229
 
1230
		this.resetFormState();
1231
 
1232
		if(typeof formId == 'string'){
1233
			// Determine if the argument is a form id or a form name.
1234
			// Note form name usage is deprecated by supported
1235
			// here for legacy reasons.
1236
			oForm = (document.getElementById(formId) || document.forms[formId]);
1237
		}
1238
		else if(typeof formId == 'object'){
1239
			// Treat argument as an HTML form object.
1240
			oForm = formId;
1241
		}
1242
		else{
1243
			YAHOO.log('Unable to create form object ' + formId, 'warn', 'Connection');
1244
			return;
1245
		}
1246
 
1247
		// If the isUpload argument is true, setForm will call createFrame to initialize
1248
		// an iframe as the form target.
1249
		//
1250
		// The argument secureURI is also required by IE in SSL environments
1251
		// where the secureURI string is a fully qualified HTTP path, used to set the source
1252
		// of the iframe, to a stub resource in the same domain.
1253
		if(isUpload){
1254
 
1255
			// Create iframe in preparation for file upload.
1256
			this.createFrame(secureUri?secureUri:null);
1257
 
1258
			// Set form reference and file upload properties to true.
1259
			this._isFormSubmit = true;
1260
			this._isFileUpload = true;
1261
			this._formNode = oForm;
1262
 
1263
			return;
1264
		}
1265
 
1266
		// Iterate over the form elements collection to construct the
1267
		// label-value pairs.
1268
		for (i=0,len=oForm.elements.length; i<len; ++i){
1269
			oElement  = oForm.elements[i];
1270
			oDisabled = oElement.disabled;
1271
			oName     = oElement.name;
1272
 
1273
			// Do not submit fields that are disabled or
1274
			// do not have a name attribute value.
1275
			if(!oDisabled && oName)
1276
			{
1277
				oName  = encodeURIComponent(oName)+'=';
1278
				oValue = encodeURIComponent(oElement.value);
1279
 
1280
				switch(oElement.type)
1281
				{
1282
					// Safari, Opera, FF all default opt.value from .text if
1283
					// value attribute not specified in markup
1284
					case 'select-one':
1285
						if (oElement.selectedIndex > -1) {
1286
							opt = oElement.options[oElement.selectedIndex];
1287
							data[item++] = oName + encodeURIComponent(
1288
								(opt.attributes.value && opt.attributes.value.specified) ? opt.value : opt.text);
1289
						}
1290
						break;
1291
					case 'select-multiple':
1292
						if (oElement.selectedIndex > -1) {
1293
							for(j=oElement.selectedIndex, jlen=oElement.options.length; j<jlen; ++j){
1294
								opt = oElement.options[j];
1295
								if (opt.selected) {
1296
									data[item++] = oName + encodeURIComponent(
1297
										(opt.attributes.value && opt.attributes.value.specified) ? opt.value : opt.text);
1298
								}
1299
							}
1300
						}
1301
						break;
1302
					case 'radio':
1303
					case 'checkbox':
1304
						if(oElement.checked){
1305
							data[item++] = oName + oValue;
1306
						}
1307
						break;
1308
					case 'file':
1309
						// stub case as XMLHttpRequest will only send the file path as a string.
1310
					case undefined:
1311
						// stub case for fieldset element which returns undefined.
1312
					case 'reset':
1313
						// stub case for input type reset button.
1314
					case 'button':
1315
						// stub case for input type button elements.
1316
						break;
1317
					case 'submit':
1318
						if(hasSubmit === false){
1319
							if(this._hasSubmitListener && this._submitElementValue){
1320
								data[item++] = this._submitElementValue;
1321
							}
1322
							hasSubmit = true;
1323
						}
1324
						break;
1325
					default:
1326
						data[item++] = oName + oValue;
1327
				}
1328
			}
1329
		}
1330
 
1331
		this._isFormSubmit = true;
1332
		this._sFormData = data.join('&');
1333
 
1334
		YAHOO.log('Form initialized for transaction. HTML form POST message is: ' + this._sFormData, 'info', 'Connection');
1335
 
1336
		this.initHeader('Content-Type', this._default_form_header);
1337
		YAHOO.log('Initialize header Content-Type to application/x-www-form-urlencoded for setForm() transaction.', 'info', 'Connection');
1338
 
1339
		return this._sFormData;
1340
	}
1341
 
1342
   /**
1343
    * @description Resets HTML form properties when an HTML form or HTML form
1344
    * with file upload transaction is sent.
1345
    * @method resetFormState
1346
    * @private
1347
    * @static
1348
    * @return {void}
1349
    */
1350
	function _resetFormState(){
1351
		this._isFormSubmit = false;
1352
		this._isFileUpload = false;
1353
		this._formNode = null;
1354
		this._sFormData = "";
1355
	}
1356
 
1357
 
1358
   /**
1359
    * @description Creates an iframe to be used for form file uploads.  It is remove from the
1360
    * document upon completion of the upload transaction.
1361
    * @method createFrame
1362
    * @private
1363
    * @static
1364
    * @param {string} optional qualified path of iframe resource for SSL in IE.
1365
    * @return {void}
1366
    */
1367
	function _createFrame(secureUri){
1368
 
1369
		// IE does not allow the setting of id and name attributes as object
1370
		// properties via createElement().  A different iframe creation
1371
		// pattern is required for IE.
1372
		var frameId = 'yuiIO' + this._transaction_id,
1373
			ie9 = (dM === 9) ? true : false,
1374
			io;
1375
 
1376
		if(YAHOO.env.ua.ie && !ie9){
1377
			io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
1378
 
1379
			// IE will throw a security exception in an SSL environment if the
1380
			// iframe source is undefined.
1381
			if(typeof secureUri == 'boolean'){
1382
				io.src = 'javascript:false';
1383
			}
1384
		}
1385
		else{
1386
			io = document.createElement('iframe');
1387
			io.id = frameId;
1388
			io.name = frameId;
1389
		}
1390
 
1391
		io.style.position = 'absolute';
1392
		io.style.top = '-1000px';
1393
		io.style.left = '-1000px';
1394
 
1395
		document.body.appendChild(io);
1396
		YAHOO.log('File upload iframe created. Id is:' + frameId, 'info', 'Connection');
1397
	}
1398
 
1399
   /**
1400
    * @description Parses the POST data and creates hidden form elements
1401
    * for each key-value, and appends them to the HTML form object.
1402
    * @method appendPostData
1403
    * @private
1404
    * @static
1405
    * @param {string} postData The HTTP POST data
1406
    * @return {array} formElements Collection of hidden fields.
1407
    */
1408
	function _appendPostData(postData){
1409
		var formElements = [],
1410
			postMessage = postData.split('&'),
1411
			i, delimitPos;
1412
 
1413
		for(i=0; i < postMessage.length; i++){
1414
			delimitPos = postMessage[i].indexOf('=');
1415
			if(delimitPos != -1){
1416
				formElements[i] = document.createElement('input');
1417
				formElements[i].type = 'hidden';
1418
				formElements[i].name = decodeURIComponent(postMessage[i].substring(0,delimitPos));
1419
				formElements[i].value = decodeURIComponent(postMessage[i].substring(delimitPos+1));
1420
				this._formNode.appendChild(formElements[i]);
1421
			}
1422
		}
1423
 
1424
		return formElements;
1425
	}
1426
 
1427
   /**
1428
    * @description Uploads HTML form, inclusive of files/attachments, using the
1429
    * iframe created in createFrame to facilitate the transaction.
1430
    * @method uploadFile
1431
    * @private
1432
    * @static
1433
    * @param {int} id The transaction id.
1434
    * @param {object} callback User-defined callback object.
1435
    * @param {string} uri Fully qualified path of resource.
1436
    * @param {string} postData POST data to be submitted in addition to HTML form.
1437
    * @return {void}
1438
    */
1439
	function _uploadFile(o, callback, uri, postData){
1440
		// Each iframe has an id prefix of "yuiIO" followed
1441
		// by the unique transaction id.
1442
		var frameId = 'yuiIO' + o.tId,
1443
		    uploadEncoding = 'multipart/form-data',
1444
		    io = document.getElementById(frameId),
1445
		    ie8 = (dM >= 8) ? true : false,
1446
		    oConn = this,
1447
			args = (callback && callback.argument)?callback.argument:null,
1448
            oElements,i,prop,obj, rawFormAttributes, uploadCallback;
1449
 
1450
		// Track original HTML form attribute values.
1451
		rawFormAttributes = {
1452
			action:this._formNode.getAttribute('action'),
1453
			method:this._formNode.getAttribute('method'),
1454
			target:this._formNode.getAttribute('target')
1455
		};
1456
 
1457
		// Initialize the HTML form properties in case they are
1458
		// not defined in the HTML form.
1459
		this._formNode.setAttribute('action', uri);
1460
		this._formNode.setAttribute('method', 'POST');
1461
		this._formNode.setAttribute('target', frameId);
1462
 
1463
		if(YAHOO.env.ua.ie && !ie8){
1464
			// IE does not respect property enctype for HTML forms.
1465
			// Instead it uses the property - "encoding".
1466
			this._formNode.setAttribute('encoding', uploadEncoding);
1467
		}
1468
		else{
1469
			this._formNode.setAttribute('enctype', uploadEncoding);
1470
		}
1471
 
1472
		if(postData){
1473
			oElements = this.appendPostData(postData);
1474
		}
1475
 
1476
		// Start file upload.
1477
		this._formNode.submit();
1478
 
1479
		// Fire global custom event -- startEvent
1480
		this.startEvent.fire(o, args);
1481
 
1482
		if(o.startEvent){
1483
			// Fire transaction custom event -- startEvent
1484
			o.startEvent.fire(o, args);
1485
		}
1486
 
1487
		// Start polling if a callback is present and the timeout
1488
		// property has been defined.
1489
		if(callback && callback.timeout){
1490
			this._timeOut[o.tId] = window.setTimeout(function(){ oConn.abort(o, callback, true); }, callback.timeout);
1491
		}
1492
 
1493
		// Remove HTML elements created by appendPostData
1494
		if(oElements && oElements.length > 0){
1495
			for(i=0; i < oElements.length; i++){
1496
				this._formNode.removeChild(oElements[i]);
1497
			}
1498
		}
1499
 
1500
		// Restore HTML form attributes to their original
1501
		// values prior to file upload.
1502
		for(prop in rawFormAttributes){
1503
			if(YAHOO.lang.hasOwnProperty(rawFormAttributes, prop)){
1504
				if(rawFormAttributes[prop]){
1505
					this._formNode.setAttribute(prop, rawFormAttributes[prop]);
1506
				}
1507
				else{
1508
					this._formNode.removeAttribute(prop);
1509
				}
1510
			}
1511
		}
1512
 
1513
		// Reset HTML form state properties.
1514
		this.resetFormState();
1515
 
1516
		// Create the upload callback handler that fires when the iframe
1517
		// receives the load event.  Subsequently, the event handler is detached
1518
		// and the iframe removed from the document.
1519
		uploadCallback = function() {
1520
			var body, pre, text;
1521
 
1522
			if(callback && callback.timeout){
1523
				window.clearTimeout(oConn._timeOut[o.tId]);
1524
				delete oConn._timeOut[o.tId];
1525
			}
1526
 
1527
			// Fire global custom event -- completeEvent
1528
			oConn.completeEvent.fire(o, args);
1529
 
1530
			if(o.completeEvent){
1531
				// Fire transaction custom event -- completeEvent
1532
				o.completeEvent.fire(o, args);
1533
			}
1534
 
1535
			obj = {
1536
			    tId : o.tId,
1537
			    argument : args
1538
            };
1539
 
1540
			try
1541
			{
1542
				body = io.contentWindow.document.getElementsByTagName('body')[0];
1543
				pre = io.contentWindow.document.getElementsByTagName('pre')[0];
1544
 
1545
				if (body) {
1546
					if (pre) {
1547
						text = pre.textContent?pre.textContent:pre.innerText;
1548
					}
1549
					else {
1550
						text = body.textContent?body.textContent:body.innerText;
1551
					}
1552
				}
1553
				obj.responseText = text;
1554
				// responseText and responseXML will be populated with the same data from the iframe.
1555
				// Since the HTTP headers cannot be read from the iframe
1556
				obj.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
1557
			}
1558
			catch(e){}
1559
 
1560
			if(callback && callback.upload){
1561
				if(!callback.scope){
1562
					callback.upload(obj);
1563
					YAHOO.log('Upload callback.', 'info', 'Connection');
1564
				}
1565
				else{
1566
					callback.upload.apply(callback.scope, [obj]);
1567
					YAHOO.log('Upload callback with scope.', 'info', 'Connection');
1568
				}
1569
			}
1570
 
1571
			// Fire global custom event -- uploadEvent
1572
			oConn.uploadEvent.fire(obj);
1573
 
1574
			if(o.uploadEvent){
1575
				// Fire transaction custom event -- uploadEvent
1576
				o.uploadEvent.fire(obj);
1577
			}
1578
 
1579
			YE.removeListener(io, "load", uploadCallback);
1580
 
1581
			setTimeout(
1582
				function(){
1583
					document.body.removeChild(io);
1584
					oConn.releaseObject(o);
1585
					YAHOO.log('File upload iframe destroyed. Id is:' + frameId, 'info', 'Connection');
1586
				}, 100);
1587
		};
1588
 
1589
		// Bind the onload handler to the iframe to detect the file upload response.
1590
		YE.addListener(io, "load", uploadCallback);
1591
	}
1592
 
1593
	YCM.setForm = _setForm;
1594
	YCM.resetFormState = _resetFormState;
1595
	YCM.createFrame = _createFrame;
1596
	YCM.appendPostData = _appendPostData;
1597
	YCM.uploadFile = _uploadFile;
1598
})();
1599
 
1600
YAHOO.register("connection", YAHOO.util.Connect, {version: "2.9.0", build: "2800"});
1601
 
1602
}, '2.9.0' ,{"requires": ["yui2-yahoo", "yui2-event"], "supersedes": ["yui2-connectioncore"]});