/* DOM functions */
function getElementsByClassName(baseElement,className,tagName) {
	var foundElements = new Array();
	if (!tagName) var tagName = "*";
	var elements = baseElement.getElementsByTagName(tagName);
	for (var i=0; i<elements.length; i++) {
		var regEx = new RegExp("(^|\\s)"+className+"(\\s|$)","i");
		if ((elements[i].className)&&(regEx.test(elements[i].className))) foundElements.push(elements[i]);
	}
	return foundElements;
}
function addClass(element,str) {
	var regEx = new RegExp("(^|\\s)"+str+"(\\s|$)","i");
	if (element.className) { if (!regEx.test(element.className)) element.className += " "+str; } else { element.className = str; }
}
function delClass(element,str) {
	var regEx = new RegExp("(^|\\s)"+str+"(\\s|$)","gi");
	if (element.className) { element.className = element.className.replace(regEx," ").replace(/(^\s+|\s+$)/,""); if (element.className == "") element.removeAttribute("class"); }
}
function hasClass(element,str) {
	var regEx = new RegExp("(^|\\s)"+str+"(\\s|$)","i");
	if (element.className) { if (regEx.test(element.className)) return true; else return false; }
}

/* Login */
/*
var errorMsg = new Object();
errorMsg["INVALID_LOGIN"] = "Onjuiste login";
function getStatus(response) {
	var codes = response.split("::");
	switch (codes[0]) {
		case "ERROR" : document.getElementById("error").innerHTML = errorMsg[codes[1]]; document.forms['login'].reset(); document.forms['login'].elements['name'].focus(); break;
		case "OK"    : window.location = "index.php"; break;
		default      : document.getElementById("error").innerHTML = "SCRIPT ERROR";
	}
}
function checkLogin() {
	var login_e = document.getElementById("email").value;
	var login_p = document.getElementById("password").value;
	var a = new Ajax();
	a.request("ajax/checklogin.php","post",getStatus,{email:login_e,pass:login_p});
}
*/

/* MAIL sending */
function dummy(transport) {
}
function sendResultsEmail(serializedData) {
	var a = new Ajax();
	a.request("ajax/sendresultsemail.php","post",dummy,{data:serializedData});
}


/* GUI functionalities */
function attachUpDown(id,min,max) {
	var element = document.getElementById(id);
	if ((element.tagName.toLowerCase()=="input")&&(element.type.toLowerCase()=="text")) {
		var container = document.createElement("div");
		container.style.cssText = "margin:"+element.style.margin+";padding:"+element.style.padding+";";
		var inputDiv = document.createElement("div");
		inputDiv.style.cssText = "float:left;border:1px #A5ACB2 solid;background-color:#fff;height:18px;";
		var newTextElement = element.cloneNode(true);
		newTextElement.style.margin      = "0";
		newTextElement.style.padding     = "0";
		newTextElement.style.borderWidth = "0";
		var btnUp = document.createElement("div");
		btnUp.style.cssText = "width:15px;height:9px;background-color:red;overflow:hidden;background:url(images/misc/btn_up.gif) no-repeat 4px 2px #fff;border-top:1px #A5ACB2 solid;border-right:1px #A5ACB2 solid;border-bottom:1px #A5ACB2 solid;";
		btnUp.onclick = function(){ var inputElement = this.parentNode.getElementsByTagName("input")[0]; value = parseInt(inputElement.value); if (isNaN(value)) value = 0; if (value<max) value++; inputElement.value = value; inputElement.focus(); inputElement.onkeyup(); }
		var btnDown = document.createElement("div");
		btnDown.style.cssText = "width:15px;height:8px;background-color:blue;overflow:hidden;background:url(images/misc/btn_down.gif) no-repeat 4px 2px #fff;border-right:1px #A5ACB2 solid;border-bottom:1px #A5ACB2 solid;";
		btnDown.onclick = function(){ var inputElement = this.parentNode.getElementsByTagName("input")[0]; value = parseInt(inputElement.value); if (isNaN(value)) value = 0; if (value>min) value--; inputElement.value = value; inputElement.focus(); inputElement.onkeyup(); }
		inputDiv.appendChild(newTextElement);
		container.appendChild(inputDiv);
		container.appendChild(btnUp);
		container.appendChild(btnDown);
		element.parentNode.replaceChild(container,element);
	}
}


