﻿////////////////////////////////////////////////////////////////////////////////////////////////////
// Norman Geiersbach
// Eitido (c) 2007
// Version 1.0.1.9
////////////////////////////////////////////////////////////////////////////////////////////////////


// Global blend configuration
////////////////////////////////////////////////////////////////////////////////////////////////////

// Example configuration
// var blendColorConfig = new Array(new blendColorConfigObject(43, 43, 55, 184, 183, 183, 375, 375, false, false));
// var blendOpacityConfig = new Array(new blendOpacityConfigObject(50, 0, 375, 375, false));


// blendOpacityConfigObject
// Initializes opacity blend configuration object
  function blendOpacityConfigObject(blendOpacityIn, blendOpacityOut, timeBlendIn, timeBlendOut, waitBlendOut)
  {
    this.blendOpacityIn = blendOpacityIn; // opacity value to blend in
    this.blendOpacityOut = blendOpacityOut; // opacity value to blend out
    
    this.timeBlendIn = timeBlendIn; // time in ms to blend in
    this.timeBlendOut = timeBlendOut; // time in ms to blend out
    
    this.waitBlendOut = waitBlendOut; // blend out wait for blend in finished or not
                                      // if true blend out starts after blend in finished
                                      // if false blend in finishes immediately and blend starts
  }


// blendColorConfigObject
// Initializes color blend configuration object
  function blendColorConfigObject(redBlendIn, greenBlendIn, blueBlendIn, redBlendOut, greenBlendOut, blueBlendOut, 
                                  timeBlendIn, timeBlendOut, waitBlendOut, backgroundMode)
  {
    this.redBlendIn = redBlendIn; // red color value to blend in
    this.greenBlendIn = greenBlendIn; // green color value to blend in
    this.blueBlendIn = blueBlendIn; // blue color value to blend in
    this.redBlendOut = redBlendOut; // red color value to blend out
    this.greenBlendOut = greenBlendOut; // green color value to blend out
    this.blueBlendOut = blueBlendOut; // blue color value to blend out
        
    this.timeBlendIn = timeBlendIn; // time in ms to blend in
    this.timeBlendOut = timeBlendOut; // time in ms to blend out
    
    this.waitBlendOut = waitBlendOut; // blend out wait for blend in finished or not
                                      // if true blend out starts after blend in finished
                                      // if false blend in finishes immediately and blend starts
                                      
    this.backgroundMode = backgroundMode; // if set blend operation changes background color instead text color
  }


// Blending utility functions
////////////////////////////////////////////////////////////////////////////////////////////////////
  
// blendEnable
// Enables blend operation for an element (by default it is)
  function blendEnable(element)
  {
    // Delete disable attribute
    deleteAttribute(element, "blendDisable"); 
  }
  
  
// blendDisable
// Disables blend operation for an element (by default it is enabled)
  function blendDisable(element)
  {
    // Set disable attribute
    setAttribute(element, "blendDisable", 1);
  }  
  
  
// blendReset
// Resets blend operation attributes
  function blendReset(element)
  {
    // Clear running timer
    var blendTimer = getAttribute(element, "blendTimer");
    if( blendTimer != null )
      clearTimeout(blendTimer);
    
    // Delete attributes    
    deleteAttribute(element, "blendConfig");
    deleteAttribute(element, "blendMode");    
    deleteAttribute(element, "blendOutWaiting");    
    deleteAttribute(element, "blendTimer");
    deleteAttribute(element, "blendValue");   
  }  
  

// blendMonitor
// Monitors blend states for easy debug
  function blendMonitor(element, monitor)
  {
    // Validate element parameters
    if( typeof element == "string" )
      element = gen_element(element);
    if( typeof monitor == "string" )
      monitor = gen_element(monitor);
      
    // Get status
    var opacityCurrent = getOpacity(element);
    var blendMode = getAttribute(element, "blendMode");
    var blendOutCall = getAttribute(element, "blendOutCall");
    var blendOutWaiting = getAttribute(element, "blendOutWaiting");
    var blendTimer = getAttribute(element, "blendTimer");    
    var blendValue = getAttribute(element, "blendValue");    
    
    // Monior
    monitor.innerHTML = "opacityCurrent = " + opacityCurrent + "<br />" +
                               "blendMode = " + blendMode + "<br />" +
                               "blendOutCall = " + blendOutCall + "<br />" +
                               "blendOutWaiting = " + blendOutWaiting + "<br />" +
                               "blendTimer = " + (blendTimer != null ? "set" : "null") + "<br />"+ 
                               "blendValue = " + blendValue;
    
    // Monitor all 50 ms
    setTimeout("blendMonitor('" + element.id + "', '" + monitor.id + "');", 50);
  }
  
 
