/**
* Filename................: mel.js
* Project.................: web pages SDK
* Last Modified...........: $Date: 26/3/2008 14:45:59 $
* CVS Revision............: $Revision: 0.0.27 $
* 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;
	MEL.w = window;

	MEL.d.getEl = MEL.d.getElementById;
	MEL.d.getEls = MEL.d.getElementsByName;
	MEL.d.getTags = MEL.d.getElementsByTagName;
//

// browser name and version
	var ua = MEL.ua = {
		str:		navigator.userAgent,
		other:		true
	}

	var i, tmp, uas = [["opera"], ["safari"], ["konqueror", "konq"], ["msie", "ie"], ["mozilla"]];
	for (i in uas)
	{
		i = uas[i];
		if (tmp = ua.str.match(new RegExp(i[0]+".([0-9\.]+)", "i")))
		{
			ua[i[1] || i[0]] = tmp[1];
			ua.other = false;
			break;
		}
		else
			ua[i[1] || i[0]] = false;
	}
//

// cross browser debug
	if (opera && !console)
		var console = { log: opera.postError };
	else if (console && !opera)
		var opera = { postError: console.log };
	else if (!console && !opera)
	{
		var console = { log: function(){} };
		var opera = { postError: function(){} };
	}
//


// 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
			{
				if (el.style.getAttribute)
					return el.style.getAttribute("cssText");
				else
					return el.getAttribute("style");
			}
			return "";
		},


		setStyle: function(el, str)
		{
			if (el.style.setAttribute)
				el.style.setAttribute("cssText", str);
			else
				el.setAttribute("style", str);
		},


		haveClass: function(el, name)
		{
			return ((" "+el.className+" ").search(" "+name+" ") > -1);
		},

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

		removeClass: function(el, name)
		{
			el.className = (" "+el.className+" ").replace(" "+name+" ", "").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)
				el.setAttribute(name, val);
			else
			{
				if (items[0] == "filter") items[0] = "filters";
				if ((items[0] == "filters") && !el[items[0]][items[1]] && MEL.ua.ie)
					el.style.filter += " " + items[1] + "(" + items[2] + "=" + val + ")";

				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)
		{
			var pnt = {x:0, y:0};
			while (el)
			{
				pnt.x += el.offsetLeft;
				pnt.y += el.offsetTop;
				el = el.offsetParent;
			}
			return pnt;
		},


		getElementSize: function(el)
		{
			if (!el) return [];
			var wnd = (el.tagName == "BODY" ? MEL.w : null);
//			var wnd = (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 (wnd)
			{
				if (self.innerHeight)									// IE6 (Strict)
				{
					res.w = self.innerWidth;	res.h = self.innerHeight;
					res.sx = self.pageXOffset;	res.sy = self.pageYOffset;
				}
				else if (de && de.clientHeight)
				{
					res.w = de.clientWidth;		res.h = de.clientHeight;
					res.sx = de.scrollLeft;		res.sy = de.scrollTop;
				}
			}
			if (res.h < 0)
			{
				if (MEL.ua.safari)
				{
					res.w = el.offsetWidth;
					res.h = el.offsetHeight;
				}
				else
				{
					res.w = el.clientWidth || el.offsetWidth;
					res.h = el.clientHeight || el.offsetHeight;
				}
				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;

			return res;
		},

		
		insertRow2Table: function(tbl, row, idx)
		{
			var i, nr = tbl.insertRow(idx);
			this.setStyle(nr, this.getStyle(row))
			MEL.copyElAttrs(nr, row);
			var cln, arr = row.childNodes;
			for (i=0; i<arr.length; i++)
				nr.appendChild(arr[i].cloneNode(true));
			return nr;
		}
	}
//


// 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][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]);
		},

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


		__hMouseInOut: function(e)
		{
			e = e || event;
			var i, pos, size, out, list = MEL.event.__onmouseinout;
			for (i in list) if (list[i])
			{
				pos = MEL.dom.getAbsolutePos(list[i][0]);
				size = MEL.dom.getElementSize(list[i][0]);
				out = ((e.clientX < pos.x) || (e.clientY < pos.Y) || (e.clientX > pos.x+size.sw) || (e.clientY > pos.y+size.sh));
				if (out != list[i][1])
				{
					MEL.exec(list[i][(out ? 2 : 3)], list[i][0], e);
					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;
		}
	}
//


// 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;
		},


		getUTC: function(dt)
		{
			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]);
			this.in_use[i] = [null, obj, func_name, interval];
			this.in_use[i][0] = ( interval ? window.setInterval("MEL.timer.__cb(" + i + ")", msec) : window.setTimeout("MEL.timer.__cb(" + i + ")", 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,
			WIDTH: "320px",
			HEIGHT: "200px",
			PARENT: null,

			BACKGROUND: "#000",
			OPACITY: 0.5,
			DRAGDROP: true,
			MODAL: true,
			SCROLLING: "auto",

			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 (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:1000; position: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)
			{
				if (popup_div)
					MEL.d.body.appendChild(popup_div);
				MEL.d.body.appendChild(popup_form);
			}
			else
				popup_form.parentNode.insertBefore(popup_div, popup_form);

			var top = (cfg.Y !== false ? cfg.Y : Math.round((psize.h / 2) - ((div.offsetHeight || parseInt(MEL.dom.getStyle(div, "height"))) / 2) + psize.sy));
			var left = (cfg.X !== false ? cfg.X : Math.round((psize.w / 2) - ((div.offsetWidth || parseInt(MEL.dom.getStyle(div, "width"))) / 2) + psize.sx));
			var ss = "; visibility:visible; position:absolute; z-index:1000; top:" + top + "px; left:" + left + "px;";
			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.srcElement || e.target;
			}
			while (el && el.style.zIndex < 1000) el = el.parentNode;
			if (el.previousSibling)
			{
				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.haveClass(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:15px; 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)
		{
			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 (MEL.animation && this.cfg.ANIMATE)
			{
				if (!this.__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;
					}
					this.__hAnimate = anim;
				}
				this.__hAnimate.start();
			}
			this.__hBar = bar;
		},


		hide: function()
		{
			if (this.__hAnimate)
				this.__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;
		}
	}
//


// 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.getCopy = function(obj, name)
	{
		var i, ret = obj;
		if (obj && (typeof obj == "object"))
		{
			ret = (obj.pop ? [] : {} );
			for (i in obj)
				ret[i] = MEL.getCopy(obj[i], i);
		}
		return ret;
	}

	MEL.to_array = 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.copyElSize = function(el, source)
	{
		var size = MEL.dom.getElementSize(source || el);
		el.style.width = (size.w - parseInt(MEL.dom.getStyle(el, "padding-left")) - parseInt(MEL.dom.getStyle(el, "padding-right"))) + "px";
		el.style.height = (size.h - parseInt(MEL.dom.getStyle(el, "padding-top")) - parseInt(MEL.dom.getStyle(el, "padding-bottom"))) + "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++)
			MEL.dom.setAttribute(el, source.attributes[i].name, source.attributes[i].value);
	}

	MEL.findPopupBestPosition = function(btn, popup)
	{
		var pos = MEL.dom.getAbsolutePos(btn);

		var btn		= {x:pos.x,	y:pos.y,	width:btn.offsetWidth,		height:btn.offsetHeight};	// + (btn.offsetHeight < 20 ? 10 : 0)
		var popup	= {x:btn.x,	y:0,		width:popup.offsetWidth,	height:popup.offsetHeight};
		var pg_size = MEL.dom.getElementSize(MEL.d.body);

		// find X
			if (pg_size.w < (btn.x + popup.width))
				popup.x = pg_size.w - popup.width;
			if (popup.x < 0) popup.x = 0;
		//

		// find Y
			if ((pg_size.h < (btn.y + btn.height + popup.height)) && (pg_size.sy < (btn.y - popup.height)))
				popup.y = btn.y - popup.height;
			else if (((btn.y - popup.height) >= 0) && (pg_size.sh > (btn.y + btn.height + popup.height)))
			{
				if ((pg_size.h < (btn.y + btn.height + popup.height)) && ((btn.y - pg_size.sy) > (pg_size.h + pg_size.sy - btn.y - btn.height)))
					popup.y = btn.y - popup.height;
				else
					popup.y = btn.y + btn.height;
			}
			if (popup.y <= 0) 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)
	{
		var pos = this.findPopupBestPosition(btn, popup);
		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, sy = e.clientY + MEL.de.scrollTop;
		return ((sx >= pos.x) && (sx <= pos.x + size.w) && (sy >= pos.y) && (sy <= pos.y + size.h));
	}

	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;
		return -1;
	}

	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.haveClass(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";
			}
		}
	}
//
