/* Simple AJAX Code-Kit (SACK) v1.6.1 */
/* ©2005 Gregory Wild-Smith */
/* www.twilightuniverse.com */
/* Software licenced under a modified X11 licence,
   see documentation or authors website for more details 
   COPYRIGHT AND PERMISSION NOTICE for Simple AJAX Code Kit (SACK).

Copyright © 2005 Gregory Wild-Smith
Authors Website: http://www.twilightuniverse.com/

All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s), authors website url, and this permission notice appear in all copies of the Software and that the above copyright notice(s), authors url, and this permission notice appear in supporting documentation.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.
   */

function sack(file) {
	this.xmlhttp = null;

	this.resetData = function() {
		this.method = "POST";
  		this.queryStringSeparator = "?";
		this.argumentSeparator = "&";
		this.URLString = "";
		this.encodeURIString = true;
  		this.execute = false;
  		this.element = null;
		this.elementObj = null;
		this.requestFile = file;
		this.vars = new Object();
		this.responseStatus = new Array(2);
  	};

	this.resetFunctions = function() {
  		this.onLoading = function() { };
  		this.onLoaded = function() { };
  		this.onInteractive = function() { };
  		this.onCompletion = function() { };
  		this.onError = function() { };
		this.onFail = function() { };
	};

	this.reset = function() {
		this.resetFunctions();
		this.resetData();
	};

	this.createAJAX = function() {
		try {
			this.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e1) {
			try {
				this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e2) {
				this.xmlhttp = null;
			}
		}

		if (! this.xmlhttp) {
			if (typeof XMLHttpRequest != "undefined") {
				this.xmlhttp = new XMLHttpRequest();
			} else {
				//IFrame fallback for IE
				this.xmlhttp = new XMLHttpRequestI();
				signalUseFallBack()
				//alert("used fallback")
				//this.failed = true;
			}
		}
	};

	this.setVar = function(name, value){
		this.vars[name] = Array(value, false);
	};

	this.encVar = function(name, value, returnvars) {
		if (true == returnvars) {
			return Array(encodeURIComponent(name), encodeURIComponent(value));
		} else {
			this.vars[encodeURIComponent(name)] = Array(encodeURIComponent(value), true);
		}
	}

	this.processURLString = function(string, encode) {
		encoded = encodeURIComponent(this.argumentSeparator);
		regexp = new RegExp(this.argumentSeparator + "|" + encoded);
		varArray = string.split(regexp);
		for (i = 0; i < varArray.length; i++){
			urlVars = varArray[i].split("=");
			if (true == encode){
				this.encVar(urlVars[0], urlVars[1]);
			} else {
				this.setVar(urlVars[0], urlVars[1]);
			}
		}
	}

	this.createURLString = function(urlstring) {
		if (this.encodeURIString && this.URLString.length) {
			this.processURLString(this.URLString, true);
		}

		if (urlstring) {
			if (this.URLString.length) {
				this.URLString += this.argumentSeparator + urlstring;
			} else {
				this.URLString = urlstring;
			}
		}

		// prevents caching of URLString
		this.setVar("rndval", new Date().getTime());

		urlstringtemp = new Array();
		for (key in this.vars) {
			if (false == this.vars[key][1] && true == this.encodeURIString) {
				encoded = this.encVar(key, this.vars[key][0], true);
				delete this.vars[key];
				this.vars[encoded[0]] = Array(encoded[1], true);
				key = encoded[0];
			}

			urlstringtemp[urlstringtemp.length] = key + "=" + this.vars[key][0];
		}
		if (urlstring){
			this.URLString += this.argumentSeparator + urlstringtemp.join(this.argumentSeparator);
		} else {
			this.URLString += urlstringtemp.join(this.argumentSeparator);
		}
	}

	this.runResponse = function() {
		eval(this.response);
	}

	this.runAJAX = function(urlstring) {
		if (this.failed) {
			this.onFail();
		} else {
			this.createURLString(urlstring);
			if (this.element) {
				this.elementObj = document.getElementById(this.element);
			}
			if (this.xmlhttp) {
			
//alert("1.In runAJAX. Sending to requestFile: "+this.requestFile+", using method: "+this.method+",  urlstring="+this.URLString)

				var self = this;
				if (this.method == "GET") {
					totalurlstring = this.requestFile + this.queryStringSeparator + this.URLString;
					this.xmlhttp.open(this.method, totalurlstring, true);
				} else { // method=="POST"
					this.xmlhttp.open(this.method, this.requestFile, true);
					try {
						this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
					} catch (e) { }
				}

				this.xmlhttp.onreadystatechange = function() {
					switch (self.xmlhttp.readyState) {
						case 1:
							self.onLoading();
							break;
						case 2:
							self.onLoaded();
							break;
						case 3:
							self.onInteractive();
							break;
						case 4:
							self.response = self.xmlhttp.responseText;
							//alert("self.xmlhttp.responseText="+self.xmlhttp.responseText)
							self.responseXML = self.xmlhttp.responseXML;
							//alert("self.xmlhttp.responseXML="+self.xmlhttp.responseXML)
							//!!! FF throws exception on self.xmlhttp.status in certain combi's with form submission and submit button not being type='button', probably simultaneously normal-submitting form and ajax-submitting, see: http://markos.gaivo.net/blog/?p=109
							self.responseStatus[0] = self.xmlhttp.status;
							//alert("self.xmlhttp.status="+self.xmlhttp.status)
							self.responseStatus[1] = self.xmlhttp.statusText;
							//alert("self.xmlhttp.statusText="+self.xmlhttp.statusText)
							if (self.execute) {
								self.runResponse();
							}
							if (self.elementObj) {
								elemNodeName = self.elementObj.nodeName;
								elemNodeName.toLowerCase();
								if (elemNodeName == "input"
								|| elemNodeName == "select"
								|| elemNodeName == "option"
								|| elemNodeName == "textarea") {
									self.elementObj.value = self.response;
								} else {
									self.elementObj.innerHTML = self.response;
								}
							}
							if (self.responseStatus[0] == "200") {
							
								self.onCompletion();
							} else {
								self.onError();
							}

							self.URLString = "";
							break;
					}
				};
//alert("In runAJAX. Sending with this.URLString="+this.URLString)

				this.xmlhttp.send(this.URLString);
			}
		}
	};

	this.reset();
	this.createAJAX();
}



