/*
Externe musi byt nadefinovano:

BASE_LOC_PATH

Cele cesty k obrazkum pro bary (toggleBar(), initBar()).
BAR_OPEN_IMG
BAR_CLOSE_IMG
*/

var DEBUG_MODE = false;
var BUBBLE_OOBH = true; // only one bubble hiding - postupne skryvat se bude akorat posledni


function getObj(id) {
	if (document.getElementById) {
		return document.getElementById(id);
	}
	return null;
}

function debug(msg) {
	if (!DEBUG_MODE) return;
	var d = getObj('JSDebug');
	if (!d) {
		if (!document.createElement || !document.appendChild || !document.body) return;
		d = document.createElement('SPAN');
		if (!d) return;
		d.id = 'JSDebug';
		d.style.position = 'absolute';
		d.style.top = d.style.right = '0px';
		d.style.width = '200px';
		d.style.padding = '1px';
		d.style.backgroundColor = '#ffffff';
		document.body.appendChild(d);
	}
	d.innerHTML += msg+'<br />';
}

function getPos(obj) {
	var l = t = 0;
	if (obj && obj.offsetParent) {
		l = obj.offsetLeft;
		t = obj.offsetTop;
		while (obj = obj.offsetParent) {
			l += obj.offsetLeft;
			t += obj.offsetTop;
		}
	}
	return [l,t];
}

function getMousePos(e) {
	var x = y = 0;
	if (e.pageX || e.pageY) { // Non IE, k document
		x = e.pageX;
		y = e.pageY;
	} else if ((e.clientX || e.clientY) && document.body) { // IE, Mozilla, Opera...; k window
		x = e.clientX + document.body.scrollLeft;
		y = e.clientY + document.body.scrollTop;
		if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { // IE
			x += document.documentElement.scrollLeft ? document.documentElement.scrollLeft : 0;
			y += document.documentElement.scrollTop ? document.documentElement.scrollTop : 0;
		}
	}
	return [x,y];
}

/** Sirka a vyska viditelneho dokumentu. */
function getViewDimensions() {
	var w = h = 0;
	if (window.innerWidth || window.innerHeight) {
		//Non-IE
		w = window.innerWidth ? window.innerWidth : 0;
		h = window.innerHeight ? window.innerHeight : 0;
	} else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) { // Explorer 6 Strict Mode
		//IE 6+ in 'standards compliant mode'
		w = document.documentElement.clientWidth?document.documentElement.clientWidth:0;
		h = document.documentElement.clientHeight?document.documentElement.clientHeight:0;
	} else if (document.body) { // other Explorers (IE 4 compatible)
		w = document.body.clientWidth?document.body.clientWidth:0;
		h = document.body.clientHeight?document.body.clientHeight:0;
	}
	return [w,h];
}

/** Posunuti okna ci dokumentu pri skrolovani. */
function getViewScrollOffset() {
	var x = y = 0;
	// Pokud neni treba, jedno z page-Offset nemusi byt nadefinovo
	if (self.pageXOffset || self.pageYOffset) { // all except Explorer (Netscape compliant)
		x = self.pageXOffset ? self.pageXOffset : 0;
		y = self.pageYOffset ? self.pageYOffset : 0;
	} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
		// Explorer 6 Strict (standards compliant mode)
		x = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : 0;
		y = document.documentElement.scrollTop ? document.documentElement.scrollTop : 0;
	} else if (document.body) { // all other Explorers (DOM compliant)
		x = document.body.scrollLeft ? document.body.scrollLeft : 0;
		y = document.body.scrollTop ? document.body.scrollTop : 0;
	}
	return [x,y];
}

function isParent(parentObj, childObj) {
	while (childObj && childObj != parentObj && childObj.nodeName != 'BODY') {
		childObj = childObj.parentNode;
	}
	return childObj == parentObj ? true : false;
}

function getBubbleParent(childObj) {
	while (childObj.onmouseover != showBubble && childObj.nodeName != 'BODY') {
		childObj = childObj.parentNode;
	}
	return childObj.onmouseover == showBubble ? childObj : null;
}

/** opacity od 0 - 100 */
function setOpacity(obj, opacity) {
	obj.style.filter = 'alpha(opacity='+opacity+')';
	obj.style.opacity = opacity/100;
}

