//*****************************************************************************************************************
//*****		AJAX FUNCTIONS FOR LIVE SEARCH + DYNAMIC DROPDOWNS
//*****		Beginnings of an Ajax library, feel free to add to this/extend/fix. 
//*****		These should be cross server and cross browser
//*****		* Text field observer implemented.
//*****		* Remote link implemented.
//*****		* Remote forms implemented.
//*****		* show progress functions implemented for remote forms.
//*****		* remote link with progress implemented
//*****		Developer: James Burrows
//*****************************************************************************************************************
//***** API																NOTES
//***** decodeToVars(stringToDecode)					 			 -  Decodes a query string into a collection of keys and values.
//***** observe(fieldname, rate, scrtarget, replacediv)	 			 -  observes a form field, usually a text input or dropdown, scrtarget = remote method to call, replacediv is the part of the current page which will be updated.
//***** remoteLink(scrtarget, replacediv)				 			 -  goes in an anchor href, scrtarget is the remote script, replacediv is the portion of the page to be replaced.
//***** remoteLinkWithProgress(scrtarget, replacediv, progressdiv) 	 -  as above but progressdiv is the div to show whilst waiting on remote process to complete
//***** remoteForm(scrtarget, formname, replacediv, progressdiv) 	 -  goes in the form onSubmit action, does not work with multipart forms, formname is the name of the form to be collected and sent for processing
//***** showProgress(divName) 										 -  usually internal only but is used to show a specified progress div
//***** hideProgress() 												 -  usually internal but is used to hide the last shown progress div
//***** initialise(intSetdebug, strSeterrormode)					 -  sets debug level and where debug messages are sent. strSeterrormode can be "alert" for pop up messages or the name of a div for more controlled output
//********************************************** Global vars/Initialisations ****************************************************

var debug = 1; 					// 1 debugs XMLHttpRequest(), 2 debugs return methods, 0 is off.
var errorMode = "alert"; 		// can be 'alert' or the name of a div where you want errors output to.
var obTimeout = new Array(); 	// array of timeout references for observers
var obData = new Array(); 		// form field data held on last pass (so we can work out if there is any change on the next pass) 
var postbody; 					// the post variables we are sending to the remote process
var currentProgress; 			// the name of the currently active progress div
var currentProgressTop; 			// the name of the currently active progress div
postbody = "";					// init this var to avoid 411 errors from the server (when the server thinks we haven't sent anything!)

//********************************************** Support functions ****************************************************

function ajaxIsPresent() {
	return true;
}

function newXMLHttpRequest() {
  var xmlreq = false;
  if (window.XMLHttpRequest) {
    // Create XMLHttpRequest object in non-Microsoft browsers
    xmlreq = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    // Create XMLHttpRequest via MS ActiveX
    try {
      // Try to create XMLHttpRequest in later versions
      // of Internet Explorer
      xmlreq = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e1) {
      // Failed to create required ActiveXObject
      try {
        // Try version supported by older versions
        // of Internet Explorer
        xmlreq = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e2) {
        // Unable to create an XMLHttpRequest with ActiveX
      }
    }
  }

  return xmlreq;
}

function getReadyStateHandler(req, responseXmlHandler, type, replacediv)
{
  // Return an anonymous function that listens to the
  // XMLHttpRequest instance
  return function () {
    // If the request's status is "complete"
    if (req.readyState == 4) {
      // Check that a successful server response was received
      if (req.status == 200) {
        // Pass the XML payload of the response to the
        // handler function
        if (type == "XML") {
            responseXmlHandler(req.responseXML, replacediv);
        } else {
            responseXmlHandler(req.responseText, replacediv);
        }
      } else {
        // An HTTP problem has occurred
        if (debug == 1) {
			logError("HTTP error: "+req.status+req.responseText);
		}
      }
    }
  }
}

function decodeToVars(stringToDecode)
{
	var elements = stringToDecode.split("&");
    var associative = new Array();

    for (i = 0; i < elements.length; i++) {
        var pair = elements[i];
        var components = pair.split("=");
        var key = components[0];
        var value = components[1];
        key = unescape(key);
        value = unescape(value);
        key = key.replace(/\+/g, " ");
        value = value.replace(/\+/g, " ");
        associative[key] = value;
    }

    return associative;
}