/* GUI actualizing */
function price(value) {
	return String(value).replace(/([0-9]+)([0-9]{3})$/,"$1.$2")+",-";
}

function newStep(step) {
	curStep = step;
	var container = document.getElementById("content");
	var stepDivs  = [];
	for (var i=0;i<container.childNodes.length;i++) if ((container.childNodes[i].tagName)&&(container.childNodes[i].tagName.toLowerCase()=="div")) stepDivs.push(container.childNodes[i]);
	for (var i=0;i<stepDivs.length;i++) stepDivs[i].style.display = "none";
	stepDivs[curStep-1].style.display = "block";
	actualizeStep(curStep);
}
function prevStep() {
	if (curStep>1) newStep(curStep-1);
}
function nextStep() {
	if (validStep(curStep)&&(curStep<11)) newStep(curStep+1);
}
function setStep(step) {
	if (validStep(curStep)&&(step==curStep+1)) newStep(step); else
	if (step<curStep) newStep(step);
}

function actualizeBudget(newBudget) {
	var newBudgetStr = String(newBudget).replace(/([0-9]+)([0-9]{3})$/,"$1.$2");
	var container = document.getElementById("budgetover");
	var sign      = getElementsByClassName(container,"sign","span")[0];
	var currency  = getElementsByClassName(container,"currency","span")[0];
	var figure    = getElementsByClassName(container,"figure","span")[0];
	if (newBudget<0) {
		sign.innerHTML = "-";
		addClass(container,"negative"); 
	} else {
		sign.innerHTML = "";
		delClass(container,"negative");
	}
	currency.innerHTML = "&euro;";
	figure.innerHTML = price(Math.abs(newBudget));
}
function actualizeStepButtons(currentStep,valid) {
	var zbStep = currentStep-1;
	var btnList = document.getElementById("steps").getElementsByTagName("div");
	for (var i=0;i<zbStep;i++) btnList[i].className = "step done"; 
	btnList[zbStep].className = "step";
	zbStep++; if (zbStep<11) if (valid) btnList[currentStep].className = "step allowed"; else btnList[currentStep].className = "step disabled";
	zbStep++; if (zbStep<11) for (var i=zbStep;i<11;i++) btnList[i].className = "step disabled";
}
function actualizePrevNext(currentStep,valid) {
	var prevs = getElementsByClassName(document.getElementById("budgetplanner"),"prev");
	var nexts = getElementsByClassName(document.getElementById("budgetplanner"),"next");
	for (var i=0;i<prevs.length;i++) if (currentStep==1) prevs[i].className = "prev disabled"; else prevs[i].className = "prev";
	for (var i=0;i<nexts.length;i++) if ((currentStep==11)||(!valid)) nexts[i].className = "next disabled"; else nexts[i].className = "next";
}

