var tt = new Tooltip( function(){ return document.getElementsByTagName('*');	});

function Tooltip(collectDOMfunction)
{
	// Simple JavaScript Tooltip
	// (c) endo.ch 2007, 2009 Christoph Berger, www.endo.ch

	var toolObj = this;
	this.tooltip = null; // DOM <div>-objekt des Tooltips
	this.sequencer = null; // Faderobjekt
	this.ttactive = false; // true sobald Tooltip angezeigt wird
	this.collectDOMfunction = collectDOMfunction;
	
	this.updateTT = function(e) {
		if (toolObj.ttactive) {
			x = (document.all) ? e.clientX + (document.documentElement.scrollLeft | document.body.scrollLeft) : e.pageX;
			y = (document.all) ? e.clientY + (document.documentElement.scrollTop  | document.body.scrollTop)  : e.pageY;

			toolObj.tooltip.style.left = (x + 20) + 'px';
			toolObj.tooltip.style.top 	= (y + 12) + 'px';
			toolObj.tooltip.style.display = 'block';
		}
	}
	
	this.showTT = function(element) {
		if (!element.tooltip)
			return;
		title = element.tooltip;
		toolObj.tooltip.innerHTML = '<p>'+title+'</p>';
		toolObj.ttactive = true;
		toolObj.sequencer.start( function(){ toolObj.tooltip.style.display = 'none';	toolObj.ttactive = false; });
		//toolObj.updateTT(window.event);
	}
	
	this.hideTT = function(element) {
		toolObj.sequencer.close();
		/*toolObj.tooltip.style.display = 'none';
		toolObj.ttactive = false;*/
	}
	
	this.init = function(){
		// an Stelle von  <div id="tooltip"></div>
		// im HTML Quellcode
		toolObj.tooltip = document.createElement('div');
		toolObj.tooltip.setAttribute('id','tooltip');
		toolObj.tooltip.style.position = 'absolute';
		toolObj.tooltip.style.display = 'none';
		document.getElementsByTagName('body')[0].appendChild(toolObj.tooltip);
		
		// an Stelle von  <img src=".." title="xyz" onmouseover="showTT(this)" onmouseout="hideTT(this)">
		// im HTML Quellcode
		var objArr = toolObj.collectDOMfunction();
		for(var i=0; i<objArr.length; i++){
			if (objArr[i].title){
				objArr[i].tooltip =  objArr[i].title;
				objArr[i].title = '';
				toolObj.addListener(objArr[i], 'mouseover', function(e){ toolObj.showTT(e.srcElement||this)});
				toolObj.addListener(objArr[i], 'mouseout', function(e){ toolObj.hideTT(e.srcElement||this)});
			}
		}
		toolObj.addListener(document, 'mousemove', toolObj.updateTT);
		
		toolObj.sequencer = new Sequencer(toolObj.tooltip);
		
	}
	
	this.unload = function() {
		// Safari Problem mit Back Button beheben, indem die Änderungen
		// beim Verlassen der Seite rückgängig gemacht werden
		try{
			if (navigator.vendor && navigator.vendor.match(/Apple/)){
				var objArr = toolObj.collectDOMfunction();
				for(var i=0; i<objArr.length; i++){
					if (objArr[i].tooltip){
						objArr[i].title = objArr[i].tooltip;
					}
				}
			}
		}
		catch(e) {}
	}
	
	this.addListener = function(element, event, listener, bubble) {
		if(element.addEventListener) {
			if(typeof(bubble) == 'undefined'){
				bubble = false;
			}
			element.addEventListener(event, listener, bubble);
		} else if(document.attachEvent) {
			element.attachEvent("on" + event, listener);
		}
	}
	
	// init nach Ende des Ladevorgangs aufrufen
	this.addListener(window, 'load', this.init);
	this.addListener(window, 'unload', this.unload);
}

