//////////////////////////////////////////////////////
// Expander.js ///////////////////////////////////////
//
// Expander v1.1
//
// written by: Gary Hussey 2008 | http://www.
//
// License:
//  Open and Free. It's not like anyone couldn't have
//  written this. If you improve it, I'd like to see.
//
// *requires mootools v1.2
//
// This simple class takes uses pre-existing markup
// to create expandable secions.

/*
EXAMPLE #1:

  <div class="Expander">
    <span>title<span><a href="/link.html" class="handle"></a>
    <div class="contents">html content</div>
  </div>

  <script>
    new Expander('.Expander',{
      handles:['.handle','span'],
      contents:'.contents'
    });
  </script>
*/

//
// Expander.Ajax
//
// options: options beyond those in Expander
//   waitclass -> classname to apply to contents when loading
//   waitcontent -> content to insert into contents while loading

/*
EXAMPLE:

  <div class="ExpanderAjax" request="/serverside.php">
    <span>title<span><a href="/link.html" class="handle"></a>
    <div class="contents"></div>
  </div>

  <script>
    new Expander.Ajax('.ExpanderAjax',{
      handles:['.handle','span'],
      contents:'.contents'
    });
  </script>
*/

var Expander = new Class({
  Implements:[Options,Events],
  options:{
    contents:'.contents',
    hideLast:false,
    maxHeight:false,
    minHeight:false,
    handles:[],
    hideStickyOnClose:true
  },
  selector:"",
  stickySelector:null,
  initialize:function(selector,options){
    this.setOptions(options);
    this.selector = selector || ".Expander";
    this.stickySelector = this.options.stickySelector || "";
    this.onContents = false;
    $$(this.selector).each(this.newExpander.bind(this));
  },
  open:function(el){
    if(el.hasClass('open'))return;
    this.hideSticky(el,false  );
    if(this.options.hideLast)$$(this.selector+'.open').each(this.close.bind(this));
    var contents = el.getElement(this.options.contents);
    contents.setStyle('display','block');
    contents.set('morph',{onComplete:this.onOpen.bind(this,contents)});
    if(this.options.maxHeight && contents.getScrollSize().y > this.options.maxHeight){
      contents.morph({
        'height':this.options.maxHeight
      });
    }else if(this.options.minHeight && contents.getScrollSize().y < this.options.minHeight){
      contents.morph({
        'height':this.options.minHeight
      });
    }else{
      contents.morph({
        'height':contents.getScrollSize().y
      });
    }
    el.addClass('open');
  },
  close:function(el){
    if(el.hasClass('sticky') || !el.hasClass('open'))return;
    this.hideSticky(el,true);
    var contents = el.getElement(this.options.contents);
    contents.set('morph',{onComplete:this.onClose.bind(this,contents)});
    contents.morph({
      'height':1
    });
    el.removeClass('open');
  },
  hide:function(el){
    this.hideSticky(el,true);
    var contents = el.getElement(this.options.contents);
    contents.setStyles({
      'display':'none',
      'height':1
    });
  },
  toggle:function(el){
    if(this.onContents)return;
    if(el.hasClass('open')){
      this.close(el);
    }else{
      this.open(el);
    }
  },
  onOpen:function(el){
    el.getParent(this.selector).fireEvent('onOpen',el);
  },
  onClose:function(el){
    el.setStyle('display','none');
    el.getParent(this.selector).fireEvent('onClose',el);
  },
  toggleSticky:function(el){
    el.toggleClass('sticky');
    if(!el.hasClass('sticky')) this.close(el);
  },
  newExpander:function(el){
    el.getElement(this.options.contents).setStyles({
      'overflow':this.options.maxHeight?'auto':'hidden'
    });

    var trigger = el.getElement(this.stickySelector);
    if(trigger){
      trigger.addEvent('click',this.toggleSticky.bind(this,el));
    }
    this.setHandle(el);
    if(!el.hasClass('open')){
      this.hide(el);
    }else{
      this.onOpen(el.getElement(this.options.contents));
    }
  },
  handle:function(handle){
    this.toggle(handle.getParent(this.selector));
    return false;
  },
  setHandle:function(el){
    if(this.options.handles){
      for(var i=0 ; this.options.handles[i] ; i++){
        var handle = el.getElement(this.options.handles[i]);
        if($chk(handle))handle.addEvent('click',this.handle.bind(this,handle));
      }
    }else{
      el.addEvent('click',this.toggle.bind(this,el));
      el.getElement(this.options.contents).addEvent('mouseenter',function(){this.onContents = true}.bind(this));
      el.getElement(this.options.contents).addEvent('mouseleave',function(){this.onContents = false}.bind(this));
    }
  },
  hideSticky:function(el,hide){
    if(!this.options.hideStickyOnClose || this.stickySelector == "")return;
    el.getElement(this.stickySelector).setStyle("visibility", hide ? "hidden" : "visible");
  }
});



Expander.Ajax = new Class({
	Extends:Expander,
	initialize:function(selector,options){
		this.parent(selector,options);
	},
	onOpen:function(contents){
		this.parent(contents);
		var el = contents.getParent(this.selector);
		if(!el.hasClass('loaded')){
		  contents.addClass("wait");
		  contents.set('html',this.options.waitcontent || '');
		  contents.set('load',{onComplete:this.onHtml.bind(this,el)});
		  contents.load(el.get('request'));
		}
	},
	onHtml:function(el){
		el.addClass('loaded');
		var contents = el.getElement(this.options.contents);
		contents.removeClass(this.options.waitclass||"wait");
	}
});