function getData(url, processfunc, replacediv) {
	if (debug == 2) {
		logError("sending request for processing at: "+url)
	}
    var req = newXMLHttpRequest();
	
    var handlerFunction = getReadyStateHandler(req, eval(processfunc), "plaintext", replacediv);
    req.onreadystatechange = handlerFunction;

    req.open("POST", url, true);

    req.setRequestHeader("Content-Type",
                       "application/x-www-form-urlencoded");
	req.send(postbody);
	postbody = ""
}

//********************************************** Business End (end user stuff) ****************************************************

function initialise(intSetdebug, strSeterrormode) {
	var debug = intSetdebug
	var errorMode = strSeterrormode
}

function observe(fieldname, rate, scrtarget, replacediv) {
	if (obTimeout[fieldname] == null) {
		// set up a new observer
		newtimeout = setTimeout("observe('"+fieldname+"', "+rate+", '"+scrtarget+"', '"+replacediv+"')", rate);
		obData[fieldname] = document.getElementById(fieldname).value
		obTimeout[fieldname] = newtimeout;
	} else {
		// do something with an existing observer
		clearTimeout(obTimeout[fieldname]);
		fdata = document.getElementById(fieldname).value;
		if (obData[fieldname] != fdata) {
			getData(scrtarget+"&"+fieldname+"="+fdata, "testProcess", replacediv);
		}
		obData[fieldname] = fdata;
		obTimeout[fieldname] = setTimeout("observe('"+fieldname+"', "+rate+", '"+scrtarget+"', '"+replacediv+"')", rate);
	}
}

function observeWithProgress(fieldname, rate, scrtarget, replacediv, progressdiv) {
	if (obTimeout[fieldname] == null) {
		// set up a new observer
		newtimeout = setTimeout("observeWithProgress('"+fieldname+"', "+rate+", '"+scrtarget+"', '"+replacediv+"', '"+progressdiv+"')", rate);
		obData[fieldname] = document.getElementById(fieldname).value
		obTimeout[fieldname] = newtimeout;
	} else {
		// do something with an existing observer
		clearTimeout(obTimeout[fieldname]);
		fdata = document.getElementById(fieldname).value;
		if (obData[fieldname] != fdata) {
			showProgress(progressdiv); //show the progress div only if we're punching out to the remote process
			getData(scrtarget+"&"+fieldname+"="+fdata, "testProcess", replacediv);
		}
		obData[fieldname] = fdata;
		obTimeout[fieldname] = setTimeout("observeWithProgress('"+fieldname+"', "+rate+", '"+scrtarget+"', '"+replacediv+"', '"+progressdiv+"')", rate);
	}
}

function remoteLink(scrtarget, replacediv) {
	getData(scrtarget, "testProcess", replacediv);
}

function remoteValue(scrtarget, setVar) {
	getData(scrtarget, "getValue", setVar);
}

function remoteLinkWithProgress(scrtarget, replacediv, progressdiv) {
	showProgress(progressdiv);
	getData(scrtarget, "testProcess", replacediv);
}

function remoteForm(scrtarget, formname, replacediv, progressdiv) {
	//scan through form elements and get a postbody together!
	targetform = document.getElementById(formname);
	//targetform = eval("document."+formname);
	t = 0
	for(i=0; i<targetform.elements.length; i++){
	//for (x in targetform.elements) {
		if (targetform.elements[t] != null) {
			//alert(targetform.elements[t].type);
			if (targetform.elements[t].type == 'checkbox') {
				if (targetform.elements[t].checked == true) {
					fieldElement = targetform.elements[t];
					postbody += escape(fieldElement.name)+"="+encodeURIComponent(fieldElement.value)+"&";
				}
			} else if (targetform.elements[t].type == 'select-multiple') {
				//DOES NOT WORK IN SAFARI 3 (1 AND 2 NOT TESTED)
				values = ""
				fieldElement = targetform.elements[t];
				for (var i=targetform.elements[t].options.length-1; i >= 0;i--) {
					if (targetform.elements[t].options[i].selected) {
						postbody += escape(fieldElement.name)+"="
						postbody += encodeURIComponent(targetform.elements[t].options[i].value)+"&";
					}
				}
			} else {
				fieldElement = targetform.elements[t];
				postbody += escape(fieldElement.name)+"="+encodeURIComponent(fieldElement.value)+"&";
			}
		}
		t += 1
	}
	
	if (debug == 2) {
		logError("form data sent: "+postbody);
	}
	
	//show progress indicator and send data to server
	showProgress(progressdiv);
	getData(scrtarget, "testProcess", replacediv);
	
	//should probably clear form fields here
	t = 0
	for (x in targetform.elements) {
		if (targetform.elements[t] != null) {
			fieldElement = targetform.elements[t];
			// make sure we dont kill any button text or hidden field values!
			if (fieldElement.type != "button" && fieldElement.type != "submit" && fieldElement.type != "hidden" && fieldElement.type != "select-one" && fieldElement.type != "select-multiple") {
				fieldElement.value = "";
			}
		}
		t += 1
	}
	
	//return false as we dont actually want the form to be submitted normally
	return false;
}

