2 // jsrsClient.js - javascript remote scripting client include
4 // Author: Brent Ashley [jsrs@megahuge.com]
6 // make asynchronous remote calls to server without client page refresh
8 // see license.txt for copyright and license information
11 see history.txt for full history
12 2.0 26 Jul 2001 - added POST capability for IE/MOZ
13 2.2 10 Aug 2003 - added Opera support
14 2.3(beta) 10 Oct 2003 - added Konqueror support - **needs more testing**
17 // callback pool needs global scope
18 var jsrsContextPoolSize = 0;
19 var jsrsContextMaxPool = 10;
20 var jsrsContextPool = new Array();
21 var jsrsBrowser = jsrsBrowserSniff();
25 // constructor for context object
26 function jsrsContextObj( contextID ){
32 this.container = contextCreateContainer( contextID );
35 this.GET = contextGET;
36 this.POST = contextPOST;
37 this.getPayload = contextGetPayload;
38 this.setVisibility = contextSetVisibility;
41 // method functions are not privately scoped
42 // because Netscape's debugger chokes on private functions
43 function contextCreateContainer( containerName ){
44 // creates hidden container to receive server data
46 switch( jsrsBrowser ) {
48 container = new Layer(100);
49 container.name = containerName;
50 container.visibility = 'hidden';
51 container.clip.width = 100;
52 container.clip.height = 100;
56 document.body.insertAdjacentHTML( "afterBegin", '<span id="SPAN' + containerName + '"></span>' );
57 var span = document.all( "SPAN" + containerName );
58 var html = '<iframe name="' + containerName + '" src=""></iframe>';
59 span.innerHTML = html;
60 span.style.display = 'none';
61 container = window.frames[ containerName ];
65 var span = document.createElement('SPAN');
66 span.id = "SPAN" + containerName;
67 document.body.appendChild( span );
68 var iframe = document.createElement('IFRAME');
69 iframe.name = containerName;
70 iframe.id = containerName;
71 span.appendChild( iframe );
76 var span = document.createElement('SPAN');
77 span.id = "SPAN" + containerName;
78 document.body.appendChild( span );
79 var iframe = document.createElement('IFRAME');
80 iframe.name = containerName;
81 iframe.id = containerName;
82 span.appendChild( iframe );
87 var span = document.createElement('SPAN');
88 span.id = "SPAN" + containerName;
89 document.body.appendChild( span );
90 var iframe = document.createElement('IFRAME');
91 iframe.name = containerName;
92 iframe.id = containerName;
93 span.appendChild( iframe );
96 // Needs to be hidden for Konqueror, otherwise it'll appear on the page
97 span.style.display = none;
98 iframe.style.display = none;
99 iframe.style.visibility = hidden;
108 function contextPOST( rsPage, func, parms ){
111 var unique = d.getTime() + '' + Math.floor(1000 * Math.random());
112 var doc = (jsrsBrowser == "IE" ) ? this.container.document : this.container.contentDocument;
114 doc.write('<html><body>');
115 doc.write('<form name="jsrsForm" method="post" target="" ');
116 doc.write(' action="' + rsPage + '?U=' + unique + '">');
117 doc.write('<input type="hidden" name="C" value="' + this.id + '">');
119 // func and parms are optional
121 doc.write('<input type="hidden" name="F" value="' + func + '">');
124 if (typeof(parms) == "string"){
126 doc.write( '<input type="hidden" name="P0" '
127 + 'value="[' + jsrsEscapeQQ(parms) + ']">');
129 // assume parms is array of strings
130 for( var i=0; i < parms.length; i++ ){
131 doc.write( '<input type="hidden" name="P' + i + '" '
132 + 'value="[' + jsrsEscapeQQ(parms[i]) + ']">');
138 doc.write('</form></body></html>');
140 doc.forms['jsrsForm'].submit();
143 function contextGET( rsPage, func, parms ){
148 // always send context
149 URL += "?C=" + this.id;
151 // func and parms are optional
153 URL += "&F=" + escape(func);
156 if (typeof(parms) == "string"){
158 URL += "&P0=[" + escape(parms+'') + "]";
160 // assume parms is array of strings
161 for( var i=0; i < parms.length; i++ ){
162 URL += "&P" + i + "=[" + escape(parms[i]+'') + "]";
168 // unique string to defeat cache
170 URL += "&U=" + d.getTime();
173 switch( jsrsBrowser ) {
175 this.container.src = URL;
178 this.container.document.location.replace(URL);
181 this.container.src = '';
182 this.container.src = URL;
185 this.container.src = '';
186 this.container.src = URL;
189 this.container.src = '';
190 this.container.src = URL;
195 function contextGetPayload(){
196 switch( jsrsBrowser ) {
198 return this.container.document.forms['jsrs_Form'].elements['jsrs_Payload'].value;
200 return this.container.document.forms['jsrs_Form']['jsrs_Payload'].value;
202 return window.frames[this.container.name].document.forms['jsrs_Form']['jsrs_Payload'].value;
204 var textElement = window.frames[this.container.name].document.getElementById("jsrs_Payload");
206 var textElement = window.frames[this.container.name].document.getElementById("jsrs_Payload");
207 return textElement.value;
211 function contextSetVisibility( vis ){
212 switch( jsrsBrowser ) {
214 this.container.visibility = (vis)? 'show' : 'hidden';
217 document.all("SPAN" + this.id ).style.display = (vis)? '' : 'none';
220 document.getElementById("SPAN" + this.id).style.visibility = (vis)? '' : 'hidden';
222 document.getElementById("SPAN" + this.id).style.visibility = (vis)? '' : 'hidden';
223 this.container.width = (vis)? 250 : 0;
224 this.container.height = (vis)? 100 : 0;
229 // end of context constructor
231 function jsrsGetContextID(){
233 for (var i = 1; i <= jsrsContextPoolSize; i++){
234 contextObj = jsrsContextPool[ 'jsrs' + i ];
235 if ( !contextObj.busy ){
236 contextObj.busy = true;
237 return contextObj.id;
240 // if we got here, there are no existing free contexts
241 if ( jsrsContextPoolSize <= jsrsContextMaxPool ){
242 // create new context
243 var contextID = "jsrs" + (jsrsContextPoolSize + 1);
244 jsrsContextPool[ contextID ] = new jsrsContextObj( contextID );
245 jsrsContextPoolSize++;
248 alert( "jsrs Error: context pool full" );
253 function jsrsExecute( rspage, callback, func, parms, visibility ){
254 // call a server routine from client code
256 // rspage - href to asp file
257 // callback - function to call on return
258 // or null if no return needed
259 // (passes returned string to callback)
260 // func - sub or function name to call
261 // parm - string parameter to function
262 // or array of string parameters if more than one
263 // visibility - optional boolean to make container visible for debugging
266 var contextObj = jsrsContextPool[ jsrsGetContextID() ];
267 contextObj.callback = callback;
269 var vis = (visibility == null)? false : visibility;
270 contextObj.setVisibility( vis );
272 if ( jsrsPOST && ((jsrsBrowser == 'IE') || (jsrsBrowser == 'MOZ'))){
273 contextObj.POST( rspage, func, parms );
275 contextObj.GET( rspage, func, parms );
278 return contextObj.id;
281 function jsrsLoaded( contextID ){
282 // get context object and invoke callback
283 var contextObj = jsrsContextPool[ contextID ];
284 if( contextObj.callback != null){
285 contextObj.callback( jsrsUnescape( contextObj.getPayload() ), contextID );
287 // clean up and return context to pool
288 contextObj.callback = null;
289 contextObj.busy = false;
292 function jsrsError( contextID, str ){
293 alert( unescape(str) );
294 jsrsContextPool[ contextID ].busy = false
297 function jsrsEscapeQQ( thing ){
298 return thing.replace(/'"'/g, '\\"');
301 function jsrsUnescape( str ){
302 // payload has slashes escaped with whacks
303 return str.replace( /\\\//g, "/" );
306 function jsrsBrowserSniff(){
307 if (document.layers) return "NS";
309 // But is it really IE?
310 // convert all characters to lowercase to simplify testing
311 var agt=navigator.userAgent.toLowerCase();
312 var is_opera = (agt.indexOf("opera") != -1);
313 var is_konq = (agt.indexOf("konqueror") != -1);
325 if (document.getElementById) return "MOZ";
329 /////////////////////////////////////////////////
333 function jsrsArrayFromString( s, delim ){
334 // rebuild an array returned from server as string
335 // optional delimiter defaults to ~
336 var d = (delim == null)? '~' : delim;
340 function jsrsDebugInfo(){
341 // use for debugging by attaching to f1 (works with IE)
342 // with onHelp = "return jsrsDebugInfo();" in the body tag
343 var doc = window.open().document;
345 doc.write( 'Pool Size: ' + jsrsContextPoolSize + '<br><font face="arial" size="2"><b>' );
346 for( var i in jsrsContextPool ){
347 var contextObj = jsrsContextPool[i];
348 doc.write( '<hr>' + contextObj.id + ' : ' + (contextObj.busy ? 'busy' : 'available') + '<br>');
349 doc.write( contextObj.container.document.location.pathname + '<br>');
350 doc.write( contextObj.container.document.location.search + '<br>');
351 doc.write( '<table border="1"><tr><td>' + contextObj.container.document.body.innerHTML + '</td></tr></table>' );
353 doc.write('</table>');