/*
usage for fader:
onmouseover="fadeObject(this,100,80,10,true)" onmouseout="fadeObject(this,35,80,10,true)"

usage for rollout:
onmouseover="rollObject(this,'100%','100%',20,5,3,false);" onmouseout="rollObject(this,'10%','10%',20,5,3,false)"
*/

function setOpacity(obj,value){
  
	value = parseInt(value);

  if(obj.style.opacity != null) {
  	obj.style.opacity  = value/100;
  	return true;
  }
  	
	if(obj.style.MozOpacity != null) {
		obj.style.MozOpacity = value/100;	
		return true;
	}

	if(obj.filters != 'undefined') {
  	obj.filters.alpha.opacity = value;
  	return true;
	}

  if(obj.style.KhtmlOpacity != 'undefined') {
  	obj.style.KhtmlOpacity  = value/100;
  	return true;
  } 
  
  return true; 
}

function getOpacity(obj){

	if(obj.style.opacity != null) return parseInt(obj.style.opacity*100);
	
	if(obj.style.MozOpacity != null) return parseInt(obj.style.MozOpacity*100);	
	
  if(obj.filters != 'undefined') return parseInt(obj.filters.alpha.opacity);
  
  if(obj.style.KhtmlOpacity != 'undefined') return parseInt(obj.style.KhtmlOpacity*100);

  //wifrd nichts gefunden, wird angenommen, das Element sei komplett durchsichtig
	return 0;
}

var FadeObjects = new Object();
var FadeTimers = new Object();
var FadeOpacities = {};
var gStartOpacity = 100;

/*Params
 * 
 * object      :Object 
 * destOpacity :destination opacity
 * speed       :speed(gaps between refresh)
 * step        :size of one step for showing opacity (linear)
 * smooth      :kurven-förmige Anpassung
 */
function fadeObject(object,destOpacity,speed,step,smooth){
  object = isObject(object);
  
  // if given "object" isn't an object, reset Timeout and return
	if (!object){
	  setTimeout("fadeObject("+object+","+destOpacity+","+speed+","+step+","+smooth+")",0);
	  return true;
	} 
  
  var oid = object.sourceIndex;
  if(oid==undefined) oid = buildUniqueObjectID(object);  //Fierfox doesn't know "sourceIndex"
  
	//timeout zurücksetzen
	if(FadeTimers[oid]) clearTimeout(FadeTimers[oid]);

  //read current opacity of object
  var currentOpacity = getOpacity(object);
  if(FadeOpacities[oid]) currentOpacity = FadeOpacities[oid];
  
  destOpacity = recalcValue2px(destOpacity,100);
  var diff = calcDifference(destOpacity,currentOpacity);

  // if destination-opacity is reached, return
  if(diff.direction > 0){
    if(currentOpacity >= destOpacity) return true;
  }else{
    if(currentOpacity <= destOpacity) return true;
  }

  //get minimum
  var handlestep = Math.min(diff.difference,step);
  if(handlestep==0) handlestep = 1;
  step = diff.direction * parseInt(handlestep);
  
  var newOpacity;
  if(smooth==true) {
    //smoothing
    if(step>1) step-= 1;
  }

  newOpacity = currentOpacity + step;

  //setting opacity
	setOpacity(object,newOpacity);

  //register object and its timer
	FadeObjects[oid] = object;
	FadeOpacities[oid] = newOpacity;
	FadeTimers[oid] = setTimeout("fadeObject(FadeObjects["+oid+"],"+destOpacity+","+speed+","+handlestep+","+smooth+")",speed);

	return true;
}


function setRollout(obj,width,height,style){

  if(style=='') style = 1;
	width = parseInt(width);
	height = parseInt(height);

	switch (style) {
		case 1:
	    obj.style.clip = 'rect(0px '+width+'px '+height+'px 0px)';
			break;
		case 2:
		  obj.style.overflow = 'hidden';
		  setElementSize(obj,width,height);
			break;
		case 3:
		  moveElementTo(obj,width,height);
		  break;
	}

	return true;
}


