/**
 * A bare-bones JavaScript library that covers basic Ajax functionality. 
 *
 * Author:  Derrick Bowen <derrickbowen at gmail dot com>
 * Project Site: http://sourceforge.net/projects/dynamicajax/
 * License: Apache v2.0  http://www.apache.org/licenses/LICENSE-2.0
 * meant for open use by anyone.
 * inspired by tutorials at www.quirksmode.org
 * 
 * To Use, put
 *   <script src="javascript/dajax.js" type="text/javascript"></script>
 * in the header section, 
 * and in button or link or anything else:
 * 		onclick="zapDiv('div-ID', 'url.html'); return false;"
 * OR if you want to specifically submit a form in a form tag:
 *    onsubmit="zapSubmit('div-ID', 'form-Name');"
 *   
 * It will replace the content of the selected div with the html from the url.
 *
 * You can also automatically add the contents of a Form to the first one:
 * 		onsubmit="zapDiv('div-ID', 'url.html?'+getFormAsString('formName')); return false;"
 * 
 * 
 */

/**
 * The main function to call. Without request parameters
 * div = id of the div (or any other DOM object) that you want to
 *  clear its contents and replace with something else.
 * url = the relative url of the behind the scenes request.
 */
function zapDiv(div, url) {
if (document.getElementById && document.createElement)
  {
    var main = document.getElementById(div);
    removeChildren(main);
    sendRequest(''+url, handleRequest, main);
  }
    else alert('Your browser doesn\'t support the Level 1 DOM');

}

/**
 * Conveniently grabs the url and get parameters from the desired form.
  * div = id of the div (or any other DOM object) that you want to
 *  clear its contents and replace with something else.
 * formName= the form to get the action and request parameters from.
 */
function zapSubmit(div, formName) {
if (document.getElementById && document.createElement)
  {
      //Get the form
    var form=document.forms[formName];
    var url=form.action;
    var main = document.getElementById(div);
    removeChildren(main);
    sendRequest(''+url+'?'+getFormAsString(formName), handleRequest, main);
  }
    else alert('Your browser doesn\'t support the Level 1 DOM');

}

/**
 * Decprecated.  it really does get data by the way.
 * The other main function to call. 
 * div = id of the div (or any other DOM object) that you want to
 *  clear its contents and replace with something else.
 * postData = a String to append to the URL so that you can make
 *  requests behind the scene. Put it in an array, like so:
 *  ['val1=value','val2='+input.value] the second example being how to
 *  get it from an input that already exists in a form.
 * url = the relative url of the behind the scenes request.
 */
function zapDiv2(div, postData, url) {
if (document.getElementById && document.createElement)
  {
		var main = document.getElementById(div);
		removeChildren(main);
		var getIt = arrangePostData(postData);
		sendRequest(''+url+'?'+getIt, handleRequest, main);
	}
		else alert('Your browser doesn\'t support the Level 1 DOM');

}

/**
 * Same as the first zap, but it displays a message that things are happening
 * in case the request takes a long time to complete.
 */
function zapDivLong(div, url) {
if (document.getElementById && document.createElement)
  {
    var main = document.getElementById(div);
    removeChildren(main);
		main.innerHTML = '<br />Please wait while the data loads.<br />';
    sendRequest(''+url, handleRequest, main);
  }
    else alert('Your browser doesn\'t support the Level 1 DOM');

}

/**
 * For debugging weirdness.
 */
function zapDivDebug(div, url) {
if (document.getElementById && document.createElement)
  {
  	alert('div: '+div);
    var main = document.getElementById(div);
  	alert('div: '+div+'retreived successfully');
    removeChildren(main);
  	alert('children removed successfully');
    sendRequest(''+url, handleRequest, main);
  }
    else alert('Your browser doesn\'t support the Level 1 DOM');

}

/**
 * Takes the post data array and puts them in one big string with
 * "&"s in between each one.
 */
function arrangePostData(postData) {
    var getIt = '';
        for(var j=0;j<postData.length;j++){
            getIt +=postData[j];
            if (j!=postData.length-1){
                getIt +='&';
            }
        }
    return getIt;
}

/**
 * Removes all the children from a node.  I've tried a few different ways,
 *  and this one is supposed to use the least processing power.
 * (it removes the need to evaluate hasChild nodes every time,
 *   and you don't keep referencing a live collection,
 *   which takes resources).
 *
 *  I've left the old ways of doing it in as comments for reference.
 */
function removeChildren(node) {
    if (!node) return;
    while(node.firstChild) {
    	node.removeChild(node.firstChild);
    }
   
//    while (node.hasChildNodes()) {
//        removeChildrenRecursively(node.firstChild);
//        node.removeChild(node.firstChild);
//    }
   
//    for(var i = 0; node.childNodes[i]; i++ ){
//        node.removeChild(node.childNodes[i]);
//    }

//    if ( node.hasChildNodes() )
//    {
//        while ( node.childNodes.length >= 1 )
//        {
//            node.removeChild( node.firstChild );      
//        }
//    }
}

