//------------------------
// ajax wrapper functions
//------------------------
// XML returns (or passes to CallBackFunc) a parsed XMLDOM object
// GetRequest returns (or passes to CallBackFunc) response as a string: raw JScode, Text, HTML, or unparsed XML
// To make an Asyncronous call, pass in a valid CallBackFunc (optional)
// To use cached responses, pass in bUseCache = true (optional)
//------------------------
function GetRequest    (url, bUseCache,   CallBackFunc ){ return GetReq( url, bUseCache, CallBackFunc, false, null ); }
function GetRequestXML (url, bUseCache,   CallBackFunc ){ return GetReq( url, bUseCache, CallBackFunc, true,  null );  }
function PostRequest   (url, postDataStr, CallBackFunc ){ return GetReq( url, null,      CallBackFunc, false, postDataStr ); }
function PostRequestXML(url, postDataStr, CallBackFunc ){ return GetReq( url, null,      CallBackFunc, true,  postDataStr );  }
function ImportScript  (jsurl, bUseCache, CallBackFunc, SafariTest, WindowTarget ){ return _ImportScript(jsurl, bUseCache, CallBackFunc, SafariTest, WindowTarget );}
function ImportStyle  (cssurl, bUseCache, CallBackFunc, SafariTest, WindowTarget ){ return _ImportStyle(cssurl, bUseCache, CallBackFunc, SafariTest, WindowTarget );};
function GetJSObject   (jsurl){ return _GetJSObject(jsurl); }
function GetJSObjectPOST(jsurl,postdata){ return _GetJSObject(jsurl,postdata); }
//function CreateScriptTag(str) { return _CreateScriptTag(str); } //defined below
//function CreateStyleTag (str) { return _CreateStyleTag (str); }

//------------------------
// Syncronous JS loading usage:  eval(GetRequest(jsscripturl);
// Asyncronous JS loading usage: eval(GetRequest(jsscripturl, false, myCallBack);
//------------------------
//Use this "base" object to create and load a single self-contained dynamic objects (syncronous)
function _GetJSObject(jsurl){
  //example code to be eval'd:  this.value1 = x; this.value2 = y; (only the innards of the object)
  // Usage: 
  // var obj = new GetJSObject(jsurl); //create and load a dynamic js object
  // obj.reload(optionalUrl); //reload with current data
  // alert(obj.value1); //do something with it
  this.url = jsurl;
  this.reload = function(newurl){
    this.url = ((newurl)?newurl:this.url);
    eval(GetRequest(this.url));
    return this;
  }
  return this.reload();
}
function _GetJSObjectPOST(jsurl,postdata){ //POST version of above
  this.url = jsurl;
  this.post = postdata;
  this.reload = function(newurl){
    this.url = ((newurl)?newurl:this.url);
    eval(GetRequest(this.url,false,null,false,this.post));
    return this;
  }
  return this.reload();
}
function _GetJSObjectASync(jsurl,callback,postdata){
  this.url = jsurl;
  this.post = postdata;
  this.reload = function(newurl){
    this.url = ((newurl)?newurl:this.url);
    GetRequest(this.url,false,this.cb,false,this.post);
    return this;
  }
  this.cb = function(s){
    eval(s);
    callback(this)
    return this;
  }
  return this.reload();
}
//------------------------
// Cross-Domain Asynconsous JS script loading function (loaded script is executed in window.scope)
function _ImportScript( jsurl, bUseCache, CallBackFunc, SafariTest, WindowTarget ) //WindowTarget defaults to self
{
  //Supply CallBack to verify load before accessing loaded objects.  
  //Use SafariTest to trigger the callback func for safari, e.g. test for vars defined in the loaded script
  WindowTarget = GetWin(WindowTarget);
  var doc = GetDoc(WindowTarget);
  var head = doc.getElementsByTagName('head').item(0);
  var s = doc.createElement("SCRIPT");
  s.src = ((bUseCache)?jsurl:GetUniqueURL(jsurl));
  s.type = "text/javascript";
  if(typeof CallBackFunc == "function" ){ // || (CallBackFunc instanceOf Function)){
    if(typeof s.onreadystatechange != "undefined"){//ie
      s.onreadystatechange = function(){if(/loaded|complete/.test(s.readyState)){s.onreadystatechange = null; CallBackFunc();} };
    }else if(/safari/i.test(navigator.userAgent) && SafariTest ){ //Safari does not support event callbacks - use timer callbacks test for defined conditions
      WindowTarget.SafariLoaded = function(){if(eval(SafariTest)){ CallBackFunc(); }else{ WindowTarget.setTimeout("window.SafariLoaded()",100)}; }
      WindowTarget.SafariLoaded();
    }else{
      CallBackFunc.once = true;//avoid repeated callbacks
      addEvent(     s, "load", function(){ if(CallBackFunc.once){CallBackFunc.once = false; CallBackFunc();} } ); //mac:camino,moz,fx. win:moz,fx,opera 9x
      addEvent(WindowTarget, "load", function(){ if(CallBackFunc.once){CallBackFunc.once = false; CallBackFunc();} } ); //opera 8x
    }
  }
  head.appendChild(s);
}
//------------------------
// Cross-Domain Asynconsous CSS StyleSheet loading function (auto-loaded into top level <head> scope)
function _ImportStyle(jsurl, bUseCache, CallBackFunc, WindowTarget )
{
  // Supply CallBack to verify load before accessing loaded objects
  WindowTarget = GetWin(WindowTarget);
  var doc = GetDoc(WindowTarget);
  var head = doc.getElementsByTagName('head').item(0);
  var s = doc.createElement("LINK");
  s.rel = "stylesheet";
  s.href = ((bUseCache)?jsurl:GetUniqueURL(jsurl));
  s.type = "text/css";
  if(navigator.userAgent.match(/opera/i)) 
    addEvent(WindowTarget, "load", CallBackFunc );//opera
  else{
    addEvent(s, "load", CallBackFunc ); //moz
    s.onreadystatechange = function(){if(s.readyState=="loaded") CallBackFunc();}; //ie
  }
  head.appendChild(s);
}
//------------------------
// Dynamic <TAG>String<TAG> functions
function CreateStyleTag( str, win )//create, parse, execute a new <style> string </style> tag
{
  var d = GetDoc(win);
  var s = d.createElement('style');
  s.setAttribute('type', 'text/css');
  if(s.styleSheet)   { s.styleSheet.cssText = str; }//IE
  else{ s.appendChild( d.createTextNode(str) ); }//the world
  (d.getElementsByTagName('head')[0] ).appendChild(s);
}
function CreateScriptTag( str, win )//create, parse, execute a new <script> string </script> tag
{
  var d = GetDoc(win);
  var s = d.createElement('script');
  s.setAttribute('type', 'text/javascript');
  if(s.text)   { s.text = str; }//IE
  else{ s.appendChild( d.createTextNode(str) ); }//the world
  (d.getElementsByTagName('head')[0] ).appendChild(s);
}
function GetDoc(win){ return (win&&win.document)? win.document : window.document; }
function GetWin(win){ return (win&&win.document)? win : window; }

