default to location.host for server
[Evergreen.git] / Open-ILS / web / opac / common / js / RemoteRequest.js
1 var XML_HTTP_GATEWAY = "gateway";
2 var XML_HTTP_SERVER = "";
3 var XML_HTTP_MAX_TRIES = 3;
4
5 //var IAMXUL = false;
6 function isXUL() { try { if(IAMXUL) return true;}catch(e){return false;}; }
7
8 /* some communication exceptions */
9 function EX(message) { this.init(message); }
10 EX.prototype.init = function(message) { this.message = message; }
11 EX.prototype.toString = function() { return "\n *** Exception Occured \n" + this.message; }  
12 EXCommunication.prototype              = new EX();
13 EXCommunication.prototype.constructor  = EXCommunication;
14 EXCommunication.baseClass              = EX.prototype.constructor;
15 function EXCommunication(message) { this.classname="EXCommunication"; this.init("EXCommunication: " + message); }                          
16 /* ------------------------------------------------ */
17
18
19 var _allrequests = {};
20
21 function cleanRemoteRequests() {
22         for( var i in _allrequests ) 
23                 destroyRequest(_allrequests[i]);
24 }
25
26 function abortAllRequests() {
27         for( var i in _allrequests ) {
28                 var r = _allrequests[i];
29                 if(r) { 
30                         /* this has to come before abort() or IE will puke on you */
31                         r.xmlhttp.onreadystatechange = function(){};
32                         r.abort();
33                         destroyRequest(r);
34                 }
35         }
36 }
37
38 function destroyRequest(r) {
39         if(r == null) return;
40
41         if( r.xmlhttp ) {
42                 r.xmlhttp.onreadystatechange = function(){};
43                 r.xmlhttp = null;
44         }
45
46         r.callback                              = null;
47         r.userdata                              = null;
48         _allrequests[r.id]      = null;
49 }
50
51 /* ----------------------------------------------------------------------- */
52 /* Request object */
53 function RemoteRequest( service, method ) {
54
55
56         this.service    = service;
57         this.method             = method;
58         this.xmlhttp    = false;
59         this.name               = null;
60         this.sendCount = 0;
61
62         this.type               = "POST"; /* default */
63         this.id                 = service + method + Math.random();
64         this.cancelled = false;
65
66         _allrequests[this.id] = this;
67
68         var i = 2;
69         this.params = ""; 
70
71         while(i < arguments.length) {
72                 var object = js2JSON(arguments[i++]);
73                 this.params += "&param=" + encodeURIComponent(object);
74         }
75
76         if(!this.params) { this.params = ""; }
77         this.param_string = "service=" + service + "&method=" + method + this.params;
78         if( this.buildXMLRequest() == null ) alert("Browser is not supported!");
79 }
80
81 RemoteRequest.prototype.abort = function() {
82         if( this.xmlhttp ) this.xmlhttp.abort();
83 }
84
85 /* constructs our XMLHTTPRequest object */
86 RemoteRequest.prototype.buildXMLRequest = function() {
87
88         var x;
89         try { 
90                 x = new ActiveXObject("Msxml2.XMLHTTP"); 
91         } catch (e) {
92                 try { 
93                         x = new ActiveXObject("Microsoft.XMLHTTP"); 
94                 } catch (E) {
95                         x = false;
96                 }
97         }
98
99         if (!x && typeof XMLHttpRequest!='undefined') x = new XMLHttpRequest();
100
101         if(!x) {
102                 alert("NEEDS NEWER JAVASCRIPT for XMLHTTPRequest()");
103                 return null;
104         }
105
106         this.xmlhttp = x;
107         return true;
108 }
109
110
111 function _remoteRequestCallback(id) {
112
113         var object = _allrequests[id];
114         if(object.cancelled) return;
115
116         if( object.xmlhttp.readyState == 4 ) {
117                 try {
118                         object.callback(object);
119                 } catch(E) {
120
121                         /* if we receive a communication error, retry the request up
122                                 to XML_HTTP_MAX_TRIES attempts */
123                         if( E && E.classname == "EXCommunication" ) {
124
125                                 //try { dump('Communication Error: ' + E ); } catch(e){}
126                                 alert('Debug:  Communication Error: ' + E );
127
128                                 if(object.sendCount >= XML_HTTP_MAX_TRIES ) {
129                                         if(isXUL()) throw object;
130                                          else alert("Arrrgghh, Matey! Error communicating:\n" + E  + "\n" + object.param_string);
131                                 } else {
132                                         object.buildXMLRequest();
133                                         object.send();
134                                         return;
135                                 }
136                         } else { throw E; }
137
138                 } finally { 
139                         destroyRequest(object); 
140                         object = null; 
141                 }  
142         }
143 }
144
145
146 /* define the callback we use when this request has received
147         all of its data */
148 RemoteRequest.prototype.setCompleteCallback = function(callback) {
149         if(this.cancelled) return;
150         this.callback = callback;
151         var id = this.id;
152         this.xmlhttp.onreadystatechange = function() { _remoteRequestCallback(id); }
153 }
154
155
156 /* http by default.  This makes it https. *ONLY works when
157         embedded in a XUL app. */
158 RemoteRequest.prototype.setSecure = function(bool) {
159         this.secure = bool; 
160 }
161
162 RemoteRequest.prototype.send = function(blocking) {
163
164         if(this.cancelled) return;
165
166         /* determine the xmlhttp server dynamically */
167         var url = location.protocol + "//" + location.host + "/" + XML_HTTP_GATEWAY;
168
169         if(isXUL() && XML_HTTP_SERVER) {
170                 if(this.secure || url.match(/^https:/) )
171                         url =   "https://" + XML_HTTP_SERVER + "/" + XML_HTTP_GATEWAY;
172                 else
173                         url =   "http://" + XML_HTTP_SERVER + "/" + XML_HTTP_GATEWAY;
174         }
175
176         var data = null;
177         if( this.type == 'GET' ) url +=  "?" + this.param_string; 
178
179         try {
180
181                 if(blocking) this.xmlhttp.open(this.type, url, false);
182                 else this.xmlhttp.open(this.type, url, true);
183                 
184         } catch(E) {
185                 alert("Fatal error opening XMLHTTPRequest for URL:\n" + url + '\n');
186                 return;
187         }
188
189
190         if( this.type == 'POST' ) {
191                 data = this.param_string;
192                 this.xmlhttp.setRequestHeader('Content-Type',
193                                 'application/x-www-form-urlencoded');
194         }
195
196         try{ this.xmlhttp.send( data ); } catch(e){}
197
198         this.sendCount += 1;
199         return this;
200 }
201
202 /* returns the actual response text from the request */
203 RemoteRequest.prototype.getText = function() {
204         return this.xmlhttp.responseText;
205 }
206
207 RemoteRequest.prototype.isReady = function() {
208         return this.xmlhttp.readyState == 4;
209 }
210
211
212 /* returns the JSON->js result object  */
213 RemoteRequest.prototype.getResultObject = function() {
214
215         if(this.cancelled) return null;
216         if(!this.xmlhttp) return null;
217
218         var text = this.xmlhttp.responseText;
219         if(text == "" || text == " " || text == null) null;
220
221         var obj = JSON2js(text);
222         if(!obj) return null;
223
224         if( obj.status != 200 ) {
225                 if(!isXUL()) {
226                         alert("A Server Error Occured.  Debug information follows:\n" +
227                                 "Status: " + obj.status + '\n' + obj.debug + '\n' 
228                                 + 'Payload: ' + js2JSON(obj.payload) + '\n');
229                 } else { 
230                         dump('Remote Request Error:' +
231                                         '\ncode = '             + obj.status + 
232                                         '\ndebug: '             + obj.debug + 
233                                         '\npayload: '   + js2JSON(obj.payload)); 
234                         throw obj;
235                 }
236         }
237
238         var payload = obj.payload;
239         if(!payload || payload.length == 0) return null;
240         payload = (payload.length == 1) ? payload[0] : payload;
241
242         if(payload.__isfieldmapper && payload.classname == "perm_ex") {
243                 if(!isXUL()) alert(payload.err_msg());
244                 throw payload;
245         }
246
247         return payload;
248 }
249
250 /* adds a new parameter to the request */
251 RemoteRequest.prototype.addParam = function(param) {
252         var string = encodeURIComponent(js2JSON(param));
253         this.param_string += "&param=" + string;
254 }
255