/**
 * picks an html form out of the page and returns its values in one big string.
 */
function getFormAsString(formName){
        
  //Setup the return String
  returnString ="";
        
  //Get the form values
  formElements=document.forms[formName].elements;
        
  //loop through the array, building up the url
  //in the format '/strutsaction.do&name=value'
  
  for(var i=formElements.length-1;i>=0; --i ){
	  var type = formElements[i].type;
  			switch(type)
				{
				case "radio":
				case "checkbox": //checkbox and radio button values should only be added if they are checked.
				  //we escape (encode) each value
					if (formElements[i].checked){
						returnString+="&" 
						+escape(formElements[i].name)+"=" 
						+escape(formElements[i].value);
					}
				  break;
			  case "select-multiple": //select that can have multiple are also handled differently.
			  	 for (var n=0; n < formElements[i].options.length; n++) {
				  	 if (formElements[i].options[n].selected) {
					  	 returnString+="&" 
						 +escape(formElements[i].name)+"=" 
						 +escape(formElements[i].options[n].value);
				  	 } 
			  	 } 
				 break;
				default:
				  //we escape (encode) each value
	        returnString+="&" 
	        +escape(formElements[i].name)+"=" 
	        +escape(formElements[i].value);
				}
 }
 
 //return the values
 return returnString; 
}

/**
 * picks an html form out of the page and returns its values in one big string.
 * same as the above, but it also clears the form.
 */
function getFormAsStringAndClear(formName){
        
  //Setup the return String
  returnString ="";
        
  //Get the form values
  formElements=document.forms[formName].elements;
        
  //loop through the array, building up the url
  //in the format '/strutsaction.do&name=value'
  
  for(var i=formElements.length-1;i>=0; --i ){
	  var type = formElements[i].type;
  			switch(type)
				{
				case "radio":
				case "checkbox": //checkbox and radio button values should only be added if they are checked.
				  //we escape (encode) each value
					if (formElements[i].checked){
						returnString+="&" 
						+escape(formElements[i].name)+"=" 
						+escape(formElements[i].value);
						formElements[i].value="";
					}
				  break;
			  case "select-multiple": //select that can have multiple are also handled differently.
			  	 for (var n=0; n < formElements[i].options.length; n++) {
				  	 if (formElements[i].options[n].selected) {
					  	 returnString+="&" 
						 +escape(formElements[i].name)+"=" 
						 +escape(formElements[i].options[n].value);
						 formElements[i].options[n].value="";
				  	 } 
			  	 } 
				 break;
				default:
				  //we escape (encode) each value
	        returnString+="&" 
	        +escape(formElements[i].name)+"=" 
	        +escape(formElements[i].value);
				if(type != "hidden") formElements[i].value="";
				}
 }
 
 //return the values
 return returnString; 
}

/**
 * to get the value of a drop down list or other form element.
 */
function getElementValue(nodeID) {
	var node = document.getElementById(nodeID);
	return node.value;
}


/**
 * Calls the url through an XMLHTTP object, then hands the call to the
 * specified callback function (in our case handleRequest)
 *
 * The method leaves it open to be able to put in the data as a GET instead
 * of as a POST, but I'm not sure what form the data is supposed to be in,
 * (that was how quirks mode did it)  so that's why I created the method
 * to add the values in the URL.
 */
function sendRequest(url,callback,node,postData) {
    //fix to the IE GET cache issue (they cache GET requests as the RFC says you can)
    var mytime= '';
    if (url.indexOf('?')>-1) {
        mytime= '&msajaxfix='+new Date().getTime();
    } else {
        mytime= '?msajaxfix='+new Date().getTime();
    }
    url=url+mytime;
		var req = createXMLHTTPObject();
    if (!req) return;
    var method = (postData) ? "POST" : "GET";
    req.open(method,url,true);
    req.setRequestHeader('User-Agent','XMLHTTP/1.0');
    if (postData)
        req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
    req.onreadystatechange = function () {
        if (req.readyState != 4) return;
        if (req.status != 200 && req.status != 304) {
            return;
        }
        callback(req,node);
    }
    if (req.readyState == 4) return;
    req.send(postData);
}

/**
 * gets the text from the given request and writes it
 * inside of the given node.
 */
function handleRequest(req, node) {
    removeChildren(node);
    node.innerHTML = req.responseText;
}

/**
 * Tries a couple of different ways to create an Http object.
 */
function createXMLHTTPObject() {
    var xmlhttp = false;
    for (var i=0;i<XMLHttpFactories.length;i++) {
        try {
            xmlhttp = XMLHttpFactories[i]();
        }
        catch (e) {
            continue;
        }
        break;
    }
    return xmlhttp;
}

/**
 * Factory of different ways to create an Http object.
 */
var XMLHttpFactories = [
    function () {return new XMLHttpRequest()},
    function () {return new ActiveXObject("Msxml2.XMLHTTP")},
    function () {return new ActiveXObject("Msxml3.XMLHTTP")},
    function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];



