/********************************/
//	Dynamic Dependant Project
//	AJAX Stuff
//	Requires the foundation code
/********************************/

var ddp;
if(!ddp) ddp = {};
ddp.a = {};

/********************************/
//	DDP -> AJAX
/********************************/
(function() {

  /***************************************************************/
  //loadJSON
  //add a script element to the document header using the supplied url
  //----arguments----
  //url:  string  -the url to get the "script" file from
	function loadJSON(url)
	{
	  var headID = document.getElementsByTagName("head")[0];  //get a reference to the document's <head> element
	  var newScript = document.createElement('script'); //create a new script element
	      newScript.type = 'text/javascript'; //set it's properties
	      newScript.src = url;
	  headID.appendChild(newScript); //and append it to the head.
	}
  
  
  /***************************************************************/
  //addHeaderScript
  //-strURL:    a url to a page to generate return data
  //-fnSuccess: callback function to recieve the returned data
  //-objWindow: optional. the window that the new script should be added to. (default is the current)
	function addHeaderScript(strURL, fnSuccess, objWindow){
    //if a browser window wasn't supplied, use the current one 
    objWindow = (typeof objWindow == 'object') ? objWindow : window;
    //get a reference to the document's <head> element
	  var elHead = objWindow.document.getElementsByTagName('head')[0];
    //create a half time-based, half random-number string for the function name (e.g cbf125053068355207244769124226434)
    var strFunctionName = 'cbf' + new Date().getTime() + String(Math.random()).replace('.', '');
    //if the url already has a ? then add an &; otherwise, add a ?.
    strURL += (strURL.indexOf('?')+1) ? '&' : '?';
    //add a name value pair for passing the callback function name we generated.
    strURL += 'callback=' + strFunctionName;
    //create a global function with our function name 
    objWindow[strFunctionName] = function(){
      //pass all arguments to our success function
      fnSuccess.apply(objWindow, arguments);
      //once our function has executed, remove the global refernece to the callback function name we generated.
      objWindow[strFunctionName] = undefined;
    };
    //create a new script element
    var elNewScript = objWindow.document.createElement('script');
    elNewScript.type = 'text/javascript';
    elNewScript.src = strURL;
    //append the new script element to the end of the head element
    elHead.appendChild(elNewScript);
	}

  
  /***************************************************************/
  function request(url,destination){
    function successHandler(strData){
      if(typeof destination == 'object')
        destination.innerHTML = strData;
      else
        document.getElementById(destination).innerHTML = strData;
    }
    function failureHandler(intErrorNumber, strMessage){
      alert(intErrorNumber + ': ' + strMessage);
    }
    return HTTPRequest('get', url, null, successHandler, failureHandler);
  }

   
  /***************************************************************/
	function requestPost(url,params,callback){ //Uses POST and a Callback function (JSON response)
    return HTTPRequest('post', url, params, callback, function(intErrorNumber, strMessage){ alert(intErrorNumber + ': ' + strMessage); }, 'json');
  }
  
  /*
  //just a wrapper to rearrange the arguments
  function xhr(strUrl, strData, strMethod, strReturnFormat, successCallback, failureCallback, progressCallback, blnSync){
    return HTTPRequest(strMethod, strURL, strData, successCallback, failureCallback, strReturnFormat, progressCallback, blnSync);
  }
  */
  
  /***************************************************************/
  //HTTPRequest
  //performs a get or post http request
  //----arguments----
  //strMethod:        string    -'get' or 'post' or null (defaults to 'get')
  //strURL:           string    -the url (can include name/value arguments. eg. '/path/page.php?name=value&test=1') 
  //strData:          string    -request data in the form of a name/value string ('variableName=variableValue&pizza=yes')
  //                  object    -if you pass a form element in strData, the form will be parsed and stringified automatically!
  //successCallback:  function  -function to be executed when the data is returned.
  //                             data will be returned as the first argument of the function (optional)
  //failureCallback:  function  -function to be executed if the request fails. (optional) 
  //strReturnFormat:  string    -'json' to return a JSON object, 'xml' to return an xmlDocument or
  //                             'text' to return a plain text string (defaults to 'text')
  //progessCallback:  function  -function which is executed periodically during the transfer. (only supported in Mozilla/FF)
  //                             recieves three arguments (percentageComplete, bytesSoFar, bytesTotal)
  //blnSync:          boolean   -when set to true (defaults to false), the request is syncronous and the data is returned from
  //                             the actual function (false is returned on error)
  function HTTPRequest(strMethod, strURL, strData, successCallback, failureCallback, strReturnFormat, progressCallback, blnSync){
    //create a new httpRequestObject object
    var newRequest = new httpRequestClass();
    
    newRequest.fnSuccess = (typeof successCallback == 'function') ? successCallback : null; //if a success function was specified, use it
    newRequest.fnProgress = (typeof progressCallback == 'function') ? progressCallback : null; //if a progress function was specified, use it
    //newRequest.fnProgress = function(percentage, bytesSoFar, bytesTotal){ if(console) console.log(percentage + '% complete'); };
    newRequest.fnFailure = (typeof failureCallback == 'function') ? failureCallback : null; //if a failure function was specified, use it

    if(ddp.f.isString(strData))  //if the user supplied a string in strData or a form was parsed into a string of data
      newRequest.strData = strData; //then set the httpRequestObject property    
    else if(strData && typeof strData == 'object'){ //take care of all the stuff if a form element is passed
      var objObject = strData;
      if(objObject.nodeType && objObject.nodeType==1){
        //if the element is a form, try and get the form properties for the request
        if(objObject.tagName && objObject.tagName.toLowerCase()=='form'){
          if(objObject.onsubmit){ //if the form has an onsubmit event
        		if(objObject.onsubmit() == false) //execute it and see if it tried to stop form submission
              return newRequest.failHandler(3, 'Request was cancelled by the form element\'s onsubmit().'); //if it returns false, cancel the whole request
        	}
          newRequest.strURL = (objObject.action && objObject.action.length) ? objObject.action : '?';
          if(objObject.method && objObject.method.toLowerCase() == 'post')  //if the form says to do a POST,
            newRequest.strMethod = 'post';  //then do a post
        }
        //go through the element's children and parse all the name/value pairs from the inputs into a string (using encodeURIComponent())
        newRequest.strData = parseForm(objObject);
      }
      else{
        var strNameValuePairs = '';
  			for(propertyName in objObject){
  				if(strNameValuePairs.length > 0)
  				  strNameValuePairs += '&';
          strNameValuePairs += encodeURIComponent(propertyName) + '=' + encodeURIComponent(objObject[propertyName]);
  			}
        newRequest.strData = strNameValuePairs;
      }
    }
    
    if(strURL && strURL.length && strURL.length > 0)
      newRequest.strURL = strURL; //set the url property of this object
    
    if(ddp.f.isString(strMethod)) //if a method was supplied in the arguments
      //if it was 'post' set the method to post, other wise set it to get
      newRequest.strMethod = (strMethod.toLowerCase() == 'post') ? 'post' : 'get';
     
    if(ddp.f.isString(strReturnFormat)){ //if a format was specified in the arguments
      strReturnFormat = strReturnFormat.toLowerCase(); //change it to lower case
      if(strReturnFormat == 'text' || strReturnFormat == 'json' || strReturnFormat == 'xml') //if it is either json or xml,
        newRequest.strReturnFormat = strReturnFormat; //then use it (otherwise it will remain 'text')
    }
  
    //set the "sychronous execution" flag in the object accordingly
    newRequest.blnSync = (blnSync) ? true : false;
    if(blnSync)
      return newRequest.execute();  //execute the request.
    else if(newRequest.execute() == true)
      return newRequest; //return the request object;
    else
      return null;
  }
  
  
  //httpRequestObject
  //the wrapper object used to make a request cross-browser compatible
  //basically, set all the properties you need to and then execute() the request.
  function httpRequestClass(){
    this.fnSuccess = null;  //by default, don't use a success function
    this.fnProgress = null;  //by default, don't use a progress function
    this.fnFailure = null;  //by default, don't use a failure function
    this.strMethod = 'get'; //by default, use the 'get' method
    this.strURL = null;
    this.strData = null;
    this.strReturnFormat = 'default'; //by default, the the 'text' return format
    this.blnSync = false;
    var objThisRequest = this;  //keep a reference to this object
    objThisRequest.http = null;
    var strErrorURL = ''; //the URL that will be reported on errors
    
    
    //abort
    //abort the HTTPRequest
    this.abort = function(){
      if(objThisRequest.http){
        try{
          objThisRequest.blnAborting = true;
          objThisRequest.http.abort();
          objThisRequest.blnAborting = false;
          return true;
        }
        catch(e){
          objThisRequest.blnAborting = false;
          return false;
        }
      }
      else
        return false;
    };

    
    //failHandler
    //Fired when there is an error with the request
    //----arguments----
    //intNumber:      integer -the error number
    //strDescription: string  -the error description
    this.failHandler = function(intNumber, strDescription){
      if(objThisRequest.progressInterval){
        window.clearInterval(objThisRequest.progressInterval); //clear it
        objThisRequest.progressInterval = null; //and set the reference to it to null
      }
      if(objThisRequest.fnFailure) //if there is a failure specified,
        return objThisRequest.fnFailure(intNumber, strDescription, strErrorURL);  //use it
      else if(!objThisRequest.blnSync) //if there is no handler specified then just throw the error
        throw new Error('ddp.a.HTTPRequestClass: ' + strDescription + ' (' + intNumber + ') "' + strErrorURL + '"');
      return false;//return false to a syncronous request to indicate that there was a problem
    }
    
    
    //execute
    //takes all the properties that have been setup and performs the request
  	this.execute = function(){
      var http = null;
      
      //create the request in (Firefox/Mozilla/Opera)
      if(typeof XMLHttpRequest == 'function'){
        http = new XMLHttpRequest();
        objThisRequest.objectVersion = 'XMLHttpRequest'; //save the object version
      }
      //create the request (IE)
    	else if(typeof ActiveXObject != 'undefined'){
        var XMLHTTP_IDS = [
          'Msxml2.XMLHTTP.6.0',   //installed with IE7. ships with vista out-of-the-box.
          'MSXML2.XMLHTTP.4.0',   //designed to support legacy applications.
          'MSXML2.XMLHTTP.3.0'    //installed on all Win2k (sp4) and up Microsoft OSs. Does not support "Xml Schema" (XSD 1.0)
        ];
        
        //'MSXML2.XMLHTTP.5.0', //installed with Office 2003 but is off by default in IE7 and causes a "gold bar" to pop up when instanciated.
        //'MSXML2.XMLHTTP' //too old to be usable (no support for abort() method)
        //'Microsoft.XMLHTTP'`//too old to be usable (no support for abort(), among other things)
        
        for(var i=0, l=XMLHTTP_IDS.length; i<l && !http; i++){
           try{
             http = new ActiveXObject(XMLHTTP_IDS[i]);
             objThisRequest.objectVersion = XMLHTTP_IDS[i]; //save the object version
           }
           catch(e){}
        }
    	}
      
      objThisRequest.http = http;
      
      if(!http) //if the object couldn't be created
        return objThisRequest.failHandler(1, 'XMLHTTPRequest object could not be created.');  //fire the failure handler and quit

      /*
      //decided that, to be consistent across browsers, the content type should be set on the server and not overridden on the client
      if(http.overrideMimeType) //if we can override the MIME type of the response (not able to in IE's implementation)
        http.overrideMimeType('text/xml; charset=utf-8;');  //use this content type and charset
      */
      
      //stateChangeHandler
      //hook the onreadystatechange event of the request object with our own function (stateChangeHandler)
      //wait for the readyState to change to 4 ("loaded") and make sure the http status is 200 ("OK")
  	  var stateChangeHandler = function(){
        if(http.readyState == 4){  //readyState will be 4 when the document is loaded.
          //if there is a progress interval set,
          if(objThisRequest.progressInterval){
            window.clearInterval(objThisRequest.progressInterval); //clear it
            objThisRequest.progressInterval = null; //and set the reference to it to null
          }
          if(objThisRequest.blnAborting)
            return false;
      		else if(http.status == 200){
            progressHandler(http); //fire the progress handler to make sure we show a progress of 100%
            //if the return type was left as 'default', try to determine the proper return type from the response 'content-type' header
            if(objThisRequest.strReturnFormat=='default'){
              var strResponseType = http.getResponseHeader('Content-Type'); //get the content-type string from the header
              strResponseType = strResponseType.toLowerCase();
              //if it's a json/javascript content type,
              if(strResponseType.indexOf('application/json') == 0 || strResponseType.indexOf('application/javascript') == 0 || strResponseType.indexOf('text/json') == 0 || strResponseType.indexOf('text/javascript') == 0)
                objThisRequest.strReturnFormat = 'json'; //set the return type to json
              //if it's an xml content type
              else if(strResponseType.indexOf('application/xml') == 0 || strResponseType.indexOf('text/xml') == 0 || strResponseType.indexOf('application/xhtml+xml') == 0)
                objThisRequest.strReturnFormat = 'xml'; //set the return type as xml
              else
                objThisRequest.strReturnFormat = 'text'; //otherwise return plain text
            }
            
      			var result = null; //return null if something goes wrong
      			if(objThisRequest.strReturnFormat == 'json' && http.responseText) //If the return is in JSON format, eval the result before returning it.
     					result = parseJSON(http.responseText);  //parse the string into a json object
      			else if(objThisRequest.strReturnFormat == 'xml') //If the return is in XML format,
     					result = (http.responseXML.documentElement) ? http.responseXML.documentElement : http.responseXML; //return the responseXML object.
            else if(objThisRequest.strReturnFormat == 'text' && http.responseText) //otherwise
     					result = http.responseText; //return the plain text string
      			
      			if(objThisRequest.fnSuccess)  //if a success function was specified
              objThisRequest.fnSuccess(result);//execute it, passing the data to it.
            objThisRequest.http = null;
            //http = null;
            return result;
      		}
      		else //if the http status wasn't 200, then there was a problem 
      			return objThisRequest.failHandler(http.status, 'HTTP Error'); //fire the failure handler 
      	}
    	};
      
      //progressHandler
      //this is our progress handler, which will be fired periodicaly by the XmlHttpRequest object.
      //we, in turn, will fire the user-defined progress handler and pass it three args: percent complete, bytes recieved and total bytes.
      //----arguments----
      //obj:  object  -an object that is passed from the XmlHttpRequest()
      var progressHandler = function(obj){
        var percentComplete = 0;
        var bytesTotal = 0;
        var bytesSoFar = 0;
        
        if(obj){
          if(typeof obj.totalSize != 'undefined'){ //older style object/properties (pre ff3)
            bytesTotal = obj.totalSize;
            bytesSoFar = obj.position;
          }
          else if(typeof obj.total != 'undefined'){ //using NN based browsers 
            bytesTotal = obj.total;
            bytesSoFar = obj.loaded;
          }
          else if(obj==http){
            try{
              bytesTotal = obj.getResponseHeader('Content-Length');
              //bytesSoFar = http.responseBody.length;
              bytesSoFar = obj.responseText.length;
            }
            catch(e){}
          }
        }
        
        //if we aren't going to end up dividing by zero...
        if(bytesTotal > 0)
          //round the percentage to two decimal places (eg. 25.66)
          percentComplete = roundToDecimalPlace(bytesSoFar / bytesTotal * 100, 2);
        
        if(typeof objThisRequest.fnProgress == 'function') //if the progress function has been defined
          objThisRequest.fnProgress(percentComplete, bytesSoFar, bytesTotal); //execute it with our progress info
      };
      
      function roundToDecimalPlace(intNumber, numberOfPlaces){
        return Math.round(intNumber * Math.pow(10,numberOfPlaces)) / Math.pow(10,numberOfPlaces);
      }
      
      //make sure a url was supplied 
  		if(!objThisRequest.strURL) return objThisRequest.failHandler(2, 'URL argument not supplied');
  		
      //avoid the cache problem in IE by creating a different URL each time
      var strUniqueId = new Date().getTime() + String(Math.random()).replace('.','');
 
      try{
        if(typeof http.onprogress != 'undefined')
          http.onprogress = progressHandler;
        else
          objThisRequest.progressInterval = window.setInterval(function(){progressHandler(http);}, 250);
        if(objThisRequest.strMethod=='post'){
          var strCompiledURL = objThisRequest.strURL;
          strErrorURL = strCompiledURL;
          strCompiledURL += (strCompiledURL.indexOf('?')+1) ? '&' : '?';
          strCompiledURL += strUniqueId;
          http.open('POST', strCompiledURL, !objThisRequest.blnSync);
          http.onreadystatechange = stateChangeHandler;
    			http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded;'); //Send the proper header information along with the request
    			http.setRequestHeader('Content-length', objThisRequest.strData.length);
    			http.setRequestHeader('Connection', 'close');
          http.send(objThisRequest.strData);  //send the post request
        }
        else if(objThisRequest.strMethod=='get'){
          var strCompiledURL = objThisRequest.strURL;
          if(objThisRequest.strData){    //if there's anything in strData,
            strCompiledURL += (strCompiledURL.indexOf('?')+1) ? '&' : '?'; //add a "?" if there isn't one, otherwise add a "&"
            strCompiledURL += objThisRequest.strData;  //add it to the url
          }
          strErrorURL = strCompiledURL;
          strCompiledURL += (strCompiledURL.indexOf('?')+1) ? '&' : '?';
          strCompiledURL += strUniqueId;
          http.open('GET', strCompiledURL, !objThisRequest.blnSync); //open the request
          http.onreadystatechange = stateChangeHandler;
          http.send(null);  //and send it
        }
        return (objThisRequest.blnSync) ? stateChangeHandler() : true;  //return true to indicate that the request was sent
      }
  		catch(e){ //if something goes wrong
  			return objThisRequest.failHandler(-1, e.fileName + ', line ' + e.lineNumber + ', ' + e.name + ': ' + e.message);//fire the failHandler
  		}
  	};
  }
  
 
  
  /***************************************************************/
  //accepts a form element and iterates through it's child elements looking for elements with a name and value property
  //returns a string of name value pairs eg. "varname=varvalue&vartwo=vartwovalue" 
	function parseForm(objForm){
		var strNameValuePairs = '';
		if(typeof objForm == 'object'){
			var elInputs = objForm.getElementsByTagName('*');
			for(var i=0, l=elInputs.length; i<l; i++){
				if(typeof elInputs[i].name != 'undefined' && elInputs[i].name != '' && typeof elInputs[i].value != 'undefined'){
					if(strNameValuePairs.length > 0)
						strNameValuePairs += '&';
          strNameValuePairs += encodeURIComponent(elInputs[i].name) + '=' + encodeURIComponent(elInputs[i].value);
				}
			}
			return strNameValuePairs;
		}
		return null;
	}
	
  
  /***************************************************************/
  // The parseJSON method takes a string and returns
  // a JavaScript value if the string is a valid JSON text.
  function parseJSON(text){
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        gap,
        indent,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        rep;
  
    cx.lastIndex = 0;
  	
    //convert special characters to unicode escaped equivalent
    if(cx.test(text))
    	text = text.replace(cx, function(a){ return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); });
  
  	if(/^[\],:{}\s]*$/.
  		test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
  		replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
  		replace(/(?:^|:|,)(?:\s*\[)+/g, ''))){
      
      try{
        //eval the string and return the results
        var objData = eval('(' + text + ')');
        
        //if the result is an object and it contains a property named "ddpSchema", then recursively
        //convert the data to date objects, decoded strings, boolean values etc.. following the schema.  
        return (objData && objData.ddpSchema) ? _convertData(objData, objData.ddpSchema) : objData;  
      }
      catch(objEvalError){
        var strErr = 'Error: ddp.a.parseJSON: Error evaling JSON data';
        try{ console.log(strErr); }
        catch(e){ alert(strErr); }
        throw(objEvalError);
      }
    }
  	
  	return false;
  };
  