// Blending color functions
////////////////////////////////////////////////////////////////////////////////////////////////////
  
  
// blendInitColor
// Initializes the color blend out state for an element
  function blendInitColor(element, blendConfigIndex, blendMode)
  {
    var blendConfig = blendColorConfig[blendConfigIndex];
  
    // Set blend out color
    if( blendConfig.backgroundMode )
    {
      if( (blendMode == null) || (blendMode == "out") )
        setBackgroundColor(element, toHex(blendConfig.redBlendOut, blendConfig.greenBlendOut, blendConfig.blueBlendOut));
      else
        setBackgroundColor(element, toHex(blendConfig.redBlendIn, blendConfig.greenBlendIn, blendConfig.blueBlendIn));
    }
    else
    {
      if( (blendMode == null) || (blendMode == "out") )
        setColor(element, toHex(blendConfig.redBlendOut, blendConfig.greenBlendOut, blendConfig.blueBlendOut));
      else
        setColor(element, toHex(blendConfig.redBlendIn, blendConfig.greenBlendIn, blendConfig.blueBlendIn));
    }
  }


// blendInColor
// Starts a color blend in effect for the element
  function blendInColor(element, blendConfigIndex)
  {
    if( getAttribute(element, "blendDisable") )
      return false;
    
    var blendMode = getAttribute(element, "blendMode");
    
    if( blendMode != "in" )
    {
      // Reset and stop any running blend
      blendReset(element);
        
      // Hold new blend status      
      setAttribute(element, "blendConfig", blendConfigIndex);
      setAttribute(element, "blendMode", "in");
        
      // Start blend in
      blendColor(element);
    }    
  }

  
// blendOutColor
// Starts a color blend out effect for the element
  function blendOutColor(element, blendConfigIndex)
  {
    if( getAttribute(element, "blendDisable") )
      return false;
  
    var blendConfig = blendColorConfig[getAttribute(element, "blendConfig")];
    var blendMode = getAttribute(element, "blendMode");    
        
    // Check whether blend in is running
    if( blendMode == "in" )
    {
      if( blendConfig.waitBlendOut )
      {
        // Register for blend out and wait until blend in ends
        setAttribute(element, "blendOutWaiting", true);
        return;
      }
      else
      {
        // If blend out should start immediately
        // set color to final value and start blend out
        if( blendConfig.backgroundMode )
          setBackgroundColor(element, toHex(blendConfig.redBlendIn, blendConfig.greenBlendIn, blendConfig.blueBlendIn));
        else
          setColor(element, toHex(blendConfig.redBlendIn, blendConfig.greenBlendIn, blendConfig.blueBlendIn));
      }
    }
    
    if( blendMode != "out" )
    {      
      // Reset and stop any running blend
      blendReset(element);      
        
      // Hold new blend status      
      setAttribute(element, "blendConfig", blendConfigIndex);
      setAttribute(element, "blendMode", "out");
        
      // Start blend out
      blendColor(element);
    }
  }  
  
  