/*function remoteFormWithOutClear(scrtarget, formname, replacediv, progressdiv) {
	targetform = document.getElementById(formname);
	t = 0
	for (x in targetform.elements) {
		if (targetform.elements[t] != null) {
			if (targetform.elements[t].type == 'checkbox') {
				if (targetform.elements[t].checked == true) {
					fieldElement = targetform.elements[t];
					postbody += escape(fieldElement.name)+"="+encodeURIComponent(fieldElement.value)+"&";
				}
			} else if (targetform.elements[t].type == 'select-multiple') {
				//DOES NOT WORK IN SAFARI 3 (1 AND 2 NOT TESTED)
				values = ""
				fieldElement = targetform.elements[t];
				for (var i=targetform.elements[t].options.length-1; i >= 0;i--) {
					if (targetform.elements[t].options[i].selected) {
						postbody += escape(fieldElement.name)+"="
						postbody += encodeURIComponent(targetform.elements[t].options[i].value)+"&";
					}
				}
			} else {
				fieldElement = targetform.elements[t];
				postbody += escape(fieldElement.name)+"="+encodeURIComponent(fieldElement.value)+"&";
			}
		}
		t += 1
	}
	
	if (debug == 2) {
		logError("form data sent: "+postbody);
	}
	
	//show progress indicator and send data to server
	showProgress(progressdiv);
	getData(scrtarget, "testProcess", replacediv);
	
	//return false as we dont actually want the form to be submitted normally
	return false;
}*/

function remoteFormWithOutClear(scrtarget, formname, replacediv, progressdiv) {
	targetform = document.getElementById(formname);
	//targetform = eval("document."+formname);
	t = 0
	for(t=0; t<targetform.elements.length; t++) {
		if (targetform.elements[t] != null) {
			if (targetform.elements[t].type == 'checkbox') {
				if (targetform.elements[t].checked == true) {
					fieldElement = targetform.elements[t];
					postbody += escape(fieldElement.name)+"="+encodeURIComponent(fieldElement.value)+"&";
				}
			} else if (targetform.elements[t].type == 'select-multiple') {
				//DOES NOT WORK IN SAFARI 3 (1 AND 2 NOT TESTED)
				values = ""
				fieldElement = targetform.elements[t];
				for (var i=targetform.elements[t].options.length-1; i >= 0;i--) {
					if (targetform.elements[t].options[i].selected) {
						postbody += escape(fieldElement.name)+"="
						postbody += encodeURIComponent(targetform.elements[t].options[i].value)+"&";
					}
				}
			} else {
				fieldElement = targetform.elements[t];
				postbody += escape(fieldElement.name)+"="+encodeURIComponent(fieldElement.value)+"&";
			}
		}
		//t += 1
	}
	
	if (debug == 2) {
		logError("form data sent: "+postbody);
	}
	
	//show progress indicator and send data to server
	showProgress(progressdiv);
	getData(scrtarget, "testProcess", replacediv);
	
	//return false as we dont actually want the form to be submitted normally
	return false;
}

function testProcess(data, replacediv) {
	if (debug == 2) {
		logError("processing returned data: "+data);
	}
	document.getElementById(replacediv).innerHTML = data;
	if (data.indexOf("<script>") != -1) {
		if (debug == 2) {
			logError("processing returned javascript: "+data);
		}
		// process any script sent by the browser
		scripttagstart = data.indexOf("<script>")+8
		scripttagend = data.indexOf("</script>")
		eval(data.slice(scripttagstart,scripttagend))
	}
	hideProgress();
}

