/**
 * @fileoverview tabs.js
 * Widget.Tabs creates a tabview control from existing markup.<br />
 * Requires Prototype (http://www.prototypejs.org) 1.6 or later as well as Widget.Activator<br /><br />
 *
 * Copyright (c) 2008 Marc Heiligers (marc@eternal.co.za) http://www.eternal.co.za<br /><br />
 */

var Widget = window.Widget || {};
Widget.Tabs = Class.create({
	initialize: function(element, options) {
		this.element = $(element);

		var classNames = Object.extend({
			normal: Widget.Tabs.normalClass,
			hover: Widget.Tabs.hoverClass,
			active: Widget.Tabs.activeClass,
			selected: Widget.Tabs.selectedClass,
			disabled: Widget.Tabs.disabledClass
		}, options ? options.classNames || {} : {});

		var events = Object.extend({
			mouseover: Widget.Tabs.mouseoverEvent,
			mouseout: Widget.Tabs.mouseoutEvent,
			mousedown: Widget.Tabs.mousedownEvent,
			mouseup: Widget.Tabs.mouseupEvent,
			click: Widget.Tabs.clickEvent,
			changing: Widget.Tabs.changingEvent,
			changed: Widget.Tabs.changedEvent
		}, options ? options.events || {} : {});

		this.options = Object.extend({
			tabSelector: "li",
			linkSelector: "a[href]",
			linkMethod: Widget.Tabs.hrefLinks,
			selected: 0,
			changeOn: "click"
		}, options || {});
		this.options.classNames = classNames;
		this.options.events = events;

		this.activator = new Widget.Activator("#" + this.element.identify() + " " + this.options.tabSelector, {
			classNames: classNames,
			events: events,
			container: this.element,
			singleSelect: true,
			extendElements: true
		});

		this.activator.getElements("*").each(function(e) {
			this.panels(e).invoke("hide");
		}, this);

		this.observe = this.activator.observe.bind(this.activator);
		this.stopObserving = this.activator.stopObserving.bind(this.activator);
		this.fire = Element.fire.curry(this.element);

		this.observe(this.activator.options.events[this.options.changeOn], this.show.bind(this));
		this.show(this.options.selected);

	},
	show: function(e) {
		var tab;
		if(Object.isNumber(e) || Object.isString(e)) {
			tab = this.activator.getElement(e);
		} else {
			tab = this.activator.isElement(e.memo.element);
		}
		if(!tab) return;

		var memo = { from: this.selected, to: tab, tabs: this, event: e.memo ? e.memo.event : null };
		var ev = this.fire(this.options.events.changing, memo);
		if(ev.stopped) return;

		if(this.selected) {
			this.activator.setSelected(this.selected, false);
			this.panels(this.selected).invoke("hide");
		}
		this.selected = tab;
		this.activator.setSelected(this.selected, true);
		this.panels(this.selected).invoke("show");

		this.fire(this.options.events.changed, memo);
	},
	panels: function(tab) {
		return $$(this.options.linkMethod(tab.down(this.options.linkSelector)));
	},
	destroy: function() {
		this.activator.getElements("*").each(function(e) {
			this.panels(e).invoke("show");
		}, this);
		this.activator.destroy();
	}
});


/**
 * Constants
 */
Object.extend(Widget.Tabs, {
	normalClass: null,
	hoverClass: "hover",
	activeClass: "active",
	selectedClass: "selected",
	disabledClass: "disabled",
	/**
	 * Name of mouseover event fired by the tabs.
	 */
	mouseoverEvent: "tab:mouseover",
	/**
	 * Name of mouseout event fired by the tabs.
	 */
	mouseoutEvent: "tab:mouseout",
	/**
	 * Name of mousedown event fired by the tabs.
	 */
	mousedownEvent: "tab:mousedown",
	/**
	 * Name of mouseup event fired by the tabs.
	 */
	mouseupEvent: "tab:mouseup",
	/**
	 * Name of click event fired by the tabs.
	 */
	clickEvent: "tab:click",
	/**
	 * Name of changing event fired by the tabs.
	 */
	changingEvent: "tab:changing",
	/**
	 * Name of changed event fired by the tabs.
	 */
	changedEvent: "tabs:changed",
	hrefLinks: function(e) {
		return "#" + e.getAttribute("href").split("#")[1];
	},
	classLinks: function(e) {
		return l = "." + $w(e.className).find(function(s) {
			return s.startsWith("tabs-show-");
		}).substr(10);
	}
});
