
/**
 *  class for everything that has to do with displaying elements
 *  
 *  @author  Tobias Hettinger
 *  @version $Id: display.js 124 2011-09-16 12:26:15Z tobias $
 */


/**
 *  constructor of the WAT display manager
 *  
 *  @param object element  DHTML element to which the display manager is connected or
 *                         the id of the element as string
 */
var WATDisplay = function(element)
{
  //  get the element
  if (element && typeof(element) == 'string') element = document.getElementById(element);
  this.element = element;
  
  //  fading properties
  this.fading = false;  
  this.lastFadeCommand = 0;
  this.lastFadeTime = 0; 
  
  //  events
  this.onFadeFinished = null;
}


//---------------------------------------------------------------------------------------------------------------------
//  opacity and fading

/**
 *  function to set the opacity of the element
 *
 *  @param int opacity  opacity between 0 (invisible) and 1 (completely visible)
 */
WATDisplay.prototype.SetOpacity = function(opacity)
{
  if (opacity == 1)
  {
    //  if no transparency is required, simply delete the filter
    if (WATBrowserInfo.IsIE)
      this.element.style.filter = "";
    else
      this.element.style.opacity = opacity;
  }
  else
  {
    //  set the opacity
    if (WATBrowserInfo.IsIE)
      this.element.style.filter="Alpha(opacity="+(opacity*100)+", finishopacity="+(opacity*100)+", style=1)";
    else
      this.element.style.opacity = opacity;
  }
}

/**
 *  function to get the opacity of the element
 *
 *  @return float  the function returns the opacity of the element as float value
 */
WATDisplay.prototype.GetOpacity = function()
{
   //  the function returns 0 if the opacity can not be determined
  var result = 0;

  //  in case of the Internet Explorer, the filter string has to be parsed
  if (WATBrowserInfo.IsIE)
  {   
    //  parse the filter string
    var filter = this.element.style.filter;    
    var startPos = filter.indexOf('opacity=');
    if (startPos > 0)
    {
      startPos += 8;
      var endPos = filter.indexOf(',', startPos);
      if (endPos > startPos)
      {
        var opacity = filter.substr(startPos, endPos-startPos);
        result = opacity / 100;
      }
    }
    else
    {
      //  there is no filter, opacity must be 1
      result = 1;
    }
  }
  else
  {
    //  get the opacity
    if (this.element.style.opacity) result = this.element.style.opacity;
  }
  
  //  return the opacity
  return parseFloat(result);
}

/**
 *  function to fade the element in. The function does nothing if the current opacity is higher than the required one
 *
 *  @param int opacity  opacity, the object should have when fading has finished (1-100, 0 fades to 100%)
 *  @param int msec     time in milliseconds to fade in (if the parameter is not defined, the time is set to 350 msec)
 */
WATDisplay.prototype.FadeIn = function(opacity, msec)
{
  //  check the parameters
  if (!msec) msec = 350;
  if (!opacity || opacity < 0 || opacity > 100) opacity = 100;

  //  get the current opacity
  var currentOpacity = this.GetOpacity() * 100;
  if (this.element.style.display == 'none') currentOpacity = 0;
  var opacityDiff = opacity - currentOpacity;
  if (opacityDiff < 0) return false;
  
  //  check if fading is possible and set the flags
  this.lastFadeCommand = 1;
  this.lastFadeTime = msec;
  if (this.fading) return false;
  this.fading = true;

  //  initialize fading
  var step = 20;
  var speed = Math.round(msec / 100 * step); 
  var timer = 0;
  var fadingStep = 0;
  var obj = this;
  
  //  function to execute fading
  function __FadeIn()
  {
    obj.SetOpacity((currentOpacity + fadingStep) / 100);
    if (fadingStep == 0) obj.element.style.display = 'block';
    if (obj.fading && fadingStep >= opacityDiff) { obj.fading = false; obj.__FinishFading(1); }
    fadingStep += step;
  }
  
  //  fade the element in
  for(i=0; i<=opacityDiff; i+=step)
  {
    setTimeout(__FadeIn, timer*speed);
    timer++; 
  }
}

/**
 *  function to fade the element out. The function does nothing if the current opacity is lower than the required one
 *
 *  @param int opacity  opacity, the object should have when fading has finished (0-100)
 *  @param int msec     time in milliseconds to fade out (if the parameter is not defined, the time is set to 500 msec)
 */