// Return a boolean value telling whether // the first argument is a string. 

  function _convertData(objData, objDataTypes){
    //if the object passed is an array
    //if(typeof objData == 'object' && typeof objData.constructor == 'object' && objData.constructor == Array){
    if(ddp.f.isArray(objData)){
      //iterate through it 
      for(var i=0; i<objData.length; i++)
        //and convert each index (maintaining the same level of depth in objDataTypes
        objData[i] = _convertData(objData[i], objDataTypes)
      return objData;
    }
    //if the object passed is an object but not an array
    //else if(typeof objData == 'object'){
    else if(objData && typeof objData == 'object' && !ddp.f.isString(objData)){
      //go through the properties
      for(property in objData){
        //and if the property has a corresponding property in the ddp schema
        if(objDataTypes[property])
          //then convert the property
          objData[property] = _convertData(objData[property], objDataTypes[property]);
      }
      return objData;
    }
    //if the object passed is not an object, just a primitive data type
    else{
      switch(objDataTypes){
        case 'date': //for 'date' types
          if(ddp.f.isString(objData) && objData.indexOf('ddpDate') == 0){
            var arDateParts = objData.split(' ');
            arDateParts.splice(0, 1); //splice out the ddpDate marker
            for(var i=arDateParts.length; i<7; i++)
              arDateParts[i] = 0;
            return new Date(arDateParts[0], arDateParts[1], arDateParts[2], arDateParts[3], arDateParts[4], arDateParts[5], arDateParts[6])
          }
          else if(isFinite(objData)){  //if it's just a number
            var returnValue = new Date();//create a new date object
            //assume we were passed the number of milliseconds since
            //midnight january 1st 1970 and set the date using "setTime"
            returnValue.setTime(objData);
            return returnValue;
          }
          else{
            //try and return the value from the DDP date parsing method
            var d = ddp.f.parseDateString(objData);
            //return either the successfully parsed date or the string itself
            return d ? d : objData;
          } 
        case 'boolean':
          return (objData || (objData.toLowerCase && objData.toLowerCase() == 'true') ) ? true : false;
        case 'number':
          return (ddp.f.isString(objData)) ? objData * 1 : objData;
        case 'string':
          return (objData==null) ? '' : objData;
        default:
          return objData;
      }
    }
  }
  
  
  
  /**************************************************/
  //loadXmlDocument
  function loadXmlDocument(strURL, fnSuccess){
    var docXML = null;
    if(document.implementation && document.implementation.createDocument){
      try{
        docXML = document.implementation.createDocument('', '', null);
        ddp.f.addEvent(docXML, 'load', function(){ fnSuccess(docXML); });
        docXML.load(strURL);
        return true;
      }
      catch(e){}
    }
    else if(window.ActiveXObject){
      try{
        docXML = new ActiveXObject("Microsoft.XMLDOM");
        docXML.async = true;
    	  docXML.onreadystatechange = function(){ if(docXML.readyState == 4) fnSuccess(docXML);	};
        docXML.load(strURL);
        return true;
      }
      catch(e){}
    }
    return false;
  }
  
  
  /**************************************************/
  //submitToIframe
  //
  //
  function submitToIframe(elForm, fnResponse, strReturnType){
    var strUniqueId = 'ddpSubmitToIframe' + String(Math.random()).replace('.','');
    //var strIframeSrc = 'about:blank'; //gets reported in IE6 as an unencrypted item under https protocol
    var strIframeSrc = 'javascript: false;';
    var elIFrame = document.createElement('iframe');
    
    strReturnType = (typeof strReturnType == 'string') ? strReturnType.toLowerCase() : 'text';
    
    elIFrame.setAttribute('src', strIframeSrc);
    elIFrame.setAttribute('id', strUniqueId);
    elIFrame.setAttribute('NAME', strUniqueId);
    elIFrame.style.display = 'none';
    document.getElementsByTagName('body')[0].appendChild(elIFrame);
    //bug fix for IE (if left out IE opens a new window instead of using the new iframe)
    try{ window.frames[strUniqueId].name = strUniqueId; }catch(e){ }
    
    //add a handler to the iframe's load event
    ddp.f.addEvent(elIFrame, 'load', function(){
      //get the iframe's document (cross-browser wise)
      var elDocument = (elIFrame.contentDocument)?(elIFrame.contentDocument):((elIFrame.contentWindow)?(elIFrame.contentWindow.document):(self.frames[strUniqueId].document));
      
      if(elDocument.location.href != strIframeSrc){ //if the iframe's url is not the one we just gave it
        if(typeof fnResponse == 'function'){
          var returnValue;
          if(strReturnType == 'json')
            returnValue = parseJSON(elDocument.body.innerHTML);
          else if(strReturnType == 'xml')
            returnValue = elDocument;
          else
            returnValue = elDocument.body.innerHTML;
          fnResponse(returnValue); //fire the response handler
        }
        ddp.f.removeEvent(elIFrame, 'load', arguments.callee); //remove this handler
        //remove the iframe since we don't need it anymore
        //but wait 1 second so firefox will stop showing activity
        setTimeout(function(){ elIFrame.parentNode.removeChild(elIFrame); }, 1000); 
      }
    });
    
    elForm.setAttribute('target', strUniqueId);
    elForm.submit();
  }
  
  
  
	
  /**************************************************/
  //createAjaxIframe
  //Creates an IFRAME element for transfering data to the server and 
  //sets a timeout to remove it a specified number of seconds after
  //it is created.
  function createAjaxIframe(secondsBeforeRemoval, url){
  	var body = document.getElementsByTagName('BODY')[0];
  	var f = document.createElement('IFRAME');
  	f.src = url;
  	f.style.display='none';
  	var timeNow = new Date().getTime();
  	f.id = 'frame' + timeNow;
  	var x = setTimeout('document.getElementById(\'' + f.id + '\').parentNode.removeChild(document.getElementById(\'' + f.id + '\'));', secondsBeforeRemoval * 1000);
  	body.appendChild(f);
  }

/**************************************************/
//Export the public functions to a public namespace
/**************************************************/

//Exports go here
var ddpns = ddp.a;
ddpns.loadJSON = loadJSON;
ddpns.addHeaderScript = addHeaderScript;
ddpns.request = request;
ddpns.requestPost = requestPost;
ddpns.HTTPRequest = HTTPRequest;
ddpns.httpRequest = HTTPRequest; //easier to type it
ddpns.httpRequestClass = httpRequestClass;
ddpns.parseForm = parseForm;
ddpns.parseJSON = parseJSON;
ddpns.loadXmlDocument = loadXmlDocument;
ddpns.submitToIframe = submitToIframe;
ddpns.createAjaxIframe = createAjaxIframe;
})();