/////////////////////////////////////////////////////////////////////
//IFrame fallback
//Source: TinyAjax, http://www.metz.se/tinyajax/
/*
coded by Kae - http://verens.com/
use this code as you wish, but retain this notice

MK - notice retained, but renamed function to XMLHttpRequestI and
modified initial timeout

2-12-2007 modified to also handle POST by Paul Gobee
*/
XMLHttpRequestI = function() {
	var i=0;
	var url='';
	var responseText='';
	this.onreadystatechange=function(){
		return false;
	};
	
	this.open=function(method,url){
		this.i= ++kXHR_instances; // id number of this request
		this.method=method;
		this.url=url;
		/*necessary to insert iframe with innerHTML instead of DOM methods because attribute 'name' is read only with DOM methods. 'name' is necessary as target for form for POST. Container div is necessary to put innerHTML in. innerHTML directly in document would overwrite whole document.
		*/
		var contDiv = document.createElement('div');
		contDiv.setAttribute("id","container_"+this.i);
		contDiv=document.body.appendChild(contDiv);
        var iFrameId="kXHR_iframe_"+this.i;
		var iFrameHTML= "<iframe name='"+iFrameId+"'  id='"+iFrameId+"' style='display:none'></iframe>"
        contDiv.innerHTML = iFrameHTML;
	};
	
	this.send=function(postData){	
		if(this.method.toLowerCase()=="get"){
			var el=document.getElementById('kXHR_iframe_'+this.i);
			el.src=this.url;
		}
		else if(this.method.toLowerCase()=="post"){
			//create temporary form for POST data
			var form= document.createElement('form');
			form.setAttribute("method","post");		
			form.setAttribute("action",this.url); //page to post to
			form.setAttribute("target",'kXHR_iframe_'+this.i); //iframe receiving response
			form.style.display = 'none';	
			form=document.body.appendChild(form);
			var arData=postData.split("&");
			var arSnglDataPair,input;
			for(var i=0;i<arData.length;i++) 
            	{arSnglDataPair=arData[i].split("=");
				input=document.createElement('input');
				input.setAttribute("id",arSnglDataPair[0]); //key
				input.setAttribute("name",arSnglDataPair[0]); //key
				input.setAttribute("value",arSnglDataPair[1]); //value
				form.appendChild(input)
            	}
			form.submit();	
			form.parentNode.removeChild(form);
		}

		kXHR_objs[this.i]=this;
		setTimeout('XMLHttpRequestI_checkState('+this.i+')',200);
	};
	
	return true;
};


function XMLHttpRequestI_checkState(inst){
	var el=document.getElementById('kXHR_iframe_'+inst);
	var cont=document.getElementById("container_"+inst);	
	
	if(el.readyState=='complete'){
		if(!window.frames['kXHR_iframe_'+inst].document || !window.frames['kXHR_iframe_'+inst].document.body || !window.frames['kXHR_iframe_'+inst].document.body.childNodes[0] || ! window.frames['kXHR_iframe_'+inst].document.body.childNodes[0].data) 
			{var responseText=""}
		else
			{var responseText=window.frames['kXHR_iframe_'+inst].document.body.childNodes[0].data;}
		kXHR_objs[inst].responseText=responseText;
		kXHR_objs[inst].readyState=4;
		kXHR_objs[inst].status=200;
		kXHR_objs[inst].onreadystatechange();
		cont.parentNode.removeChild(cont);
	}else{
		setTimeout('XMLHttpRequestI_checkState('+inst+')',200);
	}
}
var kXHR_instances=0;
var kXHR_objs=[];



//dummy function to prevent errors. Can be overwritten in an app to report use of IframeFallback
if(typeof window.signalUseFallBack=="undefined"){
	signalUseFallBack=function(){} 
	}
	

