//
//  jsrsClient.js - javascript remote scripting client include
//
//  Author:  Brent Ashley [jsrs@megahuge.com]
//
//  make asynchronous remote calls to server without client page refresh
//
//  see license.txt for copyright and license information

var g_strRootPathRS = "/";
var g_bDevelopment = 1;

function ClearError() 
{
	history.go();
	return true;
}

// callback pool needs global scope
var jsrsContextPoolSize = 0;
var jsrsContextMaxPool = 50;
var jsrsContextPool = new Array();
var tmp = window.onerror;
window.onerror = ClearError;
var jsrsBrowser = jsrsBrowserSniff();
window.onerror = tmp;
var jsrsPOST = true;

// constructor for context object
function jsrsContextObj( contextID )
{
	// properties
	this.id = contextID;
	this.busy = true;
	this.callback = null;
	this.container = contextCreateContainer( contextID );

	// methods
	this.GET = contextGET;
	this.POST = contextPOST;
	this.getPayload = contextGetPayload;
	this.setVisibility = contextSetVisibility;
}

function EmptyFrameLoaded(containerName)
{
}

//  method functions are not privately scoped
//  because Netscape's debugger chokes on private functions
function contextCreateContainer( containerName )
{
	// creates hidden container to receive server data
	var container;
	switch( jsrsBrowser ) {
    case 'NS':
      container = new Layer(100);
      container.name = containerName;
      container.visibility = 'hidden';
      container.clip.width = 100;
      container.clip.height = 100;
      break;

    case 'IE':
      document.body.insertAdjacentHTML( "afterBegin", '<span id="SPAN' + containerName + '"></span>' );
      var span = document.all["SPAN" + containerName];
      var html = '<iframe name="' + containerName + '" src="about:blank"></iframe>';
      span.style.display = 'none';
      span.innerHTML = html;
	  container = window.frames[containerName];

	  try
	  {
	  	  var d = container.document;
	  }
	  catch(exception)
	  {
	      var html = '<iframe name="' + containerName + '" src="' + g_strRootPath + 'rs/empty.htm" onload="EmptyFrameLoaded(\'' + containerName + '\')"></iframe>';
	      span.style.display = 'none';
	      span.innerHTML = html;
		  container = window.frames[containerName];
	  }
      break;

    case 'MOZ':
      var span = document.createElement('SPAN');
      span.style.visibility = "hidden";
      span.style.position = "absolute";
      span.style.top = "0px"; span.style.left = "0px";
      span.id = "SPAN" + containerName;
      document.body.appendChild( span );
      var iframe = document.createElement('IFRAME');
      iframe.style.visibility = "hidden";
      iframe.name = containerName;
      span.appendChild( iframe );
      container = iframe;
      break;
	case 'OPR':  	
		var span = document.createElement('SPAN');	
		span.id = "SPAN" + containerName;	
		document.body.appendChild( span );	
		var iframe = document.createElement('IFRAME');	
		iframe.name = containerName;	
		iframe.id = containerName;	
		span.appendChild( iframe );	
		container = iframe;	
		break;	
	case 'KONQ':  	
		var span = document.createElement('SPAN');	
		span.id = "SPAN" + containerName;	
		document.body.appendChild( span );	
		var iframe = document.createElement('IFRAME');	
		iframe.name = containerName;	
		iframe.id = containerName;	
		span.appendChild( iframe );	
		container = iframe;	
		// Needs to be hidden for Konqueror, otherwise it'll appear on the page	
		span.style.display = none;	
		iframe.style.display = none;	
		iframe.style.visibility = hidden;	
		iframe.height = 0;	
		iframe.width = 0;
		break;
  }
  return container;
}

