2 var XML_HTTP_GATEWAY = "gateway";
3 var XML_HTTP_SERVER = "gapines.org";
4 var XML_HTTP_MAX_TRIES = 3;
8 /* true if we've been absorbed by a XUL app */
19 /* ----------------------------------------------------------------------- */
22 /* keeping all requests in a global cache allows us to manage request
23 resends effectively */
25 /* Array of globally pending requests */
26 RemoteRequest.pending = new Array();
28 /* cleans requests (and null entries) from the pending array */
29 RemoteRequest.prunePending = function(id) {
30 var tmpArray = new Array();
31 for( var x in RemoteRequest.pending ) {
32 if( RemoteRequest.pending[x] != null ) {
33 var req = RemoteRequest.pending[x];
40 RemoteRequest.pending = tmpArray;
43 /* returns the number of pending requests */
44 RemoteRequest.numPending = function() {
45 return RemoteRequest.pending.length;
48 RemoteRequest.cancelAll = function() {
49 for( var x in RemoteRequest.pending ) {
50 if( RemoteRequest.pending[x] != null ) {
51 debug("Cancelling request...");
52 var req = RemoteRequest.pending[x];
60 /* ----------------------------------------------------------------------- */
61 /* Generic request manager */
62 function RequestBatch() {
63 this.requests = new Array();
65 RequestBatch.prototype.add = function(request) {
66 this.requests.push(request);
69 RequestBatch.prototype.remove = function(request) {
70 var newArray = new Array();
71 for( var i in this.requests ) {
72 if( this.requests[i] != null &&
73 this.requests[i].id != request.id )
74 newArray.push(this.requests[i]);
76 this.requests = newArray;
79 RequestBatch.prototype.pending = function() {
80 return this.requests.length;
83 /* cancels all requests in this batch that have not already been sent */
84 RequestBatch.prototype.cancel = function() {
85 for(var i in this.requests) {
86 if(this.requests[i] != null)
87 this.requests.cancelled = true;
91 /* ----------------------------------------------------------------------- */
93 function RemoteRequest( service, method ) {
95 this.service = service;
101 this.type = "POST"; /* default */
102 this.id = service + method + Math.random();
103 this.cancelled = false;
108 while(i < arguments.length) {
109 var object = js2JSON(arguments[i++]);
110 this.params += "¶m=" + encodeURIComponent(object);
111 debug("Remote Request adding param => " + object);
114 if(!this.params) { this.params = ""; }
115 this.param_string = "service=" + service + "&method=" + method + this.params;
117 if( ! this.type || ! this.service || ! this.method ) {
118 alert( "ERROR IN REQUEST PARAMS");
122 if( this.buildXMLRequest() == null )
123 alert("NEWER BROWSER");
126 RemoteRequest.prototype.clean = function() {
127 this.xmlhttp.onreadystatechange = function(){};
128 this.callback = null;
131 /* constructs our XMLHTTPRequest object */
132 RemoteRequest.prototype.buildXMLRequest = function() {
135 this.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
138 this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
140 this.xmlhttp = false;
144 if (!this.xmlhttp && typeof XMLHttpRequest!='undefined') {
145 this.xmlhttp = new XMLHttpRequest();
149 alert("NEEDS NEWER JAVASCRIPT for XMLHTTPRequest()");
154 this.setCompleteCallback( this.callback );
160 /* define the callback we use when this request has received
162 RemoteRequest.prototype.setCompleteCallback = function(callback) {
164 if(this.cancelled) return;
167 var obj = this.xmlhttp;
168 this.callback = callback;
170 this.xmlhttp.onreadystatechange = function() {
171 if( obj.readyState == 4 ) {
174 if(object.cancelled) return;
179 debug("Processing Error in complete callback: [" + E + "]");
181 /* if we receive a communication error, retry the request up
182 to XML_HTTP_MAX_TRIES attempts */
183 if( instanceOf(E, EXCommunication) ) {
185 debug("Communication Error: [" + E + "]");
186 if(object.sendCount >= XML_HTTP_MAX_TRIES ) {
190 alert("Arrrgghh, Matey! Error communicating:\n" +
191 E + "\n" + object.param_string);
194 object.buildXMLRequest();
199 /* any other exception is alerted for now */
200 RemoteRequest.prunePending(object.id);
201 //alert("Exception: " + E);
206 /* on success, remove the request from the pending cache */
207 RemoteRequest.prunePending(object.id);
213 /* http by default. This makes it https. *ONLY works when
214 embedded in a XUL app. */
215 RemoteRequest.prototype.setSecure = function(bool) {
220 * By default, all calls are asynchronous. if 'blocking' is
221 * set to true, then the call will block until a response
222 * is received. If blocking, callbacks will not be called.
223 * In other words, you can assume the data is avaiable
224 * (getResponseObject()) as soon as the send call returns.
226 RemoteRequest.prototype.send = function(blocking) {
228 if(this.cancelled) return;
230 if( this.sendCount == 0)
231 RemoteRequest.pending.push(this);
233 debug("Resending request with id " + this.id
234 + " and send count " + this.sendCount);
236 /* determine the xmlhttp server dynamically */
237 var url = location.protocol + "//" + location.host + "/" + XML_HTTP_GATEWAY;
241 url = "https://" + XML_HTTP_SERVER + "/" + XML_HTTP_GATEWAY;
243 //url = "http://" + XML_HTTP_SERVER + ":8080/" + XML_HTTP_GATEWAY;
244 url = "http://" + XML_HTTP_SERVER + "/" + XML_HTTP_GATEWAY;
249 if( this.type == 'GET' ) {
250 url += "?" + this.param_string;
254 this.xmlhttp.open(this.type, url, false);
256 this.xmlhttp.open(this.type, url, true);
260 if( this.type == 'POST' ) {
261 data = this.param_string;
262 this.xmlhttp.setRequestHeader('Content-Type',
263 'application/x-www-form-urlencoded');
266 //alert("Sending from " + location.href + " to " + url + " data [" + data + "]");
267 this.xmlhttp.send( data );
269 debug("Remote Request done sending");
273 /* returns the actual response text from the request */
274 RemoteRequest.prototype.getText = function() {
275 return this.xmlhttp.responseText;
278 RemoteRequest.prototype.isReady = function() {
279 return this.xmlhttp.readyState == 4;
283 /* returns the JSON->js result object */
284 RemoteRequest.prototype.getResultObject = function() {
285 if(this.cancelled) return null;
287 var text = this.xmlhttp.responseText;
288 var obj = JSON2js(text);
291 debug("received null response");
296 if( obj.err_msg.match("OpenSRF::EX::User") ) {
297 alert("Session has timed out or cannot be authenticated.\nPlease log out and log back in if necessary.");
301 debug("Something's Wrong: " + js2JSON(obj));
302 throw new EXCommunication(obj.err_msg);
305 if( obj[0] != null && obj[1] == null )
308 /* these are user level exceptions from the server code */
309 if(instanceOf(obj, ex)) {
310 debug("Received user level exception: " + obj.err_msg());
311 /* the opac will go ahead and spit out the error msg */
312 if(!isXUL()) alert(obj.err_msg());
316 if(instanceOf(obj, perm_ex)) {
317 debug("Received permission error: " + obj.err_msg());
318 /* the opac will go ahead and spit out the error msg */
319 if(!isXUL()) alert(obj.err_msg());
327 /* adds a new parameter to the request */
328 RemoteRequest.prototype.addParam = function(param) {
329 var string = encodeURIComponent(js2JSON(param));
330 this.param_string += "¶m=" + string;