/*
yodeler YUI Addons - widget.ScrollTabView
Copyright 2008 Reid Burke <me@reidburke.com>
Code licensed under the BSD License: http://internal.reidburke.com/yui-addons/license.txt
*/

/**
 * An extension of TabView that transitions between tabs using a Scroll Animation.
 *
 * @namespace YAHOO.yodeler.widget
 * @module ScrollTabView
 * @requires yahoo, event, dom, anim, tabview
 * @author Reid Burke <me@reidburke.com>
 * @version 0.1
 */

if (typeof YAHOO != "undefined")
{
  YAHOO.namespace('yodeler.widget');

(function() {

    /**
     * @constructor
     * @extends YAHOO.widget.TabView
     * @param {HTMLElement | String | Object} el (optional) The html
     * element that represents the ScrollTabView, or the attribute
     * object to use.
     * An element will be created if none provided.
     * @param {Object} attr (optional) A key map of ScrollTabView's
     * initial attributes. Ignored if first arg is attributes object.
     */
    YAHOO.yodeler.widget.ScrollTabView = function (el, attr) {
        YAHOO.yodeler.widget.ScrollTabView.superclass.constructor.call(this, el, attr);
    }

    YAHOO.lang.extend(YAHOO.yodeler.widget.ScrollTabView, YAHOO.widget.TabView);

    var proto = YAHOO.yodeler.widget.ScrollTabView.prototype,
        Dom = YAHOO.util.Dom;

    /**
     * Overrides default contentTransition with a transition
     * that animates between Tab views.
     *
     * @method contentTransition
     * @param {YAHOO.widget.Tab} newTab
     * @param {YAHOO.widget.Tab} oldTab
     * @return void
     */
    proto.contentTransition = function(newTab, oldTab) {
        var px, dims, ani;
        switch (this.get('direction')) {
            case 'horizontal':
                px = this.get('width') * this.getTabIndex(newTab);
                dims = [px, 0];
            break;
            case 'vertical':
                px = this.get('height') * this.getTabIndex(newTab);
                dims = [0, px]
            break;
        }
        newTab.set('contentVisible', true);
        ani = new YAHOO.util.Scroll(this._contentParent,
            { scroll: { to: dims } },
            this.get('duration'),
            this.get('easing')
        );
        ani.onComplete.subscribe(function() {
            oldTab.set('contentVisible', false);
            // Keep content visible for effect during transitions
            oldTab.get('contentEl').style.display = 'block';
        });
        ani.animate();
    }

    /**
     * Adds a Tab to the ScrollTabView.
     * If no index is specified, the tab is added to the end of the tab list.
     *
     * @method addTab
     * @param {YAHOO.widget.Tab} tab A Tab instance to add.
     * @param {Integer} index The position to add the tab.
     * @return void
     */
    proto.addTab = function(tab, index) {
        YAHOO.yodeler.widget.ScrollTabView.superclass.addTab.call(this, tab, index);
        _initTabStyle.call(this);
    }

    /**
     * Removes the specified Tab from the ScrollTabView.
     *
     * @method removeTab
     * @param {YAHOO.widget.Tab} item The Tab instance to be removed.
     * @return void
     */
    proto.removeTab = function(tab) {
        YAHOO.yodeler.widget.ScrollTabView.superclass.removeTab.call(this, tab);
        _initTabStyle.call(this);
    }

    /**
     * setAttributeConfigs ScrollTabView specific properties.
     *
     * @method initAttributes
     * @param {Object} attr Hash of initial attributes
     */
    proto.initAttributes = function(attr) {

        YAHOO.yodeler.widget.ScrollTabView.superclass.initAttributes.call(this, attr);

        this.setAttributeConfig('width', {
            value: attr.width || false,
            method: _initTabStyle.call(this),
            validator: YAHOO.lang.isNumber
        });
        this.setAttributeConfig('height', {
            value: attr.height || false,
            method: _initTabStyle.call(this),
            validator: YAHOO.lang.isNumber
        });
        this.setAttributeConfig('direction', {
            value: attr.direction || 'horizontal',
            method: _initTabStyle.call(this)
        });
        this.setAttributeConfig('easing', {
            value: attr.easing || YAHOO.util.Easing.easeBothStrong,
            validator: YAHOO.lang.isFunction
        });
        this.setAttributeConfig('duration', {
            value: attr.duration || 1,
            validator: YAHOO.lang.isNumber
        });

        // Override TabView's refusal to contentTransition
        // when the tab is already set to contentVisible
        this.addListener('activeTabChange', function(ev) {
            var activeTab = this.get('activeTab');
            if (ev.newValue && !(activeTab && ev.newValue != activeTab)) {
                this.contentTransition(ev.newValue, activeTab);
            }
        });

        // Setup element styles
        _initTabStyle.call(this);
    }

    var _initTabStyle = function() {

        var width = this.get('width');
        var height = this.get('height');
        var direction = this.get('direction');

        if (!width || !height || !direction) return false; // wait until all Attributes are set

        Dom.setStyle(this._contentParent, 'overflow', 'hidden');
        Dom.setStyle(this._contentParent, 'position', 'relative');
        Dom.setStyle(this._contentParent, 'width', width + 'px');
        Dom.setStyle(this._contentParent, 'height', height + 'px');

        var tabs = this.get('tabs');

        for (var i = 0, length = tabs.length; i < length; ++i) {

            var contentElement = tabs[i].get('contentEl');

            Dom.setStyle(contentElement, 'position', 'absolute');

            switch (direction) {
                case 'horizontal':
                    Dom.setStyle(contentElement, 'top', '0');
                    Dom.setStyle(contentElement, 'left', (width * i) + 'px');
                    Dom.setStyle(contentElement, 'width', width + 'px');
                break;
                case 'vertical':
                    Dom.setStyle(contentElement, 'left', '0');
                    Dom.setStyle(contentElement, 'top', (height * i) + 'px');
                    Dom.setStyle(contentElement, 'height', height + 'px');
                break;
            }

            // Keep content visible for effect during transitions
            contentElement.style.display = 'block';

        }

    }

})();
}