// blendColor
// Blending heartbeat for an element started by blendInOpacity/blendOutOpacity
  function blendColor(element)
  {
    // Get blend properties        
    var blendConfig = blendColorConfig[getAttribute(element, "blendConfig")];
    var blendMode = getAttribute(element, "blendMode");
    var blendOutWaiting = getAttribute(element, "blendOutWaiting");
    var blendValue = getAttribute(element, "blendValue");
    var timeBlend = (blendMode == "in") ? blendConfig.timeBlendIn : blendConfig.timeBlendOut;
    var timeInterval = 10;
    
    if( (blendConfig == null) || (blendMode == null) )
      return;
      
    // Initialize blend value if necessary
    if( blendValue == null )
    {
      blendValue = (blendMode == "in") ? 0 : 100;
      setAttribute(element, "blendValue", blendValue);
    }
		
		// Check if blend value is already reached
		if( ((blendMode == "in") ? blendValue >= 100 : blendValue <= 0) || (timeBlend < 1) )
		{		  
		  // Switch to blend out mode if it is on waiting
		  if( (blendMode == "in") && blendOutWaiting )
		  {
		    setAttribute(element, "blendMode", "out");
		    blendColor(element);
		  }
		  
		  // Finalize and return if opacity result already reached
		  blendReset(element);		  
		  return;
		}
		
		// Calculate new blend value
		if( (blendMode == "in") )
		  // use long version instead of += to make a workaround for firefox
		  blendValue = Number(blendValue) + (timeInterval * 100 / blendConfig.timeBlendIn);
		else
		  blendValue = Number(blendValue) - (timeInterval * 100 / blendConfig.timeBlendOut);
		
		// Calculate new color value
		// Use blend state to determine current/next color value,
		// because its to expensive to convert string to color rgb		
		var red = Math.round(blendConfig.redBlendOut + ((blendConfig.redBlendIn - blendConfig.redBlendOut) * (blendValue / 100)));
    var green = Math.round(blendConfig.greenBlendOut + ((blendConfig.greenBlendIn - blendConfig.greenBlendOut) * (blendValue / 100)));
    var blue = Math.round(blendConfig.blueBlendOut + ((blendConfig.blueBlendIn - blendConfig.blueBlendOut) * (blendValue / 100)));
		  
		// Set new color value
		if( blendConfig.backgroundMode )
      setBackgroundColor(element, toHex(red, green, blue));
    else
	    setColor(element, toHex(red, green, blue));
	  
	  // Hold new blend value
	  setAttribute(element, "blendValue", blendValue);
		
		// Set timeout for callback and hold blend states		
		var blendTimer = setTimeout("blendColor('" + element + "')", timeInterval);		
		setAttribute(element, "blendTimer", blendTimer);
  }  
  

// Blending opacity functions
////////////////////////////////////////////////////////////////////////////////////////////////////
  
// blendInitOpacity
// Initializes the opacity blend out state for an element
  function blendInitOpacity(element, blendConfigIndex, blendMode)
  {
    var blendConfig = blendOpacityConfig[blendConfigIndex];
  
    // Set blend out opacity
    setOpacity(element, (blendMode == null) || (blendMode == "out") ? blendConfig.blendOpacityOut : blendConfig.blendOpacityIn);
  }
  
  
// blendInOpacity
// Starts a opacity blend in effect for the element
  function blendInOpacity(element, blendConfigIndex)
  {
    if( getAttribute(element, "blendDisable") )
      return false;
  
    var blendMode = getAttribute(element, "blendMode");    
    
    if( blendMode != "in" )
    {
      // Reset and stop any running blend
      blendReset(element);
        
      // Hold new blend status      
      setAttribute(element, "blendConfig", blendConfigIndex);
      setAttribute(element, "blendMode", "in");
        
      // Start blend in
      blendOpacity(element);
    }    
  }

  
// blendOutOpacity
// Starts a opacity blend out effect for the element
  function blendOutOpacity(element, blendConfigIndex)
  {
    if( getAttribute(element, "blendDisable") )
      return false;
      
    var blendConfig = blendOpacityConfig[getAttribute(element, "blendConfig")];
    var blendMode = getAttribute(element, "blendMode");    
        
    // Check whether blend in is running
    if( blendMode == "in" )
    {
      if( blendConfig.waitBlendOut )
      {
        // Register for blend out and wait until blend in ends
        setAttribute(element, "blendOutWaiting", true);
        return;
      }
      else
      {
        // If blend out should start immediately
        // set opacity to final value and start blend out
        setOpacity(element, blendConfig.blendOpacityIn);
      }
    }
    
    if( blendMode != "out" )
    {      
      // Reset and stop any running blend
      blendReset(element);      
        
      // Hold new blend status      
      setAttribute(element, "blendConfig", blendConfigIndex);
      setAttribute(element, "blendMode", "out");
        
      // Start blend out
      blendOpacity(element);
    }
  }  
  
  
