/**
* Filename................: mel.js
* Project.................: web pages SDK
* Last Modified...........: $Date: 24/05/2011 15:15:12 $
* CVS Revision............: $Revision: 0.0.51 $
* Idea and Developed by...: Maxim Bulygin (sailormax@gmail.com)
*/

if (typeof MEL != "object") var MEL = {};

// aliases
	MEL.d = document;
	MEL.de = MEL.d.documentElement;
	MEL.ds = MEL.d.selection;
	MEL.dc = MEL.d.cookie;		// TODO: remove. This is no the link :(
	MEL.w = window;

	MEL.d.getEl = MEL.d.getElementById;
	MEL.d.getEls = MEL.d.getElementsByName;
	MEL.d.getTags = MEL.d.getElementsByTagName;
//
	MEL.now = new Date();
	MEL.trace_only_local_errors = true;

// browser name and version
	var ua = MEL.ua = {
		str:		navigator.userAgent,
		name:		"",
		ver:		"",
		other:		true,
		is_crawler:	(null != navigator.userAgent.match(/(Yahoo!|Crawler|Google|MSNBot|Slurp|Teoma|Gigabot|Scrubby|Robozilla|BecomeBot|Nutch|Yandex|Rambler|Aport|Spider|MJ12bot|KalamBot|genieBot|Latnet-search-engine|Letonika.lv|ia_archiver|findlinks|Mail.Ru|Snapbot|PycURL|psbot|larbin|Exabot|libwww-perl|Jakarta|voyager|MSRBOT|Jyxobot|Scooter|accelobot|yetibot|Yeti\/|heritrix|eBolot)/i)),
		browser_name:	"",
		browser_ver:	""
	}
//

// small init
	new function()
	{
		// detect browser (without check on crawler, because user agent can has crawler words)
		var i, j, tmp, tmp2, item;
		//			name, alias, alternative mask for version, alternative names
		var uas = [["opera", "", "Version.([0-9\.]+)",		["Opera Mini", "Opera"]],
					["safari", "", "",						["Chrome", "Safari"]],
					["konqueror", "konq", "",				["Konqueror"]],
					["msie", "ie", "",						["MSIE"]],
					["mozilla", "", "rv.([0-9\.]+)",		["Firefox", "Mozilla"]]];
		for (i in uas)
		{
			item = uas[i];
			if (tmp = ua.str.match(new RegExp(item[0]+".([0-9\.]+)", 'i')))
			{
				if (item[2] && (tmp2 = ua.str.match(new RegExp(item[2], 'i')))) tmp = tmp2;

				ua.browser_name	= ua.name = item[1] || item[0];
				ua.ver = parseFloat(tmp[1])
				ua.browser_ver	= tmp[1];
				ua[ua.name] = ua.ver;
				ua.other = false;

				if (item[3])
					for (j in item[3])
						if (((ua.name == item[3][j].toLowerCase()) && (tmp = ua.str.match(new RegExp("Version.([0-9\.]+)", 'i'))))
							|| (tmp = ua.str.match(new RegExp(item[3][j]+".([0-9\.]+)", 'i'))))
						{
							ua.browser_name = item[3][j];
							ua.browser_ver = tmp[1];
							break;
						}
				break;
			}
//			else
//				ua[item[1] || item[0]] = false;
		}

		if (ua.safari) ua.iPad = (ua.str.indexOf("iPad;") > 0);
//		alert( [ua.safari, ua.name, ua.ver, ua.browser_name, ua.browser_ver].join("\n") );
		//

		// error handler
			MEL.last_js_error = "";
			document.cookie = "mel_js_errors=;expires=Thu, 01-Jan-70 00:00:01 GMT;path=/"; 
			window.onerror = function(msg, url, line)
			{
				if (!msg || msg.type) return true;								// Events do not has message
				if ((msg == "Script error.") && !url && !line) return true;		// Useless error
				var str_js_error = msg+"\nin "+url+" at "+line;
				if (MEL.last_js_error == str_js_error) return true;	// Repeatable error

				var dl = document.location;
				if (MEL.trace_only_local_errors && (url != ""))
				{
					var our_domain = "", err_domain = "";
					if (dl.href.search(/^[^\/]+\/\/([^\/]+)/) == 0) our_domain = RegExp.$1;
					if (url.search(/^[^\/]+\/\/([^\/]+)/) == 0) err_domain = RegExp.$1;
					if (our_domain != err_domain)
					{
						if ((typeof console == "object") && console.log) console.log(msg+"\nin "+url+" at "+line);
						return true;		// ignore errors of not our scripts
					}
				}

				MEL.last_js_error = str_js_error;
				if (url == dl.href)
					url = dl.pathname + dl.search;
				else
					url += " ("+dl.pathname + dl.search+")";

				var prev_stored_error = (
						(document.cookie.search(/(^|[; ])mel_js_errors=([^;]*)/) >= 0)
						? RegExp.$2 + escape("\n\n")
						: escape(ua.browser_name + " " + ua.browser_ver + "\n")
					);

				document.cookie = "mel_js_errors=" + prev_stored_error + escape(msg+"\nin "+url+" at "+line) + ";path=/";
				if ((typeof console == "object") && console.log) console.log(msg+"\nin "+url+" at "+line);
				return true;
			}
		//

		// detect timeshift + daylight time
//		var locale_date = new Date(2010, 8, 7, 19, 6, 5);
		var locale_date = new Date(2010, 4, 13, 19, 6, 5);
		var locale_str = locale_date.toLocaleString();
		var re_time = /[0-9]{1,2}:[0-9]{1,2}/;
		var delim_pos = locale_str.search(re_time);
		// time
			var time_mask = "";
			var hour = locale_str.substr(delim_pos).split(':', 2)[0];
			if (hour == "19")
			{
				var tmp_date = locale_date;
				tmp_date.setHours(7);
				hour = tmp_date.toLocaleString().substr(delim_pos).split(':', 2)[0];
				time_mask += (hour == "7" ? 'H:mm' : "HH:mm");
			}
			else
				time_mask += (hour == "7" ? 'h:mm' : "hh:mm");
		//

		// date
			var item, words = [];
			var short_weekday = false;
			var date_mask = locale_str.substr(0, delim_pos);
			var re_word = /[^,\.\- 0-9][^,\.\-0-9]+/g;
			while ((item = re_word.exec(date_mask)) != null) words.push(item);

			// remove week day
				var shift = 0;
				while (words.length > 1)
				{
					item = words.shift();
					item[0] = item[0].replace(/[ ,\.\-]+$/, "");
					if ((item.index > 0) && (!isNaN(parseInt(date_mask.substr(shift+item.index-1, 1)))))	// japan dates
					{
						date_mask = date_mask.substring(0, shift+item.index) + "/" + date_mask.substr(shift+item.index+item[0].length);
						shift -= item[0].length-1;
					}
					else
					{
						short_weekday = (item[0].length <= 3);
						date_mask = date_mask.substring(0, shift+item.index) + date_mask.substr(shift+item.index+item[0].length+1);
						shift -= item[0].length+1;
					}
				}
			//

			if (words.length)
			{
				if (!isNaN(parseInt(date_mask.substr(shift+words[0].index-1, 1))))	// japan dates
					date_mask = date_mask.substring(0, shift+words[0].index) + date_mask.substr(shift+words[0].index+words[0][0].length);
				else
					date_mask = date_mask.replace(words[0][0].replace(/[ ,\.\-]+$/, ""), (short_weekday ? "MMM" : "MMMM"));
			}

			date_mask = date_mask.replace(/([0-9]+)/g, function(num)
				{
					inum = num-0;
					if (num == locale_date.getFullYear())
						return "yyyy";
					else if (num == (locale_date.getFullYear()+"").substr(-2))
						return "yy";
					else if (inum == (locale_date.getMonth()+1))
						return (num.length > 1 ? "MM" : "M");
					else if (inum == locale_date.getDate())
						return (num.length > 1 ? "dd" : "d");
					return "";
				});
		//
		date_mask = date_mask.replace(/^[ ,.-]+/, "").replace(/[ ,.-]+$/, "");

		if (/[^dMy ,\.\-]/.test(date_mask))	// exception
			date_mask = "d.MM.yyyy";

		var exp = new Date();
		exp.setFullYear(MEL.now.getFullYear()+10);
		document.cookie = "MEL_UTC=" + escape(-MEL.now.getTimezoneOffset()) + ";expires="+exp.toGMTString()+";path=/";
		var winter = new Date(MEL.now.getFullYear(), 1, 1);
		var summer = new Date(MEL.now.getFullYear(), 6, 1);
//		if (winter.getTimezoneOffset() != summer.getTimezoneOffset())
		{
			document.cookie = "MEL_DST=" + escape((MEL.now.getTimezoneOffset()!=winter.getTimezoneOffset())-0) + ";expires="+exp.toGMTString()+";path=/";
			document.cookie = "MEL_DTS=" + escape(-(summer.getTimezoneOffset()-winter.getTimezoneOffset())) + ";expires="+exp.toGMTString()+";path=/";
		}
/*
		else
		{
			document.cookie = "MEL_DST=;expires="+exp.toGMTString()+";path=/";		// Daylight saving time
			document.cookie = "MEL_DTS=0;expires="+exp.toGMTString()+";path=/";		// Daylight time shift
		}
*/
		document.cookie = "MEL_DATE_FORMAT=" + escape(date_mask) + ";expires="+exp.toGMTString()+";path=/";
		document.cookie = "MEL_TIME_FORMAT=" + escape(time_mask) + ";expires="+exp.toGMTString()+";path=/";
	}();
//

// cross browser debug
/*
	if (opera && !console)
		var console = { log: opera.postError };
	else if (console && !opera)
		var opera = { postError: console.log };
	else if (!console)
	{
		var console = { }, opera = { };
		console.log = opera.postError = function(str)
		{
			var el = MEL.d.createElement("DIV");
			el.className = "debug";
			el.style.zIndex = 1000;
			el.style.position = "relative";
			el.style.backgroundColor = "white";
			el.innerHTML = str;
			MEL.d.body.appendChild(el);
		}
	}
*/
//

