/* -*- Mode: JavaScript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */

/* a type of light weight messaging mechanism that you can see on this site: http://www.instantslideup.com. */

// shortcuts to YAHOO objects
if(typeof(Dom) == 'undefined'){
  Dom = YAHOO.util.Dom;
  Evt = YAHOO.util.Event;
  Anim = YAHOO.util.Anim;
}

// alias to console.log function
log = function(){}
if(typeof(console) != 'undefined' && typeof(console.log) != 'undefined' && !YAHOO.env.ua.ie){
  log = function(){
    console.log.apply(console, arguments); 
  }
}

// There at least 4 slideup objects, created on demand through the SlideUp factory (see below)
var SlideUpObject = function(params) {
  var _options = params;              // options passed to our slideup factory
  var _pos = _options['position'];    // we do a lot of calculations based on the position of the element
  var _dimension = '';                // dimension in which the animation is made (height for top and bottom; width for left and right)
  var _slides = [];                   // slides belonging to this slideup
  var _current_slide_idx = 0;         // index of the slide currently shown
  var _main_elem = null;              // the DOM element of the slideup (a div)
  var _fixelement_timer = 0;          // the interval timer used to fix the element to one of the sides
  var _stretch_timer = 0;             // the interval timer used to stretch the element to fit one of the sides
  var _ie_need_fix = false;
  
  var _detectIE = function(){
  	
    if(document.documentMode){
      _ie_need_fix = (document.documentMode != 8 && document.documentMode != 7);
    }else{
      if(YAHOO.env.ua.ie && YAHOO.env.ua.ie < 8){
        _ie_need_fix = true;
      }
    }
  }

  // stretch element to the whole dimension of the side
  var _stretch = function(){
    // stretch the div, depending on position
    if(_pos == 'bottom' || _pos == 'top'){
      var dW = Dom.getDocumentWidth()-2;
      _main_elem.style.width = dW + 'px';
    }
    if(_pos == 'right' || _pos == 'left'){
      var dH = Dom.getDocumentHeight()-2;
      _main_elem.style.height = dH + 'px';
    }
  }

  // -- initialization for slideup object
  var _init = function(){
    // we need to detect which version of IE we are running
    _detectIE();
    // create the DOM element of the slideup
    _main_elem = document.createElement('div');
    _main_elem.id = 'slideup_' + _pos;
    _main_elem.className = 'slideup';
    
    // offline element dont cause a reflow, so no worries here
    // we use a local variable to shorten the scope in which JS has to look for the variable
    var style = _main_elem.style;
    if(_ie_need_fix){
    	style.position = 'absolute';
    }else{
    	style.position = 'fixed';
    }
    style.height = '0px'; // these two are set when we stretch the div or when we are going to animate
    style.width = '0px';  // they also change between slide transition animation
    style.left = '0px';
    style.overflow = 'hidden';

    // if the client wants a close button, create it
    if(_options['close_button']){
      // same here: offline element, dont cause a reflow
      var close_button = document.createElement('div');
      close_button.id = 'slideup_close_button_'+_pos;
      close_button.innerHTML = '&nbsp;';
      style = close_button.style;
      style.cssFloat = 'right';
      if(YAHOO.env.ua.ie){
        style.styleFloat = 'right';
      }else{
        style.cssFloat = 'right';
      }
      style.width = '15px';
      style.height = '15px';
      Evt.addListener(close_button, "click", function(){_disappear();});
      _main_elem.appendChild(close_button);
    }
    if(_pos == 'bottom' || _pos == 'top'){
      _dimension = 'height';
    }
    if(_pos == 'right' || _pos == 'left'){
      _dimension = 'width';
    }
    _stretch();
    _stretch_timer = window.setInterval(_stretch, 100);
    
  }();

  var _appear = function() {
    // show the main DOM element and reset "appear" animation
    document.body.appendChild(_main_elem);
    _current_slide_index = 0;
    _slides[_current_slide_index].style.display = 'block';
    var style = _main_elem.style;
    _animateAppear();
    if(typeof(_options['disappear_in']) == 'number'){
      window.setTimeout(_disappear, _options['disappear_in'] * 1000);
    }
  }

  var _disappear = function() {
    window.clearInterval(_fixelement_timer);
    _animateDisappear();
  }

  var _getSlideDim = function(style) {
    var current_slide_style = _slides[_current_slide_idx].style[style];
    var intvalue = parseInt(current_slide_style.replace('px','').replace('pt','').replace('em',''));
    if(!intvalue){
      if(_options[style]){
        intvalue = _options[style];
      }else{
        intvalue = 50;
      }
    }
    return intvalue;
  }

   // only for IE with buggy fixed positioning - fix the element to one of the sides
  var _fixElementIE = function(){
    var offset = 0;
    if(_dimension == 'height'){
      offset = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
      if(_pos == 'bottom'){
        offset = -offset;
      }
  	}
  	if(_dimension == 'width'){
  	  offset = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft;
  	  if(_pos == 'right'){
  	    offset = -offset;
  	  }
  	}
  	_main_elem.style[_pos] = offset + 'px'; 
  }
  
  // animation functions
  // do the appear animation based on dimension (width or height)
  var _animateAppear = function() {
    // get the integer value for the current slide dimension (width or height)
    var slide_dim = _getSlideDim(_dimension);
    // cache main element style on local variable
    var style = _main_elem.style;
    // position element outside the viewport 
    style[_pos] = (-slide_dim) + 'px';
    style[_dimension] = slide_dim + 'px';
    var anim_params = {};
    anim_params[_pos] = {to:0};
    var animation = new Anim(_main_elem.id, anim_params, 0.5);
    if(_ie_need_fix){
      animation.onComplete.subscribe(function(){
        _fixelement_timer = window.setInterval(_fixElementIE, 100);
      });
    }
    animation.animate();
  }

  // disappear
  var _animateDisappear = function() {
    var slide_dim = _getSlideDim(_dimension);
    var anim_params = {};
    anim_params[_pos] = {to:-slide_dim};
    var animation = new Anim(_main_elem.id, anim_params, 0.5);
    animation.onComplete.subscribe(function(){
      document.body.removeChild(_main_elem);
    });
    animation.animate();
  }

  var _animateResize = function() {
    var current_slide_style = _slides[_current_slide_idx].style;
    current_slide_style.display = 'block';
    var slide_dim = parseInt(current_slide_style[_dimension].replace('px',''));
    // change only if the new slide have a new dimension
    if(slide_dim){
      var anim_params={};
      anim_params[_dimension] = {to:slide_dim};
      var animation = new Anim(_main_elem.id, anim_params,0.5);
      animation.animate();
    }
  }

  return {
    addSlide: function(slide) {
      if(typeof(slide) == 'string'){
        slide = Dom.get(slide);
      }
      var parentElem = slide.parentNode;
      parentElem.removeChild(slide);
      if(_options['close_button']){
        // if(YAHOO.env.ua.ie){
        //   slide.style.styleFloat = 'right';
        // }else{
        //   slide.style.cssFloat = 'right';
        // }
        var width = parseInt(_main_elem.style.width.replace('px',''));
        slide.style.width = (width - 15) + 'px';
      }
      slide.style.display = 'none';
      _main_elem.appendChild(slide);
      _slides.push(slide);
    },
    show: function() {
      if(typeof(_options['appear_in']) == 'number'){
        window.setTimeout(_appear, _options['appear_in'] * 1000);
      }else{
        _appear();
      }
    },
    next: function() {
      _current_slide_idx += 1;
      if(_current_slide_idx >= _slides.length){
        _current_slide_idx -= 1;
      }
      _slides[_current_slide_idx - 1].style.display = 'none';
      _animateResize();
    },
    close: function() {
      _disappear();
    }
  }
}

// Factory of "SlideUpObject"
var SlideUp = function() {
  var _objects = {};
  return {
    init: function(options) {
      if(typeof(options['position']) != 'string'){
        log('slideup error: wrong data type for position parameter, has to be a string, got: %s instead', typeof(options['position']));
        return null;
      }
      if(options['position'] != 'bottom' && options['position'] != 'top' &&
         options['position'] != 'left' && options['position'] != 'right'){
        log('slideup error: wrong argument for position parameter, has to be: top, bottom, left or right. Got %s instead', options['position']);
        return null;
      }
      _objects[options['position']] = SlideUpObject(options);
      return _objects[options['position']];
    },
    get: function(position) {
      if(typeof(_objects[position]) == 'undefined'){
        return null;
      }
      return _objects[position];
    }
  }
}();


