author | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2011-10-02 23:56:18 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2011-10-02 23:56:18 (UTC) |
commit | ef68436ac04da078ffdcacd7e1f785473a303d45 (patch) (unidiff) | |
tree | c403752d66a2c4775f00affd4fa8431b29c5b68c /frontend/beta/js/YUI/connection.js | |
parent | 597ecfbc0249d83e1b856cbd558340c01237a360 (diff) | |
download | clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.zip clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.gz clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.bz2 |
First version of the newly restructured repository
Diffstat (limited to 'frontend/beta/js/YUI/connection.js') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/beta/js/YUI/connection.js | 960 |
1 files changed, 960 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI/connection.js b/frontend/beta/js/YUI/connection.js new file mode 100644 index 0000000..58f6d0f --- a/dev/null +++ b/frontend/beta/js/YUI/connection.js | |||
@@ -0,0 +1,960 @@ | |||
1 | /* | ||
2 | Copyright (c) 2006, Yahoo! Inc. All rights reserved. | ||
3 | Code licensed under the BSD License: | ||
4 | http://developer.yahoo.net/yui/license.txt | ||
5 | version: 0.12.0 | ||
6 | */ | ||
7 | |||
8 | /** | ||
9 | * @description | ||
10 | * The Connection Manager provides a simplified interface to the XMLHttpRequest | ||
11 | * object. It handles cross-browser instantiantion of XMLHttpRequest, negotiates the | ||
12 | * interactive states and server response, returning the results to a pre-defined | ||
13 | * callback you create. | ||
14 | * | ||
15 | * @namespace YAHOO.util | ||
16 | * @module Connection | ||
17 | * @Class Connect | ||
18 | */ | ||
19 | YAHOO.util.Connect = | ||
20 | { | ||
21 | /** | ||
22 | * @description Array of MSFT ActiveX ids for XMLHttpRequest. | ||
23 | * @property _msxml_progid | ||
24 | * @private | ||
25 | * @static | ||
26 | * @type array | ||
27 | */ | ||
28 | _msxml_progid:[ | ||
29 | 'MSXML2.XMLHTTP.3.0', | ||
30 | 'MSXML2.XMLHTTP', | ||
31 | 'Microsoft.XMLHTTP' | ||
32 | ], | ||
33 | |||
34 | /** | ||
35 | * @description Object literal of HTTP header(s) | ||
36 | * @property _http_header | ||
37 | * @private | ||
38 | * @static | ||
39 | * @type object | ||
40 | */ | ||
41 | _http_header:{}, | ||
42 | |||
43 | /** | ||
44 | * @description Determines if HTTP headers are set. | ||
45 | * @property _has_http_headers | ||
46 | * @private | ||
47 | * @static | ||
48 | * @type boolean | ||
49 | */ | ||
50 | _has_http_headers:false, | ||
51 | |||
52 | /** | ||
53 | * @description Determines if a default header of | ||
54 | * Content-Type of 'application/x-www-form-urlencoded' | ||
55 | * will be added to any client HTTP headers sent for POST | ||
56 | * transactions. | ||
57 | * @property _use_default_post_header | ||
58 | * @private | ||
59 | * @static | ||
60 | * @type boolean | ||
61 | */ | ||
62 | _use_default_post_header:true, | ||
63 | |||
64 | /** | ||
65 | * @description Determines if a default header of | ||
66 | * Content-Type of 'application/x-www-form-urlencoded' | ||
67 | * will be added to any client HTTP headers sent for POST | ||
68 | * transactions. | ||
69 | * @property _default_post_header | ||
70 | * @private | ||
71 | * @static | ||
72 | * @type boolean | ||
73 | */ | ||
74 | _default_post_header:'application/x-www-form-urlencoded', | ||
75 | |||
76 | /** | ||
77 | * @description Property modified by setForm() to determine if the data | ||
78 | * should be submitted as an HTML form. | ||
79 | * @property _isFormSubmit | ||
80 | * @private | ||
81 | * @static | ||
82 | * @type boolean | ||
83 | */ | ||
84 | _isFormSubmit:false, | ||
85 | |||
86 | /** | ||
87 | * @description Property modified by setForm() to determine if a file(s) | ||
88 | * upload is expected. | ||
89 | * @property _isFileUpload | ||
90 | * @private | ||
91 | * @static | ||
92 | * @type boolean | ||
93 | */ | ||
94 | _isFileUpload:false, | ||
95 | |||
96 | /** | ||
97 | * @description Property modified by setForm() to set a reference to the HTML | ||
98 | * form node if the desired action is file upload. | ||
99 | * @property _formNode | ||
100 | * @private | ||
101 | * @static | ||
102 | * @type object | ||
103 | */ | ||
104 | _formNode:null, | ||
105 | |||
106 | /** | ||
107 | * @description Property modified by setForm() to set the HTML form data | ||
108 | * for each transaction. | ||
109 | * @property _sFormData | ||
110 | * @private | ||
111 | * @static | ||
112 | * @type string | ||
113 | */ | ||
114 | _sFormData:null, | ||
115 | |||
116 | /** | ||
117 | * @description Collection of polling references to the polling mechanism in handleReadyState. | ||
118 | * @property _poll | ||
119 | * @private | ||
120 | * @static | ||
121 | * @type object | ||
122 | */ | ||
123 | _poll:{}, | ||
124 | |||
125 | /** | ||
126 | * @description Queue of timeout values for each transaction callback with a defined timeout value. | ||
127 | * @property _timeOut | ||
128 | * @private | ||
129 | * @static | ||
130 | * @type object | ||
131 | */ | ||
132 | _timeOut:{}, | ||
133 | |||
134 | /** | ||
135 | * @description The polling frequency, in milliseconds, for HandleReadyState. | ||
136 | * when attempting to determine a transaction's XHR readyState. | ||
137 | * The default is 50 milliseconds. | ||
138 | * @property _polling_interval | ||
139 | * @private | ||
140 | * @static | ||
141 | * @type int | ||
142 | */ | ||
143 | _polling_interval:50, | ||
144 | |||
145 | /** | ||
146 | * @description A transaction counter that increments the transaction id for each transaction. | ||
147 | * @property _transaction_id | ||
148 | * @private | ||
149 | * @static | ||
150 | * @type int | ||
151 | */ | ||
152 | _transaction_id:0, | ||
153 | |||
154 | /** | ||
155 | * @description Member to add an ActiveX id to the existing xml_progid array. | ||
156 | * In the event(unlikely) a new ActiveX id is introduced, it can be added | ||
157 | * without internal code modifications. | ||
158 | * @method setProgId | ||
159 | * @public | ||
160 | * @static | ||
161 | * @param {string} id The ActiveX id to be added to initialize the XHR object. | ||
162 | * @return void | ||
163 | */ | ||
164 | setProgId:function(id) | ||
165 | { | ||
166 | this._msxml_progid.unshift(id); | ||
167 | }, | ||
168 | |||
169 | /** | ||
170 | * @description Member to enable or disable the default POST header. | ||
171 | * @method setDefaultPostHeader | ||
172 | * @public | ||
173 | * @static | ||
174 | * @param {boolean} b Set and use default header - true or false . | ||
175 | * @return void | ||
176 | */ | ||
177 | setDefaultPostHeader:function(b) | ||
178 | { | ||
179 | this._use_default_post_header = b; | ||
180 | }, | ||
181 | |||
182 | /** | ||
183 | * @description Member to modify the default polling interval. | ||
184 | * @method setPollingInterval | ||
185 | * @public | ||
186 | * @static | ||
187 | * @param {int} i The polling interval in milliseconds. | ||
188 | * @return void | ||
189 | */ | ||
190 | setPollingInterval:function(i) | ||
191 | { | ||
192 | if(typeof i == 'number' && isFinite(i)){ | ||
193 | this._polling_interval = i; | ||
194 | } | ||
195 | }, | ||
196 | |||
197 | /** | ||
198 | * @description Instantiates a XMLHttpRequest object and returns an object with two properties: | ||
199 | * the XMLHttpRequest instance and the transaction id. | ||
200 | * @method createXhrObject | ||
201 | * @private | ||
202 | * @static | ||
203 | * @param {int} transactionId Property containing the transaction id for this transaction. | ||
204 | * @return object | ||
205 | */ | ||
206 | createXhrObject:function(transactionId) | ||
207 | { | ||
208 | var obj,http; | ||
209 | try | ||
210 | { | ||
211 | // Instantiates XMLHttpRequest in non-IE browsers and assigns to http. | ||
212 | http = new XMLHttpRequest(); | ||
213 | // Object literal with http and tId properties | ||
214 | obj = { conn:http, tId:transactionId }; | ||
215 | } | ||
216 | catch(e) | ||
217 | { | ||
218 | for(var i=0; i<this._msxml_progid.length; ++i){ | ||
219 | try | ||
220 | { | ||
221 | // Instantiates XMLHttpRequest for IE and assign to http. | ||
222 | http = new ActiveXObject(this._msxml_progid[i]); | ||
223 | // Object literal with conn and tId properties | ||
224 | obj = { conn:http, tId:transactionId }; | ||
225 | break; | ||
226 | } | ||
227 | catch(e){} | ||
228 | } | ||
229 | } | ||
230 | finally | ||
231 | { | ||
232 | return obj; | ||
233 | } | ||
234 | }, | ||
235 | |||
236 | /** | ||
237 | * @description This method is called by asyncRequest to create a | ||
238 | * valid connection object for the transaction. It also passes a | ||
239 | * transaction id and increments the transaction id counter. | ||
240 | * @method getConnectionObject | ||
241 | * @private | ||
242 | * @static | ||
243 | * @return {object} | ||
244 | */ | ||
245 | getConnectionObject:function() | ||
246 | { | ||
247 | var o; | ||
248 | var tId = this._transaction_id; | ||
249 | |||
250 | try | ||
251 | { | ||
252 | o = this.createXhrObject(tId); | ||
253 | if(o){ | ||
254 | this._transaction_id++; | ||
255 | } | ||
256 | } | ||
257 | catch(e){} | ||
258 | finally | ||
259 | { | ||
260 | return o; | ||
261 | } | ||
262 | }, | ||
263 | |||
264 | /** | ||
265 | * @description Method for initiating an asynchronous request via the XHR object. | ||
266 | * @method asyncRequest | ||
267 | * @public | ||
268 | * @static | ||
269 | * @param {string} method HTTP transaction method | ||
270 | * @param {string} uri Fully qualified path of resource | ||
271 | * @param {callback} callback User-defined callback function or object | ||
272 | * @param {string} postData POST body | ||
273 | * @return {object} Returns the connection object | ||
274 | */ | ||
275 | asyncRequest:function(method, uri, callback, postData) | ||
276 | { | ||
277 | var o = this.getConnectionObject(); | ||
278 | |||
279 | if(!o){ | ||
280 | return null; | ||
281 | } | ||
282 | else{ | ||
283 | if(this._isFormSubmit){ | ||
284 | if(this._isFileUpload){ | ||
285 | this.uploadFile(o.tId, callback, uri, postData); | ||
286 | this.releaseObject(o); | ||
287 | |||
288 | return; | ||
289 | } | ||
290 | |||
291 | //If the specified HTTP method is GET, setForm() will return an | ||
292 | //encoded string that is concatenated to the uri to | ||
293 | //create a querystring. | ||
294 | if(method == 'GET'){ | ||
295 | if(this._sFormData.length != 0){ | ||
296 | // If the URI already contains a querystring, append an ampersand | ||
297 | // and then concatenate _sFormData to the URI. | ||
298 | uri += ((uri.indexOf('?') == -1)?'?':'&') + this._sFormData; | ||
299 | } | ||
300 | else{ | ||
301 | uri += "?" + this._sFormData; | ||
302 | } | ||
303 | } | ||
304 | else if(method == 'POST'){ | ||
305 | //If POST data exist in addition to the HTML form data, | ||
306 | //it will be concatenated to the form data. | ||
307 | postData = postData?this._sFormData + "&" + postData:this._sFormData; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | o.conn.open(method, uri, true); | ||
312 | |||
313 | if(this._isFormSubmit || (postData && this._use_default_post_header)){ | ||
314 | this.initHeader('Content-Type', this._default_post_header); | ||
315 | if(this._isFormSubmit){ | ||
316 | this.resetFormState(); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | if(this._has_http_headers){ | ||
321 | this.setHeader(o); | ||
322 | } | ||
323 | |||
324 | this.handleReadyState(o, callback); | ||
325 | o.conn.send(postData || null); | ||
326 | |||
327 | return o; | ||
328 | } | ||
329 | }, | ||
330 | |||
331 | /** | ||
332 | * @description This method serves as a timer that polls the XHR object's readyState | ||
333 | * property during a transaction, instead of binding a callback to the | ||
334 | * onreadystatechange event. Upon readyState 4, handleTransactionResponse | ||
335 | * will process the response, and the timer will be cleared. | ||
336 | * @method handleReadyState | ||
337 | * @private | ||
338 | * @static | ||
339 | * @param {object} o The connection object | ||
340 | * @param {callback} callback The user-defined callback object | ||
341 | * @return {void} | ||
342 | */ | ||
343 | handleReadyState:function(o, callback) | ||
344 | { | ||
345 | var oConn = this; | ||
346 | |||
347 | if(callback && callback.timeout){ | ||
348 | this._timeOut[o.tId] = window.setTimeout(function(){ oConn.abort(o, callback, true); }, callback.timeout); | ||
349 | } | ||
350 | |||
351 | this._poll[o.tId] = window.setInterval( | ||
352 | function(){ | ||
353 | if(o.conn && o.conn.readyState == 4){ | ||
354 | window.clearInterval(oConn._poll[o.tId]); | ||
355 | delete oConn._poll[o.tId]; | ||
356 | |||
357 | if(callback && callback.timeout){ | ||
358 | delete oConn._timeOut[o.tId]; | ||
359 | } | ||
360 | |||
361 | oConn.handleTransactionResponse(o, callback); | ||
362 | } | ||
363 | } | ||
364 | ,this._polling_interval); | ||
365 | }, | ||
366 | |||
367 | /** | ||
368 | * @description This method attempts to interpret the server response and | ||
369 | * determine whether the transaction was successful, or if an error or | ||
370 | * exception was encountered. | ||
371 | * @method handleTransactionResponse | ||
372 | * @private | ||
373 | * @static | ||
374 | * @param {object} o The connection object | ||
375 | * @param {object} callback The sser-defined callback object | ||
376 | * @param {boolean} isAbort Determines if the transaction was aborted. | ||
377 | * @return {void} | ||
378 | */ | ||
379 | handleTransactionResponse:function(o, callback, isAbort) | ||
380 | { | ||
381 | // If no valid callback is provided, then do not process any callback handling. | ||
382 | if(!callback){ | ||
383 | this.releaseObject(o); | ||
384 | return; | ||
385 | } | ||
386 | |||
387 | var httpStatus, responseObject; | ||
388 | |||
389 | try | ||
390 | { | ||
391 | if(o.conn.status !== undefined && o.conn.status != 0){ | ||
392 | httpStatus = o.conn.status; | ||
393 | } | ||
394 | else{ | ||
395 | httpStatus = 13030; | ||
396 | } | ||
397 | } | ||
398 | catch(e){ | ||
399 | // 13030 is the custom code to indicate the condition -- in Mozilla/FF -- | ||
400 | // when the o object's status and statusText properties are | ||
401 | // unavailable, and a query attempt throws an exception. | ||
402 | httpStatus = 13030; | ||
403 | } | ||
404 | |||
405 | if(httpStatus >= 200 && httpStatus < 300){ | ||
406 | try | ||
407 | { | ||
408 | responseObject = this.createResponseObject(o, callback.argument); | ||
409 | if(callback.success){ | ||
410 | if(!callback.scope){ | ||
411 | callback.success(responseObject); | ||
412 | } | ||
413 | else{ | ||
414 | // If a scope property is defined, the callback will be fired from | ||
415 | // the context of the object. | ||
416 | callback.success.apply(callback.scope, [responseObject]); | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | catch(e){} | ||
421 | } | ||
422 | else{ | ||
423 | try | ||
424 | { | ||
425 | switch(httpStatus){ | ||
426 | // The following cases are wininet.dll error codes that may be encountered. | ||
427 | case 12002: // Server timeout | ||
428 | case 12029: // 12029 to 12031 correspond to dropped connections. | ||
429 | case 12030: | ||
430 | case 12031: | ||
431 | case 12152: // Connection closed by server. | ||
432 | case 13030: // See above comments for variable status. | ||
433 | responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort?isAbort:false)); | ||
434 | if(callback.failure){ | ||
435 | if(!callback.scope){ | ||
436 | callback.failure(responseObject); | ||
437 | } | ||
438 | else{ | ||
439 | callback.failure.apply(callback.scope, [responseObject]); | ||
440 | } | ||
441 | } | ||
442 | break; | ||
443 | default: | ||
444 | responseObject = this.createResponseObject(o, callback.argument); | ||
445 | if(callback.failure){ | ||
446 | if(!callback.scope){ | ||
447 | callback.failure(responseObject); | ||
448 | } | ||
449 | else{ | ||
450 | callback.failure.apply(callback.scope, [responseObject]); | ||
451 | } | ||
452 | } | ||
453 | } | ||
454 | } | ||
455 | catch(e){} | ||
456 | } | ||
457 | |||
458 | this.releaseObject(o); | ||
459 | responseObject = null; | ||
460 | }, | ||
461 | |||
462 | /** | ||
463 | * @description This method evaluates the server response, creates and returns the results via | ||
464 | * its properties. Success and failure cases will differ in the response | ||
465 | * object's property values. | ||
466 | * @method createResponseObject | ||
467 | * @private | ||
468 | * @static | ||
469 | * @param {object} o The connection object | ||
470 | * @param {callbackArg} callbackArg The user-defined argument or arguments to be passed to the callback | ||
471 | * @return {object} | ||
472 | */ | ||
473 | createResponseObject:function(o, callbackArg) | ||
474 | { | ||
475 | var obj = {}; | ||
476 | var headerObj = {}; | ||
477 | |||
478 | try | ||
479 | { | ||
480 | var headerStr = o.conn.getAllResponseHeaders(); | ||
481 | var header = headerStr.split('\n'); | ||
482 | for(var i=0; i<header.length; i++){ | ||
483 | var delimitPos = header[i].indexOf(':'); | ||
484 | if(delimitPos != -1){ | ||
485 | headerObj[header[i].substring(0,delimitPos)] = header[i].substring(delimitPos+2); | ||
486 | } | ||
487 | } | ||
488 | } | ||
489 | catch(e){} | ||
490 | |||
491 | obj.tId = o.tId; | ||
492 | obj.status = o.conn.status; | ||
493 | obj.statusText = o.conn.statusText; | ||
494 | obj.getResponseHeader = headerObj; | ||
495 | obj.getAllResponseHeaders = headerStr; | ||
496 | obj.responseText = o.conn.responseText; | ||
497 | obj.responseXML = o.conn.responseXML; | ||
498 | |||
499 | if(typeof callbackArg !== undefined){ | ||
500 | obj.argument = callbackArg; | ||
501 | } | ||
502 | |||
503 | return obj; | ||
504 | }, | ||
505 | |||
506 | /** | ||
507 | * @description If a transaction cannot be completed due to dropped or closed connections, | ||
508 | * there may be not be enough information to build a full response object. | ||
509 | * The failure callback will be fired and this specific condition can be identified | ||
510 | * by a status property value of 0. | ||
511 | * | ||
512 | * If an abort was successful, the status property will report a value of -1. | ||
513 | * | ||
514 | * @method createExceptionObject | ||
515 | * @private | ||
516 | * @static | ||
517 | * @param {int} tId The Transaction Id | ||
518 | * @param {callbackArg} callbackArg The user-defined argument or arguments to be passed to the callback | ||
519 | * @param {boolean} isAbort Determines if the exception case is caused by a transaction abort | ||
520 | * @return {object} | ||
521 | */ | ||
522 | createExceptionObject:function(tId, callbackArg, isAbort) | ||
523 | { | ||
524 | var COMM_CODE = 0; | ||
525 | var COMM_ERROR = 'communication failure'; | ||
526 | var ABORT_CODE = -1; | ||
527 | var ABORT_ERROR = 'transaction aborted'; | ||
528 | |||
529 | var obj = {}; | ||
530 | |||
531 | obj.tId = tId; | ||
532 | if(isAbort){ | ||
533 | obj.status = ABORT_CODE; | ||
534 | obj.statusText = ABORT_ERROR; | ||
535 | } | ||
536 | else{ | ||
537 | obj.status = COMM_CODE; | ||
538 | obj.statusText = COMM_ERROR; | ||
539 | } | ||
540 | |||
541 | if(callbackArg){ | ||
542 | obj.argument = callbackArg; | ||
543 | } | ||
544 | |||
545 | return obj; | ||
546 | }, | ||
547 | |||
548 | /** | ||
549 | * @description Public method that stores the custom HTTP headers for each transaction. | ||
550 | * @method initHeader | ||
551 | * @public | ||
552 | * @static | ||
553 | * @param {string} label The HTTP header label | ||
554 | * @param {string} value The HTTP header value | ||
555 | * @return {void} | ||
556 | */ | ||
557 | initHeader:function(label,value) | ||
558 | { | ||
559 | if(this._http_header[label] === undefined){ | ||
560 | this._http_header[label] = value; | ||
561 | } | ||
562 | else{ | ||
563 | // Concatenate multiple values, comma-delimited, | ||
564 | // for the same header label, | ||
565 | this._http_header[label] = value + "," + this._http_header[label]; | ||
566 | } | ||
567 | |||
568 | this._has_http_headers = true; | ||
569 | }, | ||
570 | |||
571 | /** | ||
572 | * @description Accessor that sets the HTTP headers for each transaction. | ||
573 | * @method setHeader | ||
574 | * @private | ||
575 | * @static | ||
576 | * @param {object} o The connection object for the transaction. | ||
577 | * @return {void} | ||
578 | */ | ||
579 | setHeader:function(o) | ||
580 | { | ||
581 | for(var prop in this._http_header){ | ||
582 | if(this._http_header.hasOwnProperty(prop)){ | ||
583 | o.conn.setRequestHeader(prop, this._http_header[prop]); | ||
584 | } | ||
585 | } | ||
586 | delete this._http_header; | ||
587 | |||
588 | this._http_header = {}; | ||
589 | this._has_http_headers = false; | ||
590 | }, | ||
591 | |||
592 | /** | ||
593 | * @description This method assembles the form label and value pairs and | ||
594 | * constructs an encoded string. | ||
595 | * asyncRequest() will automatically initialize the | ||
596 | * transaction with a HTTP header Content-Type of | ||
597 | * application/x-www-form-urlencoded. | ||
598 | * @method setForm | ||
599 | * @public | ||
600 | * @static | ||
601 | * @param {string || object} form id or name attribute, or form object. | ||
602 | * @param {string} optional boolean to indicate SSL environment. | ||
603 | * @param {string || boolean} optional qualified path of iframe resource for SSL in IE. | ||
604 | * @return {string} string of the HTML form field name and value pairs.. | ||
605 | */ | ||
606 | setForm:function(formId, isUpload, secureUri) | ||
607 | { | ||
608 | this.resetFormState(); | ||
609 | var oForm; | ||
610 | if(typeof formId == 'string'){ | ||
611 | // Determine if the argument is a form id or a form name. | ||
612 | // Note form name usage is deprecated by supported | ||
613 | // here for legacy reasons. | ||
614 | oForm = (document.getElementById(formId) || document.forms[formId]); | ||
615 | } | ||
616 | else if(typeof formId == 'object'){ | ||
617 | // Treat argument as an HTML form object. | ||
618 | oForm = formId; | ||
619 | } | ||
620 | else{ | ||
621 | return; | ||
622 | } | ||
623 | |||
624 | // If the isUpload argument is true, setForm will call createFrame to initialize | ||
625 | // an iframe as the form target. | ||
626 | // | ||
627 | // The argument secureURI is also required by IE in SSL environments | ||
628 | // where the secureURI string is a fully qualified HTTP path, used to set the source | ||
629 | // of the iframe, to a stub resource in the same domain. | ||
630 | if(isUpload){ | ||
631 | |||
632 | // Create iframe in preparation for file upload. | ||
633 | this.createFrame(secureUri?secureUri:null); | ||
634 | |||
635 | // Set form reference and file upload properties to true. | ||
636 | this._isFormSubmit = true; | ||
637 | this._isFileUpload = true; | ||
638 | this._formNode = oForm; | ||
639 | |||
640 | return; | ||
641 | } | ||
642 | |||
643 | var oElement, oName, oValue, oDisabled; | ||
644 | var hasSubmit = false; | ||
645 | |||
646 | // Iterate over the form elements collection to construct the | ||
647 | // label-value pairs. | ||
648 | for (var i=0; i<oForm.elements.length; i++){ | ||
649 | oElement = oForm.elements[i]; | ||
650 | oDisabled = oForm.elements[i].disabled; | ||
651 | oName = oForm.elements[i].name; | ||
652 | oValue = oForm.elements[i].value; | ||
653 | |||
654 | // Do not submit fields that are disabled or | ||
655 | // do not have a name attribute value. | ||
656 | if(!oDisabled && oName) | ||
657 | { | ||
658 | switch (oElement.type) | ||
659 | { | ||
660 | case 'select-one': | ||
661 | case 'select-multiple': | ||
662 | for(var j=0; j<oElement.options.length; j++){ | ||
663 | if(oElement.options[j].selected){ | ||
664 | if(window.ActiveXObject){ | ||
665 | this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oElement.options[j].attributes['value'].specified?oElement.options[j].value:oElement.options[j].text) + '&'; | ||
666 | } | ||
667 | else{ | ||
668 | this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oElement.options[j].hasAttribute('value')?oElement.options[j].value:oElement.options[j].text) + '&'; | ||
669 | } | ||
670 | |||
671 | } | ||
672 | } | ||
673 | break; | ||
674 | case 'radio': | ||
675 | case 'checkbox': | ||
676 | if(oElement.checked){ | ||
677 | this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&'; | ||
678 | } | ||
679 | break; | ||
680 | case 'file': | ||
681 | // stub case as XMLHttpRequest will only send the file path as a string. | ||
682 | case undefined: | ||
683 | // stub case for fieldset element which returns undefined. | ||
684 | case 'reset': | ||
685 | // stub case for input type reset button. | ||
686 | case 'button': | ||
687 | // stub case for input type button elements. | ||
688 | break; | ||
689 | case 'submit': | ||
690 | if(hasSubmit == false){ | ||
691 | this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&'; | ||
692 | hasSubmit = true; | ||
693 | } | ||
694 | break; | ||
695 | default: | ||
696 | this._sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&'; | ||
697 | break; | ||
698 | } | ||
699 | } | ||
700 | } | ||
701 | |||
702 | this._isFormSubmit = true; | ||
703 | this._sFormData = this._sFormData.substr(0, this._sFormData.length - 1); | ||
704 | |||
705 | return this._sFormData; | ||
706 | }, | ||
707 | |||
708 | /** | ||
709 | * @description Resets HTML form properties when an HTML form or HTML form | ||
710 | * with file upload transaction is sent. | ||
711 | * @method resetFormState | ||
712 | * @private | ||
713 | * @static | ||
714 | * @return {void} | ||
715 | */ | ||
716 | resetFormState:function(){ | ||
717 | this._isFormSubmit = false; | ||
718 | this._isFileUpload = false; | ||
719 | this._formNode = null; | ||
720 | this._sFormData = ""; | ||
721 | }, | ||
722 | |||
723 | /** | ||
724 | * @description Creates an iframe to be used for form file uploads. It is remove from the | ||
725 | * document upon completion of the upload transaction. | ||
726 | * @method createFrame | ||
727 | * @private | ||
728 | * @static | ||
729 | * @param {string} secureUri Optional qualified path of iframe resource for SSL in IE. | ||
730 | * @return {void} | ||
731 | */ | ||
732 | createFrame:function(secureUri){ | ||
733 | |||
734 | // IE does not allow the setting of id and name attributes as object | ||
735 | // properties via createElement(). A different iframe creation | ||
736 | // pattern is required for IE. | ||
737 | var frameId = 'yuiIO' + this._transaction_id; | ||
738 | if(window.ActiveXObject){ | ||
739 | var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />'); | ||
740 | |||
741 | // IE will throw a security exception in an SSL environment if the | ||
742 | // iframe source is undefined. | ||
743 | if(typeof secureUri == 'boolean'){ | ||
744 | io.src = 'javascript:false'; | ||
745 | } | ||
746 | else if(typeof secureURI == 'string'){ | ||
747 | // Deprecated | ||
748 | io.src = secureUri; | ||
749 | } | ||
750 | } | ||
751 | else{ | ||
752 | var io = document.createElement('iframe'); | ||
753 | io.id = frameId; | ||
754 | io.name = frameId; | ||
755 | } | ||
756 | |||
757 | io.style.position = 'absolute'; | ||
758 | io.style.top = '-1000px'; | ||
759 | io.style.left = '-1000px'; | ||
760 | |||
761 | document.body.appendChild(io); | ||
762 | }, | ||
763 | |||
764 | /** | ||
765 | * @description Parses the POST data and creates hidden form elements | ||
766 | * for each key-value, and appends them to the HTML form object. | ||
767 | * @method appendPostData | ||
768 | * @private | ||
769 | * @static | ||
770 | * @param {string} postData The HTTP POST data | ||
771 | * @return {array} formElements Collection of hidden fields. | ||
772 | */ | ||
773 | appendPostData:function(postData) | ||
774 | { | ||
775 | var formElements = new Array(); | ||
776 | var postMessage = postData.split('&'); | ||
777 | for(var i=0; i < postMessage.length; i++){ | ||
778 | var delimitPos = postMessage[i].indexOf('='); | ||
779 | if(delimitPos != -1){ | ||
780 | formElements[i] = document.createElement('input'); | ||
781 | formElements[i].type = 'hidden'; | ||
782 | formElements[i].name = postMessage[i].substring(0,delimitPos); | ||
783 | formElements[i].value = postMessage[i].substring(delimitPos+1); | ||
784 | this._formNode.appendChild(formElements[i]); | ||
785 | } | ||
786 | } | ||
787 | |||
788 | return formElements; | ||
789 | }, | ||
790 | |||
791 | /** | ||
792 | * @description Uploads HTML form, including files/attachments, to the | ||
793 | * iframe created in createFrame. | ||
794 | * @method uploadFile | ||
795 | * @private | ||
796 | * @static | ||
797 | * @param {int} id The transaction id. | ||
798 | * @param {object} callback - User-defined callback object. | ||
799 | * @param {string} uri Fully qualified path of resource. | ||
800 | * @return {void} | ||
801 | */ | ||
802 | uploadFile:function(id, callback, uri, postData){ | ||
803 | |||
804 | // Each iframe has an id prefix of "yuiIO" followed | ||
805 | // by the unique transaction id. | ||
806 | var frameId = 'yuiIO' + id; | ||
807 | var io = document.getElementById(frameId); | ||
808 | |||
809 | // Initialize the HTML form properties in case they are | ||
810 | // not defined in the HTML form. | ||
811 | this._formNode.action = uri; | ||
812 | this._formNode.method = 'POST'; | ||
813 | this._formNode.target = frameId; | ||
814 | |||
815 | if(this._formNode.encoding){ | ||
816 | // IE does not respect property enctype for HTML forms. | ||
817 | // Instead use property encoding. | ||
818 | this._formNode.encoding = 'multipart/form-data'; | ||
819 | } | ||
820 | else{ | ||
821 | this._formNode.enctype = 'multipart/form-data'; | ||
822 | } | ||
823 | |||
824 | if(postData){ | ||
825 | var oElements = this.appendPostData(postData); | ||
826 | } | ||
827 | |||
828 | this._formNode.submit(); | ||
829 | |||
830 | if(oElements && oElements.length > 0){ | ||
831 | try | ||
832 | { | ||
833 | for(var i=0; i < oElements.length; i++){ | ||
834 | this._formNode.removeChild(oElements[i]); | ||
835 | } | ||
836 | } | ||
837 | catch(e){} | ||
838 | } | ||
839 | |||
840 | // Reset HTML form status properties. | ||
841 | this.resetFormState(); | ||
842 | |||
843 | // Create the upload callback handler that fires when the iframe | ||
844 | // receives the load event. Subsequently, the event handler is detached | ||
845 | // and the iframe removed from the document. | ||
846 | |||
847 | var uploadCallback = function() | ||
848 | { | ||
849 | var obj = {}; | ||
850 | obj.tId = id; | ||
851 | obj.argument = callback.argument; | ||
852 | |||
853 | try | ||
854 | { | ||
855 | obj.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null; | ||
856 | obj.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document; | ||
857 | } | ||
858 | catch(e){} | ||
859 | |||
860 | if(callback.upload){ | ||
861 | if(!callback.scope){ | ||
862 | callback.upload(obj); | ||
863 | } | ||
864 | else{ | ||
865 | callback.upload.apply(callback.scope, [obj]); | ||
866 | } | ||
867 | } | ||
868 | |||
869 | if(YAHOO.util.Event){ | ||
870 | YAHOO.util.Event.removeListener(io, "load", uploadCallback); | ||
871 | } | ||
872 | else if(window.detachEvent){ | ||
873 | io.detachEvent('onload', uploadCallback); | ||
874 | } | ||
875 | else{ | ||
876 | io.removeEventListener('load', uploadCallback, false); | ||
877 | } | ||
878 | setTimeout(function(){ document.body.removeChild(io); }, 100); | ||
879 | }; | ||
880 | |||
881 | |||
882 | // Bind the onload handler to the iframe to detect the file upload response. | ||
883 | if(YAHOO.util.Event){ | ||
884 | YAHOO.util.Event.addListener(io, "load", uploadCallback); | ||
885 | } | ||
886 | else if(window.attachEvent){ | ||
887 | io.attachEvent('onload', uploadCallback); | ||
888 | } | ||
889 | else{ | ||
890 | io.addEventListener('load', uploadCallback, false); | ||
891 | } | ||
892 | }, | ||
893 | |||
894 | /** | ||
895 | * @description Method to terminate a transaction, if it has not reached readyState 4. | ||
896 | * @method abort | ||
897 | * @public | ||
898 | * @static | ||
899 | * @param {object} o The connection object returned by asyncRequest. | ||
900 | * @param {object} callback User-defined callback object. | ||
901 | * @param {string} isTimeout boolean to indicate if abort was a timeout. | ||
902 | * @return {boolean} | ||
903 | */ | ||
904 | abort:function(o, callback, isTimeout) | ||
905 | { | ||
906 | if(this.isCallInProgress(o)){ | ||
907 | o.conn.abort(); | ||
908 | window.clearInterval(this._poll[o.tId]); | ||
909 | delete this._poll[o.tId]; | ||
910 | if(isTimeout){ | ||
911 | delete this._timeOut[o.tId]; | ||
912 | } | ||
913 | |||
914 | this.handleTransactionResponse(o, callback, true); | ||
915 | |||
916 | return true; | ||
917 | } | ||
918 | else{ | ||
919 | return false; | ||
920 | } | ||
921 | }, | ||
922 | |||
923 | /** | ||
924 | * Public method to check if the transaction is still being processed. | ||
925 | * | ||
926 | * @method isCallInProgress | ||
927 | * @public | ||
928 | * @static | ||
929 | * @param {object} o The connection object returned by asyncRequest | ||
930 | * @return {boolean} | ||
931 | */ | ||
932 | isCallInProgress:function(o) | ||
933 | { | ||
934 | // if the XHR object assigned to the transaction has not been dereferenced, | ||
935 | // then check its readyState status. Otherwise, return false. | ||
936 | if(o.conn){ | ||
937 | return o.conn.readyState != 4 && o.conn.readyState != 0; | ||
938 | } | ||
939 | else{ | ||
940 | //The XHR object has been destroyed. | ||
941 | return false; | ||
942 | } | ||
943 | }, | ||
944 | |||
945 | /** | ||
946 | * @description Dereference the XHR instance and the connection object after the transaction is completed. | ||
947 | * @method releaseObject | ||
948 | * @private | ||
949 | * @static | ||
950 | * @param {object} o The connection object | ||
951 | * @return {void} | ||
952 | */ | ||
953 | releaseObject:function(o) | ||
954 | { | ||
955 | //dereference the XHR instance. | ||
956 | o.conn = null; | ||
957 | //dereference the connection object. | ||
958 | o = null; | ||
959 | } | ||
960 | }; \ No newline at end of file | ||