function dumpVar(_var, _prefix, _level) {
	var i, rval = new stringWriter(), addenum="";
	if(!_level) _level=0;
	if(_level>10) return "< too deep ... >";
	if(!_prefix) _prefix = "";
	_prefix += "  ";
        if (isAlien(_var)) {
                return "alien";
        } else if (isUndefined(_var)) {
                return "undefined";
        } else if (isNull(_var)) {
                rval.write("null");
        } else if (isNumber(_var)) {
                rval.write(_var);
        } else if (isString(_var)) {
                rval.write('"').write(_var).write('"');
        } else if (isFunction(_var)) {
                rval.write("<function>");
        } else if (isDate(_var)) {
                rval.write("<Date: ").write(_var).write(">");
        } else if (isArray(_var)) {
                rval.writeln("[");
                for (i=0; i<_var.length; i++) {
                        if (addenum!="") rval.writeln(",");
                        rval.write(_prefix).write(this.dumpVar(_var[i], _prefix, _level+1));
                        addenum = ","; 
                }
                rval.write("]");
        } else if (isObject(_var)) {
                rval.writeln("{");
                for (i in _var) {
                        if (addenum!="") rval.writeln(",");
                        rval.write(_prefix).write(i).write(":")
                                .write(this.dumpVar(_var[i], _prefix, _level+1));
                        addenum = ","; 
                }
                rval.write("}");
        } else {
                rval.write(_var);
        }
        return rval.toString();
};

function vNull($v) {
	return $v == null ? "" : $v;
}

Function.prototype.method = function (name, func) {
        this.prototype[name] = func;
        return this;
};

function isAlien(a) {
	return isObject(a) && typeof a.constructor != 'function';
}

function isArray(a) {
	return isObject(a) && a.constructor == Array;
}

function isBoolean(a) {
	return typeof a == 'boolean';
}

function isEmpty(o) {
	var i, v;
	if(isObject(o)) {
		for (i in o) {
			v = o[i];
			if (isUndefined(v) && isFunction(v)) {
				return false;
			}
		}
	}

	return true;
}

function isFunction(a) {
	return typeof a == 'function';
}

function isNull(a) {
	return typeof a == 'object' && !a;
}

function isNumber(a) {
	return (typeof a == 'number' && isFinite(a)) || a instanceof Number;
}

function isDate(a) {
	return a instanceof Date;
}

function isObject(a) {
	return (a && typeof a == 'object') || isFunction(a);
}

function isString(a) {
	return typeof a == 'string' || a instanceof String;
}

function isUndefined(a) {
	return typeof a == 'undefined';
} 








/**
 *  Basic String extensions {{{
**/

/**
 *  Improve String with XML escaping
**/
String.method('escapeXML', function () {
        return this.replace(/&/g, "&amp;").replace(/</g,
                "&lt;").replace(/>/g, "&gt;");
});

