// functions 2.0
// requires dom 3.8
// 	2.0	object variable added. It is the namespace for variable related functions
// 	2.0	JSON format full support added
// 	1.12	object actions added. It is namespace for event handlers
// 	1.11	method clone added. Some debugging functions added
// 	1.10	method String.escapeHtml added
// 	1.9	method log.clear added
// 	1.8	method log.write improved
// 	1.7	object cook added, some minor changes
// 	1.6	some legacy functions added
// 	1.5	object log separated
// 	1.4	added functions isSet and isDefined
// 	1.3	exception handling wrapped to object xcp
// 	1.2	object browser added - it detects the browser version
// 	1.1	method String.prototype.removeHtmlEntities enhanced
// 		method String.prototype.removeInlineHtml added
// 		functions winH and winW removed (moved to dhtml)
// 	1.0	nbsp character definition added
// 		function isDefined added
// 		function isEmpty(variable) added
// 		function isSet(variable) added

var nbsp = String.fromCharCode(160); // non-breaking space

/*
Object.prototype.extend = function(oSuper) {
	// usage: function ClassB() { this.extend(new ClassA()); }
	for (sProperty in oSuper) {
		this[sProperty] = oSuper[sProperty];
	}
	return true;
}
*/

// skip leading whitespace
String.prototype.ltrim = function() {return this.replace(/^\s*(.*)/, "$1");}

// skip trailing whitespace
// String.prototype.rtrim = function() {return(this.replace(/(.*?)\s*$/, "$1"));}
String.prototype.rtrim = function() {return this.replace(/\s*$/, "");}

// skip leading and trailing whitespace
// String.prototype.trim = function() {return(this.replace(/\s*(.*?)\s*$/, "$1"));}
String.prototype.trim = function() {return this.ltrim().rtrim();}

// test if the string is empty
// String.prototype.isEmpty = function() {return (this.search(/\S/) < 0) ? true : false;}
String.prototype.isEmpty = function() {return (this.search(/\S/) < 0) ? true : false;}

// test if string is empty HTML
String.prototype.isBlank = function() {
	// by fczbkk
	var str = this;
	var blankCharacters = [" ", "&nbsp;", "&#032;"];
	for (var i = 0; i < blankCharacters.length; i++)
		str = str.replace(eval("/" + blankCharacters[i] + "/gi"), "");
	return (str.isEmpty());
}

// replaces HTML entities with normal characters
String.prototype.removeHtmlEntities = function() {
	var str = this;
	str = str.replace(/&nbsp;/g," ");
	str = str.replace(/&amp;/g,"&");
	str = str.replace(/&hellip;/g,"...");
	str = str.replace(/&quot;/g,'"');
	str = str.replace(/&lt;/g,"<");
	str = str.replace(/&gt;/g,">");
	return str;
}

String.prototype.removeInlineHtml = function() {
	var str = this;
	str = str.replace(/[<]{1}[^<>]*[>]{1}/g, ""); // remove all tags
	str = str.replace(/[ ]{2}/g, " "); // remove multiple spaces
	str = str.removeHtmlEntities(); // translate entities
	return str;
}

String.prototype.escapeHtml = function() {
	var str = this;
	str = str.replace(/[&]/,"&amp;");
//	str = str.replace(/[>]/g,"&gt;");
//	str = str.replace(/[<]/g,"&lt;");
//	str = str.replace(/["]/,'&quot;');
	return str;
}

//	Split string into 2 substrings by delimiter
String.prototype.split2 = function(delimiter) {
	var text = this;
	var result = new Array();
	var index = text.indexOf(delimiter);
	if (index < 0) {
		result[0] = text;
	} else {
		result[0] = text.substring(0, index);
		result[1] = text.substring(index + 1);
	}
	return result;
}




// logging
var log = {
	enabled:      true,  // if true, logging is on
	initialized:  false, // if true, log is prepared to work
	messagesId:   "messages",
	messages:     null,
	messagesList: null,
	
	init: function(messagesId) {
		if (typeof messagesId != "undefined")
			log.messagesId = messagesId;
		log.messages = elm.get(log.messagesId);
		if (log.messages == null)
			return false; // init failed
		log.messagesList = document.createElement("ul");
		log.messages.appendChild(log.messagesList);
		log.initialized = true; // init succeded
		return true;
	},
	
	write: function(msgText, msgType) {
		var i;
		if ((typeof msgText == "undefined") && (msgText == null)) {
			msgText = "";
		}
		msgText = msgText.toString();
		if (!log.enabled) return true;
		if (log.messagesList == null) return false; // error - list not initialized properly
		var li = document.createElement("li");
		if ((typeof msgType != "undefined") && (msgType != null) && (msgType != "")) {
			cls.add(li, msgType);
		}
		var msgLines = msgText.split("\n");
		var br = null;
		var msg = null;
		for (i = 0; i < msgLines.length; i++) {
			msg = document.createTextNode(msgLines[i]);
			br = document.createElement("br")
			li.appendChild(msg);
			li.appendChild(br);
		}
		if (log.messagesList.firstChild)
			log.messagesList.insertBefore(li, log.messagesList.firstChild);
		else
			log.messagesList.appendChild(li);
		return true;
	},
	
	clear: function() {
		while (messagesList.firstChild) {
			messagesList.removeChild(messagesList.firstChild);
		}
		return true;
	}
}




