//глобальные переобозначения и fix
(function(){
	//fix на activeElement - элемент, на котором фокус
	if (document.activeElement === undefined){
		if (document.addEventListener) {
			document.addEventListener("focus", function(e){
				if (e && e.target){
					document.activeElement = (e.target == document ? null : e.target);
				}
			}, true); 
		}
	};
})();

//объект в котором храним иерархию
function tt_hierarchy(){
	this.tree = {'_':[]};//есть только корневой узел без потомков
	this.temp = [];
};
tt_hierarchy.prototype = {
	//добавляем в иерархию новую подсказку
	//param: parent_id - id родительского окна (String)
	//param: child_id - id дочернего окна (String)
	//return: [] = void
	addNode : function(parent_id, child_id){
		var arr = this.tree;
		
		parent_id = parent_id || '_';//на случай корневого элемента, когда parent_id == undefined
		if (arr[parent_id] == undefined) return false;//родитель уже должен быть в дереве
		for (var name in arr){//а потомка не должно быть
			if (mui.inArray(child_id, arr[name]) >= 0) return false;
		}
		
		arr[parent_id].push(child_id);//добавляем потомка к предку
		arr[child_id] = [];//регистрируем добавленного потомка как новый родитель без детей
	},//end addNode()
	//INTERNAL рекурсивно добавляет потомков в массив для подальшего удаления
	//param: id - id родительского окна (String)
	//return: [] = void
	addToArray : function(id){
		if (this.tree[id] == undefined || this.tree[id] == []) return false;
		var arr = this.tree[id];
		this.temp = this.temp.concat(arr);
		
		for (var i = 0, length = arr.length; i < length; ++i){
			arguments.callee.call(this, arr[i]);
		}
	},//end _delSubRecurs()
	//удаляем (скрываем) все поддеревья подсказок id включая саму id
	//param: id - id родительского окна (String)
	//return: [] = void	
	delSubTrees : function(id){
		id = id || '_';//на случай корневого элемента, когда id == undefined
		this.temp = [];
		
		var node = parent = null;		
		var arr = (id == '_') ? this.tree[id] : [id];

		for (var i = 0, length = arr.length; i < length; ++i){
			node = $(arr[i]);
			if (node){
				node.innerHTML = '';
				parent = node.parentNode;
				parent.removeChild(node);
				parent.style.position = '';
				mui.repaint(parent);
			}
		}
			
		//удаляем елемент из списка потомков
		for (var parent in this.tree){
			var pos = mui.inArray(id, this.tree[parent]);
			if (pos >= 0 && $(id)){
				this.tree[parent].splice(pos, 1);
				break;
			}
		}
		//рекурсивно удаляем потомков
		if ($(id)) {
			this.addToArray(id);
			if (id != '_') this.temp.push(id);
			else this.tree['_'] = [];
			
			var pos = -1;
			for (var i = 0, length = this.temp.length; i < length; ++i){
				pos = mui.inArray(this.temp[i], tooltip.globals.click_stack);
				if (pos >= 0){
					tooltip.globals.click_stack.splice(pos, 1);
				}
				delete this.tree[this.temp[i]];
			}
		}
	}//end delSubTrees()
};

function tooltip(){
	//глобальные переменные
	this.globals = {
		'g_timer_out' : [],//на каждую подсказку mouseover - свой таймаут
		'z-index' : 100000,
		'g_timer_in' : {},
		'click_stack' : []
	};
	//опции для подсказок
	this.settings = {
		t_in : 1200,
		t_out : 700,
		t_key : null,
		'outerclass' : 'jouter',
		'contentclass' : 'jcontent',
		'arrowclass' : 'arrow',
		'tt_top' : 9,
		'tt_left' : 23
	};
	
	//добавляем прелоадер
	var loader = new Image();		
	loader.src = "/img/preload.gif";	
	this.loader = loader;
	
	//
	//область инициализации
	//	
	this.tree = new tt_hierarchy();//создаем новый объект иерархии
	//cache для содержимого подсказок
	this.cache = {};
}