/**
 *  Improve String with JavaScript quoting
**/
String.method('quote', function () {
        return this.replace(/([\"\\])/g, '\\$1');
});

/**
 *  Escapes special Regular expression characters
**/
String.method('reEscape', function () {
        return this.replace(/([\\\^\$\-\.\*\?\{\}\(\)\[\]])/, "\\$1");
});


function stringWriter() {
        this.open();
        this.string = [];
}

stringWriter.method("write", function(_value) {
        this.string.push(String(_value));
        return this;
});

stringWriter.method("writeln", function(_value) {
        return this.write(''+_value+'\n');
});

stringWriter.method("open", function() {
        this.string=[];
});

stringWriter.method("close", function() {});

stringWriter.method("toString", function() {
        return this.string.join('');
});



var elementObj = {
	get : function(element) {
		return typeof element == "object" ? element : document.getElementById(element);
	},
	
	cleanElement : function(element) {
		element = elementObj.get(element);
		while(element.firstChild) {
			element.removeChild(element.firstChild);
		}
	},
	
	getBounds : function(element) {
		element = elementObj.get(element);
        var o = elementObj.get(element), x=0, y=0, w=0, h=0;
        if(o) {
        	w=o.offsetWidth;
        	h=o.offsetHeight;
        	while(o && o.style && (o.style.position.toLowerCase()!='absolute' || o.style.position.toLowerCase()!='relative')) {
        		x += o.offsetLeft;
        		y += o.offsetTop;
        		o = o.offsetParent;
        	}
        }
        return {left:x, right:x+w, top:y, bottom:y+h, width:w, height:h}
	},
	
	addCss : function(element, className) {
		element = elementObj.get(element);
		if(!element.className.match(new RegExp("\\b"+className.reEscape()+"\\b"))) {
			element.className += " " + className;
		}
	},
	
	removeCss : function(element, className) {
		element = elementObj.get(element);
		var re = new RegExp("\s?\\b"+className.reEscape()+"\\b"); 
		if(element.className.match(re)) {
			element.className = element.className.replace(re,"");
		}
	},
	
	css : function(element, className, add) {
		add ? this.addCss(element, className) : this.removeCss(element, className);
	},
	
	findCss : function(element, className) {
		element = elementObj.get(element);
        return (element.className.match(new RegExp("\\b"+className.reEscape()+"\\b")));
	},
	
	display : function(element, show) {
		element = elementObj.get(element);
		element.style.display = show === false ? "none" : "block";
	},
	
	fillSelect : function(elm, data, id, value, addEmpty) {
		var i, option;
		elm = elementObj.get(elm);
		if(typeof elm == "object" && elm.tagName && elm.tagName.toLowerCase() == "select") {
			for(i=(addEmpty===true ? -1 : 0);i<data.length;i++) {
				option = document.createElement("option");
				option.value = addEmpty===true && i==-1 ? "0" : data[i][id];
				option.appendChild(document.createTextNode(addEmpty===true && i==-1 ? "" :data[i][value]));
				elm.appendChild(option);
			}
		}
	},
	
	getText : function(element) {
		element = this.get(element);
		return isUndefined(element.textContent) ? element.innerText : element.textContent;
	},
	
	setText : function(element, text) {
		element = this.get(element);
		if(isUndefined(element.textContent)) {
			element.innerText = text;
		}
		else {
			element.textContent = text;
		}
	},
	
	getFloat : function(element) {
		element = this.get(element);
		return utils.getFloat(this.getText(element));
	}
};

var utils = {

	fixNumberInput : function(element) {
		element = elementObj.get(element);
		if(element.value.indexOf(",") != -1) element.value = element.value.replace(",",".");
		return element.value;
	},
	
	getFloat : function(v) {
		v = parseFloat(v);
		return isNaN(v) ? 0 : v;
	},
	
	round : function(v) {
		return Math.round(v*100)/100;;
	},
	
	inArray : function(v, a) {
		for(var i=0;i<a.length;i++) {
			if(a[i] == v) return true;
		}
		return false;
	}
};


var cookie = {
	set : function(name,value,exp) {if(exp) {var expire=new Date(); expire.setTime(expire.getTime()+20000*60*60*24*365);} document.cookie=name+"="+escape(value)+((expire == null)?"":("; expires="+expire.toGMTString()));},
	get : function(Name) {var search=Name+"="; if (document.cookie.length > 0) {offset = document.cookie.indexOf(search); if (offset != -1) {offset+=search.length; end = document.cookie.indexOf(";",offset); if (end==-1) end = document.cookie.length; return unescape(document.cookie.substring(offset, end));}}}
};


var ajaxRequest = {

	createRequest : function() {
		return window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
	},

	readyStateHandler : function(req, onSuccess, onError) {
		if(req.readyState == 4) {
			if(req.status==200) {
				if(isFunction(onSuccess)) {
					onSuccess(req);
				}
				else {
					if(isFunction(onError)) {
						onError(req);
					}
				}
			}
		}
	},

	post : function(url, data, onSuccess, onError) {
		var me = this;
		var req = this.createRequest();
		req.open("POST", url, true);
		req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
		req.send(data);
		var f = function() {
			me.readyStateHandler(req, onSuccess, onError)
		};
		req.onreadystatechange = f;
	},

	processRequest : function(dataManager, method, info, onSuccess, onError) {
		
		//log.debug("DM="+dataManager + ", MT="+method + ", DT=" + dumpVar(info));
		
		var requestUrl = "addtocart.php5";

		this.post(requestUrl, "ajax=" + encodeURIComponent(JSON.stringify(info)),
			function(req) {
				try {
					eval("var r = " + req.responseText);
					//log.debug("JSON: " + req.responseText);
				}
				catch(e) {
					//log.error("BAD JSON: " + req.responseText);
					popupWin.createError("System Error: <b>Can not eval JSON</b><br/><br/>" + req.responseText);
					showSplash(false);
				}
				
				onSuccess(r);
			}
		);
	}

};


function onDocumentReady() {
	prepareValidation();
	elementObj.get("mainLayer").style.display = "block";
	showSplash(false);
}

function showSplash(show) {
	show = show === false ? false : true;
	elementObj.get("loaderLayer").style.display	   = show ? "block" : "none";
	elementObj.get("mainLayerAlpha").style.display = show ? "block" : "none";
	
	if(show) {
		elementObj.get("mainLayerAlpha").style.opacity = "0.65";
		elementObj.get("mainLayerAlpha").style.filter = "alpha(opacity=55)";
	}
	else {
		elementObj.get("mainLayerAlpha").style.opacity = "";
		elementObj.get("mainLayerAlpha").style.filter = "";
	}

}


function prepareValidation(obj) {
	var i, xval;
	var objs = typeof obj == "object" ? [obj] : document.getElementsByTagName("input");
	var key_patterns = {
		'nocomma'	: /[^,]/,
		'fullname'	: /[A-z\s]/,
		'alnum'		: /[\w\_\-]/,
		'search'	: /[\w\_\-\%\.\@\s\'\&\(\)]/,
		'zip'		: /[\d\-]/,
		'number'	: /\d/,
		'currency'	: /[\d\.,]/,
		'date'		: /[\d\/]/,
		'email'		: /[\w\.\_\-\@]/
	};

	

	for (i=0;i<objs.length;i++) {
		xval = objs[i].getAttribute("x_validate");
		if(xval) {
			objs[i].onkeypress = function(e) {
				if(!this) return;
				var ch;
				if(!e) {
					ch = event.keyCode;
					event.cancelBubble=true;
				}
				else {
					ch = e.charCode;
					e.stopPropagation();
				}
				
				if(ch>0) {
					ch = String.fromCharCode(ch);
					var valRule = this.getAttribute("x_validate");
					if(key_patterns[valRule] && ch) {
				
						if(ch.match(key_patterns[valRule])) {
						
							var el = e ? e.target : event.srcElement;
							var elPos = getInputStartEndPosition(el);
							elPos = el.value.substr(0,elPos.start) + el.value.substr(elPos.end);
							
							if(
								(valRule == "fullname" && ch == " " && elPos.indexOf(" ")!=-1)
								||
								(valRule == "currency" && (ch == "." || ch == ",") && elPos.indexOf(".")!=-1)
							) {
								return false;
							}
						
							return true;
						}
						else {
							return false;
						}
					}
					else {
						return true;
					}
				}
			}
		}

		objs[i].onpaste = function() {
			var i, ch, valRule, myT = clipboardData.getData("Text");
			for(i=0;i<myT.length;i++) {
				ch = myT.substr(i,1);
				valRule = this.getAttribute("x_validate");
				if(key_patterns[valRule] && !ch.match(key_patterns[valRule])) {
					return false;
				}
			}
		}
	}
}



function getInputStartEndPosition(obj) {
	var startPoint=0, endPoint=0;
	
	if(obj.selectionStart>=0)
	{
		startPoint = obj.selectionStart;
		endPoint = obj.selectionEnd;
	}
	else if(document.selection)
	{
		rng = document.selection.createRange();

		if(rng.parentElement() == obj)
		{
			var rng1 = obj.createTextRange();
			var initLength = rng.text.length;
			rng.setEndPoint("StartToStart", rng1);
			var finalLength = rng.text.length;
			startPoint = finalLength-initLength;
			endPoint = finalLength;
		}
	}

	return {start:startPoint,end:endPoint};
}



function spinControl(params) {
	return	"<div class=\"spinControl\"><center>" +
			"<table><tr><td><div class=\"left\" onclick=\""+(params.maxValue ? "if(document.getElementById('"+params.id+"').value >= "+(params.minValue+1)+")" : "")+"{document.getElementById('"+params.id+"').value--"+(params.onchange ? ";"+params.onchange+"(parseInt(document.getElementById('"+params.id+"').value))" : "")+"}\"></div></td><td>" +
			"<input onfocus=\"this.blur()\" id=\""+params.id+"\" value=\""+(params.value ? params.value : (params.minValue ? params.minValue : 0))+"\" readonly=\"true\" class=\"ro\" />" +
			"</td><td><div class=\"right\" onclick=\""+(params.maxValue ? "if(document.getElementById('"+params.id+"').value <= "+(params.maxValue-1)+")" : "")+"{document.getElementById('"+params.id+"').value++"+(params.onchange ? ";"+params.onchange+"(parseInt(document.getElementById('"+params.id+"').value))" : "")+"}\"></div></td></tr></table></center></div>";
}

spinControl.show = new Function("el", "show", "" +
		"var i = 0, el = elementObj.get(el);" +
		"while(el = el.parentNode) {" +
		"if(el.tagName.toLowerCase() == 'div' && el.className == 'spinControl') {" +
		"el.style.display = show === false ? 'none' : 'block';" +
		"break;" +
		"}" +
		"i++;" +
		"if(i>6) break;" +
		"}"
	);


function calendarControl(params) {
	return	"<span class=\"popupCalendar\" onclick = \"EVPCalendar.show(arguments[0],this.getElementsByTagName('input')[0].id)\";>" +
			"<input class=\"ro\" readonly=\"true\" type=\"text\" id=\"" + params.id +"\" " + (typeof params.value == "string" ? "value=\"" + params.value + "\"" : "") +"/>" +
			"</span>";
}


function clearMemory() {
	
	if(elementObj.get("loaderLayer")) elementObj.get("loaderLayer").style.display = "block";
	if(elementObj.get("mainLayer")) elementObj.get("mainLayer").style.display = "none";
	
	var i,i1, o, objs, tags = ["div", "span", "input", "select", "button"];
	for(i=0;i<tags.length;i++) {
		objs = document.getElementsByTagName(tags[i]);
		for(i1=0;i1<objs.length;i1++) {
			try {
				for(var o in objs[i1]) {
					objs[i1][o] = null;
				}
				objs[i1] = null;
			}
			catch(e) {
			}
		}
	}

	/*
	for(var o in window) {
		try {window[o] = null;} catch(e) {};
	} 
	 */
}