/**
 * Smooth tabs UI widget for jQuery
 *
 * Performs a smooth animation when switching between tabs -- fadding and adjusting the tab panel height
 *
 * Portions derrived from jQuery UI Tabs
 *
 * HTML is similar to that of the jQuery UI tabs.  The main difference is that
 * the tab panels must be placed inside a container for the smooth height adjustment.
 * (labelled with id="tab-panel-container" in example below)
 *
 * If you wish your tab panels to have a background, place it on the container,
 * and not the tab panels themselves.  In addition, the tab panel container
 * should not contain any padding for the best transition between tabs.  Instead,
 * place the padding on the tab panels themselves.
 *
 * <div id="tabs">
 *     <ul>
 *         <li><a href="#" id="select-tab-1">Tab 1 Name</a></li>
 *         <li><a href="#" id="select-tab-2">Tab 2 Name</a></li>
 *         <li><a href="#" id="select-tab-3">Tab 3 Name</a></li>
 *     </ul>
 *     <div id="tab-panel-container">
 *         <div id="tab-1">
 *             <!-- Tab 1 content -->
 *         </div>
 *         <div id="tab-2">
 *             <!-- Tab 2 content -->
 *         </div>
 *         <div id="tab-3">
 *             <!-- Tab 3 content -->
 *         </div>
 *    </div>
 * </div>
 *
 * Create the tabs by calling the smoothTabs() function on the jQuery element.
 *
 * <script type="text/javascript">
 * //<![CDATA[
 *     $(function() {
 *         $('#tabs').smoothTabs();
 *     });
 * //]]>
 * </script>
 *
 * You may optionally pass an options object to the smoothTabs() function. The
 * following are the available options, and their default values:
 *
 * <script type="text/javascript">
 * //<![CDATA[
 *     $(function() {
 *         $('#tabs').smoothTabs({
 *             // speed to fade out the tab panel being hidden
 *             // (can be fast, slow, normal, or the time in milliseconds)
 *             fadeOut: 'fast',
 *
 *             // speed to fade in the tab panel being shown
 *             // (can be fast, slow, normal, or the time in milliseconds)
 *             fadeIn: 'normal',
 *
 *             // speed to adjust the height between the tab panels
 *             // (can be fast, slow, normal, or the time in milliseconds)
 *             height: 'normal',
 *
 *             // CSS classes
 *             navClass: 'ui-tabs-nav',
 *             selectedClass: 'ui-tabs-selected',
 *             unselectClass: 'ui-tabs-unselect',
 *             disabledClass: 'ui-tabs-disabled',
 *             panelClass: 'ui-tabs-panel',
 *             panelContainerClass: 'ui-tabs-panel-container',
 *             hideClass: 'ui-tabs-hide'
 *         });
 *     });
 * //]]>
 * </script>
 *
 * @author Joshua Dechant <i.dream.scape@gmail.com>
 * @license BSD
 */