WATDisplay.prototype.FadeOut = function(opacity, msec)
{
  //  check the parameters
  if (!msec) msec = 500;
  if (!opacity || opacity < 0 || opacity > 100) opacity = 0;
 
  //  get the current opacity
  var currentOpacity = this.GetOpacity() * 100;
  var opacityDiff = opacity - currentOpacity;
  if (opacityDiff > 0) return false;
 
  //  check if fading is possible and set the flags
  this.lastFadeCommand = 2;
  this.lastFadeTime = msec;
  if (this.fading) return false;
  this.fading = true;
 
  //  initialize fading
  var step = 20;
  var speed = Math.round(msec / 100 * step);
  var fadingStep = currentOpacity;
  var timer = 0;
  var obj = this;
  
  //  function to execute fading
  function __FadeOut()
  {
    obj.SetOpacity(fadingStep / 100);
    if (fadingStep == 0) obj.element.style.display = 'none';
    if (obj.fading && fadingStep <= opacity) { obj.fading = false; obj.__FinishFading(2); }
    fadingStep -= step;
  }
  
  //  fade the element out
  for(i=currentOpacity; i>=opacity; i-=step)
  {
    setTimeout(__FadeOut, timer*speed);
    timer++; 
  }
}

/**
 *  function that is called when fading was finished. If fading-in finished but the last command was a fade-out,
 *  the fade-out function is triggered and vice versa.
 *
 *  @param int mode  mode of the fading function that was just finished
 *                   - 1 - the fade-in function has finished
 *                   - 2 - the fade-out function has finished
 */
WATDisplay.prototype.__FinishFading = function(mode)
{
  //  fade out if the div was just faded in but the last command was a fade-out
  if (mode == 1 && this.lastFadeCommand == 2)
    this.FadeOut(0, this.lastFadeTime);
  
  //  fade in if the div was just faded out but the last command was a fade-in
  if (mode == 2 && this.lastFadeCommand == 1)
    this.FadeIn(100, this.lastFadeTime);

  //  send a fading finished event
  if (this.onFadeFinished) this.onFadeFinished(this);
}


//---------------------------------------------------------------------------------------------------------------------
//  element dimensions

/**
 *  function to get the absolute top position of the element
 *
 *  @return int  the function returns the top position as an integer value
 */
WATDisplay.prototype.GetTop = function()
{
  //  initialize the variables
  var result = 0;
  
  //  get the position of the element
  var currentElement = this.element;  
  while (currentElement)
  {
    //  add the top offset of the current element
    result += currentElement.offsetTop;
    
    //  the border width of an absolute positioned element has not been respected yet
    if (currentElement.style.position == 'absolute')
      result += watGetElementStyle(currentElement, 'border-top-width', 'int', 0);    
    
    //  get the parent of the current element
    currentElement = currentElement.offsetParent;
  }

  //  adapt the position if the element is a child of a div that contains scrollbars
  var currentElement = this.element;
  while (currentElement)
  {
    if (currentElement.nodeName.toLowerCase() == 'div')
      if (currentElement.scrollTop > 0) result -= currentElement.scrollTop;
    currentElement = currentElement.parentNode;
  }
  
  //  return the absolute top position of the element
  return result;
}

/**
 *  function to get the absolute left position of the element
 *
 *  @return int  the function returns the left position as an integer value
 */
WATDisplay.prototype.GetLeft = function()
{
  //  initialize the variables
  var result = 0;
  
  //  get the left position of the element
  var currentElement = this.element;
  while(currentElement)
  {
    //  add the left offset of the current element
    result += currentElement.offsetLeft;
    
    //  the border width of an absolute positioned element has not been respected yet
    if (currentElement.style.position == 'absolute')
     result += watGetElementStyle(currentElement, 'border-left-width', 'int', 0);
    
    //  get the parent of the current element
    currentElement = currentElement.offsetParent;
  }
  
  //  the absolute left position has been found
  return result;
}

/**
 *  function to get the width of the element. The element needs not necessarily be visible and even
 *  needs not be contained in the DHTML element tree of the document
 *  
 *  @return int  the function returns the width of the element as an integer value
 */
WATDisplay.prototype.GetWidth = function()
{
  //  save the status of the element
  var display = this.element.style.display == 'none' ? false : true;
  var hasParent = (this.element.parentNode == null ||
                   this.element.parentNode.nodeName == '#document-fragment') ? false : true;
  
  //  prepare the element and get its width
  if (!hasParent) document.body.appendChild(this.element);
  if (!display) this.element.style.display = 'block';
  var width = this.element.offsetWidth;
  
  //  reset the element properties and return the width
  if (!display) this.element.style.display = 'none';
  if (!hasParent) document.body.removeChild(this.element);
  return width;
}

/**
 *  function to get the height of the element. The element needs not necessarily be visible and even
 *  needs not be contained in the DHTML element tree of the document
 *  
 *  @return int  the function returns the height of the element as an integer value
 */
WATDisplay.prototype.GetHeight = function()
{
  //save the status of the element
  var display = this.element.style.display == 'none' ? false : true;
  var hasParent = (this.element.parentNode == null ||
                   this.element.parentNode.nodeName == '#document-fragment') ? false : true;
  
  //  prepare the element and get its height
  if (!hasParent) document.body.appendChild(this.element);
  if (!display) this.element.style.display = 'block';
  var height = this.element.offsetHeight;
  
  //  reset the element properties and return the height
  if (!display) this.element.style.display = 'none';
  if (!hasParent) document.body.removeChild(this.element);
  return height;
}

//  the file must be included in the head section of the document, do not call the ScriptIncluded function