function hidingBubbles() {
	var max = 4;
	for (var i=0; i<hidingBubblesArray.length; i++) {
		o = hidingBubblesArray[i];
		
		if (hidingBubblesArray.length > max) o.hidingBubble = 0;
		else o.hidingBubble -= 10;
		
		if (o.hidingBubble > 0) {
			setOpacity(o, o.hidingBubble);
		} else {
			hidingBubblesArray.splice(i--, 1);
			o.isHiding = false;
			o.isVisible = false;
			o.style.display = 'none';
			o.style.visibility = 'hidden';
			debug('hidden (from hiding)');
		}
	}
	if (!hidingBubblesArray.length) {
		clearInterval(hidingBubblesInterval);
	}
}

function setVisibleBubble(obj) {
	if (obj.isHiding) {
		for (var i=0; i<hidingBubblesArray.length; i++) {
			if (hidingBubblesArray[i] == obj) {
				hidingBubblesArray.splice(i, 1);
				break;
			}
		}
	}
	if (BUBBLE_OOBH && window.hidingBubblesArray && hidingBubblesArray.length) {
		for (var i=0; i<hidingBubblesArray.length; i++) {
			setHideBubble(hidingBubblesArray[i], true);
		}
		hidingBubblesArray = new Array();
		clearInterval(hidingBubblesInterval);
	}
	obj.hidingBubble = 100;
	obj.isHiding = false;
	obj.isVisible = true;
	// Pro IE opacity az po visible! Jinak se podruhe nezobrazi.
	obj.style.visibility = 'visible';
	obj.style.zIndex = 5;
	setOpacity(obj, obj.hidingBubble);
	debug('visible');
}

function setHideBubble(obj, now) {
	if (now || !window.setInterval || !([].splice)) {
		obj.isHiding = false;
		obj.isVisible = false;
		obj.style.visibility = 'hidden';
		debug('hidden (no hiding)');
		return;
	}
	obj.hidingBubble = 100;
	obj.isHiding = true;
	obj.style.zIndex = 4;
	if (!window.hidingBubblesArray) {
		window.hidingBubblesArray = [];
	}
	hidingBubblesArray[hidingBubblesArray.length] = obj;
	if (hidingBubblesArray.length == 1) {
		hidingBubblesInterval = setInterval(hidingBubbles, 60);
	}
	debug('hiding...');
}