// step 1
function validStep(step) {
	switch (step) {
		case  1: return (parseInt(budget)>0)&&(/^(basis|gemiddeld|luxe)$/.test(prijsstelling))&&(/^(<1|<3|<6|<12|-)$/.test(geplandeAanschaf))&&(persoonlijkeSmaak>0); break;
		case  2: return (/^(recht|lopstelling|uopstelling|gopstelling|eiland|parallel)$/.test(opstelling)); break;
		case  3: return ((opstelling=="recht"?(afmeting[1]>0):(opstelling=="lopstelling"?(afmeting[1]>0&&afmeting[2]>0):(opstelling=="uopstelling"?(afmeting[1]>0&&afmeting[2]>0&&afmeting[3]>0):(opstelling=="gopstelling"?(afmeting[1]>0&&afmeting[2]>0&&afmeting[3]>0&&afmeting[4]>0&&afmeting[5]>0):(opstelling=="eiland"?(afmeting[1]>0&&afmeting[2]>0&&afmeting[4]>0&&afmeting[5]>0):(opstelling=="parallel"?(afmeting[1]>0&&afmeting[2]>0):false))))))&&(/^(vlak|kader|cassette)$/.test(kastfront)));
		case  4: return (/^(gaskookplaat|gasopglas|keramisch|inductie|vrijstaand|gasoven)$/.test(kookunit)); break;
		case  5: return (/^(wandkast|hogekast|combi)$/.test(magnetron))&&(/^(oven|stoomoven|geen)$/.test(oven))&&(/^(ja|nee)$/.test(vaatwasser)); break;
		case  6: return (/^(koelkast1|koelkast2|koelkast3|koelkast4)$/.test(koelkast)); break;
		case  7: return (/^(schouw1|schouw2|vlakscherm|afzuigkapeiland)$/.test(afzuigkap))&&(/^(tl|spots)$/.test(verlichting)); break;
		case  8: return (/^(kunststof_spaanplaat_waterkering|kunststof_multiplex_waterkering|graniet_waterkering|graniet_groef|composiet_waterkering|composiet_groef)$/.test(werkblad)); break;
		case  9: return (/^(rechthoekig_porcelein|rechthoekig_rvs_enkel|rechthoekig_rvs_anderhalf|rechthoekig_rvs_dubbel|rond_rvs_enkel)$/.test(spoelbak))&&(/^(2greeps|1hendel|nostalgisch)$/.test(kraan)); break;
		case 10: return (/^(vakman|zelf)$/.test(plaatsing)); break;
	}
}
function actualizeStep(step) {
	var stepComplete = validStep(step);
	actualizeStepButtons(step,stepComplete);
	actualizePrevNext(step,stepComplete);
	var bedrag_keukenmeubelen = calcPrice("apothekerskasten") + calcPrice("pannenladen") + calcPrice("glasdeuren") + calcPrice("kastfronten");
	var bedrag_apparatuur     = calcPrice("kookunit") + calcPrice("magnetron") + calcPrice("oven") + calcPrice("vaatwasser") + calcPrice("koelkast") + calcPrice("afzuigkap") + calcPrice("verlichting");
	var bedrag_werkbladen     = calcPrice("werkblad");
	var bedrag_spoelbakkranen = calcPrice("spoelbak") + calcPrice("kraan");
	var bedrag_plaatsing      = calcPrice("plaatsing");
	var bedrag_totaal         = bedrag_keukenmeubelen + bedrag_apparatuur + bedrag_werkbladen + bedrag_spoelbakkranen + bedrag_plaatsing;
	actualizeBudget(budget - bedrag_totaal);
	switch (step) {
		case 1:
			if (persoonlijkeSmaak>0) {
				var imgList = getElementsByClassName(document.getElementById("persoonlijkesmaak"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="persoonlijkesmaak_"+persoonlijkeSmaak) delClass(imgList[i],"blur"); else addClass(imgList[i],"blur");
			}
			break;
		case 2:
			if (opstelling!="") {
				var imgList = getElementsByClassName(document.getElementById("opstelling"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="opstelling_"+opstelling) delClass(imgList[i],"blur"); else addClass(imgList[i],"blur");
			}
			break;
		case 3:
			if (kastfront!="") {
				var imgList = getElementsByClassName(document.getElementById("kastfronten"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="kastfront_"+kastfront) { delClass(imgList[i],"blur"); imgList[i].parentNode.getElementsByTagName("input")[0].checked = true; } else addClass(imgList[i],"blur");
			}
			break;
		case 4:
			if (kookunit!="") {
				var imgList = getElementsByClassName(document.getElementById("kookunits"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="kookunit_"+kookunit) { delClass(imgList[i],"blur"); imgList[i].parentNode.getElementsByTagName("input")[0].checked = true; } else addClass(imgList[i],"blur");
			}
			break;
		case 5:
			if (magnetron!="") {
				var imgList = getElementsByClassName(document.getElementById("magnetrons"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="magnetron_"+magnetron) { delClass(imgList[i],"blur"); imgList[i].parentNode.getElementsByTagName("input")[0].checked = true; } else addClass(imgList[i],"blur");
			}
			if (oven!="") {
				var imgList = getElementsByClassName(document.getElementById("ovens"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="oven_"+oven) { delClass(imgList[i],"blur"); imgList[i].parentNode.getElementsByTagName("input")[0].checked = true; } else addClass(imgList[i],"blur");
			}
			break;
		case 6:
			if (koelkast!="") {
				var imgList = getElementsByClassName(document.getElementById("koelkasten"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="koelkast_"+koelkast) { delClass(imgList[i],"blur"); imgList[i].parentNode.getElementsByTagName("input")[0].checked = true; } else addClass(imgList[i],"blur");
			}
			break;
		case 7:
			if (afzuigkap!="") {
				var imgList = getElementsByClassName(document.getElementById("afzuigkappen"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="afzuigkap_"+afzuigkap) { delClass(imgList[i],"blur"); imgList[i].parentNode.getElementsByTagName("input")[0].checked = true; } else addClass(imgList[i],"blur");
			}
			if (verlichting!="") {
				var imgList = getElementsByClassName(document.getElementById("verlichtingen"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="verlichting_"+verlichting) { delClass(imgList[i],"blur"); imgList[i].parentNode.getElementsByTagName("input")[0].checked = true; } else addClass(imgList[i],"blur");
			}
			break;
		case 8:
			if (werkblad!="") {
				var imgList = getElementsByClassName(document.getElementById("werkbladen"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="werkblad_"+werkblad) { delClass(imgList[i],"blur"); imgList[i].parentNode.getElementsByTagName("input")[0].checked = true; } else addClass(imgList[i],"blur");
			}
			break;
		case 9:
			if (spoelbak!="") {
				var imgList = getElementsByClassName(document.getElementById("spoelbakken"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="spoelbak_"+spoelbak) { delClass(imgList[i],"blur"); imgList[i].parentNode.getElementsByTagName("input")[0].checked = true; } else addClass(imgList[i],"blur");
			}
			if (kraan!="") {
				var imgList = getElementsByClassName(document.getElementById("kranen"),"image","div");
				for (var i=0;i<imgList.length;i++) if (imgList[i].id=="kraan_"+kraan) { delClass(imgList[i],"blur"); imgList[i].parentNode.getElementsByTagName("input")[0].checked = true; } else addClass(imgList[i],"blur");
			}
			break;
		case 10:
			break;
		case 11:
			document.getElementById("keukenmeubelen_bedrag").innerHTML = price(bedrag_keukenmeubelen);
			document.getElementById("apparatuur_bedrag").innerHTML = price(bedrag_apparatuur);
			document.getElementById("werkbladen_bedrag").innerHTML = price(bedrag_werkbladen);
			document.getElementById("spoelbakkranen_bedrag").innerHTML = price(bedrag_spoelbakkranen);
			document.getElementById("plaatsing_bedrag").innerHTML = price(bedrag_plaatsing);
			document.getElementById("totaal_bedrag").innerHTML = price(bedrag_totaal);
			document.getElementById("budget_bedrag").innerHTML = price(budget);
			document.getElementById("delta_label").innerHTML = budget-bedrag_totaal>=0?"Resterend budget":"Te kort";
			document.getElementById("delta_bedrag").innerHTML = price(Math.abs(budget-bedrag_totaal));
			sendResultsEmail(
				serialize([
					price(budget),prijsstelling,geplandeAanschaf,persoonlijkeSmaak,
					opstelling,
					afmeting,apothekerskasten,pannenladen,glasdeuren,kastfront,price(bedrag_keukenmeubelen),
					kookunit,magnetron,oven,vaatwasser,koelkast,afzuigkap,verlichting,price(bedrag_apparatuur),
					werkblad,price(bedrag_werkbladen),
					spoelbak,kraan,price(bedrag_spoelbakkranen),
					plaatsing,
					price(bedrag_totaal),
					budget-bedrag_totaal,
					price(Math.abs(budget-bedrag_totaal))
				])
			);
			break;
	}
}

// step 1
function setBudget(el) {
	budget = parseInt(el.value.replace(/\D/g,""));
	if (isNaN(budget)) budget = 0;
	if (budget>50000) budget = 50000;
	el.value = budget==0?"":budget;
	actualizeStep(1);
}
function setPrijsstelling(value) {
	prijsstelling = value;
	actualizeStep(1);
}
function setGeplandeaanschaf(value) {
	geplandeAanschaf = value;
	actualizeStep(1);
}
function setPersoonlijkesmaak(value) {
	persoonlijkeSmaak = value;
	actualizeStep(1);
}

// step 2
function setOpstelling(value) {
	opstelling = value;
	document.getElementById("maatvoering_recht").style.display = opstelling=="recht"?"block":"none";
	document.getElementById("maatvoering_lopstelling").style.display = opstelling=="lopstelling"?"block":"none";
	document.getElementById("maatvoering_uopstelling").style.display = opstelling=="uopstelling"?"block":"none";
	document.getElementById("maatvoering_gopstelling").style.display = opstelling=="gopstelling"?"block":"none";
	document.getElementById("maatvoering_eiland").style.display = opstelling=="eiland"?"block":"none";
	document.getElementById("maatvoering_parallel").style.display = opstelling=="parallel"?"block":"none";
	var inputs  = document.getElementById("maatvoering_"+opstelling).getElementsByTagName("input");
	var selects = document.getElementById("maatvoering_"+opstelling).getElementsByTagName("select");
	for (var i=0;i<inputs.length;i++) inputs[i].value="";
	for (var i=0;i<selects.length;i++) selects[i].options[0].selected = true;
	afmeting[1]=0;afmeting[2]=0;afmeting[3]=0;afmeting[4]=0;afmeting[5]=60;
	actualizeStep(2);
}

// step 3
function setAfmeting(idx,el) {
	afmeting[idx] = parseInt(el.value.replace(/\D/g,"").substr(0,3));
	if (isNaN(afmeting[idx])) afmeting[idx] = 0;
	el.value = afmeting[idx]==0?"":afmeting[idx];
	actualizeStep(3);
}
function setAfmetingSel(idx,value) {
	afmeting[idx] = parseInt(value.replace(/\D/g,""));
	actualizeStep(3);
}
function setMeubilair(key,el,max) {
	var v = parseInt(el.value.replace(/\D/g,"").substr(0,3));
	if (isNaN(v)) v = 0;
	if (v>max) v=max;
	switch (key) {
		case "apothekerskasten" : apothekerskasten = v; break;
		case "pannenladen"      : pannenladen      = v; break;
		case "glasdeuren"       : glasdeuren       = v; break;
	}
	el.value = v==0?"":v;
	actualizeStep(3);
}
function setKastFront(value) {
	kastfront = value;
	actualizeStep(3);
}

// step 4
function setKookunit(value) {
	kookunit = value;
	actualizeStep(4);
}

// step 5
function setMagnetron(value) {
	magnetron = value;
	actualizeStep(5);
}
function setOven(value) {
	oven = value;
	actualizeStep(5);
}
function setVaatwasser(value) {
	vaatwasser = value;
	actualizeStep(5);
}

// step 6
function setKoelkast(value) {
	koelkast = value;
	actualizeStep(6);
}

// step 7
function setAfzuigkap(value) {
	afzuigkap = value;
	actualizeStep(7);
}
function setVerlichting(value) {
	verlichting = value;
	actualizeStep(7);
}

// step 8
function setWerkblad(value) {
	werkblad = value;
	actualizeStep(8);
}

// step 9
function setSpoelbak(value) {
	spoelbak = value;
	actualizeStep(9);
}
function setKraan(value) {
	kraan = value;
	actualizeStep(9);
}

// step 10
function setPlaatsing(value) {
	plaatsing = value;
	actualizeStep(10);
}


// calculations
function calcPrice(type) {
	switch (type) {
		case "apothekerskasten" : return apothekerskasten * prijslijst["keukenmeubilair"]["apothekerskasten"][prijsstelling]; break;
		case "pannenladen"      : return pannenladen * prijslijst["keukenmeubilair"]["pannenladen"][prijsstelling]; break;
		case "glasdeuren"       : return glasdeuren * prijslijst["keukenmeubilair"]["glasdeuren"][prijsstelling]; break;
		case "kastfronten"      : var meters = (opstelling=="recht"?(afmeting[1]):(opstelling=="lopstelling"?(afmeting[1]+afmeting[2]):(opstelling=="uopstelling"?(afmeting[1]+afmeting[2]+afmeting[3]):(opstelling=="gopstelling"?(afmeting[1]+afmeting[2]+afmeting[3]+afmeting[4]/*+afmeting[5]*/):(opstelling=="eiland"?(afmeting[1]+afmeting[2]+afmeting[4]/*+afmeting[5]*/):(opstelling=="parallel"?(afmeting[1]+afmeting[2]):0))))))/100; if (kastfront!="") return Math.round(meters * prijslijst["kastfronten"][kastfront][prijsstelling]); else return 0; break;
		case "kookunit"         : if (kookunit!="") return prijslijst["kookunits"][kookunit][prijsstelling]; else return 0; break;
		case "magnetron"        : if (magnetron!="") return prijslijst["magnetrons"][magnetron][prijsstelling]; else return 0; break;
		case "oven"             : if (oven!="") return prijslijst["ovens"][oven][prijsstelling]; else return 0; break;
		case "vaatwasser"       : if (vaatwasser!="") return prijslijst["vaatwasser"][vaatwasser][prijsstelling]; else return 0; break;
		case "koelkast"         : if (koelkast!="") return prijslijst["koelkasten"][koelkast][prijsstelling]; else return 0; break;
		case "afzuigkap"        : if (afzuigkap!="") return prijslijst["afzuigkappen"][afzuigkap][prijsstelling]; else return 0; break;
		case "verlichting"      : if (verlichting!="") return prijslijst["verlichtingen"][verlichting][prijsstelling]; else return 0; break;
		case "werkblad"         : if (werkblad!="") { var meters = (opstelling=="recht"?(afmeting[1]):(opstelling=="lopstelling"?(afmeting[1]+afmeting[2]):(opstelling=="uopstelling"?(afmeting[1]+afmeting[2]+afmeting[3]):(opstelling=="gopstelling"?(afmeting[1]+afmeting[2]+afmeting[3]/*+afmeting[4]+afmeting[5]*/):(opstelling=="eiland"?(afmeting[1]+afmeting[2]/*+afmeting[4]+afmeting[5]*/):(opstelling=="parallel"?(afmeting[1]+afmeting[2]):0))))))/100; var price = meters * prijslijst["werkbladen"][werkblad][60]; if (/^(gopstelling|eiland)$/.test(opstelling)) { var meters = afmeting[4]/100; price += meters * prijslijst["werkbladen"][werkblad][afmeting[5]]; } return Math.round(price); } else return 0;
		case "spoelbak"         : if (spoelbak!="") return prijslijst["spoelbakken"][spoelbak][prijsstelling]; else return 0; break;
		case "kraan"            : if (kraan!="") return prijslijst["kranen"][kraan][prijsstelling]; else return 0; break;
		case "plaatsing"        : var meters = (opstelling=="recht"?(afmeting[1]):(opstelling=="lopstelling"?(afmeting[1]+afmeting[2]):(opstelling=="uopstelling"?(afmeting[1]+afmeting[2]+afmeting[3]):(opstelling=="gopstelling"?(afmeting[1]+afmeting[2]+afmeting[3]+afmeting[4]/*+afmeting[5]*/):(opstelling=="eiland"?(afmeting[1]+afmeting[2]+afmeting[4]/*+afmeting[5]*/):(opstelling=="parallel"?(afmeting[1]+afmeting[2]):0))))))/100; return Math.round(meters*prijslijst["plaatsing"][plaatsing][prijsstelling]); break;
								//if (plaatsing!="") return prijslijst["plaatsing"][plaatsing][prijsstelling]; else return 0; break;
		default                 : return 0;
	}
}


// 3rd party
function serialize(mixed_value) {
	// http://kevin.vanzonneveld.net
	// +   original by: Arpad Ray (mailto:arpad@php.net)
	// +   improved by: Dino
	// +   bugfixed by: Andrej Pavlovic
	// +   bugfixed by: Garagoth
	// +      input by: DtTvB (http://dt.in.th/2008-09-16.string-length-in-bytes.html)
	// +   bugfixed by: Russell Walker (http://www.nbill.co.uk/)
	// +   bugfixed by: Jamie Beck (http://www.terabit.ca/)
	// %          note: We feel the main purpose of this function should be to ease the transport of data between php & js
	// %          note: Aiming for PHP-compatibility, we have to translate objects to arrays
	// *     example 1: serialize(['Kevin', 'van', 'Zonneveld']);
	// *     returns 1: 'a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}'
	// *     example 2: serialize({firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'});
	// *     returns 2: 'a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}'

	var _getType = function (inp) {
		var type = typeof inp, match;
		var key;
		if (type == 'object' && !inp) {
			return 'null';
		}
		if (type == "object") {
			if (!inp.constructor) {
				return 'object';
			}
			var cons = inp.constructor.toString();
			match = cons.match(/(\w+)\(/);
			if (match) {
				cons = match[1].toLowerCase();
			}
			var types = ["boolean", "number", "string", "array"];
			for (key in types) {
				if (cons == types[key]) {
					type = types[key];
					break;
				}
			}
		}
		return type;
	};
	var type = _getType(mixed_value);
	var val, ktype = '';

	switch (type) {
		case "function": 
			val = ""; 
			break;
		case "boolean":
			val = "b:" + (mixed_value ? "1" : "0");
			break;
		case "number":
			val = (Math.round(mixed_value) == mixed_value ? "i" : "d") + ":" + mixed_value;
			break;
		case "string":
			val = "s:" + encodeURIComponent(mixed_value).replace(/%../g, 'x').length + ":\"" + mixed_value + "\"";
			break;
		case "array":
		case "object":
			val = "a";
			/*
			if (type == "object") {
				var objname = mixed_value.constructor.toString().match(/(\w+)\(\)/);
				if (objname == undefined) {
					return;
				}
				objname[1] = this.serialize(objname[1]);
				val = "O" + objname[1].substring(1, objname[1].length - 1);
			}
			*/
			var count = 0;
			var vals = "";
			var okey;
			var key;
			for (key in mixed_value) {
				ktype = _getType(mixed_value[key]);
				if (ktype == "function") { 
					continue; 
				}
				okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key);
				vals += this.serialize(okey) + this.serialize(mixed_value[key]);
				count++;
			}
			val += ":" + count + ":{" + vals + "}";
			break;
		case "undefined": // Fall-through
		default: // if the JS object has a property which contains a null value, the string cannot be unserialized by PHP
			val = "N";
			break;
	}
	if (type != "object" && type != "array") {
		val += ";";
	}
	return val;
}
