/*******************************************************************************************************
 * shadower.js
 * Author: Erik Rasmussen
 * Email: erikwordpressplugins -at- gmail
 * Info: http://www.erik-rasmussen.com/blog/2006/12/04/the-shadower-realistic-drop-shadows-in-javascript/
 *******************************************************************************************************/
var Shadower =
{
  shadow: function(element)
  {
    element = $(element);
    var options = Object.extend(
    {
      distance: 4,
      angle: 130,
      opacity: 0.2,
      nestedShadows: 4,
      color: '#000',
      wide: 1
    }, arguments[1] || {});
    var positionStyle = Element.getStyle(element, 'position');
    var parent = element.parentNode;
    if (!element.shadowZIndex)
    {
      if (positionStyle != 'absolute' && positionStyle != 'fixed')
      {
        var placeHolder = this.idSafeClone(element);
        placeHolder.id = null;
        parent.insertBefore(placeHolder, element);
        Position.absolutize(element);
        Position.clone(placeHolder, element);
        element.style.margin = '0';
        placeHolder.style.visibility = 'hidden';
        positionStyle = 'absolute';
      }
      element.shadowZIndex = new Number(Element.getStyle(element, 'zIndex') ? Element.getStyle(element, 'zIndex') : 1);
      element.style.zIndex = element.shadowZIndex + options.nestedShadows;
    }
    if (arguments[2])  // force recreate
      this.deshadow(element);
    // create shadows
    if (!element.shadows)
    {
      element.shadows = new Array(options.nestedShadows);
      for (var i = 0; i < options.nestedShadows; i++)
      {
        var shadow = document.createElement('div');
        Element.hide(shadow);
        shadow.appendChild(document.createTextNode(' '));
        if (parent)
          parent.appendChild(shadow);
        shadow.style.position = positionStyle;
        shadow.style.backgroundColor = options.color;
        Element.setOpacity(shadow, options.opacity / options.nestedShadows);
        shadow.style.zIndex = element.shadowZIndex + i;
        element.shadows[i] = shadow;
      }
    }
    else
    {
      Shadower.showshadow(element);
    }
    var legendHeight = this.getLegendHeight(element);
    // position shadows
    Position.prepare();
    var offsets = Position.positionedOffset(element);
    if (options.wide){
      var topOffset = options.distance;
      var leftOffset = -options.distance;
    }else{
      var topOffset = -Math.cos(-options.angle * Math.PI / 180) * options.distance;
      var leftOffset = -Math.sin(-options.angle * Math.PI / 180) * options.distance;
    }

    var plus = options.wide?options.distance*2:0;

    element.shadows.each(function(shadow, i)
    {
      shadow.style.top = Math.ceil(offsets[1] + topOffset + i + (legendHeight / 2)) + 'px';
      shadow.style.left = (offsets[0] + leftOffset + i) + 'px';
      shadow.style.width = (element.offsetWidth +plus- (2 * i)) + 'px';
      shadow.style.height = (element.offsetHeight - (2 * i) - (legendHeight / 2)) + 'px';
      Element.show(shadow);
    });
  },

  idSafeClone: function(node)
  {
    var clone = node.cloneNode(false);
    if (clone.hasAttribute && clone.hasAttribute('id'))
      clone.removeAttribute('id');
    var clonedChildren = $A(node.childNodes).collect(this.idSafeClone.bind(this));
    clonedChildren.each(function(child)
    {
      clone.appendChild(child);
    });
    return clone;
  },

  getLegendHeight: function(element)
  {
    if (element.nodeName.toLowerCase() == 'fieldset')
    {
      var legend;
      $A(element.childNodes).each(function(child)
      {
        if (child.nodeName.toLowerCase() == 'legend')
        {
          legend = child;
          throw $break;
        }
      });
      if (legend)
        return Element.getDimensions(legend).height;
    }
    return 0;
  },

  deshadow: function(element)
  {
    element = $(element);
    if (element.shadows)
    {
      element.shadows.each(Element.remove);
      element.shadows = null;
    }
  },

  hideshadow: function(element)
  {
    element = $(element);
    if (element.shadows)
    {
      element.shadows.each(Element.hide);
    }
  },

  showshadow: function(element)
  {
    element = $(element);
    if (element.shadows)
    {
      element.shadows.each(Element.show);
    }
  },


  shadowWithClass: function(cssClass, options)
  {
    $$('.' + cssClass).each(function(element)
    {
      this.shadow(element, options);
    }.bind(this));
  }
}

// check for prototype.js
if ((typeof Prototype == 'undefined') ||
    (typeof Element == 'undefined') ||
    (typeof Element.Methods == 'undefined') ||
    parseFloat(Prototype.Version.split(".")[0] + "." +
               Prototype.Version.split(".")[1]) < 1.5)
  throw("Shadower requires the Prototype JavaScript framework >= 1.5.0");

// the cross-browser opacity code below is borrowed from script.aculo.us
Element.getOpacity = function(element)
{
  var opacity;
  if (opacity = Element.getStyle(element, 'opacity'))
    return parseFloat(opacity);
  if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/))
    if (opacity[1]) return parseFloat(opacity[1]) / 100;
  return 1.0;
}

Element.setOpacity = function(element, value)
{
  element = $(element);
  if (value == 1)
  {
    Element.setStyle(element, { opacity:
        (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ?
        0.999999 : null });
    if (/MSIE/.test(navigator.userAgent))
      Element.setStyle(element, {filter: Element.getStyle(element, 'filter').replace(/alpha\([^\)]*\)/gi, '')});
  }
  else
  {
    if (value < 0.00001) value = 0;
    Element.setStyle(element, {opacity: value});
    if (/MSIE/.test(navigator.userAgent))
      Element.setStyle(element,
      { filter: Element.getStyle(element, 'filter').replace(/alpha\([^\)]*\)/gi, '') +
                'alpha(opacity=' + value * 100 + ')' });
  }
}