// exception handling
var xcp = {
	warnings: false, // if true, warning messages are on
	errors:   true, // if true, error messages are on
	_log:     false, // true if log is on - private, do not change
	init: function() {
		if (log.initialized)
			xcp._log = true;
		return true;
	},
	
	warn: function(ex, location) { // non-critical exception handler
		if (xcp.warnings) {
			var result = "Warning"+"\n";
			result = "JavaScript exception: " + ex.name+"\n";
			result += "Warning message: " + ex.message + "\n";
			result += "Warning location: " + location + "\n";
			if (xcp._log)
				log.write(result, "warning");
		}
		return true;
	},
	
	err: function(ex, location) { // critical exception handler
		if(xcp.errors) {
			var result = "Error"+"\n";
			result += "JavaScript exception: " + ex.name+"\n";
			result += "Error message: " + ex.message + "\n";
			result += "Error location: " + location + "\n";
			if (xcp._log)
				log.write(result, "error");
		}
		return true;
	}
}




var browser = {
	// this object serves for browser detection purposes
	// may NOT use any JS library, because it is initialized before page load
	gecko: false,
	opera: false,
	ie:    false,
	ie5:   false,
	ie55:  false,
	ie6:   false,
	
	init: function() {
		var appName = navigator.appName.toLowerCase();
		
		if(appName.indexOf("netscape") > -1 && document.getElementById && document.childNodes && !document.all)
			browser.gecko = true;
		
		if(appName.indexOf("opera") > -1 && document.getElementById && document.childNodes)
			browser.opera = true;
		
 		if (appName.indexOf("explorer") > -1 && document.getElementById && document.childNodes && !document.addEventListener)
			browser.ie = true;
		
		if(!browser.ie && !browser.ns && document.addEventListener)
			browser.opera = true;
		
		var userAgent = navigator.userAgent.toLowerCase();
		
		if (browser.ie) {
			if (userAgent.indexOf("5.0") > -1) browser.ie50 = true;
			else if (userAgent.indexOf("5.5") > -1) browser.ie55 = true;
			else browser.ie6 = true;
		}
		return true;
	}
}
browser.init(); // init immediately




var cook = {
	// Cookie manager
	
	set: function(name, value, days) {
		// sets cookie
		var date; // Date
		var expires; // String
		if (typeof days != "undefined") {
			date = new Date();
			date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
			expires = "; expires=" + date.toGMTString();
		} else expires = "";
		document.cookie = name + "=" + value + expires + "; path=/";
		return true;
	},

	get: function(name) {
		// gets cookie value by name
		var i; // Int iterator
		var nameEQ = name + "="; // String
		var c; // String
		var ca = document.cookie.split(";"); // Array of Strings
		for (i = 0; i < ca.length; i++) {
			c = ca[i];
			while (c.charAt(0) == " ")
				c = c.substring(1, c.length);
			if (c.indexOf(nameEQ) == 0)
				return c.substring(nameEQ.length, c.length);
		}
		return null;
	},

	remove: function(name) {
		// unsets cookie
		saveCookie(name, "", -1);
	}
}