function getValue(data, setVar) {
	if (debug == 2) {
		logError("processing returned data: "+data);
	}
	eval(setVar+" = \""+data+"\"");
	hideProgress();
}

function showProgress(divName) {
	// show div
	if (debug == 2) {
		logError("showing progress div")
	}
	currentProgress = divName;
	document.getElementById(currentProgress).style.display = "block";
	document.getElementById(currentProgress).style.visibility = "visible";
	document.getElementById(currentProgress).className = "CMSShown";
}

function hideProgress() {
	// just toggle hidden last shown div.
	if (debug == 2) {
		logError("hiding progress div")
	}
	//alert(currentProgress);
	if ((currentProgress != "") && (currentProgress != null)) {
		document.getElementById(currentProgress).style.visibility = "hidden";
		//document.getElementById(currentProgress).style.display = "none";
		
		document.getElementById(currentProgress).className = "CMSHidden";
		//alert(document.getElementById(currentProgress).style.display);
		currentProgress = "";
	}
}

function logError(strMessage) {
	if (errorMode != "alert") {
		olderrors = document.getElementById(errorMode).innerHTML;
		olderrors += "<p>"+strMessage+"</p>";
		document.getElementById(errorMode).innerHTML = olderrors;
	} else {
		alert(strMessage)
	}
}

//********************************************************* IFRAME RELATED FUNCTIONS ********************************************
//*** Much of this is borrowed from iframeRequest by Nikola Derezic. ***//

var iFrameAppendBit = 0;		// do we append or replace, 1 = append, 0 = replace 
var multipartHandle;			// retained reference when working with multipart stuff
var iFrameReplaceDiv;			// multipart div to update

function remoteFormMultipart(replacediv, progressdiv, appendBit) {
	//alert("got this far!");
	showProgress(progressdiv);
	iFrameReplaceDiv = replacediv;
	iFrameAppendBit = appendBit;
	return true;
}

function processMultipartResponse(iFrameID) {
	//alert("got this far!")
	hideProgress();
	if ((iFrameReplaceDiv != "") && (iFrameReplaceDiv != null)) {
		data = getContentDocument(document.getElementById(iFrameID)).body.innerHTML;
		if (data.indexOf("<script>") != -1) {
			if (debug == 2) {
				logError("processing returned javascript: "+data);
			}
			// process any script sent by the browser
			scripttagstart = data.indexOf("<script>")+8
			scripttagend = data.indexOf("</script>")
			eval(data.slice(scripttagstart,scripttagend))
		}
		if (iFrameAppendBit == 0) {
			//document.getElementById(iFrameReplaceDiv).innerHTML = getContentDocument(document.getElementById(iFrameID)).body.innerHTML;
			//alert(data);
		} else {
			//document.getElementById(iFrameReplaceDiv).innerHTML += getContentDocument(document.getElementById(iFrameID)).body.innerHTML;
		}
		
		multipartCleanup(multipartHandle);
	}
}

function multipartCleanup(iframeobject) {
	// reset all variables for next use
	multipartHandle = "";
	iFrameReplaceDiv = "";
	iFrameAppendBit = 0;
}

function createIframe(inIFrameID)
{
	var iframeObj = null;
    var iFrameID = inIFrameID;
    var divID = inIFrameID+'_div';
    var iframeStyle = 'width:0px; height:0px; border: 0px; display:none;';
//    var divStyle = 'display:none;position:absolute;top:0;left:0;'; --> doesn't work in Opera
    var divStyle = 'position:absolute;top:0;left:0;width:0;height:0;overflow:hidden;';

    // ako objekat veæ postoji ... vrati referencu na njega
    if(document.getElementById(iFrameID))
      return(document.getElementById(iFrameID));
	
	var iframeHTML = '<iframe id="'+iFrameID+'" name="'+iFrameID+'" style="'+iframeStyle+'" onLoad="processMultipartResponse("'+inIFrameID+'");"><\/iframe>';

    //Put iframe in container and append to any div in page
    if (!document.getElementById(divID))
    {
        tmpDiv = document.createElement("div");
        tmpDiv.setAttribute('id', divID);
        tmpDiv.setAttribute('style', divStyle);
        tmpDiv.innerHTML = iframeHTML;
        document.getElementsByTagName('DIV')[0].appendChild(tmpDiv);
    }
    else
    {
       document.getElementById(divID).innerHTML = iframeHTML;
    }

    iframeObj = document.getElementById(iFrameID);
}

