//MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2009 Aaron Newton <http://clientcide.com/>, Valerio Proietti <http://mad4milk.net> & the MooTools team <http://mootools.net/developers>, MIT Style License.

/*
---

script: More.js

description: MooTools More

license: MIT-style license

authors:
- Guillermo Rauch
- Thomas Aylott
- Scott Kyle

requires:
- core:1.2.4/MooTools

provides: [MooTools.More]

...
*/

MooTools.More = {
	'version': '1.2.4.2',
	'build': 'bd5a93c0913cce25917c48cbdacde568e15e02ef'
};

/*
---

script: Fx.Elements.js

description: Effect to change any number of CSS properties of any number of Elements.

license: MIT-style license

authors:
- Valerio Proietti

requires:
- core:1.2.4/Fx.CSS
- /MooTools.More

provides: [Fx.Elements]

...
*/

Fx.Elements = new Class({

	Extends: Fx.CSS,

	initialize: function(elements, options){
		this.elements = this.subject = $$(elements);
		this.parent(options);
	},

	compute: function(from, to, delta){
		var now = {};
		for (var i in from){
			var iFrom = from[i], iTo = to[i], iNow = now[i] = {};
			for (var p in iFrom) iNow[p] = this.parent(iFrom[p], iTo[p], delta);
		}
		return now;
	},

	set: function(now){
		for (var i in now){
			var iNow = now[i];
			for (var p in iNow) this.render(this.elements[i], p, iNow[p], this.options.unit);
		}
		return this;
	},

	start: function(obj){
		if (!this.check(obj)) return this;
		var from = {}, to = {};
		for (var i in obj){
			var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {};
			for (var p in iProps){
				var parsed = this.prepare(this.elements[i], p, iProps[p]);
				iFrom[p] = parsed.from;
				iTo[p] = parsed.to;
			}
		}
		return this.parent(from, to);
	}

});

/*
---

script: Fx.Accordion.js

description: An Fx.Elements extension which allows you to easily create accordion type controls.

license: MIT-style license

authors:
- Valerio Proietti

requires:
- core:1.2.4/Element.Event
- /Fx.Elements

provides: [Fx.Accordion]

...
*/

var Accordion = Fx.Accordion = new Class({

	Extends: Fx.Elements,

	options: {/*
		onActive: $empty(toggler, section),
		onBackground: $empty(toggler, section),
		fixedHeight: false,
		fixedWidth: false,
		*/
		display: 0,
		show: false,
		height: true,
		width: false,
		opacity: true,
		alwaysHide: false,
		trigger: 'click',
		initialDisplayFx: true,
		returnHeightToAuto: true
	},

	initialize: function(){
		var params = Array.link(arguments, {'container': Element.type, 'options': Object.type, 'togglers': $defined, 'elements': $defined});
		this.parent(params.elements, params.options);
		this.togglers = $$(params.togglers);
		this.container = document.id(params.container);
		this.previous = -1;
		this.internalChain = new Chain();
		if (this.options.alwaysHide) this.options.wait = true;
		if ($chk(this.options.show)){
			this.options.display = false;
			this.previous = this.options.show;
		}
		if (this.options.start){
			this.options.display = false;
			this.options.show = false;
		}
		this.effects = {};
		if (this.options.opacity) this.effects.opacity = 'fullOpacity';
		if (this.options.width) this.effects.width = this.options.fixedWidth ? 'fullWidth' : 'offsetWidth';
		if (this.options.height) this.effects.height = this.options.fixedHeight ? 'fullHeight' : 'scrollHeight';
		for (var i = 0, l = this.togglers.length; i < l; i++) this.addSection(this.togglers[i], this.elements[i]);
		this.elements.each(function(el, i){
			if (this.options.show === i){
				this.fireEvent('active', [this.togglers[i], el]);
			} else {
				for (var fx in this.effects) el.setStyle(fx, 0);
			}
		}, this);
		if ($chk(this.options.display)) this.display(this.options.display, this.options.initialDisplayFx);
		this.addEvent('complete', this.internalChain.callChain.bind(this.internalChain));
	},

	addSection: function(toggler, element){
		toggler = document.id(toggler);
		element = document.id(element);
		var test = this.togglers.contains(toggler);
		this.togglers.include(toggler);
		this.elements.include(element);
		var idx = this.togglers.indexOf(toggler);
		var displayer = this.display.bind(this, idx);
		toggler.store('accordion:display', displayer);
		toggler.addEvent(this.options.trigger, displayer);
		if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'});
		if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'});
		element.fullOpacity = 1;
		if (this.options.fixedWidth) element.fullWidth = this.options.fixedWidth;
		if (this.options.fixedHeight) element.fullHeight = this.options.fixedHeight;
		element.setStyle('overflow', 'hidden');
		if (!test){
			for (var fx in this.effects) element.setStyle(fx, 0);
		}
		return this;
	},

	detach: function(){
		this.togglers.each(function(toggler) {
			toggler.removeEvent(this.options.trigger, toggler.retrieve('accordion:display'));
		}, this);
	},

	display: function(index, useFx){
		if (!this.check(index, useFx)) return this;
		useFx = $pick(useFx, true);
		if (this.options.returnHeightToAuto){
			var prev = this.elements[this.previous];
			if (prev && !this.selfHidden){
				for (var fx in this.effects){
					prev.setStyle(fx, prev[this.effects[fx]]);
				}
			}
		}
		index = ($type(index) == 'element') ? this.elements.indexOf(index) : index;
		if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this;
		this.previous = index;
		var obj = {};
		this.elements.each(function(el, i){
			obj[i] = {};
			var hide;
			if (i != index){
				hide = true;
			} else if (this.options.alwaysHide && ((el.offsetHeight > 0 && this.options.height) || el.offsetWidth > 0 && this.options.width)){
				hide = true;
				this.selfHidden = true;
			}
			this.fireEvent(hide ? 'background' : 'active', [this.togglers[i], el]);
			for (var fx in this.effects) obj[i][fx] = hide ? 0 : el[this.effects[fx]];
		}, this);
		this.internalChain.chain(function(){
			if (this.options.returnHeightToAuto && !this.selfHidden){
				var el = this.elements[index];
				if (el) el.setStyle('height', 'auto');
			};
		}.bind(this));
		return useFx ? this.start(obj) : this.set(obj);
	}

});