var variable = {
	
	isDefined: function(obj) {
		// checks if variable is defined
		if (typeof obj == "undefined") {
			return false;
		} else {
			return true;
		}
	},
	
	isSet: function(obj) {
		// checks if variable is defined
		if (!variable.isDefined(obj)) {
			return false;
		} else if (obj === null) {
			return false;
		} else {
			return true;
		}
	},
	
	getProps: function(obj, resultType) {
		if (typeof resultType == "undefined") {
			resultType = "array";
		}
		var result;
		switch (resultType) {
			case "array":
				result = new Array();
				for (propName in obj) {
					result[result.length] = propName;
				}
				break;
			case "csv":
				result = "";
				for (propName in obj) {
					result += propName + "; ";
				}
				break;
			case "csvdump":
				result = "";
				for (propName in obj) {
					if (typeof obj[propName] != "function") {
						result += propName + "=" + obj[propName] +"; ";
					}
				}
				break;
		}
		return result;
	},
	
	clone: function(obj, deep) {
		// clones object and returns it's copy.
		// shallow clone. TODO - create deep cloning method
		var objClone = {};
		var prop;
		for (prop in obj) {
			objClone[prop] = obj[prop];

		}
		return objClone;
	},
	
	getJsonString: function(obj) {
		// gets JSON string of given object
		// copyright: (c)2005 JSON.org
		// license: http://www.crockford.com/JSON/license.html
		
		var arr = [];
		
		function addStr(arr, str) {
			// emit a string
			arr[arr.length] = str;
			return arr;
		}
		
		function convertVal(obj) {
			// convert a value
			var c, i, l, v;
			
			switch (typeof obj) {
			case 'object':
				if (obj) {
					if (obj instanceof Array) {
						arr = addStr(arr, '[');
						l = arr.length;
						for (i = 0; i < obj.length; i += 1) {
							v = obj[i];
							if (typeof v != 'undefined' &&
									typeof v != 'function') {
								if (l < arr.length) {
									arr = addStr(arr, ',');
								}
								convertVal(v);
							}
						}
						arr = addStr(arr, ']');
						return;
					} else if (typeof obj.valueOf == 'function') {
						arr = addStr(arr, '{');
						l = arr.length;
						for (i in obj) {
							v = obj[i];
							if (typeof v != 'undefined' &&
									typeof v != 'function' &&
									(!v || typeof v != 'object' ||
										typeof v.valueOf == 'function')) {
								if (l < arr.length) {
									arr =addStr(arr, ',');
								}
								convertVal(i);
								arr = addStr(arr, ':');
								convertVal(v);
							}
						}
						arr = addStr(arr, '}');
						return arr;
					}
				}
				arr = addStr(arr, 'null');
				return;
			case 'number':
				arr = addStr(arr, isFinite(obj) ? +obj : 'null');
				return;
			case 'string':
				l = obj.length;
				arr = addStr(arr, '"');
				for (i = 0; i < l; i += 1) {
					c = obj.charAt(i);
					if (c >= ' ') {
						if (c == '\\' || c == '"') {
							arr = addStr(arr, '\\');
						}
						arr = addStr(arr, c);
					} else {
						switch (c) {
						case '\b':
							arr = addStr(arr, '\\b');
							break;
						case '\f':
							arr = addStr(arr, '\\f');
							break;
						case '\n':
							arr = addStr(arr, '\\n');
							break;
						case '\r':
							arr = addStr(arr, '\\r');
							break;
						case '\t':
							arr = addStr(arr, '\\t');
							break;
						default:
							c = c.charCodeAt();
							arr = addStr(arr, '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16));
						}
					}
				}
				arr = addStr(arr, '"');
				return;
			case 'boolean':
				arr = addStr(arr, String(obj));
				return;
			default:
				arr = addStr(arr, 'null');
				return;
			}
		}
		convertVal(obj);
		return arr.join('');
	},
	
	parseJsonString: function(jsonString) {
		// parses JSON string. If illegal, throws exception
		// copyright: (c)2005 JSON.org
		// license: http://www.crockford.com/JSON/license.html
		return !(/[^,:{}[]0-9.-+Eaeflnr-u \n\r\t]/.test(jsonString.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + jsonString + ')');
	}
}




var actions = {
	goBack: {
		cls: "goBack",
		
		onClick: function(e) {
			history.go(-1);
			evt.cancel(e);
			return true;
		}
	},
	
	popupWindow: {
		cls:        "popupWindow",
		widthAttr:  "popupWidth", // custom attribute name
		heightAttr: "popupHeight", // custom attribute name
		
		onClick: function(e) {
			var obj = evt.getTrigger(e);
			while (!cls.has(obj, actions.popupWindow.cls)) {
				obj = obj.parentNode;
			}
			if (obj == null) return false;
			var scrollBarWidth = 18; // guess...
			var winWidth = obj.getAttribute(actions.popupWindow.widthAttr);
			var winHeight = obj.getAttribute(actions.popupWindow.heightAttr);
			var winUrl = obj.getAttribute("href");
			var paramStr = (winWidth ? "width=" + (parseInt(winWidth) + scrollBarWidth) + ", " : "") + (winHeight ? "height=" + (parseInt(winHeight) + scrollBarWidth) + ", " : "") + " menubar=0, resizable=1, status=0";
			var popupWin = window.open(crUrl, "_blank", paramStr);
			evt.cancel(e);
			return true;
		}
	},
	
	openUrl: {
		cls:        "openUrl",
		selectCls:  "openSelectedUrl", // class when url is select's option value
		sourceAttr: "openUrlSource", // custom attribute, specifies target input field
		
		onClick: function(e) {
			var obj = evt.getTrigger(e);
			var source = obj.getAttribute(actions.openUrl.sourceAttr);
			var url = "";
			if ((source != null) && (source != "")) {
				var sourceInput = elm.get(source);
				if ((sourceInput.tagName.toLowerCase() == "select") && cls.has(sourceInput, actions.openUrl.selectCls)) {
					url = sourceInput.options[sourceInput.selectedIndex].text;
				} else { // normal input
					url = elm.getValue(sourceInput); 
				}
			}
			if ((url != null) && (url != "") && (elm.getValue(sourceInput) != "-1"))
				var popupWin = window.open(url, "_blank");
			evt.cancel(e);
			return true;
		}
	},
	
	openMail: {
		cls:           "openMail",
		selectCls:     "openSelectedMail",
		recipientAttr: "openMailSource", // custom attribute, specifies source input field
		
		onClick: function(e) {
			var obj = evt.getTrigger(e);
			var source = obj.getAttribute(actions.openMail.recipientAttr);
			if ((source != null) && (source != "")) {
				var sourceInput = elm.get(source);

				if ((sourceInput.tagName.toLowerCase() == "select") && cls.has(sourceInput, actions.openMail.selectCls)) {
					url = sourceInput.options[sourceInput.selectedIndex].text;
				} else { // normal input
					url = elm.getValue(sourceInput); 
				}
			}
			if ((url != null) && (url != "") && (url != "-1"))
				window.location = "mailto:" + url;
			evt.cancel(e);
			return true;
		}
	}
}






// legacy functions
// deprecated, don't use

var replaceByImage = function(obj, src, alt) {
	// replaces object content by image
	obj.innerHTML = "<img src=\""+src+"\" alt=\""+alt+"\" />";
	return true;
}

function setTarget(link) {
	if (link.href) {
		var domain = document.location.host;
		// Obsahuje-li domain port, odstranime ho
		if (domain) domain = (domain.indexOf(":")>-1)? domain.substr(0,domain.indexOf(":")): domain;
		var host = link.host;
		// Obsahuje-li host port, odstranime ho
		if(host) host = (host.indexOf(":")>-1)? host.substr(0,host.indexOf(":")): host;
		var protocol = link.protocol;
		if ((host != domain) && (host != ("www."+domain) && ("www."+host) != domain)&&((protocol == "http:") || (protocol == "https:") || (protocol == "ftp:"))) {
			// jestlize se domena dokumentu a odkazu neshoduji, otevirani nastavime do noveho okna
			link.target="_blank";
//			if (!cls.has(link,"noIcon")) addIcon(link,newWindowIcon,"after");
		}
		return true;
	}
	else return false;
}

function addContent(item, contentString, position) {
/*
	try {
		var cnt = document.createTextNode(contentString);
		if (position == "before") item.insertBefore(cnt.cloneNode(true), item.firstChild);
		else item.appendChild(cnt.cloneNode(true));
		return true;
	} catch (ex) {
		alert("addContent error "+ex);
		return false;
	}
*/
}

function addIcon(item, iconImage, position, iconTitle) {
	space = document.createTextNode(nbsp)
	icon = document.createElement("img");
	icon.src = iconImage;
	icon.alt = "*";
	if (typeof iconTitle != "undefined") {
		icon.title = iconTitle;
		icon.alt = iconTitle;
	};
	icon.className = "icon";
	if (position == "before") {
		item.insertBefore(space, item.firstChild);
		item.insertBefore(icon, item.firstChild);
	} else {
		item.appendChild(space);
		item.appendChild(icon);
	};
	return true;
}

function openImageWindow(e){
	link = evt.getTarget(e);
	while (link.tagName.toLowerCase()!="a") {
		link = link.parentNode;
	}
	link.target = "_blank";
}

function getChildrenByTag(tagName, srcElm) {
	try{
		return elm.getChildrenByTag(tagName, srcElm);
	} catch(ex) {alert("getChildrenByTag error ("+ex.name+"): "+ex.message);return(false);}
}

function winH() { // by pixy, http://www.pixy.cz/blogg/clanky/js-rozmery-okna.html
	if (window.innerHeight) // NN4, Opera, Mozilla
		return window.innerHeight;
	else if(document.documentElement && document.documentElement.clientHeight) // MSIE6 std. mode
		return document.documentElement.clientHeight;
	else if(document.body && document.body.clientHeight) // older MSIE + MSIE6 in quirk mode
		return document.body.clientHeight;
	else return null;
}

function winW() { // by pixy, http://www.pixy.cz/blogg/clanky/js-rozmery-okna.html
	if (window.innerWidth) // NN4, Opera, Mozilla
		return window.innerWidth;
	else if(document.documentElement && document.documentElement.clientWidth) // MSIE6 std. mode
		return document.documentElement.clientWidth;
	else if(document.body && document.body.clientWidth) // older MSIE + MSIE6 in quirk mode
		return document.body.clientWidth;
	else return null;
}