/*
 * object      :Object/ID 
 * destWidth   :destination width
 * destHeight   :destination height
 * speed       :speed(gaps between refresh)
 * step        :size of one step for showing opacity (linear)
 * rollstyle   :style to use(1:clip*, 2:size*, 3:move)  *status: under development
 * smooth      :kurven-förmige Anpassung
*/
var RollObjects = new Object();
var RollTimers = new Object();
var RollSizes = {};
var RollOriginalSizes = {};
var RollSteps = {};
function rollObject(object,destWidth,destHeight,speed,step,rollstyle,smooth){
  object = isObject(object);
  
  // if given "object" isn't an object, reset Timeout and return
	if (!object){
	  setTimeout("fadeObject("+object+","+destOpacity+","+speed+","+step+","+smooth+")",0);
	  return true;
	} 

  var oid = object.sourceIndex;
  if(oid==undefined) oid = buildUniqueObjectID(object);  //Firefox doesn't know "sourceIndex"
  
  //timeout zurücksetzen
  if(RollTimers[oid]) clearTimeout(RollTimers[oid]);
    
  var size = {width:getWidthOfElement(object),height:getHeightOfElement(object)};
  var y;
  var x;
  var destWidthCalc;
  var destHeightCalc;
  
  if(rollstyle=='') rollstyle = 3;//fallback  
  switch (rollstyle) {
  	case 1:		
  		y = size.width;
	    x = size.height;
	    
	    if(RollSizes[oid]){
		    y = RollSizes[oid].x;
			  x = RollSizes[oid].y;
	    }
	    
  		destWidth = recalcValue2px(destWidth,size.width);
	    destHeight = recalcValue2px(destHeight,size.height);
	    
	    destWidthCalc = destWidth;
	    destHeightCalc = destHeight;
  		break;
    case 2:
      y = size.width;
	    x = size.height;
	    
	    //remember original size
      if(!RollOriginalSizes[oid]) RollOriginalSizes[oid] = {x:size.width,y:size.height}; 

	    destWidth = recalcValue2px(destWidth,RollOriginalSizes[oid].x);
	    destHeight = recalcValue2px(destHeight,RollOriginalSizes[oid].y);

	    destWidthCalc = destWidth;
	    destHeightCalc = destHeight;
      break
  	case 3:
  	  destWidth = recalcValue2px(destWidth,size.width);
	    destHeight = recalcValue2px(destHeight,size.height);
      
      var visibleThresholdX = size.width * (-1);
      var visibleThresholdY = size.height * (-1);
		  var pos = {x:getLeftOfElement(object),y:getLeftOfElement(object)};
		  y = pos.y;
		  x = pos.x;
		  destWidthCalc = visibleThresholdX + destWidth;	  
	    destHeightCalc = visibleThresholdY + destHeight;	  
  		break;
  }  
  
  
  var handle = {x:x,y:y};
  var newStep = {x:step,y:step};
  
  if(RollSteps[oid]) newStep = RollSteps[oid];
  
  var nvx = calcNewValue(x,destWidthCalc,newStep.x,smooth);
  handle.x = nvx.newvalue;
  newStep.x = nvx.newstep;
  
  var nvy = calcNewValue(y,destHeightCalc,newStep.y,smooth);
  handle.y = nvy.newvalue;
  newStep.y = nvy.newstep;
  
  if(handle.x == destWidthCalc && handle.y == destHeightCalc) return true;

  //do rolling
  setRollout(object,handle.x,handle.y,rollstyle);
 
  //remeber objects/values
  RollObjects[oid] = object;
  RollSizes[oid] = {x:handle.x,y:handle.y};
  RollSteps[oid] = {x:newStep.x,y:newStep.y};
	RollTimers[oid] = setTimeout("rollObject(RollObjects["+oid+"],"+destWidth+","+destHeight+","+speed+","+step+","+rollstyle+","+smooth+")",speed);

  return true;
}


function calcNewValue(current,destination,step,smooth){
	
  //calc differende and direction
	var diff = calcDifference(destination,current);
  
  //if y reached destination Value, return
  if(diff.direction > 0){
    if(current >= destination) return {newvalue:destination,newstep:step};
  }else{
    if(current <= destination) return {newvalue:destination,newstep:step};
  }
  
  //select minimum of difference and step
  step = Math.min(diff.difference,step);
  
  var handleStep = step;
  //calc new height  
  if(smooth==true) {
    //smoothing
    if(step>1)  handleStep = step - 1;
  }
  var handlevalue = current + (diff.direction * Number(handleStep));
	
	return {newvalue:handlevalue,newstep:handleStep};
}


function calcDifference(value1,value2){

  value1 = Number(value1);
  value2 = Number(value2);

	var retdiff = value1 - value2;

	//consider which direction to go
	var retdirection = 1;
	if (value1 < value2) retdirection = -1;
  retdiff = retdirection * Number(retdiff);
  
  return {difference:retdiff,direction:retdirection};
}




/*
 * recalculate px-values and percentage-values
 */
function recalcValue2px(value,val100percent){
	
	if(value.toString().substr(-1)=='%'){  //Umrechnung bei %-Angabe
		value = (val100percent/100) * parseInt(value);
	}
  
  if(value.toString().substr(-2,2)=='px'){  //Umrechnung bei px-Angabe
    // nothing to do
	}
	
	return parseInt(value);
}