;(function($) {
$.widget("ui.smoothTabs", {
    $nav: null,
    $lis: null,
    $tabs: null,
    $panels: null,
    $container: null,
    init: function()
    {
        this.$nav = this.element.is('ul') ? this.element : this.element.children('ul:first');
        this.$lis = this.$nav.children('li:has(a[id])');
        this.$container = this.$nav.siblings(':first');
        this.$tabs = this.$lis.map(function() { return $('a', this)[0]; });
        this.$panels = $([]);

        var self = this, o = this.options;

        /**
         * Get tab panels
         */
        this.$tabs.each(function(i, a)
        {
            /**
             * If the id attribute of the anchor begins with "select-",
             * we check for the matching tab
             */
            if ($(a).attr('id').substr(0, 7) === 'select-')
            {
                /**
                 * Strip "select-" from the id attribute to get the id of
                 * the tab panel
                 */
                var id = $(a).attr('id').substr(7);

                /**
                 * Get the tab panel as a jQuery object
                 */
                var $panel = $('#' + id);

                /**
                 * If the panel exists, set its hash as the anchor href (to use later),
                 * and add it to the self.$panels array
                 */
                if ($panel.length)
                {
                    a.href = '#' + id;
                    self.$panels = self.$panels.add($panel);
                }
            }
        });

        /**
         * Attach classes for styling (if not present)
         */
        this.$nav.addClass(o.navClass);
        this.$container.addClass(o.panelContainerClass);
        this.$panels.each(function()
        {
            $(this).addClass(o.panelClass);
        });

        /**
         * Selected tab
         */
        if (o.selected === undefined)
        {
            var selected = self.$lis.filter('.' + o.selectedClass);
            if (selected.length)
            {
                o.selected = self.$lis.index(selected.eq(0));
            }
        }

        /**
         * first tab selected by default
         */
        o.selected = o.selected === null || o.selected !== undefined ? o.selected : 0;

        /**
         * highlight selected tab
         */
        this.$panels.addClass(o.hideClass);
        this.$lis.removeClass(o.selectedClass);

        if (o.selected !== null)
        {
            this.$panels.eq(o.selected).show().removeClass(o.hideClass); // use show and remove class to show in any case no matter how it has been hidden before
            this.$lis.eq(o.selected).addClass(o.selectedClass);

            /**
             * Force outer div height for proper animation
             */
            this.$container.css({ height: this.getSelectedHeight() });
        }

        /**
         * tab click event
         */
        this.$tabs.bind('click', function()
        {
            self.switchTab(this);
            return false;
        });
    },

    switchTab: function(tab)
    {
        var $li = $(tab).parents('li:eq(0)'),
            $hide = this.$panels.filter(':visible'),
            $show = $(tab.hash),
            o = this.options,
            self = this;

        /**
         * If tab is already selected, do nothing
         */
        if ($li.hasClass(o.selectedClass))
        {
            tab.blur();
            return false;
        }

        /**
         * Update selected tab
         */
        self.options.selected = self.$tabs.index(tab);

        /**
         * Stop possibly running animations
         */
        self.$panels.stop();

        /**
         * Show new tab
         */
        if ($show.length && $hide.length)
        {
            $li.addClass(o.selectedClass)
                .siblings().removeClass(o.selectedClass);

            /**
             * Here is where the "smoothing" magic happens;
             * First, fade out the tab panel to hide
             */
            $hide.fadeOut(o.fadeOut , function()
            {
                $hide.addClass(o.hideClass);

                /**
                 * Second, show the tab to show but set the opacity to 0
                 * in order to accurately calculate the new height
                 */
                $show.show().css({ opacity: 0 });

                /**
                 * Third, animate the tabs outer container height to the new height
                 */
                self.$container.animate({ height: self.getSelectedHeight() }, o.height, function()
                {
                    /**
                     * Finally, hide the tab to show, reset the opacity to 1,
                     * and fade in it's content
                     */
                    $show.hide().css({ opacity: 1 }).fadeIn(o.fadeIn, function()
                    {
                        $(this).removeClass(o.hideClass)
                    });
                });
            });
        }

        /**
         * Prevent IE from keeping other link focussed when using the back button
         * and remove dotted border from clicked link. This is controlled in modern
         * browsers via CSS
         */
        if ($.browser.msie)
        {
            tab.blur();
        }
    },

    getSelectedHeight: function()
    {
        return this.$panels.eq(this.options.selected).outerHeight(true);
    }
});

$.ui.smoothTabs.defaults = {
    // animation speeds/durations
    fadeOut: 'fast',
    fadeIn: 'normal',
    height: 'normal',

    // CSS classes
    navClass: 'ui-tabs-nav',
    selectedClass: 'ui-tabs-selected',
    unselectClass: 'ui-tabs-unselect',
    disabledClass: 'ui-tabs-disabled',
    panelClass: 'ui-tabs-panel',
    panelContainerClass: 'ui-tabs-panel-container',
    hideClass: 'ui-tabs-hide'
};

})(jQuery);

