var magicBox = new Class(
  {    
    // ###################################################################
    // ********************* DEFAULT SETTINGS ****************************
    // ###################################################################
    
    options : {
      fadeDiv : {
        id : 'fadeDiv',
        color : '#06355F',
        opacity : .65,
        fadeDuration : 1000,
        transition: 'linear',
        zIndex: '10'
      },
      boxElement : {
        duration : 1000,
        slideIn : true,
        slideOut: true,
        expandIn : true,
        expandOut: true,
        fadeIn : true,
        fadeOut : true,
        transition : 'sineIn',
        onComplete : null        
      }
    },     

    // ###################################################################
    // ********************* show(element) -- pass id or obj *************
    /* ++ Make any absolutely position block level element (currently hidden)
       ++ animate/fade onto the screen. A back drop is generated on the fly. 
       Pass any id or element to this. */
    // ###################################################################
    
    show : function(el){
      var element = null;
      if(element = $(el)){
        if(this.showFade()){
          var scrollTop = window.getScrollTop();
          var scrollLeft = window.getScrollLeft();
          var viewportHeight = window.getViewportHeight();          
          var viewportWidth = window.getViewportWidth();     
          
          var elementWidth = parseInt(this.stripPx(this.getElementStyle(element, 'width', 'width')));
          var elementHeight = parseInt(this.stripPx(this.getElementStyle(element, 'height', 'height'))); 
          
          var finalX = (viewportWidth / 2) - (elementWidth / 2) + scrollLeft;
          var finalY = (viewportHeight / 2) - (elementHeight / 2) + scrollTop;
          
          var startY = null;
          var startElementHeight = null;
          var startElementOpacity = null;
          
          (this.options.boxElement.slideIn == false)?(startY = finalY):(startY = scrollTop);
          (this.options.boxElement.expandIn == false)?(startElementHeight = elementHeight):(startElementHeight = 0);
          (this.options.boxElement.fadeIn == false)?(startElementOpacity = 1):(startElementOpacity = 0);

          var cObj = this;
          
          element.setStyles(
            {
              'opacity' : '0',
              'position':'absolute',
              'top':scrollTop + 'px',
              'left':finalX + 'px',
              'display':'block',
              'zIndex':this.options.fadeDiv.zIndex + 5
            }
          ).effects(
            {
              duration: this.options.boxElement.duration, 
              transition: Fx.Transitions[this.options.boxElement.transition],
              onComplete : function(){ if(cObj.options.boxElement.onComplete){
                cObj.options.boxElement.onComplete();
              }}
            }
          ).start(
            {
              'top' : [startY, finalY],
              'height':[startElementHeight,elementHeight],
              'opacity':[startElementOpacity,1]
            }
          );                
        }  
      }
    },
    
    // #####################################################################
    // ******************* hide(element) -- pass id or obj *****************
    /* Animate any block level element off the screen that was initiated by 
       show(); */
    // #####################################################################
    
    hide : function(el){
      var element = null;
      if(element = $(el)){
        if(this.hideFade()){
          var scrollTop = window.getScrollTop();
          var scrollLeft = window.getScrollLeft();
                  
          var finalX = scrollLeft;
          var finalY = scrollTop;
          
          var currentX = parseInt(this.stripPx(this.getElementStyle(element, 'left', 'left')));
          var currentY = parseInt(this.stripPx(this.getElementStyle(element, 'top', 'top')));
          var currentHeight = parseInt(this.stripPx(this.getElementStyle(element, 'height', 'height')));
          var currentWidth = parseInt(this.stripPx(this.getElementStyle(element, 'width', 'width')));
          
          var finalHeight = null;
          var endElementOpacity = null;
          
          (!this.options.boxElement.slideOut)?(finalY = currentY):(finalY = finalY);
          (!this.options.boxElement.expandOut)?(finalHeight = currentHeight):(finalHeight = 0);
          (this.options.boxElement.fadeOut == false)?(endElementOpacity = 1):(endElementOpacity = 0);

          element.effects(
            {
              duration: this.options.boxElement.duration, 
              transition: Fx.Transitions.sineIn,
              onComplete: this.temp(element, currentHeight, currentWidth, this)
            }
          ).start(
            {
              'top':[currentY, finalY],
              'height':[currentHeight,finalHeight],
              'opacity':[1,endElementOpacity]
            }
          )   
            
        }
      }
    },    
        
    temp : function(element, currentHeight, currentWidth, obj){
      function setClosure(){
        obj.resetSize(element, currentHeight, currentWidth);
      }
      return setClosure;
    },      
    
    resetSize : function(element, height, width){
      element.setStyles(
        {
          'height':height + 'px',
          'width':width + 'px',
          'display': 'none'
        }
      );
    },     
    
    hideFade : function(){
      $(this.options.fadeDiv.id).effect('opacity', 
			  { 
			    duration : this.options.fadeDiv.fadeDuration,
			    transition : Fx.Transitions[this.options.fadeDiv.transition]
			  }
			).start(this.options.fadeDiv.opacity, 0);
			return true;
    },
    
    // sizes and shows the background fade
    showFade : function(){
      if(!$(this.options.fadeDiv.id)){
        var el = new Element('div').setStyles({
  					'position':'absolute',
  					'left':'0px',
  					'top': '0px',
  					'margin':'0px',
  					'padding':'0px',
  					'backgroundColor':this.options.fadeDiv.color,
  					'height': window.getScrollHeight(),
  					'width': window.getWidth(),
  					'opacity' : '0',
  					'zIndex' : this.options.fadeDiv.zIndex
  			}).injectInside($$('body')[0]);
  			el.id = this.options.fadeDiv.id;
  		}
  		$(this.options.fadeDiv.id).effect('opacity', 
			  { 
			    duration : this.options.fadeDiv.fadeDuration,
			    transition : Fx.Transitions[this.options.fadeDiv.transition]
			  }
			).start(0,this.options.fadeDiv.opacity);
			return true;  		  
    },

    // ####################### Initialize ##########################

    initialize : function(newOptions){ 
      if(newOptions){
        this.options = $merge(this.options, newOptions);
      }
        
      window.getViewportWidth = function(){
        var x;
        (self.innerHeight)?(x = self.innerWidth):(
        (document.documentElement && document.documentElement.clientHeight)?(x = document.documentElement.clientWidth):(
        (document.body)?(x = document.body.clientWidth):(x = null)));
        return x;
      }
      window.getViewportHeight = function(){
        var y;
        (self.innerHeight)?(y = self.innerHeight):( // all except Explorer
        (document.documentElement && document.documentElement.clientHeight)?(y = document.documentElement.clientHeight):(
        (document.body)?(y = document.body.clientHeight):(y = null)));
        return y;
      }
      window.getScrollHeight = function(){
        var height = null;
        (window.innerHeight && window.scrollMaxY)?(height = window.innerHeight + window.scrollMaxY):(
        (window.innerHeight)?(height = window.innerHeight + window.scrollMaxY):(
        (document.body.scrollHeight > document.body.offsetHeight)?(height = document.body.scrollHeight):(height = document.body.offsetHeight)))          
        return height;          
      }
    },
    // gets the current style of an element, even if it's defined in an external stylesheet
    getElementStyle : function(elemObj, IEStyleProp, CSSStyleProp) {
      var elem = elemObj;
      if (elem.currentStyle) {
          return elem.currentStyle[IEStyleProp];
      } else if (window.getComputedStyle) {
          var compStyle = window.getComputedStyle(elem, "");
          return compStyle.getPropertyValue(CSSStyleProp);
      }
      return "";
    },
    
    getScrollOffset : function(){
      var x,y;
      if (self.pageYOffset) // all except Explorer
      {
      	x = self.pageXOffset;
      	y = self.pageYOffset;
      }
      else if (document.documentElement && document.documentElement.scrollTop)
      	// Explorer 6 Strict
      {
      	x = document.documentElement.scrollLeft;
      	y = document.documentElement.scrollTop;
      }
      else if (document.body) // all other Explorers
      {
      	x = document.body.scrollLeft;
      	y = document.body.scrollTop;
      }
      var returnArray = new Array();
      returnArray['x'] = x;
      returnArray['y'] = y;
      
      return returnArray;
    },
       
    // strip the last 'px' from a string
    stripPx : function(text){
      return text.substr(0, text.length - 2);
    }
  }
);  

magicBox.implement(new Options);