//Scoping example - eval AJAX JS into window scope, instead of function scope
/*
function GetAjaxStuffIntoWindowScope(url){
  function EvalInWindowScope(str){
    CreateScriptTag( str );
  }
  GetRequest(url,false,EvalInWindowScope);
}
*/


//GetReq( "/pns/start.htp", false, function(s){alert(s);}, false, "username=bmckinney&password=lois"  )

//------------------------
//core functions
//------------------------
function GetReq( url, bCache, CallBackFunc, bXML, postData, bCORS  )
{
  if( bCORS ) return GetReqCORS( url, bCache, CallBackFunc, bXML, postData, bCORS	);
              return GetReqSite( url, bCache, CallBackFunc, bXML, postData  );
}
function GetReqSite( url, bCache, CallBackFunc, bXML, postData  )
{
  try{
    var bAsync = (typeof CallBackFunc!="undefined");//&&typeof CallBackFunc=="function");
    var objSrvHTTP;
    objSrvHTTP = getXMLHTTPpool();
    if( objSrvHTTP ){
	  var method = "GET";
      if( typeof postData =="string"){ //Post the data
        method = "POST";
        objSrvHTTP.open("POST", url, bAsync);
        //objSrvHTTP.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		//objSrvHTTP.setRequestHeader("Content-length", String(postData.length));//Should %20 be replaced by '+'?
		//objSrvHTTP.setRequestHeader("Connection", "close"); //? do we need this header?
		objSrvHTTP.setRequestHeader("content-type", "application/x-www-form-urlencoded");
		objSrvHTTP.setRequestHeader("content-length", String(postData.length));//Should %20 be replaced by '+'?
		objSrvHTTP.setRequestHeader("Connection", "close"); //? do we need this header?
		//Post Just Won't Work in FF!
		//alert("GetReq: "+url+"\n Content-length"+ postData.length +"\n postData: "+ postData );
      }
      else if(!bCache){ //never use from cache
        try{
        objSrvHTTP.open("GET", ""+GetUniqueURL(url), bAsync);
        objSrvHTTP.setRequestHeader("Cache-Control","no-cache");
        objSrvHTTP.setRequestHeader("Pragma","no-cache");
         }catch(e){}
      }else{            //use from cache
        objSrvHTTP.open("GET", url, bAsync);
      }
      //alert("BEFORE (bAsync) objSrvHTTP.send("+ postData +")");
      if( bAsync ){//asynchronous, use callback function for return
        objSrvHTTP.onreadystatechange = function(){
          if( objSrvHTTP.readyState == 4){
	          try{//CR 4464
            	if(objSrvHTTP.status == "200"){	            
              	CallBackFunc( ((bXML)?(Str2XMLDOM(String(objSrvHTTP.responseText))):String(objSrvHTTP.responseText)) );
            	}else{
              	CallBackFunc( null );
            	}
          	}catch(e){}
            objSrvHTTP.onreadystatechange = function(){};//null func
          }
        }
        /*
        var pd = "", pairs = GetSearchPairs(null, postData );
        for(var p in pairs){
	        if(typeof(pairs[p])=='string')
	        pd += ((pd.length)?"&":"") + p +"="+escape(pairs[p]);
        }
        postData = pd;
        alert("GetReq '"+method+"': "+url+" (bAsync) objSrvHTTP.send("+ postData +")");
        */
        objSrvHTTP.send( postData );//Why doesn't this work????
        return true;
      }else{       //syncronous (blocking), send and wait here for return
        objSrvHTTP.send( postData );
        if(objSrvHTTP.status == "200")
          return ((bXML)?(Str2XMLDOM(String(objSrvHTTP.responseText))):String(objSrvHTTP.responseText));
        return false;
      }
    }
  }catch(e){ if(objSrvHTTP){objSrvHTTP.abort();} }
  return false;
}
//====================================
function GetReqCORS( url, bCache, CallBackFunc, bXML, postData, bCORS	)
{
	//try{  //alert("GetReq( url ): "+ url);
		var bAsync = (typeof CallBackFunc!="undefined");//&&typeof CallBackFunc=="function");
		var objSrvHTTP = null, bNotIEX = true, method = "GET";
		
		objSrvHTTP = getXMLHTTPpool( bCORS );
		//alert(objSrvHTTP);
		if( objSrvHTTP )
		{
			method = ((typeof postData =="string")?"POST":"GET");	
			//check for ok to pull from cache
			url = ((!bCache && method =="GET")? String( GetUniqueURL(url) ) :url); 
			//Detect Non-IE9 CORS XRequest
			if( bCORS	&& "withCredentials" in objSrvHTTP ){ 
				bNotIEX = false;		 
			}
			//open the xhr object
			if( bNotIEX ){ objSrvHTTP.open(method, url, true); } //bAsync);
			else{					objSrvHTTP.open(method, url); }
			
			//Add any special headers
			if( method == "POST" )
			{
				objSrvHTTP.setRequestHeader("content-type", "application/x-www-form-urlencoded");
				//objSrvHTTP.setRequestHeader("content-length", String(postData.length));//Should %20 be replaced by '+'?
				//objSrvHTTP.setRequestHeader("Connection", "close"); //? do we need this header?
			}
			else if(!bCache ) //avoid cache
			{ 
				//CORS TEST// objSrvHTTP.setRequestHeader("Cache-Control","no-cache");
				//objSrvHTTP.setRequestHeader("Pragma","no-cache");
			}
			if( bCORS	&& bNotIEX ){
				//objSrvHTTP.withCredentials = "true";
			}

			//alert("BEFORE (bAsync) objSrvHTTP.send("+ postData +")");
			 //asynchronous, use callback function for return
			if( bAsync || bCORS )
			{
				if( bCORS ){ objSrvHTTP.onload = CORSloaded; }
				else{				objSrvHTTP.onreadystatechange = XHRloaded; }
				objSrvHTTP.send( postData );
				return true;
			}
			else{ //syncronous (blocking), send and wait here for return
				objSrvHTTP.send( postData );
				return SyncLoaded();
			}
		}
	//}catch(e){ if(objSrvHTTP){objSrvHTTP.abort();} }
	
	//Response Processing Functions
	function GetResponseText(){
		return ((bXML)? (Str2XMLDOM(String(objSrvHTTP.responseText))):String(objSrvHTTP.responseText)); 
	}
	function SyncLoaded(){
		if(objSrvHTTP.status == "200") return GetResponseText();
		return false;
	}
	function CORSloaded(){
		CallBackFunc( GetResponseText() );
	}
	function XHRloaded()
	{ //objSrvHTTP == this?
		if( objSrvHTTP.readyState == 4)
		{
			try{ //CR 4464
				if(objSrvHTTP.status == "200"){							
					CallBackFunc( GetResponseText() );
				}else{
					CallBackFunc( null );
				}
			}catch(e){ objSrvHTTP.onreadystatechange = function(){}; } //null func
		}
	}
	//all done
	return false;
}
//------------------------
function getXMLHTTP( bCORS ){ //x-browser xmlhttp creator  
  if(window.XMLHttpRequest){
    try{
      if( bCORS )//x-domain request 
      {  
        var xhr = new XMLHttpRequest(); //IE 8, the world  
        if( "withCredentials" in xhr){
           return xhr;
        }
        else if (typeof XDomainRequest != "undefined"){ //IE9
          xhr = new XDomainRequest();
          return xhr;
        }
      }
      return new XMLHttpRequest(); //IE7 - no CORS
    }catch(e){
      try{ return new XMLHttpRequest; }catch(e){} //others
    }
  }
  if(window.ActiveXObject){ //IE5,6
    try{
      return new ActiveXObject("Microsoft.XMLHTTP");
    }catch(e){}
  }
  return null;
}
/*
//------------------------
function getXMLHTTP_Simple( bCORS ){ //x-browser xmlhttp creator  
  try{ return new XMLHttpRequest(); }catch(e){} //IE7+,FF1.5+, all else
  try{ return new XMLHttpRequest; }catch(e){}   //others
  try{ return new ActiveXObject("Microsoft.XMLHTTP"); }catch(e){} //IE6+
  try{ return new ActiveXObject("MSXML2.XMLHTTP.3.0"); }catch(e){} //IE5-
  return null;
}
//------------------------
function getXMLHTTP( bCORS ) //x-browser xmlhttp creator
{ alert("getXMLHTTP: "+getXMLHTTP)
  var xhr =  null;
  if( bCORS )
  {
    //if (typeof XMLHttpRequest != "undefined"){
    //if (typeof XDomainRequest != "undefined"){
    //try{ xhr = new XDomainRequest(); }catch(e){}
    try{ 
      var xhr = new XMLHttpRequest();   //IE8, the world  
      if( "withCredentials" in xhr){
         //xhr.open(method, url, true);
         return xhr;
      }
      else if (typeof XDomainRequest != "undefined") //IE9
      {
        xhr = new XDomainRequest();
        //xhr.open(method, url);
        return xhr;
      }
    }catch(e){} 
    //else{  //Note: Here is hwere we need to add IE6,7 CORS Handling
    //  xhr = null;
    //}
    //return xhr;
  }
  return getXMLHTTP_Simple();
}
*/
//------------------------
function getXMLHTTP_ORG(){ //x-browser xmlhttp creator  
  if(window.XMLHttpRequest){
    try{
      return new XMLHttpRequest();
    }catch(e){}
  }
  if(window.ActiveXObject){
    try{
      return new ActiveXObject("Microsoft.XMLHTTP");
    }catch(e){}
  }
  return null;
}
//------------------------
function getXMLHTTPpool( bCORS ){ //pool of reusable XMLHTTP objects
  //return getXMLHTTP( bCORS );
  var XhrCacheName = ((bCORS)?"xmlhttpfactorycors":"xmlhttpfactory");
  var XhrCacheObj  = window[XhrCacheName];
  try{
    if(typeof XhrCacheObj =="undefined"){//create a new global static object pool
      XhrCacheObj = [];
      return (XhrCacheObj[0] = getXMLHTTP( bCORS ));
    }
    else{ //get from pool
      for(var i=0; i < XhrCacheObj.length; i++){
        if ( XhrCacheObj[i].readyState == 4 || XhrCacheObj[i].readyState == 0 ){
          return XhrCacheObj[i];
        }
      }//else none available, create another one, add to pool
      return (XhrCacheObj[XhrCacheObj.length] = getXMLHTTP( bCORS ));    
    }
  }catch(e){return null;}
}
//------------------------
function Str2XMLDOM(s){ //x-browser XML factory: create parsed XMLDOMobj from string
  try{
    if(typeof ActiveXObject!="undefined"&&typeof GetObject!="undefined"){
      var b=new ActiveXObject("Microsoft.XMLDOM");
      b.loadXML(s);
      return b;
    }else if (document.implementation && document.implementation.createDocument) {
		  var p = new DOMParser();
      return p.parseFromString(s,"text/xml");
    }else if(typeof DOMParser!="undefined"){
      var p = new DOMParser();
      return p.parseFromString(s,"text/xml");
	  }
    return null;
  }
  catch(e){ return null; }
}
//------------------------
function GetUniqueURL(s){ //append unique GET query nvpair to help prevent browser cache
  s += "";
  return s + ((s.match(/\?/))?"&":"?") + (new Date()).valueOf()+"guu="+(new Date()).valueOf();
}


