/**
* Filename................: mel.js
* Project.................: web pages SDK
* Last Modified...........: $Date: 26/9/2007 19:28:04 $
* CVS Revision............: $Revision: 0.0.24 $
* 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)
				{
					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 nr = tbl.insertRow(idx);
			this.setStyle(nr, this.getStyle(row))
			nr.className = row.className;
			var arr = row.childNodes;
			for (var i=0; i<arr.length; i++)
				nr.appendChild(arr[i].cloneNode(true));
		}
	}
//


// 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(/d/, (dt.getDate() < 10 ? "0" : "") + dt.getDate());
			tpl = tpl.replace(/m/, (dt.getMonth() < 9 ? "0" : "") + (dt.getMonth()+1));
			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;
//

/*
// Drag&Drop functions
	MEL.dragdrop = {

		start_pos: [],
		start_offset: [],
		prev_doc_ondown: null,
		el_arr: [],
		el_drag: null,
		in_use: [],

		__hFalse: function(e)
		{
			return false;
		},

		__hMouseMove: function(e)
		{
			e = e || event;
			var dd = MEL.dragdrop;
			var el_arr = dd.el_arr;
			var el_drag = dd.el_drag;

			if (el_arr)
			{
				var el = el_arr[0];
				var trg = (e.srcElement || e.target).tagName;
				if ((trg == "INPUT") || (trg == "SELECT") || (trg == "TEXTAREA") || (trg == "BUTTON") || (trg == "A")) return false;

				if (!el_drag)
				{
					MEL.event.removeListener(el, "mouseup", dd.__hMouseUp);
					if (MEL.dom.haveClass(el, "draggable") && el_arr[1])
					{
						el_drag = el.cloneNode(true);
						MEL.dom.appendClass(el_drag, "draggable_clone");
						el_drag.style.position = "absolute";
						el_drag.style.margin = "0";
						MEL.dom.appendClass(el, "dragging");
						el.parentNode.insertBefore(el_drag, el);
					}
					else
						el_drag = el;

					MEL.setupElSize(el_drag, el);
					MEL.event.addListener(el_drag, "mouseup", dd.__hMouseUp);
					dd.el_drag = el_drag;
				}

				if (el_arr[3])
				{
					if (el_arr[3].tagName == "TD")
					{
						var	new_w = (dd.start_pos.w + (e.clientX - dd.start_offset[0]));
						el_arr[3].style.width = (new_w >= 0 ? new_w : 0) + "px";
					}
					else
					{
						var	new_h = (dd.start_pos.h + (e.clientY - dd.start_offset[1]));
						el_arr[3].style.height = (new_h >= 0 ? new_h : 0) + "px";
					}
				}
				else
				{
					var box = el_arr[2].length > 1 ? MEL.d.body : el_arr[2][0];
					var psize = MEL.dom.getElementSize(box);
					var pos = MEL.dom.getAbsolutePos(box);

					var new_x = dd.start_pos.x + e.clientX - dd.start_offset[0];
					var new_y = dd.start_pos.y + e.clientY - dd.start_offset[1];

					if (new_x < pos.x) new_x = pos.x;
					else if (new_x + el_drag.offsetWidth > psize.w + pos.x) new_x = psize.w + pos.x - el_drag.offsetWidth;

					if (new_y < pos.y) new_y = pos.y;
					else if (new_y + el_drag.offsetHeight > psize.h + pos.y) new_y = psize.h + pos.y - el_drag.offsetHeight;

					el_drag.style.left = new_x + "px";
					el_drag.style.top = new_y + "px";

					// TODO: count and insert delimiters
				}
			}
			MEL.event.cancel(e);
			return false;
		},

		__hMouseUp: function(e)
		{
			e = e || event;
			var dd = MEL.dragdrop;
			if (!dd.el_arr) return;

			MEL.event.removeListener(MEL.d, "mousemove", dd.__hMouseMove);
			MEL.dom.removeClass(dd.el_arr[0], "dragging");
			MEL.event.removeListener(MEL.d, "mouseup", dd.__hMouseUp);
			if (dd.el_drag)
			{
				MEL.event.removeListener(dd.el_drag, "mouseup", dd.__hMouseUp);
				if (MEL.dom.haveClass(dd.el_arr[0], "draggable") && dd.el_arr[1])
				{
					dd.el_drag.parentNode.removeChild(dd.el_drag);
					dd.el_arr[0].style.position = "static";
				}
				dd.el_drag = null;
			}
			dd.el_arr = null;
		},

		__hMouseDown: function(e)
		{
			e = e || event;
			var i, el = e.srcElement || e.target;

			var trg = el.tagName;
			if ((trg == "INPUT") || (trg == "SELECT") || (trg == "TEXTAREA") || (trg == "BUTTON") || (trg == "A")) return false;

			while (el.style.position != "absolute" && !MEL.dom.haveClass(el, "draggable")) el = el.parentNode;

			var dd = MEL.dragdrop;
			var in_use = dd.in_use;
			for (i in in_use)
				if (in_use[i][0] == el) { dd.el_arr = in_use[i]; break; }

			dd.start_offset = [e.clientX, e.clientY];
			if (el.style.position == "absolute")
			{
				if (!el.style.left) el.style.left = "0";
				if (!el.style.top) el.style.top = "0";
				dd.start_pos = {x:parseInt(el.style.left), y:parseInt(el.style.top)};
			}
			else if (dd.el_arr[3])
			{
				dd.start_pos = MEL.dom.getElementSize(dd.el_arr[3]);
			}
			else
			{
				var pos = MEL.dom.getAbsolutePos(el);
				dd.start_pos = {x:pos.x, y:pos.y};
			}

			MEL.event.addListener(MEL.d, "mousemove", dd.__hMouseMove);
			MEL.event.addListener(MEL.d, "mouseup", dd.__hMouseUp);
			MEL.d.onmousedown = dd.__hFalse;
			MEL.event.cancel(e);
		},


		init: function(el, dockable, parents, resizable)
		{
			if (!parents) parents = [MEL.d.body];
			this.in_use.push([el, dockable, (parents.length ? parents : [parents]), resizable]);
			MEL.event.addListener(el, "mousedown", this.__hMouseDown);
		},


		remove: function(el)
		{
			var in_use = this.in_use;
			for (var i in in_use)
				if (in_use[i][0] == el) { in_use.splice(i, 1); break; }
			MEL.event.removeListener(el, "mousedown", this.__hMouseDown);
		}
	}
//
*/

// Popup functions
	MEL.popup = {

		cfg: {
			X: false,
			Y: false,
			WIDTH: "320px",
			HEIGHT: "200px",
			PARENT: null,

			BACKGROUND: "#000",
			OPACITY: 0.5,
			DRAGNDROP: 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;
				}
			}
			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.DRAGNDROP)
				MEL.dragdrop.init(popup_form);

			if (!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;
		},


		close: 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";
			}
		}

	}
//


// 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(arg, obj, e)
	{
		var t = typeof arg;
		if (t == "function") arg(obj, e);
		else if (t == "string") eval(arg);
	}

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

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