// URL
	MEL.url = MEL.d.location;
	MEL.url.URI = MEL.url.href.replace(/#.*$/, ""),
	MEL.url.anchors_arr = [],
	MEL.url.anchors_of = "";
	MEL.url.getAnchors = function()
	{
		if (this.anchors_of != this.href)
		{
			var str = this.href.replace("##", "#");
			this.anchors_arr = str.search(/#.+/) > 0 ? str.replace(/^[^#]+#?/, "").split("#") : [];
		}
		return this.anchors_arr;
	}
	MEL.url.appendAnchor = function(name)
	{
		if (MEL.inArray(name, this.getAnchors()) < 0)
			this.replace(MEL.url.URI + "#" + this.getAnchors().concat([name]).join("#"));
	}
	MEL.url.removeAnchor = function(name)
	{
		var i = MEL.inArray(name, this.getAnchors());
		if (i >= 0)
		{
			var new_list = this.getAnchors();
			new_list.splice(i, 1);
			this.replace(MEL.url.URI + "#" + new_list.join("#"));	// keep empty "#" for deny reloading
		}
	}
//

// DOM functions
	MEL.dom = {

		getStyle: function(el, name)
		{
			if (name)
			{
				if (MEL.d.defaultView && MEL.d.defaultView.getComputedStyle)
					return MEL.d.defaultView.getComputedStyle(el, "").getPropertyValue(name);
				else if (el.currentStyle)
				{
					name = name.replace(/-(\w)/g, function(){ return arguments[1].toUpperCase(); });
					return el.currentStyle[name];
				}
			}
			else
			{
				var style;
				if (el.style.getAttribute)
					style = el.style.getAttribute("cssText");
				else
					style = el.getAttribute("style");

				if (style)
					return style;
			}
			return "";
		},


		setStyle: function(el, name, value)
		{
			if (typeof value == "undefined")
			{
				if (el.style.setAttribute)
					el.style.setAttribute("cssText", name);
				else
					el.setAttribute("style", name);
			}
			else if (name.indexOf("-") > 0)
				el.style[ name.replace(/-(\w)/g, function(){ return arguments[1].toUpperCase(); }) ] = value;
			else
				el.style[ name ] = value;
		},


		hasClass: function(el, name)
		{
			if (el["classList"]) return el.classList.contains(name);
			return ((" "+el.className+" ").search(" "+name+" ") > -1);
		},

		appendClass: function(el, name)
		{
			if (el["classList"]) return el.classList.add(name);
			if ((" "+el.className+" ").search(" "+name+" ") < 0)
				el.className += " " + name;
		},

		removeClass: function(el, name)
		{
			if (el["classList"]) return el.classList.remove(name);
			el.className = (" "+el.className+" ").replace(" "+name+" ", " ").replace(/^ +/, "").replace(/ +$/, "").replace(/ +/, " ");
		},

		replaceClass: function(el, name, new_name)
		{
			el.className = (" "+el.className+" ").replace(" "+name+" ", " "+new_name+" ").replace(/^ +/, "").replace(/ +$/, "");
		},


		setAttribute: function(el, name, val)
		{
			if (val-0 == val) val -= 0;
			var items = name.split('.');
			if (items.length == 1)
			{
				if (el.setAttribute)
					el.setAttribute(name, val);
				else
					el[name] = val;
			}
			else
			{
				if (items[0] == "filter") items[0] = "filters";
				if (items[0] == "filters" && el.filters)
				{
					if (!el[items[0]][items[1]])
					{
						var filter = " " + items[1] + "(" + items[2] + "=" + val + ")";
						var re = new RegExp(" " + items[1] + "\\(" + items[2] + "=([^\\)]+)\\)", "i");
						if (el.style.filter.search(re) >= 0)
							el.style.filter = el.style.filter.replace(re, filter);
						else
							el.style.filter += filter;
					}

					if (/^filters?\.alpha\.opacity$/.test(name.toLowerCase()))
					{
						if (el.filters.alpha)
							el.filters.alpha.enabled = (val >= 100 ? "false" : "true");
						if (val >= 100)
						{
//							el.style.filter = el.style.filter.replace(/ alpha\([^\)]+\)/, "");
						}
					}
				}

				var i = 0;
				while (el[items[i]] && (i < (items.length-1)))
					el = el[items[i++]];
				if (i == (items.length-1))
					el[items[i]] = val;
			}
		},


		getSelectedText: function()
		{
			return window.getSelection ? window.getSelection().toString() : MEL.ds.createRange().text;
		},


		getAbsolutePos: function(el, regarding_element)
		{
			var pnt = {x:0, y:0, ox:0, oy:0, oxoyParent:null};
			var start_el = el;
			var next_el, prev_el, deep = 0;
			while (el)
			{
				if (regarding_element == el) return pnt;

				pnt.x += el.offsetLeft;
				pnt.y += el.offsetTop;
				prev_el = el;

				// minus all scrolls
				next_el = el.offsetParent;
				if (!next_el && (el.tagName != "BODY") && MEL.ua.safari)	// Safari fix
				{
					pnt.x += window.scrollX;
					pnt.y += window.scrollY;
				}
				if (next_el)
				{
					while ((el = el.parentNode) && (el != next_el))
					{
						pnt.x -= el.pageXOffset || el.scrollLeft;
						pnt.y -= el.pageYOffset || el.scrollTop;
					}
				}
				else
					el = null;

				if (!pnt.oxoyParent)
				{
					var is_rel = (MEL.inArray(this.getStyle(prev_el, "position"), ["fixed", "relative", "absolute"]) >= 0);

					// stop offer coords, if we have not static element
					if (deep && is_rel)
						pnt.oxoyParent = prev_el;
					else
					{
						pnt.ox = pnt.x;
						pnt.oy = pnt.y;
					}

					if (is_rel && !next_el && (MEL.ua.ie == 8))			// ie8 fix
					{
						el = prev_el.parentNode;
						while (el)
						{
							if (MEL.inArray(this.getStyle(el, "position"), ["fixed", "relative", "absolute"]) >= 0)
							{
								pnt.x += el.offsetLeft;
								pnt.y += el.offsetTop;
							}
							el = el.parentNode;
						}
					}
//					else if (is_rel && !next_el && (MEL.ua.opera >= 9.8))			// opera 10 beta fix
//					{
//						pnt.y -= MEL.d.getTags("html")[0].scrollTop;
//					}
//					else if (is_rel && !next_el && MEL.ua.safari)			// safari and chrome
//					{
//						pnt.y += MEL.d.getTags("body")[0].scrollTop;
//					}
				}
				deep++;
			}

			if (this.getStyle(pnt.oxoyParent||start_el, "position") == "fixed")
			{
				pnt.x += MEL.de.scrollLeft;
				pnt.y += MEL.de.scrollTop;
			}

			return pnt;
		},


		getElementSize: function(el, with_borders, content_size)
		{
			if (!el) return [];
			var wnd = ((el.tagName == "BODY") || (el == MEL.w) ? MEL.w : null);
			var de = MEL.de;

			var res = {
				sw: el.scrollWidth,
				sh: el.scrollHeight,	// + (wnd ? wnd.scrollMaxY || 0 : 0)
				sx: -1, sy: -1,
				w: -1, h: -1
			};

			if (el.tagName == "SCRIPT" || el.tagName == "STYLE")
				return { sw:0, sh:0, sx:0, sy:0, w:0, h:0 };

			if (wnd)
			{
				if (de && de.clientHeight)
				{
					res.w = de.clientWidth;		res.h = de.clientHeight;
					res.sx = de.scrollLeft || self.pageXOffset || el.scrollLeft || 0;
					res.sy = de.scrollTop || self.pageYOffset || el.scrollTop || 0;
				}
				else if (self.innerHeight)									// IE6 (Strict)
				{
					res.w = self.innerWidth;	res.h = self.innerHeight;
					res.sx = self.pageXOffset;	res.sy = self.pageYOffset;
				}

				// scrollHeight problem with windows, where BODY.height = 100%...
				// how it detect???
//				if ((window != parent))	// if iframe, fix bug of Firefox, Opera or... web standart ;)
				{
					res.sh = 0;
					var i, size, root_childs = wnd.document.body.childNodes;
					for (i=0; i<root_childs.length; i++) if (root_childs[i].tagName)
						res.sh += this.getElementSize(root_childs[i]).h;
				}

			}
			if (res.h < 0)
			{
				if (MEL.ua.safari)
				{
					res.w = el.offsetWidth;
					res.h = el.offsetHeight;
				}
				else
				{
					if (with_borders === false)
					{
						res.w = el.clientWidth || el.offsetWidth || 0;
						res.h = el.clientHeight || el.offsetHeight || 0;
					}
					else

					{
						res.w = el.offsetWidth || el.clientWidth || 0;
						res.h = el.offsetHeight || el.clientHeight || 0;
					}
				}
				res.sx = el.scrollLeft;		res.sy = el.scrollTop;
			}

			if (res.sw < res.w) res.sw = res.w;
			if (res.sh < res.h) res.sh = res.h;
//			if (wnd && (window != parent)) res.sh = res.h;

			if (content_size && (el.tagName != "TEXTAREA") && (el.tagName != "INPUT"))	// input fields already return content size
			{
				res.w -= (parseInt(MEL.dom.getStyle(el, "padding-left")) + parseInt(MEL.dom.getStyle(el, "padding-right")));
				res.h -= (parseInt(MEL.dom.getStyle(el, "padding-top")) + parseInt(MEL.dom.getStyle(el, "padding-bottom")));
			}

			return res;
		},

		getOpenedTags: function(node)
		{
			var tags = [];
			while (node)
			{
				tags.push(node);
				var node = node.parentNode;
			}
			return tags;
		},
		
		insertRow2Table: function(tbl, row, idx, cp_attrs)
		{
			var i, nr = tbl.insertRow(idx);
			nr.className = row.className;
			this.setStyle(nr, this.getStyle(row));
			if (typeof cp_attrs == "undefined" || cp_attrs)		// IE very strange copy attrs of TR and other tags...
				MEL.copyElAttrs(nr, row);
			var cln, arr = row.childNodes;
			for (i=0; i<arr.length; i++)
				nr.appendChild(arr[i].cloneNode(true));
			return nr;
		},

		getInnerText: function(el)
		{
			var res = "";
			var childs = el.childNodes;
			var i, cnt = childs.length;
			for (i=0; i<cnt; i++) if (childs[i].nodeValue) res += childs[i].nodeValue;
			return res;
		}
	}
//


// MEL events
	MEL.event = {

		__onmouseinout: [],

		addListener: function(el, evtType, func)
		{
			if (el.addEventListener)
				el.addEventListener(evtType, func, false);
			else if (el.attachEvent)
				return el.attachEvent("on"+evtType, func);
			else
				return false;
			return true;
		},


		removeListener: function(el, evtType, func)
		{
			if (el.removeEventListener)
				el.removeEventListener(evtType, func, false);
			else if (el.detachEvent)
				return el.detachEvent("on"+evtType, func);
			else
				return false;
			return true;
		},


		addMouseInOut: function(obj, over, out)
		{
			var i, list = this.__onmouseinout;
			for (i in list) if (list[i] && (list[i][0] === obj)) return;
			if (!list.length)
			{
				this.addListener(MEL.d, "mouseout", this.__hMouseInOut);
				this.addListener(MEL.d, "mouseover", this.__hMouseInOut);
			}
			for (i in list) if (list[i] === null)
			{
				list[i] = [obj, true, out, over];
				return;
			}
			list.push([obj, true, out, over]);
		},

		hasMouseInOut: function(obj)
		{
			var i, list = this.__onmouseinout;
			for (i in list) if (list[i] && (list[i][0] === obj)) return true;
			return false;
		},

		removeMouseInOut: function(obj)
		{
			var i, list = this.__onmouseinout;
			for (i in list) if (list[i] && (list[i][0] === obj)) { list[i] = null; return; }
		},


		__hMouseInOut: function(e)
		{
			e = e || event;
			var i, j, pos, size, out, objs, list = MEL.event.__onmouseinout;
			var sx = e.clientX + (MEL.de.scrollLeft || window.pageXOffset);
			var sy = e.clientY + (MEL.de.scrollTop || window.pageYOffset);
			for (i in list) if (list[i])
			{
				out = true;
				objs = (list[i][0].concat ? list[i][0] : [list[i][0]]);
				for (j in objs)
				{
					pos = MEL.dom.getAbsolutePos(objs[j]);
					size = MEL.dom.getElementSize(objs[j]);
					out &= ((sx < pos.x) || (sy < pos.y) || (sx > pos.x+size.sw) || (sy > pos.y+size.sh));
				}
				if (out == list[i][1])
				{
					MEL.exec(list[i][(out ? 2 : 3)], list[i][0], e);
					if (list[i]) list[i][1] = out;
				}
			}
		},


		cancel: function(e)
		{
			if (e.stopPropagation) e.stopPropagation();
			if (e.preventDefault) e.preventDefault();
			e.cancelBubble = true;
			e.returnValue = false;
			return false;
		}
	}
/*
	MEL.event.addListener(window, "error", function(err, url, line)
	{
		if (typeof MEL.errorHandler == "function")
			MEL.errorHandler(err, url, line);
		else if (typeof MEL.errorHandler == "string")
			console.log(err, url, line);	// TODO: send to url error
	});
*/
//

// selection functions
MEL.selection = {

	setSelectedText: function(el, start, end)
	{
		if (el.setSelectionRange)
			el.setSelectionRange(start, end);
		else if (el.createTextRange)
		{
			var rng = el.createTextRange();
			rng.collapse(true);
			rng.moveEnd("character", end);
			rng.moveStart("character", start);
			rng.select();
		}
	},

	
	getStartSelection: function(el)
	{
		if (el.setSelectionRange)
		{
			return el.selectionStart;
		}
		else if (MEL.ds.createRange)
		{
			var rng = MEL.ds.createRange();
			if (rng.parentElement() != el)
				return -1;

			var rng2 = rng.duplicate();
			if (el.tagName == "TEXTAREA")
				rng2.moveToElementText(el)
			else
				rng2.expand("textedit");
			rng2.setEndPoint("EndToStart", rng);
			var pos = rng2.text.length;
			if (MEL.ua.ie && (el.value.substr(pos, 2) == "\r\n")) pos += 2;	// ie bug fix
			if (pos > el.value.length)
				return -1;
			return pos;
		}
		else
			return el.value.length;
	},


	getCaretPosition: function(el)
	{
		return this.getStartSelection(el);
	},


	setCaretPosition: function(el, pos)
	{
		this.setSelectedText(el, pos, pos);
	},


	getEndSelection: function(el)
	{
		if (el.setSelectionRange)
		{
			return el.selectionEnd;
		}
		else if (MEL.ds.createRange)
		{
			var rng = MEL.ds.createRange();
			if (rng.parentElement() != el)
				return -1;

			var rng2 = rng.duplicate();
			if (el.tagName == "TEXTAREA")
				rng2.moveToElementText(el)
			else
				rng2.expand("textedit");

			rng2.setEndPoint("EndToEnd", rng);
			var pos = rng2.text.length;
			if (MEL.ua.ie && (el.value.substr(pos, 2) == "\r\n")) pos += 2;	// ie bug fix
			if (pos > el.value.length)
				return -1;
			return pos;
		}
		else
			return el.value.length;
	},

	getParentElement: function(oWnd)
	{
		var sel, range;
		if (oWnd.getSelection)
			sel = oWnd.getSelection();
		else
			sel = oWnd.document.selection;

		if (sel.getRangeAt)
			range = sel.getRangeAt(0);
		else if (sel.createRange)
			range = sel.createRange();
		else
			range = sel;

		if (sel.type)
		{
			switch (sel.type)
			{
				case "Text":
				case "None":
					return range.parentElement();
				case "Control":
					return range.item(0);
				default:
					return oWnd.document.body;
			}
		}
		else
			try
			{
				var p = range.commonAncestorContainer;
				if (!range.collapsed && range.startContainer == range.endContainer
					&& range.startOffset - range.endOffset <= 1 && range.startContainer.hasChildNodes()
					)
					p = range.startContainer.childNodes[range.startOffset];

				while (p.nodeType == 3)
					p = p.parentNode;
				return p;
			}
			catch (e)
			{
				return null;
			}
	},

	getOpenedTags: function(node)
	{
		var tags = [];
		while (node)
		{
			tags.push(node);
			var node = node.parentNode;
		}
		return tags;
	}

}
//

// date functions
	MEL.date = {

		getFormatted: function(dt, tpl)
		{
			tpl = tpl.replace(/j/, dt.getDate());
			tpl = tpl.replace(/d/, (dt.getDate() < 10 ? "0" : "") + dt.getDate());
			tpl = tpl.replace(/m/, (dt.getMonth() < 9 ? "0" : "") + (dt.getMonth()+1));
			tpl = tpl.replace(/y/, dt.getYear());
			tpl = tpl.replace(/Y/, dt.getFullYear());

			tpl = tpl.replace(/s/, (dt.getSeconds() < 10 ? "0" : "") + dt.getSeconds());
			tpl = tpl.replace(/i/, (dt.getMinutes() < 10 ? "0" : "") + dt.getMinutes());
			tpl = tpl.replace(/H/, (dt.getHours() < 10 ? "0" : "") + dt.getHours());
			return tpl;
		},

		getWeekNumber: function(dt, europe)
		{
			var newYear = new Date(dt.getFullYear(), 0, 1);
			var correction = 1;
			var time = dt.getTime();
			if (europeanMode)
			{
				time -= (((dt.getDay() + 13) % 7) * 86400000);	// shift days and minus week day number
				var day = newYear.getDay();
				if (day==0 || day==5 || day==6) correction = 0;
			}
			else
				time -= ((dt.getDay()) * 86400000);	// minus week day number

			var weeknumber = Math.ceil((time - newYear.getTime()) / (7*86400000)) + correction;
			return (weeknumber ? weeknumber : arguments.callee(new Date(dt.getFullYear(), -1, 31)));
		},

		getUTC: function(dt)
		{
			if (!dt) dt = new Date();
			return new Date(dt-dt.getTimezoneOffset()*60000);
		}
	}
//


// timer functions
	MEL.timer = {

		in_use: [],

		__cb: function(i)
		{
			if (MEL.timer.in_use[i][1])
				MEL.timer.in_use[i][1][MEL.timer.in_use[i][2]]();
			else
				MEL.timer.in_use[i][2]();
		},


		setTimer: function(interval, obj, func_name, msec)
		{
			var i = -1; while (this.in_use[++i]);
			var fb = new Function("MEL.timer.__cb(" + i + ")");
			this.in_use[i] = [null, obj, func_name, interval];
			this.in_use[i][0] = ( interval ? window.setInterval(fb, msec) : window.setTimeout(fb, msec) );
			return this.in_use[i][0];
		},


		clearTimer: function(timer)
		{
			for (var i=0; i<this.in_use.length; i++)
				if (this.in_use[i] && (this.in_use[i][0] == timer))
				{
					if (this.in_use[i][3])
						window.clearInterval(timer);
					else
						window.clearTimeout(timer);
					this.in_use[i] = null;
					return;
				}
		},


		setTimeout: function(obj, func_name, msec)
		{
			return this.setTimer(false, obj, func_name, msec);
		},

		setInterval: function(obj, func_name, msec)
		{
			return this.setTimer(true, obj, func_name, msec);
		}
	}
	MEL.timer.clearTimeout = MEL.timer.clearTimer;
	MEL.timer.clearInterval = MEL.timer.clearTimer;
//


// Popup functions
	MEL.popup = {

		cfg: {
			X: false,
			Y: false,
			MOVE2CENTER: true,
			ANIMATE: false,
			WIDTH: "320px",
			HEIGHT: "200px",
			Z_INDEX: 11000,
			PARENT: null,

			BACKGROUND: "#000",
			OPACITY: 0.5,
			FIXED: true,
			DRAGDROP: true,
			MODAL: true,
			SCROLLING: "auto",
			BOX: null,				// container for dialog and background

			CLOSE: "X"
		},

		show: function(div, cfg, funcInit, funcParams)
		{
			var i, tmp, url;

			if (cfg && (cfg != null))
			{
				for (i in this.cfg)
					if (typeof cfg[i] == "undefined") cfg[i] = this.cfg[i];
			}
			else
				cfg = this.cfg;
			if (!cfg.PARENT) cfg.PARENT = MEL.d.body;
			if (cfg.FIXED && MEL.ua.ie) cfg.FIXED = false;


			if (div && (typeof div != "object"))
			{
				if (div.search && (div.search(/:\/\//) > 0))
				{
					url = div;
					div = MEL.d.createElement("DIV");
					MEL.dom.setStyle(div, "width:" + cfg.WIDTH + "; background-color:white; border:1px solid gray; padding:3px;");

					tmp = MEL.d.createElement("P");
					MEL.dom.setStyle(tmp, "float:right; font-color:red; font-size:12px; margin:3px; height:12px; cursor:pointer;");
					tmp.appendChild(MEL.d.createTextNode(cfg.CLOSE));
					tmp.onclick = MEL.popup.close;
					div.appendChild(tmp);

					tmp = MEL.d.createElement("IFRAME");
					MEL.dom.setStyle(tmp, "clear:both; width:" + cfg.WIDTH + "; height:" + (parseInt(cfg.HEIGHT)-12) + ";");
					tmp.scrolling = cfg.SCROLLING;
					tmp.frameBorder = "0";
					tmp.src = url;
					div.appendChild(tmp);
				}
				else
					div = MEL.d.getEl(div);
			}
			if (!div) return false;

  			var psize = MEL.dom.getElementSize(cfg.PARENT);
			var pos = MEL.dom.getAbsolutePos(cfg.PARENT);

			if (cfg.MODAL)
			{
				var popup_div = MEL.d.createElement("DIV");
				popup_div.onmousedown = function() { return false; }

				var ss = "z-index:"+cfg.Z_INDEX+"; position:"+(cfg.FIXED ? "fixed" : "absolute")+"; top:" + pos.y + "px; left:" + pos.x + "px;  width:" + psize.sw + "px; height:" + psize.sh + "px; background:" + cfg.BACKGROUND + ";";
				MEL.dom.setStyle(popup_div, ss);
				popup_div.className = "popup_div";

				if (cfg.OPACITY < 1)
				{
					if (MEL.ua.ie)
						popup_div.style.filter = "alpha(opacity=" + (cfg.OPACITY*100) + ")";
					else
						popup_div.style.opacity = cfg.OPACITY;
				}

				if (MEL.ua.ie && MEL.ua.ie < 7)
				{
					var sels = MEL.d.getTags("SELECT");
					for (i=0; i<sels.length; i++)
					{
						MEL.dom.appendClass(sels[i], "hide_from_popup");
						sels[i].style.visibility = "hidden";
					}
				}
			}
			else
				var popup_div = false;


			var popup_form = div;
			if (!url)
			{
				if ((popup_form.style.display == "none") && (!div.offsetWidth || !div.offsetHeight))
					throw "popup:\n Source element shouldn't have 'display: none'! Use 'visibility: hidden'.";

				// fix selected in IE
					var tmp = div.getElementsByTagName("SELECT");
					var tmp2 = popup_form.getElementsByTagName("SELECT");
					for (i=0; i<tmp.length; i++) tmp2[i].selectedIndex = tmp[i].selectedIndex;
				//
			}

			if (cfg.DRAGDROP && MEL.dragdrop)
				MEL.dragdrop.init(popup_form);

			if (!popup_form.parentNode || !popup_form.parentNode.tagName)
			{
				var box = cfg.BOX || MEL.d.body;
				if (popup_div)
					box.appendChild(popup_div);
				box.appendChild(popup_form);
			}
			else
			{
				if (popup_div)
				{
					if (cfg.BOX)
						cfg.BOX.appendChild(popup_div);
					else
						popup_form.parentNode.insertBefore(popup_div, popup_form);
				}
				if (cfg.BOX)
					cfg.BOX.appendChild( popup_form.parentNode.removeChild(popup_form) );
			}

			var ss = "; visibility:visible; position:"+(cfg.FIXED ? "fixed" : "absolute")+"; z-index:"+cfg.Z_INDEX+";";
			if (cfg.MOVE2CENTER)
			{
				var top = (cfg.Y !== false ? cfg.Y : Math.round((psize.h / 2) - ((div.offsetHeight || parseInt(MEL.dom.getStyle(div, "height"))) / 2) + (cfg.FIXED ? 0 : psize.sy)));
				var left = (cfg.X !== false ? cfg.X : Math.round((psize.w / 2) - ((div.offsetWidth || parseInt(MEL.dom.getStyle(div, "width"))) / 2) + (cfg.FIXED ? 0 : psize.sx)));
				ss += " top:" + top + "px; left:" + left + "px;"
			}
			else
				ss += " top:" + pos.y + "px; left:" + pos.x + "px;";

			if (cfg.ANIMATE && MEL.animation && popup_div)
			{
				var anim = MEL.animation.Create();
				anim.animateOpacity(popup_div, 0, cfg.OPACITY);
				anim.onFinish = function()
				{
					MEL.dom.setStyle(popup_form, MEL.dom.getStyle(popup_form) + ss);
					if (typeof funcInit == "function") funcInit(popup_form, funcParams);
				}
				anim.start();
			}
			else
			{
				MEL.dom.setStyle(popup_form, MEL.dom.getStyle(popup_form) + ss);
				if (typeof funcInit == "function") funcInit(popup_form, funcParams);
			}

			return popup_form;
		},


		hide: function(el)
		{
			if (!el || !el.tagName)
			{
				var e = el || event;
				el = e.target || e.srcElement;
			}
			while (el && el.style.zIndex < 1000) el = el.parentNode;

			if (el.previousSibling && (el.previousSibling.className == "popup_div"))
				el.parentNode.removeChild(el.previousSibling);

			el.style.visibility = "hidden";
			if (MEL.ua.ie && MEL.ua.ie < 7)
			{
				var sels = MEL.d.getTags("SELECT");
				for (i=0; i<sels.length; i++)
					if (MEL.dom.hasClass(sels[i], "hide_from_popup"))
						sels[i].style.visibility = "visible";
			}
		}

	}
	MEL.popup.close = MEL.popup.hide;						// back compatibility
//


// Status bar
	MEL.statusBar = {

		cfg: {
			IMG: "",

			BAR_STYLE: "position:absolute; top:0; right:50px; width:50px; height:13px; overflow:hidden; background-color:yellow; padding:3px; text-align:center; font-size:9px;",
			BAR_CLASS: "status_bar",
			ANIMATE: true
		},
		__hBar: null,
		__hAnimate: null,

		show: function(text, owner)
		{
			if (typeof owner == "undefined") owner = this;
			if (typeof owner.cfg == "undefined") owner.cfg = {};
			if (typeof owner.cfg.ANIMATE == "undefined") owner.cfg.ANIMATE = this.cfg.ANIMATE;

			if (!this.__hBar)
			{
				var bar = MEL.d.createElement("DIV");
				MEL.dom.setStyle(bar, this.cfg.BAR_STYLE);
				MEL.dom.setAttribute(bar, "class", this.cfg.BAR_CLASS);
				if (this.cfg.IMG)
				{
					var img = MEL.d.createElement("IMG");
					MEL.dom.setAttribute(img, "src", this.cfg.IMG);
					bar.appendChild(img);
				}
				else
					bar.appendChild(MEL.d.createTextNode(text || "Loading..."));
			}
			else
				var bar = this.__hBar;

			if (owner.cfg.ANIMATE)
			{
				if (owner.cfg.ANIMATE.tagName)
					MEL.dom.appendClass(owner.cfg.ANIMATE, "active");
				else if (MEL.animation)
				{
					if (!owner.__hAnimate)
					{
						var dot = MEL.d.createElement("DIV");
						MEL.dom.setStyle(dot, "float:left; width:5px; height:2px; background-color:#ff9191; border-left:5px solid #FFE1E1; border-right:5px solid red; margin-right:20px;");
						bar.appendChild(dot);
						MEL.d.body.appendChild(bar);

						var anim = MEL.animation.Create(dot, 0, 50);
						anim.addParam("style.marginLeft", -15, MEL.dom.getStyle(bar, "width"), "3px");
						anim.onFinish = function()
						{
							if (!this.__status)
								this.start();
							else
								this.__status = 0;
						}
						owner.__hAnimate = anim;
					}
					bar.style.visibility = "visible";
					owner.__hAnimate.start();
				}
			}
			this.__hBar = bar;
		},


		hide: function(owner)
		{
			if (typeof owner == "undefined") owner = this;
			if (typeof owner.cfg == "undefined") owner.cfg = {};
			if (typeof owner.cfg.ANIMATE == "undefined") owner.cfg.ANIMATE = this.cfg.ANIMATE;

			if (owner.cfg.ANIMATE.tagName)
				MEL.dom.removeClass(owner.cfg.ANIMATE, "active");
			if (owner.__hAnimate)
				owner.__hAnimate.stop();
			if (this.__hBar)
				this.__hBar.style.visibility = "hidden";
		},


		free: function()
		{
			this.hide();
			this.__hAnimate = null;
			if (this.__hBar)
				this.__hBar.parentNode.removeChild(this.__hBar);
			this.__hBar = null;
		}
	}
//


	MEL.cookies = {

		get: function(name)
		{  
			name += "=";
			var nlen = name.length;
			var cstr = document.cookie;
			var clen = cstr.length;
			var i = 0;  

			while (i < clen)
			{
				if (cstr.indexOf(name, i) === i)
				{
					var endstr = cstr.indexOf(";", i);
					if (endstr < 0) endstr = cstr.length;
					return unescape( cstr.substring(i+nlen, endstr) );
				}
				i = cstr.indexOf(" ", i) + 1;
				if (i == 0) break;
			}
			return null;
		},

		set: function(name, value)
		{
			var argv = arguments;
			var argc = argv.length;
			var expires	= (argc > 2) ? argv[2] : null;
			var path	= (argc > 3) ? argv[3] : "/";	 // allows the tree to remain open across pages with diff names & paths
			var domain	= (argc > 4) ? argv[4] : null;
			var secure	= (argc > 5) ? argv[5] : false;

			document.cookie = name + "=" + escape(value) +
				((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
				((path == null) ? "/" : ("; path=" + path)) +
				((domain == null) ? "" : ("; domain=" + domain)) +
				((secure == true) ? "; secure" : "");
		}
	}


// Utils
	MEL.exec = function(func, obj, e)
	{
		var t = typeof func;
		if (t == "function") return func(obj, e);
		else if (t == "string") return eval(func);
	}

	MEL.trim = function(str, chars)
	{
		if (!chars) chars = " \t\r\n\0\x0B";
		var re = new RegExp("(^["+chars+"]+)|(["+chars+"]+$)", "g");
		return str.replace(re, "");
	}

	MEL.isEmpty = function(obj)
	{
		if (!obj) return true;
		if (typeof obj == "object")
		{
			if (obj.concat)	// array
				return !obj.length;
			else
			{
				for (var i in obj) return false;
				return true;
			}
		}
		return false;
	}

	MEL.getCopy = function(obj, ignProp, withHTML, replaceKeys)
	{
		var i, ret = obj;
		if (obj && (typeof obj == "object"))
		{
			ret = (obj.pop ? [] : {} );
			for (i in obj)
				if ((!ignProp || (MEL.inArray(i, ignProp) < 0)) && (withHTML || !obj[i] || !obj[i].tagName))
				{
					if (replaceKeys && (typeof replaceKeys == "object") && replaceKeys[i])
						ret[replaceKeys[i]] = MEL.getCopy(obj[i], ignProp, withHTML);
					else
						ret[i] = MEL.getCopy(obj[i], ignProp, withHTML);
				}
		}
		return ret;
	}

	MEL.toArray = function(list)
	{
		var i, arr = [], len = list ? (list.length || 0) : 0;
		for (i=0; i<len; i++) arr.push(list.charAt ? list.charAt(i) : list[i]);
		return arr;
	}
	MEL.to_array = MEL.toArray;		// back compatibility

	MEL.copyElSize = function(el, source)
	{
		var size = MEL.dom.getElementSize(source || el);
		el.style.width = (size.w - parseInt(0+MEL.dom.getStyle(el, "padding-left")) - parseInt(0+MEL.dom.getStyle(el, "padding-right")) - parseInt(0+MEL.dom.getStyle(el, "border-left-width")) - parseInt(0+MEL.dom.getStyle(el, "border-right-width"))) + "px";
		el.style.height = (size.h - parseInt(0+MEL.dom.getStyle(el, "padding-top")) - parseInt(0+MEL.dom.getStyle(el, "padding-bottom")) - parseInt(0+MEL.dom.getStyle(el, "border-top-width")) - parseInt(0+MEL.dom.getStyle(el, "border-bottom-width"))) + "px";
		el.style.padding = MEL.dom.getStyle(el, "padding");
	}
	MEL.setupElSize = MEL.copyElSize;						// back compatibility

	MEL.copyElAttrs = function(el, source)
	{
		for (var i=0; i<source.attributes.length; i++)
			if ((source.attributes[i].value != "") && (source.attributes[i].value != "null"))
				MEL.dom.setAttribute(el, source.attributes[i].name, source.attributes[i].value);
	}

	MEL.findPopupBestPosition = function(btn, popup, over_button, pg_size, pg_borders)
	{
		var pos = MEL.dom.getAbsolutePos(btn);
		if (!pg_size) pg_size = MEL.dom.getElementSize(MEL.d.body);
		if (!pg_borders) pg_borders = {top:0, right:0, bottom:0, left:0};

		btn			= {x:pos.x,	y:pos.y,	width:btn.offsetWidth,		height:btn.offsetHeight};	// + (btn.offsetHeight < 20 ? 10 : 0)
		popup		= {x:btn.x,	y:0,		width:popup.offsetWidth,	height:popup.offsetHeight};

		// find X (default is button.x)
			if ((pg_size.w + pg_size.sx) < (btn.x + popup.width))	// if over screen at right
				popup.x = pg_size.w - popup.width;					// snap to right border

			if (popup.x < pg_size.sx)					// if over screen at left
				popup.x = pg_size.sx;					// snap to left border

			if (popup.x + popup.width > pg_size.sw - pg_borders.right)		// if over document at right
				popup.x = pg_size.sw - popup.width - pg_borders.right;		// move to the left

			if (popup.x < pg_borders.left) popup.x = pg_borders.left;	// if over document at left => x = 0
		//

		// find Y
/*
//			if ((pg_size.h < (btn.y + btn.height + popup.height))	// don't have space at bottom
			if (((pg_size.h + pg_size.sy) < (btn.y + btn.height + popup.height))	// don't have space at bottom
				&& (pg_size.sy < (btn.y - popup.height)))							// and have upper on screen
				popup.y = btn.y - popup.height;				// upper
			else if (((btn.y - popup.height) >= 0)							// have space upper
					&& (pg_size.sh > (btn.y + btn.height + popup.height)))	// and under button in document
			{
				if ((pg_size.h < (btn.y + btn.height + popup.height))							// button+popup > windows size
					&& ((btn.y - pg_size.sy) > (pg_size.h + pg_size.sy - btn.y - btn.height)))	// 	
					popup.y = btn.y - popup.height;			// upper
				else
					popup.y = btn.y + btn.height;			// under
			}
			else if (!over_button && (popup.h > btn.x + btn.height))	// if not over_button, but popup over
				popup.y = btn.y + btn.height;

			if (popup.y < 0)
			{
				if (over_button)
					popup.y = 0;
				else
					popup.y = btn.y + btn.height;
			}
*/
			if ((btn.y + btn.height + popup.height) < (pg_size.sy + pg_size.h))	// space under the button
				popup.y = btn.y + btn.height;
			else if ((btn.y - popup.height) > pg_size.sy)	// space upper above the button
				popup.y = btn.y - popup.height;
			else if (over_button)
			{
				if ((pg_size.sy + pg_size.h - popup.height) > pg_size.sy)	// space under + over button
					popup.y = pg_size.sy + pg_size.h - popup.height;
				else
					popup.y = pg_size.sy;
			}
			else
				popup.y = btn.y - popup.height;

			if ((popup.y + popup.height) > (pg_size.sh - pg_borders.bottom))	// over the document
			{
				if (over_button && ((pg_size.sh - pg_borders.bottom - popup.height) < (btn.y + btn.height)))
					popup.y = btn.y - pg_size.sh - pg_borders.bottom - popup.height;
			}

			if (popup.y < pg_borders.top)
			{
				if (over_button)
					popup.y = pg_borders.top;
				else
					popup.y = btn.y + btn.height;
			}
		//

		return {x:popup.x, y:popup.y, dir:(popup.y<btn.y ? 0 : 2)};
	}

	MEL.setPopupBestPosition = function(btn, popup, type2class, over_button)
	{
		var pos = this.findPopupBestPosition(btn, popup, over_button);
		popup.style.top	= pos.y + "px";
		popup.style.left= pos.x + "px";

		if (typeof type2class == "undefined") type2class = true;
		if (type2class)
		{
			var cl = popup.className.replace(/ (top|bottom)/i, "");
			cl += (pos.dir == 0 ? " top" : (pos.dir == 2 ? " bottom" : ""));
			MEL.dom.setAttribute(popup, "class", cl);
		}
	}

	MEL.isCursorOverEl = function(e, el)
	{
		var pos = MEL.dom.getAbsolutePos(el);
		var size = MEL.dom.getElementSize(el);

		var sx = e.clientX + MEL.de.scrollLeft;
		var sy = e.clientY + MEL.de.scrollTop;
		var res = ((sx >= pos.x) && (sx < pos.x + size.w) && (sy >= pos.y) && (sy < pos.y + size.h));

		if (res) return {mx:sx, my:sy, ex:pos.x, ey:pos.y, ew:size.w, eh:size.h};
		return false;
	}

	MEL.rgba2arr = function(rgba)
	{
		var i, arr=[], len = rgba.length;
		var piece = (len > 6 ? 2 : 1);
		for (i=0; i<len; i+=piece)
			arr.push(parseInt(rgba.substr(i, piece) + (piece<2 ? rgba.substr(i, piece) : ""), 16));
		return arr;
	}

	MEL.arr2rgba = function(arr)
	{
		var i, rgba = "";
		for (i in arr)
			rgba += (Math.round(arr[i])<16 ? "0" : "") + Math.round(arr[i]).toString(16);
		return rgba;
	}

	MEL.inArray = function(el, arr)
	{
		for (var i in arr) if (arr[i] == el) return i-0;		// convert to number
		return -1;
	}

	MEL.searchSomething = function(el, linkAttr, func)
	{
		while (el && !func(el)) el = el[linkAttr];
		if (el && func(el)) return el;
		return false;
	}
	MEL.searchSomethingUpTheTree = function(el, func) { return MEL.searchSomething(el, "parentNode", func); }

	MEL.searchAttr = function(el, linkAttr, attr, value)
	{
		if (arguments.length > 3)
		{
			while (el && (el[attr] != value)) el = el[linkAttr];
			if (el && (el[attr] == value)) return el;
		}
		else
		{
			while (el && (typeof el[attr] == "undefined")) el = el[linkAttr];
			if (el && (typeof el[attr] != "undefined")) return el;
		}
		return false;
	}
	MEL.searchAttrUpTheTree = function(el, attr, value) { return MEL.searchAttr(el, "parentNode", attr, value); }

	MEL.searchClass = function(el, linkAttr, clName)
	{
		while (el && !MEL.dom.hasClass(el, clName)) el = el[linkAttr];
		if (el && MEL.dom.hasClass(el, clName))
			return el;
		return false;
	}
	MEL.searchClassUpTheTree = function(el, clName) { return MEL.searchClass(el, "parentNode", clName) }

	MEL.searchFirstTag = function(box, tags)
	{
		if (typeof tags == "string")
			return box.getElementsByTagName(tags)[0] || false;

		if (typeof box["querySelectorAll"] == "function")
			return box.querySelector(tags.join(',')) || false;

		var els = box.childNodes;
		var res, i, cnt = els.length;
		for (i=0; i<cnt; i++)
			if (els[i].tagName)
			{
				if (MEL.inArray(els[i].tagName, tags) >= 0)
					return els[i];
				else
				{
					res = MEL.searchFirstTag(els[i], tags);
					if (res) return res;
				}
			}
		return false;
	}

	MEL.searchAllTags = function(box, tags)
	{
		if (typeof tags == "string")
			return MEL.toArray(box.getElementsByTagName(tags));

		if (typeof box["querySelectorAll"] == "function")
			return MEL.toArray(box.querySelectorAll(tags.join(',')));

		var res = [],
			els = box.childNodes;
		var i, cnt = els.length;
		for (i=0; i<cnt; i++)
			if (els[i].tagName)
			{
				if (MEL.inArray(els[i].tagName, tags) >= 0)
					res.push(els[i]);
				else
					res = res.concat(MEL.searchAllTags(els[i], tags));
			}
		return res;
	}


	MEL.selects_status = true;
	MEL.switchSelects = function()
	{
		MEL.selects_status = !MEL.selects_status;
		var i, els = MEL.d.getTags("SELECT");
		for (i=0; i<els.length; i++)
		{
			if (MEL.selects_status)
			{
				if (MEL.dom.hasClass(els[i], "tmpHide"))
				{
					MEL.dom.removeClass(els[i], "tmpHide");
					els[i].style.visibility = "visible";
				}
			}
			else if (els[i].style.visibility != "hidden")
			{
				MEL.dom.appendClass(els[i], "tmpHide");
				els[i].style.visibility = "hidden";
			}
		}
	}


	MEL.joinObjects = function(trg, src)
	{
		for (var i in src)
			if (typeof trg[i] == "undefined")
				trg[i] = src[i];
	}


	MEL.removeAttrs = function(el, attrs, recur)
	{
		if (!attrs.join) attrs = [attrs];
		var i, cnt = attrs.length;
		for (i=0; i<cnt; i++)
			if (typeof el[attrs[i]] != "undefined")
				el[attrs[i]] = null;				// why not delete???
		if (recur && el.childNodes)
		{
			cnt = el.childNodes.length;
			for (i=0; i<cnt; i++)
				arguments.callee(el.childNodes[i], attrs, true);
		}
	}


	MEL.swapElements = function(el1, el2)
	{
		// el2 -> before el1 (don't need it, if el2 already before el1)
		// el1 -> before el2_before
		var el1_box = el1.parentNode;
		var el2_box = el2.parentNode;
		var el2_before = el2.nextSibling;
		if (el2_before != el1)
			el1_box.insertBefore(el2_box.removeChild(el2), el1);
		else
			el2_before = el2;

		el1 = el1_box.removeChild(el1);
		if (el2_before)
			el2_box.insertBefore(el1, el2_before);
		else
			el2_box.appendChild(el1);
	}


	MEL.moveColumnBefore = function(col1, col2, tbl)
	{
		if ((typeof col1 == "number") && !tbl) return;
		if (!tbl) tbl = MEL.searchAttrUpTheTree(col1, "tagName", "TABLE");
		if (typeof col1 != "number") col1 = col1.cellIndex;
		if (col2 && typeof col2 != "number") col2 = col2.cellIndex;
		if (col2 > col1) col2--;

		var rows = tbl.rows;
		var row, cell;
		var i, cnt = rows.length;
		for (i=0; i<cnt; i++) if (rows[i].cells.length >= col1)
		{
			row = rows[i];
			cell = row.cells[col1];

			if (col2 < 0)
				row.appendChild( row.removeChild(cell) );
			else
				row.insertBefore( row.removeChild(cell), row.cells[col2] );
		}
	}


	MEL.__callbacks = {};
	MEL.loadExternalScript = function(url, callback_param_name, callback, onload)
	{
		var i, script = MEL.d.createElement("SCRIPT");
		script.type = "text/javascript";
		if (callback_param_name)
		{
			for (i = MEL.date.getUTC()-0; MEL.__callbacks["x"+i.toString(36)]; i++);
			var cb_uniq_name = "x"+i.toString(36);

			MEL.__callbacks[cb_uniq_name] = function()
			{
				if (typeof callback == "function") callback.apply(null, arguments);
				delete MEL.__callbacks[cb_uniq_name];
				script.parentNode.removeChild(script);
			};
			url += (url.indexOf("?") > 0 ? "&" : "?") + callback_param_name + "=MEL.__callbacks." + cb_uniq_name;
		}
		if (onload) MEL.event.addListener(script, "load", onload);
		script.src = url;
		(MEL.d.getTags("head")[0] || MEL.d.getTags("body")[0]).appendChild(script);
	}
//
var embed_uid,embed_in_site,embed_form;if(MEL.url.href.match(/[\?&](embedId=WebAnketa.*&site=[^&]+)/)){var embed_params=RegExp.$1;var setup_focus=true;var html=MEL.d.getTags("HTML")[0];MEL.dom.appendClass(html,"embed");embed_in_site=embed_params.indexOf("&site=");var arr_params=embed_params.substr(0,embed_in_site).split("&");embed_in_site=decodeURIComponent(embed_params.substr(embed_in_site+6).split("#",2)[0].replace(/&$/,""));embed_form=MEL.url.href.match(/^[^\?]*(\/forms\/[^\/]+\/)/);if(embed_form){embed_form=embed_form[1]}var i,item;for(i=0;i<arr_params.length;i++){item=arr_params[i].split("=",2);if(item[0]=="embedId"){embed_uid=item[1]}else{if(item[0]=="firstLoad"){setup_focus=(item[1]=="0")}else{if(item[0]=="startWidth"){if((item[1]-0)<550){MEL.dom.appendClass(html,"small-screen")}if((item[1]-0)<250){MEL.dom.appendClass(html,"tiny")}}else{if(item[0]=="site"){break}}}}}if(embed_uid){if(embed_params){embed_params=embed_params.replace(/&firstLoad=[^&]+&/i,"&firstLoad=0&")}var lastHeight=0;function updateLinkObjectHref(c,d,e){var b,a=c.length;for(b=0;b<a;b++){if(c[b][d].indexOf(embed_form)>=0){c[b].target=e;if(c[b][d].indexOf("embedId="+embed_uid)<0){if(c[b][d].indexOf("?")>0){c[b][d]=c[b][d]+"&"+embed_params}else{c[b][d]=c[b][d]+"?"+embed_params}}else{c[b][d]=c[b][d].replace(/&firstLoad=[^&]+&/i,"&firstLoad=0&")}}}}function resizeIframe(h){h=h||event;var f,j;var d=MEL.d.getTags("DIV");var b=(d.length&&d[0].className=="body"?d[0]:MEL.d.body);var g={sw:b.clientWidth,sh:b.clientHeight};if(g.sw<550){MEL.dom.appendClass(MEL.d.getTags("HTML")[0],"small-screen");if(g.sw<250){MEL.dom.appendClass(MEL.d.getTags("HTML")[0],"tiny")}else{MEL.dom.removeClass(MEL.d.getTags("HTML")[0],"tiny")}g={sw:b.clientWidth,sh:b.clientHeight};if(f=MEL.d.getEl("linkShowResults")){f.target="_blank";f.href=f.href.split("?",2)[0]}updateLinkObjectHref(MEL.d.getTags("FORM"),"action","");updateLinkObjectHref(MEL.d.getTags("A"),"href","_blank")}else{MEL.dom.removeClass(MEL.d.getTags("HTML")[0],"small-screen");updateLinkObjectHref(MEL.d.getTags("FORM"),"action","");updateLinkObjectHref(MEL.d.getTags("A"),"href","")}if(Math.abs(g.sh-lastHeight)>5){lastHeight=g.sh;if(typeof window.postMessage!="undefined"){parent.postMessage(embed_uid+".height="+g.sh+(setup_focus?";"+embed_uid+".focus":""),"*")}else{if((embed_in_site!="")&&(parent!=window)){parent.location=embed_in_site+"#"+embed_uid+".height="+g.sh+(setup_focus?";"+embed_uid+".focus":"")}}}var c,a=MEL.d.getTags("FORM");for(c=0;c<a.length;c++){if(a[c].action){a[c].action=a[c].action.replace(/&startWidth=[^&]+&/,"&startWidth="+g.sw+"&")}}if(h.type=="load"){setup_focus=false}}MEL.event.addListener(MEL.w,"load",resizeIframe);MEL.event.addListener(MEL.w,"resize",resizeIframe)}};/**
* Filename................: mel.calendar.js
* Project.................: web pages SDK
* Last Modified...........: $Date: 15/11/2010 18:06:19 $
* CVS Revision............: $Revision: 0.0.6 $
* Idea and Developed by...: Maxim Bulygin (sailormax@gmail.com)
*/

if (typeof MEL == "undefined") var MEL = {};

MEL.calendar = {

	in_use: [],
	cfg: {
		WEEKDAYS:		["S", "M", "T", "W", "T", "F", "S"],
		MONTHS:			["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
		WORD_TODAY:		"Today",
		WORD_TIME:		"Time",
		START_WEEKDAY:	0,
		WEEK_NUMBERS:	0,
		YEARS_LIST:		[],
		DROP_PLACES:	[],
		SELECTED:		[],	// days!!! since 1970

		DATE_WITH_TIME:		false,
		MULTIPLE_AT_ONCE:	false,
		DRAGNDROP:			false,
		ANIMATE_SHOW:		true,
		ANIMATE_HIDE:		true,
		ANIMATE_HIDE_ALL:	false
	},


	setYear: function(cal_idx, val)
	{
		var cal = this.in_use[cal_idx];
		if (cal)
		{
			cal.date.setDate(1);
			cal.date.setYear(val);
			cal.render(false);
		}
	},


	setMonth: function(cal_idx, val)
	{
		var cal = this.in_use[cal_idx];
		if (cal)
		{
			cal.date.setDate(1);
			cal.date.setMonth(val);
			cal.render(false);
		}
	},


	changeMonth: function(cal_idx, val)
	{
		var cal = this.in_use[cal_idx];
		if (cal)
		{
			cal.date.setMonth(cal.date.getMonth() + val);
			cal.render();
		}
	},

	changeYear: function(cal_idx, val)
	{
		var cal = this.in_use[cal_idx];
		if (cal)
		{
			cal.date.setYear(cal.date.getFullYear() + val);
			cal.render();
		}
	},


	setDay: function(cal_idx, val)
	{
		var cal = this.in_use[cal_idx];
		if (cal)
		{
			cal.date.setDate(val);
			cal.render();

			if (cal.onChoose) cal.onChoose(cal.date, cal_idx);
		}
	},


	setDate: function(cal_idx, val, choose)
	{
		var cal = this.in_use[cal_idx];
		if (cal)
		{
			cal.date = val;
			cal.render();

			if (choose && cal.onChoose) cal.onChoose(cal.date, cal_idx);
		}
	},

	changeWeeksNumPos: function(cal_idx, val)
	{
		var cal = this.in_use[cal_idx];
		if (cal)
		{
			cal.cfg.WEEK_NUMBERS = val;
			cal.render();
		}
	},

	showhide: function(cal_idx)
	{
		var cal = this.in_use[cal_idx];
		if (cal)
		{
			if (cal.div.style.visibility == "visible")
				cal.hide(this.cfg.ANIMATE_HIDE);
			else
				cal.show();
		}
	},


	__hideAll: function(e)
	{
		var i;
		var el = e.srcElement || e.target;

		var in_use = MEL.calendar.in_use;
		var click_on_calendar = false;
		while (el)
		{
			for (i in in_use)
				if (((in_use[i].div == el) || (in_use[i].button == el)) && (in_use[i].div.style.visibility == "visible"))
					click_on_calendar = true;

			el = el.parentNode;
		}

		if (!click_on_calendar)
			for (i in in_use)
				in_use[i].hide(in_use[i].cfg.ANIMATE_HIDE_ALL);
	},



	__renderHeader:  function()
	{
		var i;
		var res = "";

		var we_in_form = false;
		var tmp = this.div;
		while (tmp)
		{
			if (we_in_form = (tmp.tagName == "FORM")) break;
			tmp = tmp.parentNode;
		}


		res += (we_in_form ? "<form action='' method='' class='toolbar'>" : "<div class='toolbar'><form action='#'>");

			var years = this.cfg.YEARS_LIST;
			if (years.length)
			{
				res += "<select class='months' onchange='MEL.calendar.setMonth(" + this.__idx + ", this.selectedIndex);'><option>" + this.cfg.MONTHS.join("</option><option>") + "</option></select>";
				res += "<select class='years' onchange='MEL.calendar.setYear(" + this.__idx + ", this.value);'><option>" + years.join("</option><option>") + "</option></select>";
				res = res.replace( /\<option\>([^\<]+)\<\/option\>/ig , "<option value='$1'>$1</option>");

				var cur_month = this.cfg.MONTHS[this.date.getMonth()];
				res = res.replace("<option value='" + cur_month + "'>" + cur_month + "</option>" , "<option value='" + cur_month + "' selected='selected'>" + cur_month + "</option>");
				var cur_year = this.date.getFullYear();
				res = res.replace("<option value='" + cur_year + "'>" + cur_year + "</option>" , "<option value='" + cur_year + "' selected='selected'>" + cur_year + "</option>");
			}
			else
			{
				res += "<a href='javascript:MEL.calendar.changeMonth(" + this.__idx + ", -1);' name='prevMonth'>&#171;</a>";
				res += " <b>" + this.cfg.MONTHS[this.date.getMonth()] + " " + this.date.getFullYear() + "</b> ";
				res += "<a href='javascript:MEL.calendar.changeMonth(" + this.__idx + ", 1);' name='nextMonth'>&#187;</a>";
			}

		res += (we_in_form ? "</form>" : "</form></div>");


		res += "<div class='days_box'><table class='days' cellspacing='0'>";
		if (this.cfg.WEEKDAYS)
		{
			res += "<thead><tr>";
			var titles = [].concat(this.cfg.WEEKDAYS);

			i = this.cfg.START_WEEKDAY;
			while (i--) titles.push(titles.shift());

			if (this.cfg.WEEK_NUMBERS < 0)
				res += "<th class=\"week_num\" onclick=\"MEL.calendar.changeWeeksNumPos(" + this.__idx + ", 1)\">&gt;</th>";
			for (i in titles)
				res += "<th>" + titles[i] + "</th>";
			if (this.cfg.WEEK_NUMBERS > 0)
				res += "<th class=\"week_num\" onclick=\"MEL.calendar.changeWeeksNumPos(" + this.__idx + ", -1)\">&lt;</th>";

			res += "</tr></thead>";
		}
		res += "<tbody>";
		return res;
	},


	__renderBody: function()
	{
		// detect first week number
		var firstMonthDay = new Date(this.date);
			firstMonthDay.setDate(1);
		var firstYearDay = new Date(firstMonthDay);
			firstYearDay.setMonth(0);
		var firstYearWDay = firstYearDay.getDay() - this.cfg.START_WEEKDAY;
		var week_num = Math.ceil((Math.floor((firstMonthDay - firstYearDay) / 86400000)+1 + firstYearWDay) / 7);
		//

		var i;
		var res = "<tr>";
		if (this.cfg.WEEK_NUMBERS < 0)
			res += "<td class=\"week_num left\">"+week_num+"</td>";
		var isPrevMonth = (this.__days[0] > 1);
		var start_cnt = 0;
		var week_day = 0;
		var classes;

		for (i in this.__days)
		{
			if (week_day++ > 6)
			{
				week_num++;
				week_day = 1;
				if (this.cfg.WEEK_NUMBERS > 0)
					res += "<td class=\"week_num right\">"+week_num+"</td>";
				res += "</tr><tr>";
				if (this.cfg.WEEK_NUMBERS < 0)
					res += "<td class=\"week_num left\">"+week_num+"</td>";
			}

			if (this.cfg.START_WEEKDAY == 0)
				classes = "wd" + (week_day-1);
			else if (week_day == 7)
				classes = "wd0";
			else
				classes = "wd" + week_day;

			if (this.__today_idx == i)
				classes += " today";
			if (this.__curday_idx == i)
				classes += " curday";
			if (this.__selected_idx[i])
				classes += " selected";


			if (isPrevMonth && (this.__days[i] > 1))
				res += "<td class=\"" + classes + " out\"><span>" + this.__days[i] + "</span></td>";
			else
			{
				isPrevMonth = false;
				if (this.__days[i] == 1) start_cnt++;
				if (start_cnt > 1)
					res += "<td class=\"" + classes + " out\"><span>" + this.__days[i] + "</span></td>";
				else
					res += "<td class=\"" + classes + " in\"><a href=\"javascript:MEL.calendar.setDay(" + this.__idx + ", " + this.__days[i] + ");\">" + this.__days[i] + "</a></td>";
			}
		}

		if (this.cfg.WEEK_NUMBERS > 0)
			res += "<td class=\"week_num right\">"+week_num+"</td>";
		res += "</tr>";
		return res;
	},


	__renderFooter: function()
	{
		var res = "</tbody></table></div>";

		var today = new Date();
		res += "<div class='footer'>"
		res += "<a href=\"javascript:MEL.calendar.setDate(" + this.__idx + ", new Date(), true);\">" + this.cfg.WORD_TODAY + "</a>: " + MEL.date.getFormatted(today, "d.") + "<a href=\"javascript:MEL.calendar.setDate(" + this.__idx + ", new Date());\">" + MEL.date.getFormatted(today, "m.Y") + "</a>";
		if (this.cfg.DATE_WITH_TIME)
			res += "<form class='time'>" + this.cfg.WORD_TIME + ": <input type='text' maxlength='2' size='2' value='" + MEL.date.getFormatted(today, "H") + "' /> : <input type='text' maxlength='2' size='2' value='" + MEL.date.getFormatted(today, "i") + "' /></form>";
		res += "</div>";
		return res;
	},


	isSelected: function(dt)
	{
		var i, tmp;
		for (i in this.cfg.SELECTED)
		{
			tmp = this.cfg.SELECTED[i];
			if (isNaN(tmp))
				return ((tmp[0] <= dt) && (dt <= tmp[1]));
			else
				return (tmp[i] == dt);
		}
		return false;
	},


	render: function(fully)
	{
		var i, cursor;
		if (typeof fully == "undefined") fully = true;
		if (!this.init_date) this.init_date = new Date(this.date);

		// calculate
			var day = this.date.getDate();
			var month = this.date.getMonth();
			var year = this.date.getFullYear();
			var cur_month_begin = new Date(year, month, 1);
			var today = Math.floor(new Date() / 86400000);
			var curday = Math.floor(MEL.date.getUTC(this.init_date) / 86400000);

			this.__today_idx = -1;
			this.__curday_idx = -1;
			this.__days = [];
			this.__selected_idx = [];

			// get days of previous month
				var prev_month_begin = (month > 0 ? new Date(year, month-1, 1) : new Date(year-1, 11, 1) );
				var prev_month_days = Math.round((cur_month_begin - prev_month_begin) / 86400000);

				var cur_month_start = cur_month_begin.getDay();
				if (this.cfg.START_WEEKDAY > 0)
				{
					cur_month_start -= this.cfg.START_WEEKDAY;
					if (cur_month_start < 0) cur_month_start += 7;
				}

				cursor = Date.UTC(prev_month_begin.getFullYear(), prev_month_begin.getMonth(), prev_month_days-(cur_month_start-1)) / 86400000;
				for (i=1; i<=cur_month_start; i++)
				{
					this.__days.push(prev_month_days-(cur_month_start-i));
					if ((this.__today_idx < 0) && (today == cursor))
						this.__today_idx = this.__days.length - 1;
					if ((this.__curday_idx < 0) && (curday == cursor))
						this.__curday_idx = this.__days.length - 1;
					this.__selected_idx.push(this.isSelected(cursor));
					cursor++;
				}
			//

			// get days of current month
				var next_month_begin = (month < 11 ? new Date(year, month+1, 1) : new Date(year+1, 0, 1) );
				var cur_month_days = Math.round((next_month_begin - cur_month_begin) / 86400000);

				for (i=1; i<=cur_month_days; i++)
				{
					this.__days.push(i);
					if ((this.__today_idx < 0) && (today == cursor))
						this.__today_idx = this.__days.length - 1;
					if ((this.__curday_idx < 0) && (curday == cursor))
						this.__curday_idx = this.__days.length - 1;
					this.__selected_idx.push(this.isSelected(cursor));
					cursor++;
				}
			//

			// get days of next month
				var cur_month_end = (new Date(next_month_begin - 86400000)).getDay();
				if (this.cfg.START_WEEKDAY > 0)
				{
					cur_month_end -= this.cfg.START_WEEKDAY;
					if (cur_month_end < 0) cur_month_end += 7;
				}

				for (i=6; i>cur_month_end; i--)
				{
					this.__days.push(7-i);
					if ((this.__today_idx < 0) && (today == cursor))
						this.__today_idx = this.__days.length - 1;
					if ((this.__curday_idx < 0) && (curday == cursor))
						this.__curday_idx = this.__days.length - 1;
					this.__selected_idx.push(this.isSelected(cursor));
					cursor++;
				}
			//
		//

		if (fully && this.__renderHeader && this.__renderFooter)
		{
			var src = "";
			if (this.__renderHeader)
				src += this.__renderHeader();
			if (this.__renderBody)
				src += this.__renderBody();
			if (this.__renderFooter)
				src += this.__renderFooter();

			if (src)
				this.div.innerHTML = src;
		}
		else
		{
			var src = this.__renderBody();
			var tbodies = this.div.getElementsByTagName("TBODY");
			for (i=0; i<tbodies.length; i++)
			{
				if (tbodies[i].parentNode.className == "days")
				{
					// IE workaround :: tbody is readonly
						var tmp_div = document.createElement("DIV");
						tmp_div.innerHTML = "<table><tbody>" + src + "</tbody></table>";
						var new_tbody = tmp_div.getElementsByTagName("TBODY")[0];
					//

					tbodies[i].parentNode.replaceChild(new_tbody, tbodies[i]);
					break;
				}
			}
		}
	},


	__animateShow: function(div)
	{
		return MEL.animation.animateOpacity(div, 0, 1, 0.1);
	},

	__animateHide: function(div)
	{
		return MEL.animation.animateOpacity(div, 1, 0, 0.1);
	},

	show: function()
	{
		var i;
		if (!this.cfg.MULTIPLE_AT_ONCE)
			for (i in MEL.calendar.in_use)
				if (MEL.calendar.in_use[i].__idx != this.__idx)
					MEL.calendar.in_use[i].hide();

		if (this.cfg.DRAGNDROP && (this.div.style.position == "absolute"))
			MEL.dragdrop.init(this.div);

		this.div.style.width = "auto";
		this.div.style.height = "auto";

		if (this.button && this.div.style.position == "absolute")
			MEL.setPopupBestPosition(this.button, this.div);

		if (this.cfg.ANIMATE_SHOW && MEL.animation)
		{
			this.div.style.visibility = "visible";
			MEL.calendar.__animateShow(this.div).start();
		}
		else
			this.div.style.visibility = "visible";

		if (this.button && MEL.ua.ie && MEL.ua.ie < 7) MEL.switchSelects();
		return false;
	},


	hide: function(animate)
	{
		if (this.div.style.visibility == "hidden") return;
		if (animate && MEL.animation)
		{
			var anim = MEL.calendar.__animateHide(this.div);
			anim.onFinish = function()
			{
				this.obj.style.visibility = "hidden";
			}
			anim.start();
		}
		else
			this.div.style.visibility = "hidden";

		if (this.cfg.DRAGNDROP && (this.div.style.position == "absolute"))
			MEL.dragdrop.remove(this.div);

		if (MEL.ua.ie && MEL.ua.ie < 7) MEL.switchSelects();
		return false;
	},



	Create: function(button, div, btnOnClick)
	{
		if (!this.in_use.length && button)
			MEL.event.addListener(document, "click", MEL.calendar.__hideAll);

		if (!button && !div)
		{
			if (console && console.log)
				console.log("MEL.calendar: Can't create calendar without container or master button.");
			return null;
		}

		// required objects
			if (button && (typeof button != "object"))
				button = MEL.d.getEl(button);

			if (div && (typeof div != "object"))
				div = MEL.d.getEl(div);

			if (!div)
			{
				div = MEL.d.createElement("DIV");
				div.className = "calbox";
				if (button)
					MEL.dom.setStyle(div, "float:left; position:absolute; visibility:hidden; top:0; left:0; z-index:100;");
				MEL.d.body.insertBefore(div, MEL.d.body.childNodes[0]);
			}
		//

		var empty_idx = -1;
		var in_use = this.in_use;
		for (var i in in_use)
			if (!in_use[i]) { empty_idx = i; break }
		if (empty_idx < 0) empty_idx = in_use.length


		var new_calendar = {};
		new_calendar.date		= new Date();
		new_calendar.init_date	= "";
		new_calendar.selected	= [];
		new_calendar.__idx		= empty_idx;
		new_calendar.__days		= [];
		new_calendar.__today_idx= -1;
		new_calendar.__curday_idx= -1;
		new_calendar.__selected_idx= [];

		new_calendar.cfg	= this.cfg;
		new_calendar.button	= button;
		new_calendar.div	= div;
		new_calendar.__renderHeader	= this.__renderHeader;
		new_calendar.__renderBody	= this.__renderBody;
		new_calendar.__renderFooter	= this.__renderFooter;
		new_calendar.isSelected	= this.isSelected;
		new_calendar.render	= this.render;
		new_calendar.show	= this.show;
		new_calendar.hide	= this.hide;
		new_calendar.showhide	= this.showhide;

		new_calendar.onChoose	= null;

		new_calendar.Destroy	= this.Destroy;

		if (button && ((typeof btnOnClick == "undefined") || btnOnClick))
		{
			if (MEL.ua.ie)
				button.setAttribute("onfocus", function(){ MEL.calendar.showhide(new_calendar.__idx); });
			else
				button.setAttribute("onfocus", "return MEL.calendar.showhide(" + new_calendar.__idx + ")");
/*
			if ((button.tagName == "TEXTAREA") || (button.type == "text") || (button.type == "password"))
			{
				if (MEL.ua.ie)
					button.setAttribute("onfocus", function(){ MEL.calendar.showhide(new_calendar.__idx); });
				else
					button.setAttribute("onfocus", "return MEL.calendar.showhide(" + new_calendar.__idx + ")");
			}
			else
			{
				if (MEL.ua.ie)
					button.setAttribute("onclick", function(){ MEL.calendar.showhide(new_calendar.__idx); });
				else
					button.setAttribute("onclick", "return MEL.calendar.showhide(" + new_calendar.__idx + ")");
			}
*/
		}

		this.in_use[empty_idx] = new_calendar;
		return new_calendar;
	},

	Destroy: function()
	{
		this.div.parentNode.removeChild(this.div);
		MEL.calendar.in_use[this.__idx] = null;
		this.div = null;
	}
}
function onRadioButtonClick(sender)
{
	var btns = MEL.d.getEls(sender.name);
	var i, cnt = btns.length;
	for (i=0; i<cnt; i++)
		if (btns[i] !== sender)
			btns[i]["myChecked"] = false;

	if (sender["myChecked"] == sender.checked)
		sender["myChecked"] = sender.checked = false;
	else
		sender["myChecked"] = sender.checked;
}

function onRadioButtonDown(sender)
{
	if (sender.checked && (typeof sender["myChecked"] == "undefined")) sender["myChecked"] = sender.checked;
}

function SelectOtherOption(orig_el)
{
	var el = orig_el;
	do { el = el.previousSibling; } while (el && (el.type != "radio") && (el.type != "checkbox") && (el.tagName != "LABEL"));
	if (!el)
	{
		el = MEL.searchAttrUpTheTree(orig_el, "tagName", "TD");
		if (el && (el.cellIndex > 0))
			el = el.parentNode.cells[0].getElementsByTagName("INPUT")[0]
	}
	else if (el.tagName == "LABEL")
		el = el.getElementsByTagName("INPUT")[0];
	if (el && !el.checked)
	{
		el.checked = true;
		onRadioButtonClick(el);
	}
}

function starClick(el)
{
	var inp = el.getElementsByTagName("INPUT")[0];
	MEL.dom.removeClass(el.parentNode, "choosed");
	onRadioButtonClick(inp);
	if (inp.checked)
	{
		starMouseOver(el);
		MEL.dom.appendClass(el.parentNode, "choosed");
	}
	else
	{
		var item = el;
		while (item.previousSibling) { item = item.previousSibling };
		do{	if (MEL.dom.hasClass(item, "dl_item")) MEL.dom.removeClass(item, "active") } while (item = item.nextSibling);
	}
}

function starMouseDown(el)
{
	onRadioButtonDown( el.getElementsByTagName("INPUT")[0] );
}

function starMouseOver(el)
{
	if (MEL.dom.hasClass(el.parentNode, "choosed")) return;
	var item = el;
	do{
		if (MEL.dom.hasClass(item, "dl_item")) MEL.dom.appendClass(item, "active")
	} while (item = item.previousSibling)

	var item = el;
	while (item = item.nextSibling) {
		if (MEL.dom.hasClass(item, "dl_item")) MEL.dom.removeClass(item, "active")
	}
}

function starMouseOut(el)
{
	if (MEL.dom.hasClass(el, "choosed")) return;
	var item = el.childNodes[0];
	do{
		if (MEL.dom.hasClass(item, "dl_item")) MEL.dom.removeClass(item, "active")
	} while (item = item.nextSibling)
}


function ChangedCountry(el)
{
	var target = null;
	var boxes = el.parentNode.parentNode.getElementsByTagName("SELECT");
	var i, cnt = boxes.length;
	for (i=0; i<cnt; i++)
		if (MEL.dom.hasClass(boxes[i].parentNode, "region") || MEL.dom.hasClass(boxes[i].parentNode, "city"))
		{
			while (boxes[i].options.length > 1) boxes[i].removeChild(boxes[i].options[1]);
			if (MEL.dom.hasClass(boxes[i].parentNode, "region"))
				target = boxes[i];
		}

	if (target && (el.value != ""))
	{
		var loading = target;
		while (loading && !MEL.dom.hasClass(loading, "ajax_status")) loading = loading.nextSibling;

		var xhr = MEL.xhr.Create("/scripts/get_region_list.php", "get", "country_code="+el.value, function(res)
		{
			var item, rows = res.split("\n");
			var cnt = rows.length-2;	// last enter -> -1
			for (i=0; i<cnt; i++)
			{
				item = rows[i].split("\t", 2);
				target.options.add(new Option(item[1], item[0]));
			}
		});
		if (loading) xhr.cfg.ANIMATE = loading;
		xhr.cfg.CACHE = true;
		xhr.send();
	}
}

function ChangedRegion(el, country)
{
	var target = null;
	var boxes = el.parentNode.parentNode.getElementsByTagName("SELECT");
	var i, cnt = boxes.length;
	for (i=0; i<cnt; i++)
		if (MEL.dom.hasClass(boxes[i].parentNode, "city"))
		{
			while (boxes[i].options.length > 1) boxes[i].removeChild(boxes[i].options[1]);
			target = boxes[i];
		}
		else if (MEL.dom.hasClass(boxes[i].parentNode, "country"))
			country = boxes[i];

	if (target && (el.value != ""))
	{
		var loading = target;
		while (loading && !MEL.dom.hasClass(loading, "ajax_status")) loading = loading.nextSibling;

		var xhr = MEL.xhr.Create("/scripts/get_city_list.php", "get", "country_code="+country.value+"&region_code="+el.value, function(res)
		{
			var item, rows = res.split("\n");
			var cnt = rows.length-2;	// last enter -> -1
			for (i=0; i<cnt; i++)
				target.options.add(new Option(rows[i], rows[i]));
		});
		if (loading) xhr.cfg.ANIMATE = loading;
		xhr.cfg.CACHE = true;
		xhr.send();
	}
}




function CheckFormValues()
{
	var err = false;

	var divs = MEL.d.getTags("DIV");
	var i, cnt = divs.length;
	for (i=0; i<cnt; i++)
		if (MEL.dom.hasClass(divs[i], "el"))
		{
			var classes = divs[i].className.split(/ +/);
			if (MEL.inArray(classes, "require") > 0)
			{
			}
		}

	return !err;
}


function CheckInputValue(evt, el, type)
{
	var cfg;
	var ns = (evt.type == "keypress" ? evt.charCode : 0);
	if (el.el_cfg && el.el_cfg.parent && (cfg = el.el_cfg.parent.settings))
	{
		if (cfg.NumberType) type = cfg.NumberType.value;
	}

	switch (type)
	{
		case "number":
			el.value = el.value.replace(/[^0-9]+.*$/, "");
			break;

		case "integer":
/*
			if (ns)
			{
				if ((ns > 64) && isNaN(String.fromCharCode(ns))) MEL.event.cancel(evt);
			}
			else
*/
				el.value = el.value.replace(/[^0-9]+.*$/, "");
			break;

		case "float":
/*
			if (ns)
			{
				var chr = String.fromCharCode(ns);
				if ((ns > 64) && (chr != '.') && (chr != ',') && isNaN(chr)) MEL.event.cancel(evt);
			}
			else
*/
				el.value = el.value.replace(/[^0-9\.,]+.*$/, "");
			break;
	}
}

function fixIESelectWidth(el, evt)
{
	if (!(MEL.ua.ie && (MEL.ua.ie == 8))) return;
	if (evt.type == "focusin")
	{
		if (!el["replace_box"])
		{
			var div = MEL.d.createElement("DIV");
			MEL.copyElSize(div, el);
			MEL.dom.appendClass(div, "replace_box");
			el["replace_box"] = el.parentNode.insertBefore(div, el.nextSibling);
		}
		el["replace_box"].style.display = "block";
		MEL.dom.setStyle(el, "position:absolute; width:auto;");
	}
	else if (el["replace_box"])	// blur
	{
		el["replace_box"].style.display = "none";
		MEL.dom.setStyle(el, "");
	}
}