/** Muze se pouzit jako inline onmouseover kdyz se nepouzije registrace. */
function showBubble(e, bubbleID) {
	if (!e) var e = window.event;
	var target = e.target || e.srcElement;
	var relatedTarget = e.relatedTarget || e.toElement;
	var b = bubbleID ? getObj(bubbleID) : (target.bubbleObj ? target.bubbleObj : null);
	var pos = getMousePos(e);
	
	if (!b) {
		// Uzivatel mohl prejet mysi moc rychle a udalost mi dal jen potomek.
		var t = getBubbleParent(target);
		if (t) { // ...ano.
			b = bubbleID ? getObj(bubbleID) : (t.bubbleObj ? t.bubbleObj : null);
			if (!b) return;
			if (target == b) return; // Ta sama bublina na kterou jsem najel
			target = t;
			// getPos(target) pokud bych zjistoval pozici objektu
		} else {
			return;
		}
	}
	
	// Neozbrazovat pokud neni treba (prejizdeni - pruchody udalosti)
	if (b.isVisible) {
		// Neskryva se
		if (!b.isHiding) return;
	}
	
	// Musim nadefinovat pro bublinu - nemusi se jiz spustit hideBubble()
	b.onmouseout = function(ev) {
		if (!ev) var ev = window.event;
		var _target = ev.target || ev.srcElement;
		var _relatedTarget = ev.relatedTarget || ev.toElement;
		
		// Jiz je skryta ci se skryva
		if (!b.isVisible || b.isHiding) return;
		// Objekt (s onmouseover) je rodic objektu kam smeruje tato udalost
		// (ktera bude mit onmouseover)
		if (isParent(target, _relatedTarget)) return;
		// Objekt, co bude mit po teto udalosti onmouseover (tez podminka vyse),
		// je mezi (i neprimymi!) potomky bubliny. Tj. kvuli vnorenym tagum
		// v bubline, pres ktere udalosti prochazi.
		// Tez napr. rychle trhnuti mysi zpusobi, ze out ma element v! bubline
		// a over mimo bublinu.
		if (isParent(b, _relatedTarget)) return;
		
		debug('set hide (from bubble)');
		setHideBubble(b, false);
	}
	b.onmouseover = function (ev) {
		if (!b.isHiding) return;
		debug('set visible (from bubble)');
		setVisibleBubble(b);
	}
	// Umistim do body - zbavim se zdedenych stylu a nezadoucich prokliku na aktivni prvky
	if (document.body && document.createElement) {
		if (b.parentNode != document.body) {
			document.body.appendChild(b.parentNode.removeChild(b));
		}
	}
	// Zobrazeni
	b.style.left = b.style.top = '0px';
	b.style.visibility = 'hidden';
	b.style.display = 'block'; // Ujisteni ze neni none. Musi byt pred nastavenim pozice.
	
	var left = pos[0]+8;
	var top = pos[1]+8;
	var dim = getViewDimensions();
	var scroll = getViewScrollOffset();
	if (b.offsetWidth > dim[0]) {
		left = scroll[0];
	}
	else if (left-scroll[0]+b.offsetWidth > dim[0]) {
		left = pos[0]-((pos[0]-scroll[0]+b.offsetWidth)-dim[0]);
	}
	if (b.offsetHeight > dim[1]) {
		top = scroll[1];
	}
	else if (top-scroll[1]+b.offsetHeight > dim[1]) {
		top = pos[1]-((pos[1]-scroll[1]+b.offsetHeight)-dim[1]);
	}
	
	b.style.left = left+'px';
	b.style.top = top+'px';
	debug('set visible');
	setVisibleBubble(b);
}

/** Muze se pouzit jako inline onmouseout kdyz se nepouzije registrace. */
function hideBubble(e, bubbleID) {
	if (!e) var e = window.event;
	var target = e.target || e.srcElement;
	var relatedTarget = e.relatedTarget || e.toElement;
	var b = bubbleID ? getObj(bubbleID) : (target.bubbleObj ? target.bubbleObj : null);
	
	if (!b) {
		// Uzivatel mohl prejet mysi moc rychle a udalost mi dal jen potomek...
		var t = getBubbleParent(target);
		if (t) { // ...ano.
			target = t;
			b = bubbleID ? getObj(bubbleID) : (target.bubbleObj ? target.bubbleObj : null);
			if (!b) return;
			if (target == relatedTarget) return;
		} else {
			return;
		}
	}
	if (!b.isVisible) return;
	if (isParent(b, relatedTarget)) return;
	if (isParent(target, relatedTarget)) return;
	
	debug('set hide');
	setHideBubble(b, false);
}

/**
Zaktivuje bubliny, ktere maji tridu bubble a v 1. urovni span s tridou
config a uvnitr v 1. urovni spany s tridami, jez znaci konfiguracni direktivy:
id - povinne; aktivacni element
Napr.:
<div class="bubble"> <!-- Muze obsahovat i jine tridy. -->
	Text v bubline...
	<span class="config"><span class="id">IDElementu</span></span>
</div>
*/
function registerBubbles() {
	if (!document.getElementsByTagName) return;
	var configs = document.getElementsByTagName('SPAN');
	if (!configs || !configs.length) return;
	
	for (var i=0; i<configs.length; i++) {
		if (configs[i].className != 'config') continue;
		var bubble = configs[i].parentNode;
		if (!bubble || bubble.className.indexOf('bubble') == -1) continue;
		
		var config_id = null;
		for (var j=0; j<configs[i].childNodes.length; j++) {
			if (configs[i].childNodes[j].className == 'id') config_id = configs[i].childNodes[j];
		}
		
		if (!config_id) continue;
		var activationElement = getObj(config_id.innerHTML);
		if (!activationElement) continue;
		activationElement.bubbleObj = bubble;
		activationElement.onmouseover = showBubble;
		activationElement.onmouseout = hideBubble;
	}
}
