
/**-------------------------------------------------------------
 * getStyleProp
 * -------------------------------------------------------------
 * get a style property of an object
 * -------------------------------------------------------------
 */
function getStyleProp(obj,property) {
	var stl=getStyle(obj);
	if (!stl) return "";
	return stl[property];
}

/**-------------------------------------------------------------
 * setStyleProp
 * -------------------------------------------------------------
 * set a style property to an object
 * -------------------------------------------------------------
 */
function setStyleProp(obj,property,value) {
	if (obj) obj.style[property]=value;
}

/**-------------------------------------------------------------
 * getStyle
 * -------------------------------------------------------------
 * @return the style of an object
 * -------------------------------------------------------------
 */
function getStyle(obj) {
 if (!obj) return null;
 if(window.getComputedStyle) return window.getComputedStyle(obj,"");
 if(obj.currentStyle) return obj.currentStyle;
 if(obj.style)  return obj.style;
 return null;
}

/**-------------------------------------------------------------
 * Converts hsl-color to a rgb-color.
 * -------------------------------------------------------------
 * set a style property to an object
 * -------------------------------------------------------------
 */
function Hsl2RgbInteger(h, s, l) {
  var m1, m2;
	if (l<=0) 
		return new Array(0,0,0);
  else if(l<=0.5)
    m2 = l*(1+s);
  else
    m2 = l+s-l*s;

  m1 = 2*l-m2;

  if(s==null || String(s)=="NaN" || s==0)
  {
    //if(h==null || String(h)=="NaN")
    //{
      r=g=b=parseInt(l*255);
      return new Array(r,g,b);
    //}
    //else
    	 //return null;
  }

  r = compute(m1, m2, h+120);
  g = compute(m1, m2, h);
  b = compute(m1, m2, h-120);

  //now we have rgb-values which are between 0 to 1 but we want to have value between 0 to 255
  r = Math.floor(r*255);
  g = Math.floor(g*255);
  b = Math.floor(b*255);
  return new Array(r, g, b);

  function compute(n1, n2, hue)
  {
    var value;

    if(hue>360)
      hue = hue-360;
    else if(hue<0)
      hue = hue+360;

    if(hue<60)
      value = n1+(n2-n1)*hue/60;
    else if(hue<180)
      value = n2;
    else if(hue<240)
      value = n1+(n2-n1)*(240-hue)/60;
    else
      value = n1;

    return value;
  }
}

function Hsl2RgbHex(h, s, l) {
  var vInt = Hsl2RgbInteger(h, s, l);
  return RgbInteger2RgbHex(vInt[0], vInt[1], vInt[2]);
}

function RgbInteger2RgbHex(r, g, b)
{
  return "#"+Integer2Hex(r)+Integer2Hex(g)+Integer2Hex(b);
}

/*
  Converts an integer-value to a hex-value.

  Input:  Hex-value (example: ff)

  Output: Integer-value (example: 255)
*/
function Hex2Integer(hex)
{
  return parseInt(hex, 16);
}

/*
  Converts rgb-color to a hsl-color.

  Input:	 r (rgb-color red; expected range [0, 255])
  	 g (rgb-color green; expected range [0, 255])
          b (rgb-color blue; expected range [0, 255])

  Output: Array with hsl-color-values.
          h (hsl-color hue; expected range [0, 360])
          s (hsl-color saturation; expected range [0, 1])
          l (hsl-color lightness; expected range [0, 1])
*/
function RgbInteger2Hsl(r, g, b)
{
  var h, s, l;
  var min, max, delta;

  min = Math.min(Math.min(r,g), b);
  max = Math.max(Math.max(r,g), b);

  l = ((max+min)/2)/255;            	//l
	
	if (l<=0.0) return new Array(0,0,0);
	else if (l>=1.0) return new Array(0,0,1);
	else if(l<=0.5)				//s
    s =  ((max+min)!=0.0)? (max-min)/(max+min):0;
  else
    s = ((2-max-min)!=0.0)? (max-min)/(2-max-min):0;

  delta = max-min;
	if (delta==0.0) {
		return new Array(0,0,l);
	}
  else if(r==max)
  {
    h = (g-b)/delta;			//between yellow and magenta
  }
  else if(g==max)
  {
    h = 2+((b-r)/delta);			//between cyan and yellow
  }
  else
  {
    h = 4+((r-g)/delta);			//between magenta and cyan
  }

  h = h*60;				//degree

  if(h<0)
    h = h+360;

  return new Array(h, s, l);
}