/*
---

script: Tips.js

description: Class for creating nice tips that follow the mouse cursor when hovering an element.

license: MIT-style license

authors:
- Valerio Proietti
- Christoph Pojer

requires:
- core:1.2.4/Options
- core:1.2.4/Events
- core:1.2.4/Element.Event
- core:1.2.4/Element.Style
- core:1.2.4/Element.Dimensions
- /MooTools.More

provides: [Tips]

...
*/

(function() {

  var read = function(option, element) {
    return (option) ? ($type(option) == 'function' ? option(element) : element.get(option)) : '';
  };

  this.Tips = new Class({

    Implements: [Events, Options],

    options: {
      /*
      onAttach: $empty(element),
      onDetach: $empty(element),
      */
      onShow: function() {
        this.tip.setStyle('display', 'block');
      },
      onHide: function() {
        this.tip.setStyle('display', 'none');
      },
      title: 'title',
      text: function(element) {
        return element.get('rel') || element.get('href');
      },
      showDelay: 100,
      hideDelay: 100,
      className: 'tip-wrap',
      offset: { x: 16, y: 16 },
      fixed: false
    },

    initialize: function() {
      var params = Array.link(arguments, { options: Object.type, elements: $defined });
      this.setOptions(params.options);
      document.id(this);

      if (params.elements) this.attach(params.elements);
    },

    toElement: function() {
      if (this.tip) return this.tip;

      this.container = new Element('div', { 'class': 'tip' });
      return this.tip = new Element('div', {
        'class': this.options.className,
        styles: {
          position: 'absolute',
          top: 0,
          left: 0
        }
      }).adopt(
			new Element('div', { 'class': 'tip-top' }),
			this.container,
			new Element('div', { 'class': 'tip-bottom' })
		).inject(document.body);
    },

    attach: function(elements) {
      $$(elements).each(function(element) {
        var title = read(this.options.title, element),
				text = read(this.options.text, element);

        element.erase('title').store('tip:native', title).retrieve('tip:title', title);
        element.retrieve('tip:text', text);
        this.fireEvent('attach', [element]);

        var events = ['enter', 'leave'];
        if (!this.options.fixed) events.push('move');

        events.each(function(value) {
          var event = element.retrieve('tip:' + value);
          if (!event) event = this['element' + value.capitalize()].bindWithEvent(this, element);

          element.store('tip:' + value, event).addEvent('mouse' + value, event);
        }, this);
      }, this);

      return this;
    },

    detach: function(elements) {
      $$(elements).each(function(element) {
        ['enter', 'leave', 'move'].each(function(value) {
          element.removeEvent('mouse' + value, element.retrieve('tip:' + value)).eliminate('tip:' + value);
        });

        this.fireEvent('detach', [element]);

        if (this.options.title == 'title') { // This is necessary to check if we can revert the title
          var original = element.retrieve('tip:native');
          if (original) element.set('title', original);
        }
      }, this);

      return this;
    },

    elementEnter: function(event, element) {
      this.container.empty();

      ['title', 'text'].each(function(value) {
        var content = element.retrieve('tip:' + value);
        if (content) this.fill(new Element('div', { 'class': 'tip-' + value }).inject(this.container), content);
      }, this);

      $clear(this.timer);
      this.timer = this.show.delay(this.options.showDelay, this, element);
      this.position((this.options.fixed) ? { page: element.getPosition()} : event);
    },

    elementLeave: function(event, element) {
      $clear(this.timer);
      this.timer = this.hide.delay(this.options.hideDelay, this, element);
      this.fireForParent(event, element);
    },

    fireForParent: function(event, element) {
      element = element.getParent();
      if (!element || element == document.body) return;
      if (element.retrieve('tip:enter')) element.fireEvent('mouseenter', event);
      else this.fireForParent(event, element);
    },

    elementMove: function(event, element) {
      this.position(event);
    },

    position: function(event) {
      var size = window.getSize(), scroll = window.getScroll(),
			tip = { x: this.tip.offsetWidth, y: this.tip.offsetHeight },
			props = { x: 'left', y: 'top' },
			obj = {};

      for (var z in props) {
        obj[props[z]] = event.page[z] + this.options.offset[z];
        if ((obj[props[z]] + tip[z] - scroll[z]) > size[z]) obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z];
      }

      this.tip.setStyles(obj);
    },

    fill: function(element, contents) {
      if (typeof contents == 'string') element.set('html', contents);
      else element.adopt(contents);
    },

    show: function(element) {
      this.fireEvent('show', [this.tip, element]);
    },

    hide: function(element) {
      this.fireEvent('hide', [this.tip, element]);
    }

  });

})();