function contextPOST( rsPage, func, parms ){
  var d = new Date();
  var unique = d.getTime() + '' + Math.floor(1000 * Math.random());
  var doc = (jsrsBrowser == "IE") ? this.container.document : this.container.contentDocument;
  var strHTML = "";
  doc.open();
  strHTML += '<html><body>';
  strHTML += '<form id="jsrsForm" name="jsrsForm" method="post" target="" ';
  strHTML += ' action="' + rsPage + '?U=' + unique + '&' + g_strSessionID;
  strHTML += '">';
  strHTML += '<input type="hidden" name="C" value="' + this.id + '">';
  doc.write(strHTML);

  // func and parms are optional
  if (func != null){
  doc.write('<input type="hidden" name="F" value="' + func + '">');

    if (parms != null){
      if (typeof(parms) == "string"){
        // single parameter
        doc.write( '<input type="hidden" name="P0" '
                 + 'value="[' + jsrsEscapeQQ(parms) + ']">');
      } else {
        // assume parms is array of strings
        for ( var i=0; i < parms.length; i++ ){
          doc.write( '<input type="hidden" name="P' + i + '" '
                   + 'value="[' + jsrsEscapeQQ(parms[i]) + ']">');
        }
      } // parm type
    } // parms
  } // func

  doc.write('</form></body></html>');
  doc.close();
  doc.getElementById('jsrsForm').submit();
}

function contextGET( rsPage, func, parms ){

  // build URL to call
  var URL = rsPage;

  // always send context
  URL += "?C=" + this.id;

  // func and parms are optional
  if (func != null){
    URL += "&F=" + escape(func);

    if (parms != null){
      if (typeof(parms) == "string"){
        // single parameter
        URL += "&P0=[" + escape(parms+'') + "]";
      } else {
        // assume parms is array of strings
        for ( var i=0; i < parms.length; i++ ){
          URL += "&P" + i + "=[" + escape(parms[i]+'') + "]";
        }
      } // parm type
    } // parms
  } // func

  // unique string to defeat cache
  var d = new Date();
  URL += "&U=" + d.getTime();
  URL += "&" + g_strSessionID;

  // make the call
  switch( jsrsBrowser ) {
    case 'NS':
      this.container.src = URL;
      break;
    case 'IE':
      this.container.document.location.replace(URL);
      break;
    case 'MOZ':
      this.container.src = '';
      this.container.src = URL;
      break;
	case 'OPR':	
		this.container.src = '';	
		this.container.src = URL; 	
		break;	
	case 'KONQ':	
		this.container.src = '';	
		this.container.src = URL; 	
	break;  
	}
}

function contextGetPayload(objDocument){
  var retVal = "";

  switch( jsrsBrowser ) {
    case 'NS':
		retVal = objDocument.forms['jsrs_Form'].elements['jsrs_Payload'].value;
		break;
    case 'IE':
		retVal = objDocument.forms['jsrs_Form']['jsrs_Payload'].value;
		break;
    case 'MOZ':
		retVal = objDocument.forms['jsrs_Form']['jsrs_Payload'].value;
		break;
	case 'OPR':	
		var textElement = window.frames[this.container.name].document.getElementById("jsrs_Payload");	
	case 'KONQ':	
		var textElement = window.frames[this.container.name].document.getElementById("jsrs_Payload");	
		return textElement.value;
  }

  return retVal;
}

function contextSetVisibility( vis ){
  switch( jsrsBrowser ) {
    case 'NS':
      this.container.visibility = (vis)? 'show' : 'hidden';
      break;
    case 'IE':
      document.all("SPAN" + this.id ).style.display = (vis)? '' : 'none';
      break;
    case 'MOZ':
      document.getElementById("SPAN" + this.id).style.visibility = (vis)? '' : 'hidden';
      this.container.width = (vis)? 250 : 0;
      this.container.height = (vis)? 100 : 0;
      break;
	case 'OPR':	
		document.getElementById("SPAN" + this.id).style.visibility = (vis)? '' : 'hidden';	
		this.container.width = (vis)? 250 : 0;	
		this.container.height = (vis)? 100 : 0;	
		break;	
  }
}

// end of context constructor

function CheckJSRSInProgress()
{
	var bRes = false;

	for (var i = 1; !bRes && (i <= jsrsContextPoolSize); i++)
	{
	  contextObj = jsrsContextPool[ 'jsrs' + i ];
	  if (contextObj.busy)
	  	bRes = true;
	}
	
	return bRes;
}

