//
// COMMUNITOR SiteWare 2.0 Site Server
// Copyright by COMMUNITOR Internetservice GmbH, 2001-2010
//


/*************************************/
/*  Pulldown-Menu-Klasse SWmenu */
/*************************************/
var SWmenu = Class.create();
Object.extend(SWmenu.prototype, {
  // container containing roll over links
  initialize: function(container) {
    this.container = $(container);
    this.options = Object.extend({
      selector: 'ul.SWmenu',
      childSelector: 'li',
      subSelector: 'ul',
      leftShadowSelector: '.leftShadow',
      rightShadowSelector: '.rightShadow',
      animatedItems: 5,
      duration: 0.8
    }, arguments[1] || { });
    this.container.select(this.options.selector + ' > ' + this.options.childSelector).each(this.setup.bind(this));
  },
  setup: function(item) {
    var subMenu = item.select(this.options.subSelector)[0];
    if (!subMenu)
      return;
    // get expanded dimensions
    subMenu.setStyle({display:'block',visibility:'hidden',overflow:'visible',height:'auto',width:'auto'});
    var height = subMenu.offsetHeight,
        length = subMenu.select(this.options.childSelector).length,
        parent = item.getOffsetParent();
    subMenu.SWmenuMaxHeight = height;
    if (length > this.options.animatedItems)
      height = Math.round(height / length * (length - this.options.animatedItems));
    else
      height = 0;
    subMenu.SWmenuMinHeight = height;
    // check positioning limits
    subMenu.absolutize();
    var left,styleLeft = 0,
        parentLeft = parent.cumulativeOffset()[0],
        parentWidth = parent.offsetWidth,
        offsetLeft = subMenu.cumulativeOffset()[0],
        offsetWidth = subMenu.offsetWidth;
    ['borderLeftWidth','borderRightWidth','marginLeft','marginRight'].each(function(s){
      s = parseInt(subMenu.getStyle(s));
      if (!isNaN(s)) offsetWidth += s;
    });
    if (offsetLeft+offsetWidth > parentLeft+parentWidth) {
      left = parentLeft + parentWidth - offsetLeft - offsetWidth;
      if (offsetLeft+left >= parentLeft)
        styleLeft = left;
    }
    if (offsetLeft + styleLeft < parentLeft)
      styleLeft = parentLeft - offsetLeft - styleLeft;
    // apply style
    var newStyle = {height:height+'px',width:subMenu.offsetWidth+'px',overflow:'hidden'};
    if (styleLeft != 0)
      newStyle.left = styleLeft+'px';
    // set data
    subMenu.setStyle(newStyle).setOpacity(0);
    // check shadow divs
    var shadows = this.setupShadows(subMenu,styleLeft,offsetWidth,
      item.select(this.options.leftShadowSelector)[0],
      item.select(this.options.rightShadowSelector)[0]
    );
    item.SWmenuState = 'in';
    // observe mouse events
    item.observe('mouseover',this.overMenu.bindAsEventListener(this,item,subMenu,shadows));
    item.observe('mouseout',this.outMenu.bindAsEventListener(this,item,subMenu,shadows));
  },
  setupShadows: function(subMenu,styleLeft,offsetWidth,leftShadow,rightShadow){
    if (!leftShadow || !rightShadow)
      return null;
    // set margin height
    var bottomMargin = -parseInt(leftShadow.getStyle('bottom'));
    if (isNaN(bottomMargin)) bottomMargin = 0;
    ['borderTopWidth','borderBottomWidth','marginTop','marginBottom'].each(function(s){
      s = parseInt(subMenu.getStyle(s));
      if (!isNaN(s)) bottomMargin += s;
    });
    // set top, left and width dimensions
    var left = parseInt(leftShadow.getStyle('left'));
    if (isNaN(left)) left = 0;
    var width = Math.floor(offsetWidth/2) - left;
    leftShadow.setStyle({
      left:(left + styleLeft)+'px',
      top:subMenu.offsetTop+'px',
      width:width+'px',
      height:(subMenu.offsetHeight + bottomMargin)+'px',
      right:'',
      bottom:''
    });
    var right = parseInt(rightShadow.getStyle('right'));
    if (isNaN(right)) right = 0;
    rightShadow.setStyle({
      left:(left + styleLeft + width)+'px',
      top:subMenu.offsetTop+'px',
      width:(Math.ceil(offsetWidth/2) - right)+'px',
      height:(subMenu.offsetHeight + bottomMargin)+'px',
      right:'',
      bottom:''
    });
    return {left:leftShadow,right:rightShadow,bottomMargin:bottomMargin}
  },
  setZindex: function(container,step){
    var z = parseInt(container.getStyle('zIndex'));
    if (!isNaN(z))
      container.setStyle({zIndex: z + step});
  },
  getPosition: function(container){
    return (container.offsetHeight - container.SWmenuMinHeight) / (container.SWmenuMaxHeight - container.SWmenuMinHeight);
  },
  overMenu: function(e,item,container,shadows){
    item.SWsubState = 'over';
    if (item.SWmenuState == 'run-out' || item.SWmenuState == 'out') return;
    item.SWmenuState = 'run-out';
    this.setZindex(container,+1);
    var effects = [
      new Effect.Scale(container, 100, {
        sync: true,
        scaleX: false,
        scaleContent: false,
        scaleFrom: container.SWmenuMinHeight/container.SWmenuMaxHeight*100,
        scaleMode: { originalHeight: container.SWmenuMaxHeight, originalWidth: container.offsetWidth },
        afterSetup: this.afterSetup.bind(this,shadows),
        afterUpdate: this.afterUpdate.bind(this,shadows),
        afterFinish: this.afterFinish.bind(this,item,'out',shadows)
      }),
      new Effect.Opacity(container, { sync: true, from: 0, to: 1, transition: Effect.Transitions.linear })
    ];
    if (shadows)
      [shadows.left, shadows.right].each(function (el){
        effects.push(new Effect.Opacity(el,{
          sync: true,
          from: 0,
          to: 1,
          transition: Prototype.Browser.IE ? Effect.Transitions.round : Effect.Transitions.linear
        }));
      });
    var from = this.getPosition(container);
    new Effect.Parallel(effects, {
      duration: this.options.duration * (1-from),
      from: from,
      beforeUpdate: this.beforeUpdate.bind(this,item,'out')
    });
  },
  outMenu: function(e,item,container,shadows){
    item.SWsubState = 'out';
    if (item.SWmenuState == 'run-out' || item.SWmenuState == 'out')
      this.storeMenu.delay(0.1,this,item,container,shadows);
  },
  storeMenu: function(menu,item,container,shadows){
    if (item.SWsubState == 'over' || item.SWmenuState == 'run-in' || item.SWmenuState == 'in') return;
    item.SWmenuState = 'run-in';
    menu.setZindex(container,-1);
    var effects = [
      new Effect.Scale(container, container.SWmenuMinHeight/container.SWmenuMaxHeight*100, {
        sync: true,
        scaleX: false,
        scaleContent: false,
        scaleMode: { originalHeight: container.SWmenuMaxHeight, originalWidth: container.offsetWidth },
        afterUpdate: menu.afterUpdate.bind(menu,shadows),
        afterFinish: menu.afterFinish.bind(menu,item,'in',shadows)
      }),
      new Effect.Opacity(container, { sync: true, from: 1, to: 0, transition: Effect.Transitions.linear })
    ];
    if (shadows) {
      [shadows.left, shadows.right].each(function (el){
        effects.push(new Effect.Opacity(el,{
          sync: true,
          from: 1,
          to: 0,
          transition: Prototype.Browser.IE ? Effect.Transitions.round : Effect.Transitions.linear
        }));
      });
    }
    var delta = menu.getPosition(container);
    new Effect.Parallel(effects,{
      duration: menu.options.duration * delta,
      from: 1-delta,
      beforeUpdate: menu.beforeUpdate.bind(menu,item,'in')
    });
  },
  afterSetup: function(shadows,effect){
    effect.element.setStyle({visibility:'visible'});
    if (shadows)
      [shadows.left, shadows.right].invoke('setStyle',{visibility:'visible'});
  },
  beforeUpdate: function(item,direction,effect){
    if (item.SWmenuState != 'run-' + direction)
      effect.cancel();
  },
  afterUpdate: function(shadows,effect){
    if (shadows)
      [shadows.left, shadows.right].invoke('setStyle',{height: ( parseInt(effect.element.getStyle('height')) + shadows.bottomMargin )+'px'});
  },
  afterFinish: function(item,direction,shadows,effect){
    if (item && item.SWmenuState == 'run-' + direction)
      item.SWmenuState = direction;
    if (direction == 'in') {
      effect.element.setStyle({visibility:'hidden'});
      if (shadows)
        [shadows.left, shadows.right].invoke('setStyle',{visibility:'hidden'});
    }
  }
});