]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/opac/common/js/RemoteRequest.js
Now that we have a Dojo language picker, spread the locale-awareness
[Evergreen.git] / Open-ILS / web / opac / common / js / RemoteRequest.js
1 var XML_HTTP_GATEWAY = "osrf-gateway-v1";
2 var XML_HTTP_SERVER = "";
3
4
5 /* This object is thrown when network failures occur */
6 function NetworkFailure(stat, url) { 
7         this._status = stat; 
8         this._url = url;
9 }
10
11 NetworkFailure.prototype.status = function() { return this._status; }
12 NetworkFailure.prototype.url = function() { return this._url; }
13 NetworkFailure.prototype.toString = function() { 
14         return "Network Failure: status = " + this.status() +'\n'+this.url(); 
15 }
16
17
18
19 function isXUL() { try { if(IAMXUL) return true;}catch(e){return false;}; }
20 var _allrequests = {};
21
22 // If the legacy JSON gateway is needed by the staff client, uncomment this
23 /* 
24 if(isXUL()) {
25     XML_HTTP_GATEWAY = 'gateway';
26 }
27 */
28
29 function cleanRemoteRequests() {
30         for( var i in _allrequests ) 
31                 destroyRequest(_allrequests[i]);
32 }
33
34 function abortAllRequests() {
35         for( var i in _allrequests ) {
36                 var r = _allrequests[i];
37                 if(r) { 
38                         r.abort();
39                         destroyRequest(r);
40                 }
41         }
42 }
43
44 function destroyRequest(r) {
45         if(r == null) return;
46
47         if( r.xmlhttp ) {
48                 r.xmlhttp.onreadystatechange = function(){};
49                 r.xmlhttp = null;
50         }
51
52         r.callback                              = null;
53         r.userdata                              = null;
54         _allrequests[r.id]      = null;
55 }
56
57 /* ----------------------------------------------------------------------- */
58 /* Request object */
59 var rrId = 0;
60 function RemoteRequest( service, method ) {
61
62
63         this.service    = service;
64         this.locale             = dojo.config.locale;
65         this.method             = method;
66         this.xmlhttp    = false;
67         this.name               = null;
68         this.alertEvent = true; /* only used when isXUL is false */
69
70         this.type               = "POST"; /* default */
71         this.id                 = rrId++;
72         this.cancelled = false;
73
74         this.setSecure(false);
75         if(isXUL()) this.setSecure(true);
76
77         _allrequests[this.id] = this;
78
79         var i = 2;
80         this.params = ""; 
81
82         while(i < arguments.length) {
83                 var object = js2JSON(arguments[i++]);
84                 this.params += "&param=" + encodeURIComponent(object);
85         }
86
87         if(!this.params) { this.params = ""; }
88         this.param_string = "service=" + service + "&locale=" + locale + "&method=" + method + this.params;
89         if( this.buildXMLRequest() == null ) alert("Browser is not supported!");
90
91 }
92
93
94 RemoteRequest.prototype.timeout = function(t) {
95         t *= 1000
96         var req = this;
97         req.timeoutFunc = setTimeout(
98                 function() {
99                         if( req && req.xmlhttp ) {
100                                 req.cancelled = true;
101                                 req.abort();
102                                 if( req.abtCallback ) {
103                                         req.abtCallback(req);
104                                 }
105                         }
106                 },
107                 t
108         );
109 }
110
111 RemoteRequest.prototype.abortCallback = function(func) {
112         this.abtCallback = func;
113 }
114
115 RemoteRequest.prototype.event = function(evt) {
116         if( arguments.length > 0 )
117                 this.evt = evt;
118         return this.evt;
119 }
120
121 RemoteRequest.prototype.abort = function() {
122         if( this.xmlhttp ) {
123                 /* this has to come before abort() or IE will puke on you */
124                 this.xmlhttp.onreadystatechange = function(){};
125                 this.xmlhttp.abort();
126         }
127 }
128
129 /* constructs our XMLHTTPRequest object */
130 RemoteRequest.prototype.buildXMLRequest = function() {
131         this.xmlhttp = buildXMLRequest();
132         return true;
133 }
134
135
136 function buildXMLRequest() {
137     try {
138             return new XMLHttpRequest();
139     } catch(e) {
140             try { 
141                     return new ActiveXObject("Msxml2.XMLHTTP"); 
142             } catch (e2) {
143                     try { 
144                             return new ActiveXObject("Microsoft.XMLHTTP"); 
145                     } catch (e3) {
146                         alert("NEEDS NEWER JAVASCRIPT for XMLHTTPRequest()");
147                 return null;
148                     }
149             }
150     }
151 }
152
153
154 function _remoteRequestCallback(id) {
155
156         var object = _allrequests[id];
157         if(object.cancelled) return;
158
159         if( object.xmlhttp.readyState == 4 ) {
160
161         try {
162             object.duration = new Date().getTime() - object.sendTime;
163             dump('request ' + object.id + ': duration = ' + object.duration + ' ms\n');
164         } catch(ee){}
165
166                 try {
167                         object.callback(object);
168                 } catch(E) {
169             throw E
170                 } finally { 
171                         destroyRequest(object); 
172                         object = null; 
173                 }  
174         }
175 }
176
177
178 /* define the callback we use when this request has received
179         all of its data */
180 RemoteRequest.prototype.setCompleteCallback = function(callback) {
181         if(this.cancelled) return;
182         this.callback = callback;
183         var id = this.id;
184         this.xmlhttp.onreadystatechange = function() { _remoteRequestCallback(id); }
185 }
186
187
188 /* http by default.  This makes it https. *ONLY works when
189         embedded in a XUL app. */
190 RemoteRequest.prototype.setSecure = function(bool) {
191         this.secure = bool; 
192 }
193
194 RemoteRequest.prototype.send = function(blocking) {
195
196         if(this.cancelled) return;
197
198         /* determine the xmlhttp server dynamically */
199         var url = location.protocol + "//" + location.host + "/" + XML_HTTP_GATEWAY;
200
201         if(isXUL()) {
202                 if( XML_HTTP_SERVER ) 
203                         url = 'http://'+XML_HTTP_SERVER+'/'+XML_HTTP_GATEWAY;
204
205                 if( url.match(/^http:/) && 
206                                 (this.secure || location.href.match(/^https:/)) ) {
207                         netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
208                         url = url.replace(/^http:/, 'https:');
209                 }
210         }
211
212         var data = null;
213         if( this.type == 'GET' ) url +=  "?" + this.param_string; 
214
215         this.url = url;
216
217    //if( isXUL() ) dump('request URL = ' + url + '?' + this.param_string + '\n');
218
219         try {
220
221                 if(blocking) this.xmlhttp.open(this.type, url, false);
222                 else this.xmlhttp.open(this.type, url, true);
223                 
224         } catch(E) {
225                 alert("Fatal error opening XMLHTTPRequest for URL:\n" + url + '\n' + E);
226                 return;
227         }
228
229         if( this.type == 'POST' ) {
230                 data = this.param_string;
231                 this.xmlhttp.setRequestHeader('Content-Type',
232                                 'application/x-www-form-urlencoded');
233         }
234
235         try {
236                 var auth;
237                 try { auth = cookieManager.read(COOKIE_SES) } catch(ee) {}
238                 if( isXUL() ) auth = fetchXULStash().session.key;
239                 if( auth ) 
240                         this.xmlhttp.setRequestHeader('X-OILS-Authtoken', auth);
241
242         } catch(e) {}
243
244         if(data && data.match(/param=undefined/)) {
245                 /* we get a bogus param .. replace with NULL */
246                 try{dump('!+! UNDEFINED PARAM IN QUERY: ' + this.service + ' : ' + this.method+'\n');}catch(r){}
247                 data = data.replace(/param=undefined/g,'param=null');
248         }
249
250
251     this.sendTime = new Date().getTime();
252         try{ this.xmlhttp.send( data ); } catch(e){}
253
254         return this;
255 }
256
257 /* returns the actual response text from the request */
258 RemoteRequest.prototype.getText = function() {
259         return this.xmlhttp.responseText;
260 }
261
262 RemoteRequest.prototype.isReady = function() {
263         return this.xmlhttp.readyState == 4;
264 }
265
266
267 /* returns the JSON->js result object  */
268 RemoteRequest.prototype.getResultObject = function() {
269
270         if(this.cancelled) return null;
271         if(!this.xmlhttp) return null;
272
273         var failed = false;
274         var status = null;
275         this.event(null);
276
277         /*
278         try {
279                 dump(this.url + '?' + this.param_string + '\n' +
280                         'Returned with \n\tstatus = ' + this.xmlhttp.status + 
281                         '\n\tpayload= ' + this.xmlhttp.responseText + '\n');
282         } catch(e) {}
283         */
284
285         try {
286                 status = this.xmlhttp.status;
287                 if( status != 200 ) failed = true;
288         } catch(e) { failed = true; }
289
290         if( failed ) {
291                 if(!status) status = '<unknown>';
292                 try{dump('! NETWORK FAILURE.  HTTP STATUS = ' +status+'\n'+this.param_string+'\n');}catch(e){}
293                 if(isXUL()) 
294                         throw new NetworkFailure(status, this.param_string);
295                 else return null;
296         }
297
298         var text = this.xmlhttp.responseText;
299
300         //try{if(getDebug()) _debug('response: ' + text + '\n')}catch(e){}
301
302         if(text == "" || text == " " || text == null) {
303                 try { dump('dbg: Request returned no text!\n'); } catch(E) {}
304                 if(isXUL()) 
305                         throw new NetworkFailure(status, this.param_string);
306                 return null;
307         }
308
309         var obj = JSON2js(text);
310         if(!obj) return null;
311
312         if( obj.status != 200 ) {
313
314                 var str = 'A server error occurred. Debug information follows: ' +
315                                         '\ncode = '             + obj.status + 
316                                         '\ndebug: '             + obj.debug + 
317                                         '\npayload: '   + js2JSON(obj.payload); 
318
319                 if(isXUL()) {
320                         dump(str);
321                         throw obj;
322
323                 } else {
324                         _debug(str);
325                         throw str;
326                 }
327         }
328
329         var payload = obj.payload;
330         if(!payload || payload.length == 0) return null;
331         payload = (payload.length == 1) ? payload[0] : payload;
332
333         if(!isXUL()) {
334                 if( checkILSEvent(payload) ) {
335                         this.event(payload);
336                         if( this.alertEvent ) {
337                                 alertILSEvent(payload);
338                                 return null;
339                         }
340                 } 
341         }
342
343         return payload;
344 }
345
346 /* adds a new parameter to the request */
347 RemoteRequest.prototype.addParam = function(param) {
348         var string = encodeURIComponent(js2JSON(param));
349         this.param_string += "&param=" + string;
350 }
351
352 function fetchXULStash() {
353         if( isXUL() ) {
354                 try {
355                         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
356                         var __OILS = new Components.Constructor("@mozilla.org/openils_data_cache;1", "nsIOpenILS");
357                         var data_cache = new __OILS( );
358                         return data_cache.wrappedJSObject.OpenILS.prototype.data;
359         
360                 } catch(E) {
361                         _debug('Error in OpenILS.data._debug_stash(): ' + js2JSON(E) );
362                 }
363         }
364         return {};
365 }
366
367