/*
  Converts a hex-value to an integer-value.

  Input:  Integer-value (example: 255)

  Output: Hex-value (example: ff)
*/
function Integer2Hex(integer) {
   var hexValues = new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F");
   var hexDigit1 = Math.floor(integer / 16);
   var hexDigit2 = (integer % 16);
   return hexValues[hexDigit1] + hexValues[hexDigit2];
}

/*
  Converts a hex-value to an integer-value.

  Input:  String of rgb-color in hex-code (example: #fff or #ffffff)

  Output: Array which consists of the rgb-color as integer-code (example: 255, 255, 255)
*/
function RgbHex2RgbInteger(v)
{
  var r, g, b;
  v = v.replace(/#/, "");

  if(v.length==3)
  {
    r = Hex2Integer(v.substr(0, 1)+v.substr(0, 1));
    g = Hex2Integer(v.substr(1, 1)+v.substr(1, 1));
    b = Hex2Integer(v.substr(2, 1)+v.substr(2, 1));
  }
  else
  {
    r = Hex2Integer(v.substr(0, 2));
    g = Hex2Integer(v.substr(2, 2));
    b = Hex2Integer(v.substr(4, 2));
  }

  return new Array(r, g, b);
}

/*
  Converts rgb-color to a hsl-color.

  Input:  rgb-color in hex-code (e.g. #123456)

  Output: Array with hsl-color-values.
          h (hsl-color hue; expected range [0, 360])
          s (hsl-color saturation; expected range [0, 1])
          l (hsl-color lightness; expected range [0, 1])
*/
function RgbHex2Hsl(v) {
	var vInt = RgbHex2RgbInteger(v);
	return RgbInteger2Hsl(vInt[0],vInt[1],vInt[2]);
}

/*
  Converts hsv-color to a rgb-color.

  Input:  Array with hsb-color-values.
          h (hsv-color hue; expected range [0, 360])
          s (hsv-color saturation; expected range [0, 1])
          v (hsv-color value/grey; expected range [0, 1])

  Output: rgb-color in hex-code (e.g. #123456)
*/
function Hsv2RgbHex(h, s, v)
{
  var vInt = Hsv2RgbInteger(h, s, v);
  
  var ret = RgbInteger2RgbHex(vInt[0], vInt[1], vInt[2]);
  
  return ret;

}

/*
  Converts hsv-color to a rgb-color.

  Input:  Array with hsb-color-values.
          h (hsv-color hue; expected range [0, 360])
          s (hsv-color saturation; expected range [0, 1])
          v (hsv-color value/grey; expected range [0, 1])

  Output: r (rgb-color red; expected range [0, 255])
  	 g (rgb-color green; expected range [0, 255])
          b (rgb-color blue; expected range [0, 255])
*/
function Hsv2RgbInteger(h, s, v)
{
  var i;
  var f, p, q, t;
  var r, g, b;

  if(s==0)
  {
    //achromatic {grey}
    r = g = b = Math.floor(v*255);
    return new Array(r, g, b);
  }

  h = h/60;				//sector 0 to 5
  i = Math.floor(h);
  f = h-i;         			//factorial part of h
  p = v*(1-s);
  q = v*(1-s*f);
  t = v*(1-s*(1-f));

  switch(i)
  {
    case 0:
      r = v;
      g = t;
      b = p;
      break;
    case 1:
      r = q;
      g = v;
      b = p;
      break;
    case 2:
      r = p;
      g = v;
      b = t;
      break;
    case 3:
      r = p;
      g = q;
      b = v;
      break;
    case 4:
      r = t;
      g = p;
      b = v;
      break;
    default:	//case 5
      r = v;
      g = p;
      b = q;
      break;
  }

  //now we have rgb-values which are between 0 to 1 but we want to have value between 0 to 255
  r = Math.floor(r*255);
  g = Math.floor(g*255);
  b = Math.floor(b*255);
  return new Array(r, g, b);
}

/*
  Converts rgb-color to a hsv-color.

  Input:	 r (rgb-color red; expected range [0, 255])
  	 g (rgb-color green; expected range [0, 255])
          b (rgb-color blue; expected range [0, 255])

  Output: Array with hsb-color-values.
          h (hsv-color hue; expected range [0, 360])
          s (hsv-color saturation; expected range [0, 1])
          v (hsv-color value/grey; expected range [0, 1])
*/
function RgbInteger2Hsv(r, g, b)
{
  var h, s, v;
  var min, max, delta;

  min = Math.min(Math.min(r,g), b);
  max = Math.max(Math.max(r,g), b);
  v = max/255;				//v

  delta = max-min;

  if(max!=0)
    s = delta/max;			//s
  else
  {
    //r = g = b = 0			//s = 0, v is undefined
    s = 0;
    h = -1;
    return new Array(h, s, v);
  }

  if(r==max)
  {
    h = (g-b)/delta;			//between yellow and magenta
  }
  else if(g==max)
  {
    h = 2+((b-r)/delta);			//between cyan and yellow
  }
  else
  {
    h = 4+((r-g)/delta);			//between magenta and cyan
  }

  h = h*60;				//degree

  if(h<0)
    h = h+360;

  return new Array(h, s, v);
}

/*
  Converts rgb-color to a hsv-color.

  Input:  rgb-color in hex-code (e.g. #123456)

  Output: Array with hsb-color-values.
          h (hsv-color hue; expected range [0, 360])
          s (hsv-color saturation; expected range [0, 1])
          v (hsv-color value/grey; expected range [0, 1])
*/
function RgbHex2Hsv(v)
{
  var vInt = RgbHex2RgbInteger(v);
 
  var hsv = RgbInteger2Hsv(vInt[0],vInt[1],vInt[2]);
 
  return hsv;
}
/**-------------------------------------------------------------
 * rgbConvert
 * -------------------------------------------------------------
 * @return hex coded color from "rgb(r,g,b)"
 * -------------------------------------------------------------
 */
function rgbConvert(str) {
	if (!str) return "#000000";
	if (str.charAt(0)=='#' && str.length == 7 ) return str;
	 // convert rgb(r,g,b) to #rrggbb
   str = str.replace(/rgb\(|\)/g, "").split(",");
   str[0] = parseInt(str[0], 10).toString(16).toLowerCase();
   str[1] = parseInt(str[1], 10).toString(16).toLowerCase();
   str[2] = parseInt(str[2], 10).toString(16).toLowerCase();
   str[0] = (str[0].length == 1) ? '0' + str[0] : str[0];
   str[1] = (str[1].length == 1) ? '0' + str[1] : str[1];
   str[2] = (str[2].length == 1) ? '0' + str[2] : str[2];
   return ('#' + str.join(""));
}



var g_faders = {};


/**-------------------------------------------------------------
 * -------------------------------------------------------------
 * objectTimer
 * -------------------------------------------------------------
 * class objectTimer implements a simple timer and an object
 * -------------------------------------------------------------
 */
function objectTimer(elemid, delay, run) {
	if (!g_faders[this.TIMERCLASS])
		g_faders[this.TIMERCLASS]={};
	this.elemid = elemid;
	this.delay = delay;
	
	if (elemid) {
		this.element=document.getElementById(elemid);
		if (run) this.startTimer();
	}
	
}

/**-------------------------------------------------------------
 * startTimer()
 * -------------------------------------------------------------
 * starts the timer and puts into global collection
 * -------------------------------------------------------------
 */
objectTimer.prototype.startTimer = function() {	
	
	if (g_faders[this.TIMERCLASS][this.elemid])
			g_faders[this.TIMERCLASS][this.elemid].destroy(1,1);
		g_faders[this.TIMERCLASS][this.elemid] = this;
	this.alife=1;
	this.fade();
}

/**-------------------------------------------------------------
 * fade()
 * -------------------------------------------------------------
 * this function gets called on interval
 * -------------------------------------------------------------
 */
objectTimer.prototype.fade = function()	 {
	if(this.alife) 
	{
			this.timer = window.setTimeout("if(g_faders['"+this.TIMERCLASS+"']&&g_faders['"+this.TIMERCLASS+"']['"+this.elemid+"'])g_faders['"+this.TIMERCLASS+"']['"+this.elemid+"'].fade()", this.delay);
			
			
		}
}

/**-------------------------------------------------------------
 * destroy()
 * -------------------------------------------------------------
 * this function gets called to stop zimer and remove from
 * global collection
 * -------------------------------------------------------------
 */
objectTimer.prototype.destroy = function(killtimer,delglob) {	
		if (killtimer&&this.timer) {	
			window.clearTimeout(this.timer);
			this.timer=0;
		} 
	 	if (delglob&&g_faders[this.TIMERCLASS][this.elemid]) delete g_faders[this.TIMERCLASS][this.elemid];
		this.alife=0;
	}

objectTimer.prototype.TIMERCLASS = "timer";
objectTimer.prototype.elemid = "";
objectTimer.prototype.element = null; 
objectTimer.prototype.delay = 50;
objectTimer.prototype.timer = 0;
objectTimer.prototype.alife = 1;



/**-------------------------------------------------------------
 * -------------------------------------------------------------
 * objectCounter
 * -------------------------------------------------------------
 * class objectCounter
 * -------------------------------------------------------------
 */
function objectCounter(elemid, delay, frames,  run) {
	objectTimer.call(this, elemid, delay, 0);
	this.frames = frames;
	
	if (run) this.startTimer();
		
}
// inherit from objectTimer
objectCounter.prototype = new objectTimer;
objectCounter.prototype.constructor = objectTimer;
// methods
/**------------------------------------------------------------- 
 * set objects value to supplied value
 * -------------------------------------------------------------
 */
objectCounter.prototype.setValue = function (value) {
	this.framecounter=value;
}

/**------------------------------------------------------------- 
 * return the count of calls
 * -------------------------------------------------------------
 */
objectCounter.prototype.getValue = function () {
	return this.framecounter;
}
/**------------------------------------------------------------- 
 * calculate the value for current frame
 * -------------------------------------------------------------
 */
objectCounter.prototype.calculate = function () {
	return this.framecounter;
}
// 
/**------------------------------------------------------------- 
 * fading function, sets the current calculated value and 
 * reinstalls timeout
 * -------------------------------------------------------------
 */
objectCounter.prototype.fade = function() {
	this.setValue(this.calculate());
	if (this.framecounter<this.frames) objectTimer.prototype.fade.call(this);
	else this.destroy(1,1); 
	this.framecounter++;
}


// members
objectCounter.prototype.TIMERCLASS = "counter";
objectCounter.prototype.elemid = "";
objectCounter.prototype.element = null; 
objectCounter.prototype.delay = 50;
objectCounter.prototype.frames = 10;
objectCounter.prototype.framecounter = 0;
objectCounter.prototype.timer = 0;
objectCounter.prototype.alife = 1;


/**-------------------------------------------------------------
 * -------------------------------------------------------------
 * objectParamTimer
 * -------------------------------------------------------------
 * class objectParamTimer implements a timer that gets/sets 
 * an objects value 0..1 in time interval
 * start/end as -1 take the current value
 * -------------------------------------------------------------
 */
function objectParamTimer(elemid, delay, frames, start, end, run) {
	
	objectCounter.call(this, elemid, delay, frames, 0);
	this.start = start;
	this.end = end
	if (elemid) {
		if (this.start<0) this.start = this.getValue();
		if (this.end<0) this.end = this.getValue();
		if (run) this.startTimer();
	}
}
// inherit from objectCounter
objectParamTimer.prototype = new objectCounter;
objectParamTimer.prototype.constructor = objectParamTimer;

// constants
/** define timer class */ 
objectParamTimer.prototype.TIMERCLASS = "fader";

/**------------------------------------------------------------- 
 * calculate the value for current frame
 * -------------------------------------------------------------
 */
objectParamTimer.prototype.calculate = function () {
	return this.start + (this.end-this.start)*parseFloat(this.framecounter/this.frames);
}

// eof objectParamTimer



/**-------------------------------------------------------------
 * colorFader
 * -------------------------------------------------------------
 * class colorFader implements a timer that changes the color
 * of an object.
 * -------------------------------------------------------------
 */
function colorFader(elemid, styleprop, delay, frames, startColor, endColor, run) {
	if (!elemid)return;
	objectParamTimer.call(this, elemid, delay, frames, 0.0, 1.0,  0);
	this.STYLEPROP=styleprop;
	
	var col = getStyleProp(this.element,this.STYLEPROP);
	
	if (!col) col = startColor; 
	else col=rgbConvert(col);
	
	if (col==endColor) col=startColor;
	
	this.startColor = RgbHex2Hsl(col);
	
	this.endColor = RgbHex2Hsl(endColor);
	
	if (run) this.startTimer();
}
// inherit from objectParamTimer
colorFader.prototype = new objectParamTimer;
colorFader.prototype.constructor = colorFader;

// constants
/** define timer class */ 
colorFader.prototype.TIMERCLASS = "lightness";
/** on which style prop */ 
colorFader.prototype.STYLEPROP = "backgroundColor";

// methods
colorFader.prototype.calculateColor = Hsv2RgbHex;

/**-------------------------------------------------------------
 * overriding objectParamTimer: 
 * set the elements color according to value
 * -------------------------------------------------------------
 */
colorFader.prototype.setValue = function (value) {
	setStyleProp(this.element,this.STYLEPROP, 
	
		this.calculateColor(
			this.startColor[0]+(this.endColor[0]-this.startColor[0])*value,
			this.startColor[1]+(this.endColor[1]-this.startColor[1])*value,
			this.startColor[2]+(this.endColor[2]-this.startColor[2])*value
	));
}




/**-------------------------------------------------------------
 * fade()
 * -------------------------------------------------------------
 * overriding objectTimer this function gets called on interval
 * -------------------------------------------------------------
 */
function runIn(nl) {

	objectTimer.call(this, "", 10, 0);
	this.NAVIGLINKS=nl;
	
	for (var i in this.NAVIGLINKS) {
		document.getElementById(i).innerHTML="";
	}

	this.startTimer();
}
// inherit from objectTimer
runIn.prototype = new objectTimer;
runIn.prototype.constructor = runIn;

/**-------------------------------------------------------------
 * fade()
 * -------------------------------------------------------------
 * overriding objectTimer this function gets called on interval
 * -------------------------------------------------------------
 */
runIn.prototype.fade = function()	 {
	var remain=0;
	for (var i in this.NAVIGLINKS) {
		var elem=document.getElementById(i);
		var desttext=this.NAVIGLINKS[i];
		if (desttext[1]<desttext[0].length) {
			desttext[1]++;
			if (desttext[0].charAt(desttext[1])=='&') {
				desttext[1]++;
				while ((desttext[0].charAt(desttext[1])!=';')&&(desttext[1]<desttext[0].length))desttext[1]++;
				desttext[1]++;
			}
			elem.innerHTML=desttext[0].substring(0,desttext[1]) ;
			remain=1;
		}
		
	}
	if (remain) objectTimer.prototype.fade.call(this);
}

/**-------------------------------------------------------------
 * colorFader
 * -------------------------------------------------------------
 * class colorFader implements a timer that changes the color
 * of an object.
 * -------------------------------------------------------------
 */
function doubleFader(elemid, delay, frames, startColor, endColor, startColorFn, endColorFn, run) {
	colorFader.call(this, elemid, "backgroundColor", delay, frames, startColor, endColor, 0);  


	var col = getStyleProp(this.element,"color");
	
	if (!col) col = startColorFn; 
	else col=rgbConvert(col);
	if (col==endColorFn)col=startColorFn;
	this.startColorFn = RgbHex2Hsv(col);
	
	
	this.endColorFn = RgbHex2Hsv(endColorFn);
	
	if (run) {
		this.startTimer();
	}
}

// inherit from colorFader
doubleFader.prototype = new colorFader;
doubleFader.prototype.constructor = doubleFader;


/**-------------------------------------------------------------
 * overriding objectParamTimer: 
 * set the elements opacity according to value
 * -------------------------------------------------------------
 */
doubleFader.prototype.setValue = function (value) {
	setStyleProp(this.element,"backgroundColor", 
	
		this.calculateColor(
			this.startColor[0]+(this.endColor[0]-this.startColor[0])*value,
			this.startColor[1]+(this.endColor[1]-this.startColor[1])*value,
			this.startColor[2]+(this.endColor[2]-this.startColor[2])*value
	));
	
	setStyleProp(this.element,"color", 
	
		this.calculateColor(
			this.startColorFn[0]+(this.endColorFn[0]-this.startColorFn[0])*value,
			this.startColorFn[1]+(this.endColorFn[1]-this.startColorFn[1])*value,
			this.startColorFn[2]+(this.endColorFn[2]-this.startColorFn[2])*value
	));
}


	