// blendOpacity
// Blending heartbeat for an element started by blendInOpacity/blendOutOpacity
  function blendOpacity(element)
  {
    // Get blend properties    
    var blendConfig = blendOpacityConfig[getAttribute(element, "blendConfig")];
    var blendMode = getAttribute(element, "blendMode");
    var blendOutWaiting = getAttribute(element, "blendOutWaiting");
    
    if( (blendConfig == null) || (blendMode == null) )
      return;
  
		// Get current opacity value
		var opacityValue = getOpacity(element);
		var opacityDelta = 1;
		var opacityTo = (blendMode == "in") ? blendConfig.blendOpacityIn : blendConfig.blendOpacityOut;
		var timeBlend = (blendMode == "in") ? blendConfig.timeBlendIn : blendConfig.timeBlendOut;
		
		// Check if opacity is already reached
		//if( opacityValue == opacityTo )
	  if( ((blendMode == "in") ? opacityValue >= opacityTo : opacityValue <= opacityTo) || (timeBlend < 1))
		{
		  // Set final opacity value to get sure its right
		  setOpacity(element, opacityTo);
				  
		  // Switch to blend out mode if it is on waiting
		  if( (blendMode == "in") && blendOutWaiting )
		  {
		    setAttribute(element, "blendMode", "out");
		    blendOpacity(element);
		  }
		  
		  // Finalize and return if opacity result already reached
		  blendReset(element);		  
		  return;
		}
		
		// Calculate delta value and timer interval		
		var timeInterval = timeBlend / (Math.abs(blendConfig.blendOpacityIn - blendConfig.blendOpacityOut) / opacityDelta);	  
	  if( timeInterval < 10 )
	  {
	    timeInterval = 10;
	    opacityDelta = Math.abs(blendConfig.blendOpacityIn - blendConfig.blendOpacityOut) / (timeBlend / timeInterval);
	  }	    
		
		// Calculate new opacity value
		if( opacityValue - opacityTo > 0 )
		{
		  opacityValue = opacityValue - opacityDelta;
		  if( opacityValue < opacityTo )
		    opacityValue = opacityTo;
		} else
		{
		  opacityValue = opacityValue + opacityDelta;
		  if( opacityValue > opacityTo )
		    opacityValue = opacityTo;
		}
		  
		// Set new opacity value
	  setOpacity(element, opacityValue);		
		
		// Set timeout for callback		
		var blendTimer = setTimeout("blendOpacity('" + element + "')", timeInterval);
		setAttribute(element, "blendTimer", blendTimer);		
  }
  

// Opacity utility functions
////////////////////////////////////////////////////////////////////////////////////////////////////  
  
// getOpacity
// Returns the opacity value for an element  
  function getOpacity(element)
  {
    // Validate element parameter
    if( typeof element == "string" )
      element = gen_element(element);
      
    if( element == null )
      return false;
      
    // Return opacity value
    if( element.style.opacity != null )
      return element.style.opacity * 100;
    else if( element.style.MozOpacity != null )
      return element.style.MozOpacity * 100;
    else if( element.style.KhtmlOpacity != null )
      return element.style.KhtmlOpacity * 100;
    else 100;
  }


// setOpacity
// Sets the opacity value for an element
  function setOpacity(element, opacity)
  {
    // Validate element parameter
    if( typeof element == "string" )
      element = gen_element(element);
    
    if( element == null )
      return false;
    
	  element.style.opacity = (opacity / 100);
	  element.style.MozOpacity = (opacity / 100);
	  element.style.KhtmlOpacity = (opacity / 100);
	  element.style.filter = "alpha(opacity=" + opacity + ")";	  
  }


// Color utility functions
////////////////////////////////////////////////////////////////////////////////////////////////////

// setBackgroundColor
// Sets the background color for an element
  function setBackgroundColor(element, color)
  {
    // Validate element parameter
    if( typeof element == "string" )
      element = gen_element(element);
      
    element.style.backgroundColor = color;
  }


// setColor
// Sets the text color for an element
  function setColor(element, color)
  {
    // Validate element parameter
    if( typeof element == "string" )
      element = gen_element(element);
      
    element.style.color = color;
  }


// toColor
// Converts rgb values to its color value
  function toColor(red, green, blue)
  {
    return red + 256 * green + 65536 * blue;
  }

  
// toHex
// Converts rgb values to its hex string
  function toHex(red, green, blue)
  {
    var r = red.toString(16);
    var g = green.toString(16);
    var b = blue.toString(16);
    if (r.length == 1) r = '0' + r;
    if (g.length == 1) g = '0' + g;
    if (b.length == 1) b = '0' + b;
    return '#' + r + g + b;
  }