tooltip.prototype = {
	
	_template : function(id, settings, additional_opts){
		
		id = id.replace(/-outer$/, "");
		//внешняя оболочка
		var outer = document.createElement("div");
		
		outer.className = settings.outerclass;
		outer.id = id+'-outer';
		outer.style.zIndex = (tooltip.globals['z-index'] + 1000);
		
		//устанавливаем вспомогательные атрибуты
		for (var name in additional_opts){
			if (additional_opts[name] != undefined) {
				//добавляем стилевые атрибуты
				var match = name.match(/style_(\w+)/);
				if (match && match[1]){
					//для высоты делаем min-height
					if (match[1] == 'height'){
						outer.style['min-height'] = additional_opts[name];
						outer.style['_height'] = additional_opts[name];
					}
					else 
						outer.style[match[1]] = additional_opts[name];
				}
				else 
					outer.setAttribute(name, additional_opts[name]);
			}
		}
		
		//добавляем содержимое
		var html = "<div class='arrow'></div>";
		html += "<a href='javascript:void(0)' onclick='tooltip.tree.delSubTrees(\""+id+"-outer\");'>";
		html +=		"<img src='/img/close.gif' style='border:0px; position:absolute; top:15px; right:19px'>";
		html += "</a>";
					
		html += "<div id='"+id+"' class='"+settings.contentclass+"'></div>";
			
		outer.innerHTML = html;
		
		return outer;
	},
	
	getJtypeEl : function (node, num){
		var temp = node;
		for (var i = 0; i <= num; ++i){
			if (typeof node.getAttribute !== "undefined" && node.getAttribute('jtype') != undefined){
				return node;
			}
			else if (node && node.parentNode){
				if (node.className == tooltip.settings.outerclass) return temp;
				node = node.parentNode;
			}
		}
		return temp;
	},
	
	//добавляем новую подсказку
	appendTooltip : function(event, attr, srcElement, html){
		var globals = tooltip.globals;
		var settings = tooltip.settings;
		//создаем новое окно подсказки (получаем внутреннее окно с содержимым)
		var outer = tooltip._template(attr.jid, settings, {'jsub' : attr.jsub, 'style_width' : attr.jwidth, 'style_height' : attr.jheight});
		var par_id = tooltip.getParentWindowId(srcElement, settings.outerclass);
		if (par_id == '_') srcElement.appendChild(outer);
		else if (par_id){
			var par = $(par_id);			
			par.insertBefore(outer, par.firstChild);
		}
		//после добавления содержимого одязательно нужно сделать repaint для Opera
		mui.repaint(srcElement);	
		//находим div который будем заполнять содержимым
		var inner = tooltip.getInnerDiv(attr.jid, settings.contentclass);
		try {
			inner.innerHTML = mui.stripScripts(html);
		} catch(e){}
		mui.evalScripts(html);
		mui.repaint(outer);
		$(attr.jid).style['zIndex'] = ++globals['z-index'];
		
		//дополнительный функционал с таймерами для over-подсказок
		if (/mouseover/i.test(event.type)){
			var tree = tooltip.tree;
			$(attr.jid).setAttribute('type', 'over');
			//добавляем функционал на mouseout к данной подсказке
			function leaveHandler(event){
				var eid = {};//определим идентификатор подсказки
				var self = this;//дублируем, чтоб self можно было изменить
				
				//обрабатываем ситуацию, когда уходим с подскапзки и попадаем прямо на ссылку-источник
				var rel = event.relatedTarget || event.toElement;
				if (rel){
					rel = tooltip.getJtypeEl(rel, 3);
					if (typeof rel.getAttribute !== "undefined" && (rel.getAttribute('jid') != undefined) && (rel.getAttribute('jid') == self.id)){
						return;
					}
				}

				//бывает 2 случая: когда нужно обрабатывать обрамляющий span или сам источник
				if (typeof self.firstChild.getAttribute !== "undefined" && self.firstChild.getAttribute('jid')) self = self.firstChild;//связано с тем, что есть обрамляющие тег <a /> span-ы
				if (self.getAttribute('jid') && self.getAttribute('jtype') == 'mouseover') {
					eid = self.getAttribute('jid');
					clearTimeout(globals.timer_in);//если ушли не дождавшись появления подсказки то сбрасываем таймер на появление	
				}
				else eid = self.id;
				
				if (eid) {
					if (!/-outer/.test(eid)) eid += '-outer';
					clearTimeout(globals.g_timer_out[eid]);
					//ставим таймаут на удаление подсказки
					globals.g_timer_out[eid] = setTimeout(function(){
						if ($(eid) && $(eid).getAttribute('type') == 'over'){
							tree.delSubTrees(eid);
						}
					}, settings.t_out);
				}
			}
			//добавляем функционал на mousein к данной подсказке
			function enterHandler(event){
				//getParentWindowId - тут используется для того чтоб не чувствовались особенности на внешних элементах типа стрелки
				var self = this;
				if (typeof self.firstChild.getAttribute !== "undefined" && self.firstChild.getAttribute('jid')) self = self.firstChild;
				
				var eid = self.getAttribute('jid') || self.id || getParentWindowId((event.target || event.srcElement), settings.outerclass);
				if (eid) {
					if (!/-outer/.test(eid)) eid += '-outer';
					clearTimeout(globals.g_timer_out[eid]);
				}
			}
			
			//добавляем обработку mouseout/mousein на текущую подсказку
			enterHandler = mui.bind('mouseenter', enterHandler, $(attr.jid));
			leaveHandler = mui.bind('mouseleave', leaveHandler, $(attr.jid));
			//и на текущий srcElement
			mui.bind('mouseenter', enterHandler, srcElement);
			mui.bind('mouseleave', leaveHandler, srcElement);
		}
		else if (/click|contextmenu/i.test(event.type)){
			if (attr.jsub && mui.inArray(attr.jid, globals.click_stack) < 0){
				globals.click_stack.push(attr.jid);
			}
		}
		
	},
	
	//главная функция-обработчик события
	processEvent : function (event){
		var cloned_event = mui.clone(event);
		var settings = tooltip.settings;
		var globals = tooltip.globals;
		var doc_p = mui.getDocProps();
		var target_el = event.target || event.srcElement;

		srcElement = tooltip.getJtypeEl(target_el, 3);
		
		var attr = mui.getAttr(srcElement);//получаем установленные атрибуты srcElement в виде объекта
		attr.jid += '-outer';
		var srcName = srcElement.nodeName.toLowerCase();
		
		//обрабатываем второстепенные события:
		if (attr.jclose != undefined) {
			//дополнительная функциональность
			if (/-open/i.test(srcElement.className)){
				srcElement.className = srcElement.className.replace(/-open/i, "-close");
			}
			else if (/-close/i.test(srcElement.className)){
				srcElement.className = srcElement.className.replace(/-close/i, "-open");
			}			
			mui.fclose(attr.jclose, true);//указано какой елемент раскрыть/схлопнуть
		}
			
		if ( srcName == 'a' || srcName == 'img' || srcName == 'nobr' ) 
			srcElement = srcElement.parentNode;

		//обработка загрузки данных:
		if (attr.jsource != undefined || attr.content != undefined){//если нужно загрузить данные
			if (attr.jtarget != undefined){//загружаем данные в елемент id = jtarget
				if (attr.jsource != undefined && $(attr.jtarget) != undefined && mui.isOpened(attr.jtarget)){//берем данные с сервера
					//вставляем в jtarget с кеша
					if ((attr.jcache != undefined && attr.jcache.toLowerCase() != 'n') && tooltip.cache[attr.jsource]){
						$(attr.jtarget).innerHTML = mui.stripScripts(tooltip.cache[attr.jsource]);
						mui.evalScripts(tooltip.cache[attr.jsource]);
					}
					//загружаем в jtarget с сервера
					else {
						try{
							//добавляем лоадер
							target_el.style.position = "relative";
							//todo: Object Error in IE
							target_el.appendChild(tooltip.loader);
							tooltip.loader.className = "mtools-loader";
							tooltip.loader.style.cssText = "border:none; position:absolute; top:-"+(tooltip.loader.height*0.5+1)+"px; left:-"+(tooltip.loader.width*0.5+1)+"px;";
							if (mui.browser().opera){
								tooltip.loader.style.left = parseInt(tooltip.loader.style.left) + doc_p.scrollLeft + "px";
								tooltip.loader.style.top = parseInt(tooltip.loader.style.top) + doc_p.scrollTop + "px"; 
							}
							
							var o = {
								loader : tooltip.loader,
								srcElement : target_el
							};
						} catch(e){/*alert(e)*/}
						//загружаем данные кросс-доменно (JSON-метод)
						mui.loadJSON.call(o, attr.jsource, attr.jtarget, function(data, j_target){
							tooltip.cache[attr.jsource] = data;								
							$(j_target).innerHTML = mui.stripScripts(data);
							mui.evalScripts(data);
							mui.repaint($(j_target));
						});
					}
				}
				else if ($(attr.jtarget) != undefined && attr.content != undefined){
					$(attr.jtarget).innerHTML = attr.content;
				}
			}
			//открыавем новую подсказку
			else if (attr.jid != undefined){
				//если подсказка уже открыта
				var flg = false;
				if (mui.isOpened(attr.jid)) {
					//когда прикрепили к srcElement
					var child = srcElement.getElementsByTagName('div')[0];
					if (child && child.id == attr.jid) {
						flg = true;
					}
					//когда прикрепили к контейнеру, а не к srcElement
					if (!flg){
						var child = $(tooltip.getParentWindowId(srcElement, settings.outerclass)).getElementsByTagName('div')[0];
						if (child && child.id == attr.jid) {
							flg = true;
						}
					}
					
					//когда закрывать открытую подсказку
					if (/click|contextmenu/i.test(event.type) || (/mouseover/i.test(event.type) && !flg)){
						tooltip.tree.delSubTrees(attr.jid);
					}
					//открывать новую или нет
					if (flg) return false;
				};
				srcElement.style.cssText = "position: relative; z-index:" + globals['z-index'];
			
				//для того чтоб не было скачка в позиционировании
				var pos_obj = {};
				//подсказка уже была, заполняем с кеша
				if (attr.jsource != undefined && (attr.jcache != undefined && attr.jcache.toLowerCase() != 'n') && (tooltip.cache[attr.jsource])){//если принудительно выключено кеширование
					tooltip.appendTooltip(cloned_event, attr, srcElement, tooltip.cache[attr.jsource]);
				}
				//загружаем новую информацию
				else if (attr.jsource != undefined){
					//включаем loader
					srcElement.appendChild(tooltip.loader);
					tooltip.loader.className = "mtools-loader";
					tooltip.loader.style.cssText = "display:block; position:absolute; top:-"+(tooltip.loader.height*0.5+1)+"px; left:-"+(tooltip.loader.width*0.5+1)+"px;";
					
					if (mui.browser().opera){
						tooltip.loader.style.top = parseInt(tooltip.loader.style.left) + doc_p.scrollLeft + "px";
						tooltip.loader.style.top = parseInt(tooltip.loader.style.top) + doc_p.scrollTop + "px"; 
					}
					
					var o = {
						loader : tooltip.loader,
						srcElement : srcElement
					};
					
					//загружаем данные кросс-доменно (JSON-метод)
					var cloned_event = mui.clone(event);
					mui.loadJSON.call(o, attr.jsource, attr.jid, function(data, j_target){
						tooltip.cache[attr.jsource] = data;
						tooltip.appendTooltip(cloned_event, attr, srcElement, data);
						tooltip.fposition(cloned_event, attr.jid, srcElement, tooltip.getInnerDiv(attr.jid, settings.arrowclass), {"right" : "right", "bottom" : "bottom"});//позиционируем подсказку
						mui.repaint($(j_target));
					});
				}
				else {//загружаем информацию с атрибута 'content'
					attr.jsub = "y";
					tooltip.appendTooltip(cloned_event, attr, srcElement, attr.content);
				}
				
				pos_obj = tooltip.fposition(event, attr.jid, srcElement, tooltip.getInnerDiv(attr.jid, settings.arrowclass), {"right" : "right", "bottom" : "bottom"});//позиционируем подсказку
				tooltip.tree.addNode(tooltip.getParentWindowId(srcElement, settings.outerclass), attr.jid);
				
				return attr.jid;
			}
		}
		return undefined;
	},

	//главная функция-обработчик кликов
	onClickHandler : function (event){
		//элемент, внешний к тому, на котором произошло событие и который имеет нужные j-атрибуты
		var srcElement = tooltip.getJtypeEl(event.target || event.srcElement, 3);
		
		if (typeof srcElement.getAttribute !== "undefined"){
			//-------------------------------------------------------------
			var node = srcElement;
			//смотрим, кликнули на document или нет
			while (node && node.parentNode){
				if (node.className == tooltip.settings.outerclass){
					break;
				}
				node = node.parentNode;
			}	
			var pid = (!node || node.nodeType == 9) ? '_' : node.id+'-outer';
			
			//фнк рекурсивно удаляет открытые подсказки, у которых есть атрибут sub
			function recDelSub(pid, this_id){
				if (pid == undefined || !(pid in tooltip.tree.tree) || (tooltip.tree.tree[pid] == [])) return false;
				//копируем массив по значению
				var t_arr = [].concat(tooltip.tree.tree[pid]);
				for (var i = 0, length = t_arr.length; i < length; ++i){
					if (mui.inArray(t_arr[i], tooltip.globals.click_stack) >= 0 && (this_id != t_arr[i])){
						tooltip.tree.delSubTrees(t_arr[i]);
					}
					else {
						//рекурсивно вызываем себя
						arguments.callee.call(this, t_arr[i]);
					}
				}	
			}
			
			this_id = (srcElement.getAttribute('jid') && srcElement.getAttribute('jtype') == 'click') ? srcElement.getAttribute('jid') : '';
			recDelSub(pid, this_id+'-outer'/* this_id для того чтобы на данном этапе не закрыть подсказку*/);
			//-------------------------------------------------------------
			if (srcElement.getAttribute('jtype') != 'click') return;
		}//если jtype != "click" то не проводим обработку
		
		tooltip.processEvent(event);
		
		if (event.preventDefault)// necessary for addEventListener, works with traditional
			event.preventDefault();
		event.returnValue = false;// necessary for attachEvent, works with traditional
		return false;
	},
	//обработчик события mouseover для document (в то же время - это событие mouseenter для елементов DOM)
	onMouseOverHandler : function (event){
		//элемент, внешний к тому, на котором произошло событие и который имеет нужные j-атрибуты
		var srcElement = tooltip.getJtypeEl(event.target || event.srcElement, 3);		
		if (srcElement.getAttribute('jtype') != 'mouseover') return false;//если jtype != "mouseover" то не проводим обработку
				
		mouseoutHandler = function(event){
			tooltip.loader.style.display = 'none';
			clearTimeout(tooltip.globals.timer_in);//если ушли не дождавшись появления подсказки то сбрасываем таймер на появление
			mui.unbind('mouseleave', arguments.callee, srcElement);
		};
		//привязываем обработчик на елемент вызвавший событие
		mui.bind('mouseleave', mouseoutHandler, srcElement);
		
		//клонируем объект event перед вызовом его в setTimeout()
		//детальнее см.: http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/
		var cloned_event = mui.clone(event);
		clearTimeout(tooltip.globals.timer_in);//в текущий момент ожидается открытие только одной подсказки
		tooltip.globals.timer_in = setTimeout(function() {
			tooltip.processEvent(cloned_event);
		}, tooltip.settings.t_in);

		return false;
	},
	//возвращает внутренний div (DOM node) у которого className похоже на class
	//param: [id] = (String)
	//param: [class] = (String [className])
	//return: [] = (DOM node|undefined) 
	getInnerDiv : function (id, class_name){
		var element = $(id);
		if (!element) return false;
		//получаем коллекцию внутренних div
		var divs = element.getElementsByTagName('div'),
			reg = new RegExp(class_name, "i");
			
		for (var i = 0, length = divs.length; i < length; ++i){
			if (reg.test(divs[i].className)){
				return divs[i];
			}
		}
		return undefined;
	},//end getInnerDiv()
	//если находимся всередине окна на каком-то элементе
	//то узнаем id этого родительского окна (подсказки)
	//param: [target] = DOM element
	//param: [className] = String
	//return: [] = DOM node || undefined
	getParentWindowId : function (target, className){
		while (target && target.parentNode){
			if (target.className == className) return target.id;
			target = target.parentNode;
		};
		return '_';
	},//end getParentWindowId()
	//позиционирование подсказки
	//param: [event] = Event Object
	//param: [id] = String
	//param: [pos_flag] = Boolean
	//return: [] = void
	fposition : function (event, id, srcElement, arrow, pos_object){
		
		var flag = 0,
			class_name = 'arrow',
			ua = mui.browser();
		
		var el = $(id);
		if (!el) return;
		var event_xy = mui.getEventXY(event);
		
		if (ua.opera){
			el.style.margin = '0px 0px 0px 0px';
			el.style.visibility = 'hidden';
		}
		else {
			el.style.top = '0px';
			el.style.left = '0px';	 
		}
		 //узнаем позицию srcElement
		 var obj_pos = mui.getCoordsXY(el);
		
		 var params = mui.getDocProps(),
			 left = event_xy[0] - obj_pos[0] - tooltip.settings.tt_left,
			 top = event_xy[1] - obj_pos[1] + tooltip.settings.tt_top,
			 width = el.offsetWidth,
			 height = el.offsetHeight + tooltip.settings.tt_top + 1;
			
			//подсказка не вмещается по горизонтали и помещается слева
			if ((params.width - event_xy[0] + params.scrollLeft) < width && (event_xy[0] - params.scrollLeft) > width && pos_object.right != undefined){
				left -= (width - tooltip.settings.tt_left*2);
				class_name += " right";
			} else {class_name += " left";}
			//подсказка не вмещается по горизонтали и помещается сверху
			if ((params.height - event_xy[1] + params.scrollTop) < height && (event_xy[1] - params.scrollTop) > height  && pos_object.bottom != undefined){
				top -= (height + tooltip.settings.tt_top + 1);
				class_name += " top";
			} else {class_name += " bottom";}
						
			if (ua.opera){
				el.style.top = '';
				el.style.left = '';
				el.style.margin = top + 'px 0px 0px ' + left + 'px';
				el.style.visibility = 'visible';
			}
			else {
				el.style.top = top + 'px';
				el.style.left = left + 'px';
			}
	
		arrow.className = class_name;
		
		var pos_object = {};
		if (/top/i.test(class_name)) pos_object.bottom = "bottom";
		if (/right/i.test(class_name)) pos_object.right = "right";
		
		return pos_object;
	},//end fposition()
	//фнк, обрабатывающая елемент типа change (activeElement == elem)
	processData : function(elem){
		var jsource = elem.getAttribute('jsource');//адрес скрипта-обработчика
		var jtarget = elem.getAttribute('jtarget');//куда записать ответ с сервера
		var jwait = elem.getAttribute('jwait');//сколько ждем после введеной буквы
		var val = elem.value || elem.text;//контент тега
		
		if (jwait){
			clearTimeout(tooltip.t_key);
			tooltip.t_key = setTimeout(_do, parseInt(jwait));
		}
		else _do();
		
		function _do() {
			if (jsource && $(jtarget) && val){
				jsource += (jsource.match(/\?/) ? "&" : "?") + 'data_='+val;//escape(val)
				
				//это для приемственности записи		
				var o = {
					loader : tooltip.loader,
					srcElement : elem
				};			
				
				mui.loadJSON.call(elem, jsource, jtarget, function(data, jtarget){
					tooltip.cache[jsource] = data;									
					$(jtarget).innerHTML = unescape(data);
				});
			}
		}
	},
	//обработчик события onchange для input
	onKeyUpHandler : function (event){
		var elem = event.target || event.srcElement;//елемент, на котором произошло событие
		if (elem.getAttribute('jtype') == 'change'){
			tooltip.processData(elem);
		}
	},
	//обработчик нажатия клавиш
	onPressHandler : function (event){
		var key = event.charCode || event.keyCode;
		if (key == 13/*Enter Key*/) {
			var elem = document.activeElement;
			if (elem.getAttribute('jtype') == 'change'){
				tooltip.processData(elem);
			}
		};
		return true;
	}
};
var tooltip = new tooltip();
//
//добавляем обработчики к document
function bindEvents(){
	mui.bind('click', tooltip.onClickHandler);
	var userAgent = navigator.userAgent.toLowerCase();
	if (mui.browser().msie){mui.bind('contextmenu', tooltip.onClickHandler);}
	mui.bind('mouseover', tooltip.onMouseOverHandler);
	mui.bind('keyup', tooltip.onKeyUpHandler, document.activeElement);
	mui.bind('keypress', tooltip.onPressHandler);//общий обработчик на нажатие клавиш
	document.documentElement.className += ' js';
};

//когда готово дерево документа
mui.ready(bindEvents);

/*
var tt_settings = {
	t_in : 3000
};
if (tt_settings != undefined){
	tooltip.settings = mui.extend(tooltip.settings, tt_settings);	
}

tooltip.prototype = mui.extend(tooltip, {_template : function (...){
	...
	}
});
*/