function Fader(fadeElemnt, increment)
{
	// Simple JavaScript Fade Class
	// (c) endo.ch 2010 Christoph Berger, www.endo.ch
	
	var thisObject = this; // Instanzclosure für setTimeout Aufruf
	
	increment = (increment == 0 ? 100 : increment); // increment darf nicht 0 sein
	
	this.fadeElemnt = fadeElemnt; // Objekt, das eingeblendet wird
	this.increment = increment; // Transparenzänderung pro Aufruf in Promille; positiv:fade in, negativ: fade out;
	
	this.opacity = 0;	// Momentane Transparenz in Tausendstel (0%% = ganz transparent). Startwertfestlegung in reset()
	this.maxOpacity = 1000;	// Standardwert: 1000 = völlig deckend
	this.delay = 50; // Millisekunden zwischen Aufrufen
	this.timeOutHandler = false;
	
	this.start = function (callbackFunc) {
		thisObject.callbackFunc = callbackFunc; // wird aufgerufen, sobald die Überblendung abgeschlossen ist
		thisObject.fade();
	}
	
	this.reset = function () {
		thisObject.opacity = (thisObject.increment > 0 ? 0 : thisObject.maxOpacity);
		thisObject.changeOpacity(thisObject.opacity);
		window.clearTimeout(thisObject.timeOutHandler);
	}
	
	this.fade = function () {
		thisObject.opacity = Math.max(Math.min(thisObject.opacity + thisObject.increment, thisObject.maxOpacity), 0);
		thisObject.changeOpacity(thisObject.opacity)
		
		if (thisObject.opacity == thisObject.maxOpacity || thisObject.opacity == 0) {
			thisObject.callbackFunc();
		} 
		else {
			thisObject.timeOutHandler = window.setTimeout (thisObject.fade, thisObject.delay);
		}
	}
	
	this.changeOpacity = function (opacity) {
		thisObject.fadeElemnt.style.opacity = opacity/1000;
		thisObject.fadeElemnt.style.filter = 'alpha(opacity='+Math.floor(opacity/10)+')';
		//thisObject.fadeElemnt.style.display = (opacity == 0) ? 'none' : 'block';
			
	}
	
	
	this.reset();
}

function Sequencer(fadeElemnt)
{
	// Ein- und ausblenden, Ablauf für Tooltip-Verhalten
	// (c) endo.ch 2011 Christoph Berger, www.endo.ch
	
	var thisObject = this; // Instanzclosure für setTimeout Aufruf
	this.fadeElemnt = fadeElemnt; // Objekt, das eingeblendet wird
	
	this.delay = 150; // Verzögerung in ms, danach beginnt das Einblenden
	this.fadeinIncrement = 400; // Schrittweite beim Einblenden in Tausendel (1 < n < 1000). klein = langsam, gross = schnell
	this.sustain = 2000; // Anzeigedauer in ms, danach beginnt das Ausblenden
	this.fadeoutIncrement = -200; // Schrittweite beim Ausblenden in Tausendel (-1 > n > -1000). 
	this.maxOpacity = 900; // Opacity des fertig eingeblendeten Tooltips (1 < n < 1000) 1000 = völlig deckend
	
	this.seqPosition = 0;
	this.timeOutHandler = false;
	
	this.fadeIn = new Fader(this.fadeElemnt, this.fadeinIncrement);
	this.fadeOut = new Fader(this.fadeElemnt, this.fadeoutIncrement);
	this.fadeIn.maxOpacity = this.maxOpacity;
	this.fadeOut.maxOpacity = this.maxOpacity;
	
	this.start = function (callbackFunc) {
		//alert('start '+thisObject.seqPosition);
		thisObject.callbackFunc = callbackFunc; // wird aufgerufen, sobald die Überblendung abgeschlossen ist
		thisObject.reset();
		
		if (thisObject.seqPosition == 2 || thisObject.seqPosition == 3 || thisObject.seqPosition == 4 )
			thisObject.step2();
		else
			thisObject.step1();	
	}
	
	this.close = function () {
		//alert('close '+thisObject.seqPosition);
		if (thisObject.seqPosition == 1 ) {
			this.reset();
			thisObject.step5();
		}
		else if (thisObject.seqPosition == 2 || thisObject.seqPosition == 3 || thisObject.seqPosition == 4 ){
			this.reset();
			thisObject.step4();
		}
	}
	
	this.step1 = function () {	
		// Delay
		//alert('1');
		thisObject.seqPosition = 1;
		thisObject.timeOutHandler = window.setTimeout (thisObject.step2, thisObject.delay);
	}
	
	this.step2 = function () {
		// Fade in
		//alert('2');
		thisObject.seqPosition = 2;
		thisObject.timeOutHandler = false;
		thisObject.fadeIn.start(function(){ thisObject.step3(); });
	}
	
	this.step3 = function () {
		// Sustain
		//alert('3');
		thisObject.seqPosition = 3;
		thisObject.timeOutHandler = window.setTimeout (thisObject.step4, thisObject.sustain);
	}
	
	this.step4 = function () {
		// Fade out
		//alert('4');
		thisObject.seqPosition = 4;
		thisObject.timeOutHandler = false;
		thisObject.fadeOut.start(function(){ thisObject.step5(); });
	}
	
	this.step5 = function () {
		// Terminate
		//alert('5');
		thisObject.seqPosition = 0;
		thisObject.callbackFunc();
	}
	
	this.reset = function () {
		if (thisObject.timeOutHandler !== false)
			window.clearTimeout(thisObject.timeOutHandler);
		thisObject.timeOutHandler = false;
		
		thisObject.fadeOut.reset();
		thisObject.fadeIn.reset();
		
	}	
	
	this.reset();
}