function createIframeOLD(inIFrameID)
{
    /* Routine to create hidden iframe */
    var iframeObj = null;
    var iFrameID = inIFrameID;
    var divID = inIFrameID+'_div';
    var iframeStyle = 'width:0px; height:0px; border: 0px; display:none;';
//    var divStyle = 'display:none;position:absolute;top:0;left:0;'; --> doesn't work in Opera
    var divStyle = 'position:absolute;top:0;left:0;width:0;height:0;overflow:hidden;';

    // ako objekat veæ postoji ... vrati referencu na njega
    if(document.getElementById(iFrameID))
      return(document.getElementById(iFrameID));

    try
    {
        //Create Iframe and put it at bottom of page
        var tmpFrame = document.createElement("iframe");
        tmpFrame.setAttribute("id", iFrameID);
        tmpFrame.setAttribute("name", iFrameID);
        tmpFrame.setAttribute("style", iframeStyle);
		tmpFrame.setAttribute("onLoad", "processMultipartResponse('"+inIFrameID+"');");

        //IE 6.0 fix using wrapper div with display none
        var tmpDiv = document.createElement("div");
        tmpDiv.setAttribute("id", divID);
        tmpDiv.setAttribute("style", divStyle);
        tmpDiv.appendChild(tmpFrame);
        document.body.appendChild(tmpDiv);

        if (typeof document.frames != "undefined")
        {
            /* Required for IE 5 on Mac and throws error on IE 5.0 PC
             * which we need to branch to a different process.
             */
            iframeObj = document.frames[iFrameID];
        }
        if (!iframeObj || typeof iframeObj.nodeType == "undefined")
        {
           /* Most browsers yield null or good iframe reference above,
            * but some return an object with no properties so nodeType test.
            */
            iframeObj = document.getElementById(iFrameID);
        }
    }
    catch (e)
    {
       /* Hack to handle IE 5.0 on PC, which doesn't want to 'automate'
        * adding an iframe.
        *
        * CSS:
        * iframe-div {position: absolute;} gets it out of document flow
        * rs-frame {border-style: none; height: 0; widht: 0; visibility: hidden;}
        *
        * Reguired:
        * 1. HTML string for iframe and NOT an element object.
        * 2. use iframe src attribute to load first RPC; otherwise only subsequent calls work
        * 3. Block container for iframe
        * 4. Attach container and iframe to any block inside body but NOT the body.
        */

        //String HTML describing iframe and first URL called   ... src="'+url+'"  <-- ovo sam izbacio
        var iframeHTML = '<iframe id="'+iFrameID+'" name="'+iFrameID+'" style="'+iframeStyle+'" onLoad="processMultipartResponse("'+inIFrameID+'");"><\/iframe>';

        //Put iframe in container and append to any div in page
        if (!document.getElementById(divID))
        {
            tmpDiv = document.createElement("div");
            tmpDiv.setAttribute('id', divID);
            tmpDiv.setAttribute('style', divStyle);
            tmpDiv.innerHTML = iframeHTML;
            document.getElementsByTagName('DIV')[0].appendChild(tmpDiv);
        }
        else
        {
           document.getElementById(divID).innerHTML = iframeHTML;
        }

        iframeObj = document.getElementById(iFrameID);
    }

    //return iframeObj;

} //eof createIframe

function getContentDocument(inIFrameObj)
{
  if (inIFrameObj.contentDocument) // For NS6
  {
    // debug('<b>getContentDocument</b>:contentDocument');
    return(inIFrameObj.contentDocument);
  }
  else if (inIFrameObj.contentWindow) // For IE5.5 and IE6
  {
    // debug('<b>getContentDocument</b>:contentWindow');
    return(inIFrameObj.contentWindow.document);
  }
  else if (inIFrameObj.document) // For IE5
  {
    // debug('<b>getContentDocument</b>:document');
    return(inIFrameObj.document);
  }
 else
  {
    // debug('<b>getContentDocument</b>:undefined');
    return(undefined);
  }
}
