source: other-projects/tipple-android/i-greenstone-server-files/greenstone/webapps/greenstone3/interfaces/basic-client-xslt/js/connection.js@ 26899

Last change on this file since 26899 was 26899, checked in by davidb, 11 years ago

Tipple reborn after Chris's Summer of Code 2013

File size: 11.9 KB
Line 
1/*
2Copyright (c) 2006 Yahoo! Inc. All rights reserved.
3version 0.9.0
4*/
5
6/**
7 * The Connection Manager provides a simplified interface to the XMLHttpRequest
8 * object. It handles cross-browser instantiantion of XMLHttpRequest, negotiates the
9 * interactive states and server response returning the results to a pre-defined
10 * callback function you create.
11 * @ class
12 */
13YAHOO.util.Connect = {};
14
15YAHOO.util.Connect =
16{
17 /**
18 * Array of MSFT ActiveX ids for XMLHttpRequest.
19 * @private
20 * @type array
21 */
22 _msxml_progid:[
23 'MSXML2.XMLHTTP.5.0',
24 'MSXML2.XMLHTTP.4.0',
25 'MSXML2.XMLHTTP.3.0',
26 'MSXML2.XMLHTTP',
27 'Microsoft.XMLHTTP'
28 ],
29
30 /**
31 * Array of HTTP header(s)
32 * @private
33 * @type array
34 */
35 _http_header:[],
36
37 /**
38 * Property modified by setForm() to determine if the transaction
39 * should be processed as a HTML form POST.
40 * @private
41 * @type boolean
42 */
43 _isFormPost:false,
44
45 /**
46 * Property modified by setForm() to the HTML form POST body.
47 * @private
48 * @type string
49 */
50 _sFormData:null,
51
52 /**
53 * The polling frequency, in milliseconds, for HandleReadyState.
54 * when attempting to determine a transaction's XHR readyState.
55 * The default is 300 milliseconds.
56 * @private
57 * @type int
58 */
59 _polling_interval:300,
60
61 /**
62 * A transaction counter that increments the transaction id for each transaction.
63 * @private
64 * @type int
65 */
66 _transaction_id:0,
67
68 /**
69 * Member to add an ActiveX id to the existing xml_progid array.
70 * In the event(unlikely) a new ActiveX id is introduced, it can be added
71 * without internal code modifications.
72 * @public
73 * @param string id The ActiveX id to be added to initialize the XHR object.
74 * @return void
75 */
76 setProgId:function(id)
77 {
78 this.msxml_progid.unshift(id);
79 },
80
81 /**
82 * Instantiates a XMLHttpRequest object and returns an object with two properties:
83 * the XMLHttpRequest instance and the transaction id.
84 * @private
85 * @param {int} transactionId Property containing the transaction id for this transaction.
86 * @return connection object
87 * @type object
88 */
89 createXhrObject:function(transactionId)
90 {
91 var obj,http;
92 try
93 {
94 // Instantiates XMLHttpRequest in non-IE browsers and assigns to http.
95 http = new XMLHttpRequest();
96 // Object literal with http and id properties
97 obj = { conn:http, tId:transactionId };
98 }
99 catch(e)
100 {
101 for(var i=0; i<this._msxml_progid.length; ++i){
102 try
103 {
104 // Instantiates XMLHttpRequest for IE and assign to http.
105 http = new ActiveXObject(this._msxml_progid[i]);
106 // Object literal with http and id properties
107 obj = { conn:http, tId:transactionId };
108 }
109 catch(e){}
110 }
111 }
112 finally
113 {
114 return obj;
115 }
116 },
117
118 /**
119 * This method is called by asyncRequest and syncRequest to create a
120 * valid connection object for the transaction. It also passes a
121 * transaction id and increments the transaction id counter.
122 * @private
123 * @return object
124 */
125 getConnectionObject:function()
126 {
127 var o;
128 var tId = this._transaction_id;
129
130 try
131 {
132 o = this.createXhrObject(tId);
133 if(o){
134 this._transaction_id++;
135 }
136 }
137 catch(e){}
138 finally
139 {
140 return o;
141 }
142 },
143
144 /**
145 * Method for initiating an asynchronous request via the XHR object.
146 * @public
147 * @param {string} method HTTP transaction method
148 * @param {string} uri Fully qualified path of resource
149 * @param callback User-defined callback function or object
150 * @param callbackArg User-defined callback arguments
151 * @param {string} postData POST body
152 * @return {object} Returns the connection object
153 */
154 asyncRequest:function(method, uri, callback, postData)
155 {
156 var errorObj;
157 var o = this.getConnectionObject();
158
159 if(!o){
160 return null;
161 }
162 else{
163 var oConn = this;
164
165 o.conn.open(method, uri, true);
166 this.handleReadyState(o, callback);
167
168 if(this._isFormPost){
169 postData = this._sFormData;
170 this._isFormPost = false;
171 }
172 else if(postData){
173 this.initHeader('Content-Type','application/x-www-form-urlencoded');
174 }
175
176 //Verify whether the transaction has any user-defined HTTP headers
177 //and set them.
178 if(this._http_header.length>0){
179 this.setHeader(o);
180 }
181 postData?o.conn.send(postData):o.conn.send(null);
182
183 return o;
184 }
185 },
186
187 /**
188 * This method serves as a timer that polls the XHR object's readyState
189 * property during a transaction, instead of binding a callback to the
190 * onreadystatechange event. Upon readyState 4, handleTransactionResponse
191 * will process the response, and the timer will be cleared.
192 *
193 * @private
194 * @param {object} o The connection object
195 * @param callback User-defined callback object
196 * @param callbackArg User-defined arguments passed to the callback
197 * @return void
198 */
199 handleReadyState:function(o, callback)
200 {
201 var oConn = this;
202 var poll = window.setInterval(
203 function(){
204 if(o.conn.readyState==4){
205 oConn.handleTransactionResponse(o, callback);
206 window.clearInterval(poll);
207 }
208 }
209 ,this._polling_interval);
210 },
211
212 /**
213 * This method attempts to interpret the server response and
214 * determine whether the transaction was successful, or if an error or
215 * exception was encountered.
216 *
217 * @private
218 * @param {object} o The connection object
219 * @param {function} callback - User-defined callback object
220 * @param {} callbackArg - User-defined arguments to be passed to the callback
221 * @return void
222 */
223 handleTransactionResponse:function(o, callback)
224 {
225 var httpStatus;
226 var responseObject;
227
228 try{
229 httpStatus = o.conn.status;
230 }
231 catch(e){
232 // 13030 is the custom code to indicate the condition -- in Mozilla/FF --
233 // when the o object's status and statusText properties are
234 // unavailable, and a query attempt throws an exception.
235 httpStatus = 13030;
236 }
237
238 if(httpStatus == 200){
239 responseObject = this.createResponseObject(o, callback.argument);
240 if(callback.success){
241 if(!callback.scope){
242 callback.success(responseObject);
243 }
244 else{
245 callback.success.apply(callback.scope, [responseObject]);
246 }
247 }
248 }
249 else{
250 switch(httpStatus){
251 // The following case labels are wininet.dll error codes that may be encountered.
252 // Server timeout
253 case 12002:
254 // 12029 to 12031 correspond to dropped connections.
255 case 12029:
256 case 12030:
257 case 12031:
258 // Connection closed by server.
259 case 12152:
260 // See above comments for variable status.
261 case 13030:
262 responseObject = this.createExceptionObject(o, callback.argument);
263 if(callback.failure){
264 if(!callback.scope){
265 callback.failure(responseObject);
266 }
267 else{
268 callback.failure.apply(callback.scope,[responseObject]);
269 }
270 }
271 break;
272 default:
273 responseObject = this.createResponseObject(o, callback.argument);
274 if(callback.failure){
275 if(!callback.scope){
276 callback.failure(responseObject);
277 }
278 else{
279 callback.failure.apply(callback.scope,[responseObject]);
280 }
281 }
282 }
283 }
284
285 this.releaseObject(o);
286 },
287
288 /**
289 * This method evaluates the server response, creates and returns the results via
290 * its properties. Success and failure cases(and exceptions) will differ in their defined properties
291 * but property "type" will confirm the transaction's status.
292 * @private
293 * @param {object} o The connection object
294 * @param {} callbackArg User-defined arguments to be passed to the callback
295 * @param {boolean} isSuccess Indicates whether the transaction was successful or not.
296 * @return object
297 */
298 createResponseObject:function(o, callbackArg)
299 {
300 var obj = {};
301
302 obj.tId = o.tId;
303 obj.status = o.conn.status;
304 obj.statusText = o.conn.statusText;
305 obj.allResponseHeaders = o.conn.getAllResponseHeaders();
306 obj.responseText = o.conn.responseText;
307 obj.responseXML = o.conn.responseXML;
308 if(callbackArg){
309 obj.argument = callbackArg;
310 }
311
312 return obj;
313 },
314
315 /**
316 * If a transaction cannot be completed due to dropped or closed connections,
317 * there may be not be enough information to build a full response object.
318 * The object's property "type" value will be "failure", and two additional
319 * unique, properties are added - errorCode and errorText.
320 * @private
321 * @param {int} tId Transaction Id
322 * @param callbackArg The user-defined arguments
323 * @param {string} errorCode Error code associated with the exception.
324 * @param {string} errorText Error message describing the exception.
325 * @return object
326 */
327 createExceptionObject:function(tId, callbackArg)
328 {
329 var COMM_CODE = 0;
330 var COMM_ERROR = 'communication failure';
331
332 var obj = {};
333
334 obj.tId = tId;
335 obj.status = COMM_CODE;
336 obj.statusText = COMM_ERROR;
337 if(callbackArg){
338 obj.argument = callbackArg;
339 }
340
341 return obj;
342 },
343
344 /**
345 * Accessor that stores the HTTP headers for each transaction.
346 * @public
347 * @param {string} label The HTTP header label
348 * @param {string} value The HTTP header value
349 * @return void
350 */
351 initHeader:function(label,value)
352 {
353 var oHeader = [label,value];
354 this._http_header.push(oHeader);
355 },
356
357 /**
358 * Accessor that sets the HTTP headers for each transaction.
359 * @private
360 * @param {object} o The connection object for the transaction.
361 * @return void
362 */
363 setHeader:function(o)
364 {
365 var oHeader = this._http_header;
366 for(var i=0;i<oHeader.length;i++){
367 o.conn.setRequestHeader(oHeader[i][0],oHeader[i][1]);
368 }
369 oHeader.splice(0,oHeader.length);
370 },
371
372 /**
373 * This method assembles the form label and value pairs and
374 * constructs an encoded POST body. Both syncRequest()
375 * and asyncRequest() will automatically initialize the
376 * transaction with a HTTP header Content-Type of
377 * application/x-www-form-urlencoded.
378 * @public
379 * @param {string} formName value of form name attribute
380 * @return void
381 */
382 setForm:function(formName)
383 {
384 this._sFormData = '';
385 var oForm = document.forms[formName];
386 var oElement, elName, elValue;
387 // iterate over the form elements collection to construct the
388 // label-value pairs.
389 for (var i=0; i<oForm.elements.length; i++){
390 oElement = oForm.elements[i];
391 elName = oForm.elements[i].name;
392 elValue = oForm.elements[i].value;
393 switch (oElement.type)
394 {
395 case 'select-multiple':
396 for(var j=0; j<oElement.options.length; j++){
397 if(oElement.options[j].selected){
398 this._sFormData += encodeURIComponent(elName) + '=' + encodeURIComponent(oElement.options[j].value) + '&';
399 }
400 }
401 break;
402 case 'radio':
403 case 'checkbox':
404 if(oElement.checked){
405 this._sFormData += encodeURIComponent(elName) + '=' + encodeURIComponent(elValue) + '&';
406 }
407 break;
408 case 'file':
409 // stub case as XMLHttpRequest will only send the file path as a string.
410 break;
411 case undefined:
412 // stub case for fieldset element which returns undefined.
413 break;
414 default:
415 this._sFormData += encodeURIComponent(elName) + '=' + encodeURIComponent(elValue) + '&';
416 break;
417 }
418 }
419 this._sFormData = this._sFormData.substr(0, this._sFormData.length - 1);
420 this._isFormPost = true;
421 this.initHeader('Content-Type','application/x-www-form-urlencoded');
422 },
423
424 /**
425 * Public method to terminate a transaction, if it has not reached readyState 4.
426 * @public
427 * @param {object} o The connection object returned by asyncRequest.
428 * @return void
429 */
430 abort:function(o)
431 {
432 if(this.isCallInProgress(o)){
433 o.conn.abort();
434 this.releaseObject(o);
435 }
436 },
437
438 /**
439 * Accessor to check if the transaction associated with the connection object
440 * is still being processed.
441 * @public
442 * @param {object} o The connection object returned by asyncRequest
443 * @return boolean
444 */
445 isCallInProgress:function(o)
446 {
447 if(o){
448 return o.conn.readyState != 4 && o.conn.readyState != 0;
449 }
450 },
451
452 /**
453 * Dereference the XHR instance and the connection object after the transaction is completed.
454 * @private
455 * @param {object} o The connection object
456 * @return void
457 */
458 releaseObject:function(o)
459 {
460 //dereference the XHR instance.
461 o.conn = null;
462 //dereference the connection object.
463 o = null;
464 }
465}
Note: See TracBrowser for help on using the repository browser.