function jsrsGetContextID(){
  var contextObj;
  for (var i = 1; i <= jsrsContextPoolSize; i++){
    contextObj = jsrsContextPool[ 'jsrs' + i ];
    if ( !contextObj.busy ){
      contextObj.busy = true;
      return contextObj.id;
    }
  }
  // if we got here, there are no existing free contexts
  if ( jsrsContextPoolSize <= jsrsContextMaxPool ){
    // create new context
    var contextID = "jsrs" + (jsrsContextPoolSize + 1);
    jsrsContextPool[ contextID ] = new jsrsContextObj( contextID );
    jsrsContextPoolSize++;
    return contextID;
  } else {
    alert( "jsrs Error:  context pool full" );
    return null;
  }
}

function jsrsExecute( rspage, callback, func, parms, visibility ){
  // call a server routine from client code
  //
  // rspage      - href to asp file
  // callback    - function to call on return
  //               or null if no return needed
  //               (passes returned string to callback)
  // func        - sub or function name  to call
  // parm        - string parameter to function
  //               or array of string parameters if more than one
  // visibility  - optional boolean to make container visible for debugging

  // get context
  var contextObj = jsrsContextPool[ jsrsGetContextID() ];
  contextObj.callback = callback;

  var vis = (visibility == null)? false : visibility;
  contextObj.setVisibility( vis );
  if ( jsrsPOST && ((jsrsBrowser == 'IE') || (jsrsBrowser == 'MOZ'))){
    contextObj.POST( rspage, func, parms );
  } else {
    contextObj.GET( rspage, func, parms );
  }

  return contextObj.id;
}

function jsrsLoaded(contextID, objDocument){
  // get context object and invoke callback
  var contextObj = jsrsContextPool[ contextID ];

  if ( contextObj.callback != null){
  	strPayload = jsrsUnescape(contextObj.getPayload(objDocument));
	if (true) //send expiring info through jsrs
	{
	    strPayload = strPayload.substr(2);
	}
 	contextObj.callback( strPayload, contextID );
  }
  // clean up and return context to pool
  contextObj.callback = null;
  contextObj.busy = false;
  if (parseInt(g_bDevelopment) == 0)
  	contextObj.container.location.href = "about:blank";
}

function jsrsError( contextID, str ){
  alert( unescape(str) );
  jsrsContextPool[ contextID ].busy = false
}

function jsrsEscapeQQ( thing ){
  str = thing.toString();
  return str.split("\"").join("&quot;");
}

function jsrsUnescape( str ){
  // payload has slashes escaped with whacks
  return str.replace(/\\\//g, "/");
}

/*
function jsrsBrowserSniff(){
  if (document.layers) return "NS";
  if (document.all) return "IE";
  if (document.getElementById) return "MOZ";
  return "OTHER";
}
*/
function jsrsBrowserSniff()
{
	if (document.layers) return "NS";	
	if (document.all) 
	{	
		// But is it really IE?	
		// convert all characters to lowercase to simplify testing	
		var agt=navigator.userAgent.toLowerCase();	
		var is_opera = (agt.indexOf("opera") != -1);	
		var is_konq = (agt.indexOf("konqueror") != -1);	
		if(is_opera) {	
			return "OPR";	
		} else {	
			if(is_konq) {	
				return "KONQ";	
			} else {	
				// Really is IE	
				return "IE";	
			}	
		}	
	}	
	if (document.getElementById) return "MOZ";	
	return "OTHER";	
}

/////////////////////////////////////////////////
//
// user functions

function jsrsArrayFromString( s, delim ){
  // rebuild an array returned from server as string
  // optional delimiter defaults to ~
  var d = (delim == null)? '~' : delim;
  return s.split(d);
}

function jsrsDebugInfo(){
  // use for debugging by attaching to f1 (works with IE)
  // with onHelp = "return jsrsDebugInfo();" in the body tag
  var doc = window.open().document;
  doc.open;
  doc.write( 'Pool Size: ' + jsrsContextPoolSize + '<br><font face="arial" size="2"><b>' );
  for ( var i in jsrsContextPool ){
    var contextObj = jsrsContextPool[i];
    doc.write( '<hr>' + contextObj.id + ' : ' + (contextObj.busy ? 'busy' : 'available') + '<br>');
    doc.write( contextObj.container.document.location.pathname + '<br>');
    doc.write( contextObj.container.document.location.search + '<br>');
    doc.write( '<table border="1"><tr><td>' + contextObj.container.document.body.innerHTML + '</td></tr></table>' );
  }
  doc.write('</table>');
  doc.close();
  return false;
}
