/**
 * Tabs - jQuery plugin for accessible, unobtrusive tabs
 * @requires jQuery v1.1.1
 *
 * http://stilbuero.de/tabs/
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 2.7.4
 */

(function ($) { // block scope

    $.extend({
        tabs: {
            remoteCount: 0 // TODO in Tabs 3 this is going to be more cleanly in one single namespace
        }
    });

    /**
    * Create an accessible, unobtrusive tab interface based on a particular HTML structure.
    *
    * The underlying HTML has to look like this:
    *
    * <div id="container">
    *     <ul>
    *         <li><a href="#fragment-1">Section 1</a></li>
    *         <li><a href="#fragment-2">Section 2</a></li>
    *         <li><a href="#fragment-3">Section 3</a></li>
    *     </ul>
    *     <div id="fragment-1">
    *
    *     </div>
    *     <div id="fragment-2">
    *
    *     </div>
    *     <div id="fragment-3">
    *
    *     </div>
    * </div>
    *
    * Each anchor in the unordered list points directly to a section below represented by one of the
    * divs (the URI in the anchor's href attribute refers to the fragment with the corresponding id).
    * Because such HTML structure is fully functional on its own, e.g. without JavaScript, the tab
    * interface is accessible and unobtrusive.
    *
    * A tab is also bookmarkable via hash in the URL. Use the History/Remote plugin (Tabs will
    * auto-detect its presence) to fix the back (and forward) button.
    *
    * @example $('#container').tabs();
    * @desc Create a basic tab interface.
    * @example $('#container').tabs(2);
    * @desc Create a basic tab interface with the second tab initially activated.
    * @example $('#container').tabs({disabled: [3, 4]});
    * @desc Create a tab interface with the third and fourth tab being disabled.
    * @example $('#container').tabs({fxSlide: true});
    * @desc Create a tab interface that uses slide down/up animations for showing/hiding tab
    *       content upon tab switching.
    *
    * @param Number initial An integer specifying the position of the tab (no zero-based index) that
    *                       gets activated at first (on page load). Two alternative ways to specify
    *                       the active tab will overrule this argument. First a li element
    *                       (representing one single tab) belonging to the selected tab class, e.g.
    *                       set the selected tab class (default: "tabs-selected", see option
    *                       selectedClass) for one of the unordered li elements in the HTML source.
    *                       In addition if a fragment identifier/hash in the URL of the page refers
    *                       to the id of a tab container of a tab interface the corresponding tab will
    *                       be activated and both the initial argument as well as an eventually
    *                       declared class attribute will be overruled. Defaults to 1 if omitted.
    * @param Object settings An object literal containing key/value pairs to provide optional settings.
    * @option Array<Number> disabled An array containing the position of the tabs (no zero-based index)
    *                                that should be disabled on initialization. Default value: null.
    *                                A tab can also be disabled by simply adding the disabling class
    *                                (default: "tabs-disabled", see option disabledClass) to the li
    *                                element representing that particular tab.
    * @option Boolean bookmarkable Boolean flag indicating if support for bookmarking and history (via
    *                              changing hash in the URL of the browser) is enabled. Default value:
    *                              false, unless the History/Remote plugin is included. In that case the
    *                              default value becomes true. @see $.ajaxHistory.initialize
    * @option Boolean remote Boolean flag indicating that tab content has to be loaded remotely from
    *                        the url given in the href attribute of the tab menu anchor elements.
    * @option String spinner The content of this string is shown in a tab while remote content is loading.
    *                        Insert plain text as well as an img here. To turn off this notification
    *                        pass an empty string or null. Default: "Loading&#8230;".
    * @option String hashPrefix A String that is used for constructing the hash the link's href attribute
    *                           of a remote tab gets altered to, such as "#remote-1".
    *                           Default value: "remote-tab-".
    * @option Boolean fxFade Boolean flag indicating whether fade in/out animations are used for tab
    *                        switching. Can be combined with fxSlide. Will overrule fxShow/fxHide.
    *                        Default value: false.
    * @option Boolean fxSlide Boolean flag indicating whether slide down/up animations are used for tab
    *                         switching. Can be combined with fxFade. Will overrule fxShow/fxHide.
    *                         Default value: false.
    * @option String|Number fxSpeed A string representing one of the three predefined speeds ("slow",
    *                               "normal", or "fast") or the number of milliseconds (e.g. 1000) to
    *                               run an animation. Default value: "normal".
    * @option Object fxShow An object literal of the form jQuery's animate function expects for making
    *                       your own, custom animation to reveal a tab upon tab switch. Unlike fxFade
    *                       or fxSlide this animation is independent from an optional hide animation.
    *                       Default value: null. @see animate
    * @option Object fxHide An object literal of the form jQuery's animate function expects for making
    *                       your own, custom animation to hide a tab upon tab switch. Unlike fxFade
    *                       or fxSlide this animation is independent from an optional show animation.
    *                       Default value: null. @see animate
    * @option String|Number fxShowSpeed A string representing one of the three predefined speeds
    *                                   ("slow", "normal", or "fast") or the number of milliseconds
    *                                   (e.g. 1000) to run the animation specified in fxShow.
    *                                   Default value: fxSpeed.
    * @option String|Number fxHideSpeed A string representing one of the three predefined speeds
    *                                   ("slow", "normal", or "fast") or the number of milliseconds
    *                                   (e.g. 1000) to run the animation specified in fxHide.
    *                                   Default value: fxSpeed.
    * @option Boolean fxAutoHeight Boolean flag that if set to true causes all tab heights
    *                              to be constant (being the height of the tallest tab).
    *                              Default value: false.
    * @option Function onClick A function to be invoked upon tab switch, immediatly after a tab has
    *                          been clicked, e.g. before the other's tab content gets hidden. The
    *                          function gets passed three arguments: the first one is the clicked
    *                          tab (e.g. an anchor element), the second one is the DOM element
    *                          containing the content of the clicked tab (e.g. the div), the third
    *                          argument is the one of the tab that gets hidden. If this callback
    *                          returns false, the tab switch is canceled (use to disallow tab
    *                          switching for the reason of a failed form validation for example).
    *                          Default value: null.
    * @option Function onHide A function to be invoked upon tab switch, immediatly after one tab's
    *                         content got hidden (with or without an animation) and right before the
    *                         next tab is revealed. The function gets passed three arguments: the
    *                         first one is the clicked tab (e.g. an anchor element), the second one
    *                         is the DOM element containing the content of the clicked tab, (e.g. the
    *                         div), the third argument is the one of the tab that gets hidden.
    *                         Default value: null.
    * @option Function onShow A function to be invoked upon tab switch. This function is invoked
    *                         after the new tab has been revealed, e.g. after the switch is completed.
    *                         The function gets passed three arguments: the first one is the clicked
    *                         tab (e.g. an anchor element), the second one is the DOM element
    *                         containing the content of the clicked tab, (e.g. the div), the third
    *                         argument is the one of the tab that gets hidden. Default value: null.
    * @option String navClass A CSS class that is used to identify the tabs unordered list by class if
    *                         the required HTML structure differs from the default one.
    *                         Default value: "tabs-nav".
    * @option String selectedClass The CSS class attached to the li element representing the
    *                              currently selected (active) tab. Default value: "tabs-selected".
    * @option String disabledClass The CSS class attached to the li element representing a disabled
    *                              tab. Default value: "tabs-disabled".
    * @option String containerClass A CSS class that is used to identify tab containers by class if
    *                               the required HTML structure differs from the default one.
    *                               Default value: "tabs-container".
    * @option String hideClass The CSS class used for hiding inactive tabs. A class is used instead
    *                          of "display: none" in the style attribute to maintain control over
    *                          visibility in other media types than screen, most notably print.
    *                          Default value: "tabs-hide".
    * @option String loadingClass The CSS class used for indicating that an Ajax tab is currently
    *                             loading, for example by showing a spinner.
    *                             Default value: "tabs-loading".
    * @option String tabStruct @deprecated A CSS selector or basic XPath expression reflecting a
    *                          nested HTML structure that is different from the default single div
    *                          structure (one div with an id inside the overall container holds one
    *                          tab's content). If for instance an additional div is required to wrap
    *                          up the several tab containers such a structure is expressed by "div>div".
    *                          Default value: "div".
    * @type jQuery
    *
    * @name tabs
    * @cat Plugins/Tabs
    * @author Klaus Hartl/klaus.hartl@stilbuero.de
    */
    $.fn.tabs = function (initial, settings) {

        // settings
        if (typeof initial == 'object') settings = initial; // no initial tab given but a settings object
        settings = $.extend({
            initial: (initial && typeof initial == 'number' && initial > 0) ? --initial : 0,
            disabled: null,
            bookmarkable: $.ajaxHistory ? true : false,
            remote: false,
            spinner: 'Loading&#8230;',
            hashPrefix: 'remote-tab-',
            fxFade: null,
            fxSlide: null,
            fxShow: null,
            fxHide: null,
            fxSpeed: 'normal',
            fxShowSpeed: null,
            fxHideSpeed: null,
            fxAutoHeight: false,
            onClick: null,
            onHide: null,
            onShow: null,
            navClass: 'tabs-nav',
            selectedClass: 'tabs-selected',
            disabledClass: 'tabs-disabled',
            containerClass: 'tabs-container',
            hideClass: 'tabs-hide',
            loadingClass: 'tabs-loading',
            tabStruct: 'div'
        }, settings || {});

        $.browser.msie6 = $.browser.msie && ($.browser.version && $.browser.version < 7 || /MSIE 6.0/.test(navigator.userAgent)); // do not check for 6.0 alone, userAgent in Windows Vista has "Windows NT 6.0"

        // helper to prevent scroll to fragment
        function unFocus() {
            scrollTo(0, 0);
        }
        
        // Remove class display-none. This is to prevent all tabs flicking
        $('#producttabs').removeClass('display-none');

        // initialize tabs
        return this.each(function () {

            // remember wrapper for later
            var container = this;

            // setup nav
            var nav = $('ul.' + settings.navClass, container);
            nav = nav.size() && nav || $('>ul:eq(0)', container); // fallback to default structure
            var tabs = $('a', nav);

            // prepare remote tabs
            if (settings.remote) {
                tabs.each(function () {
                    var id = settings.hashPrefix + (++$.tabs.remoteCount), hash = '#' + id, url = this.href;
                    this.href = hash;
                    $('<div id="' + id + '" class="' + settings.containerClass + '"></div>').appendTo(container);

                    $(this).bind('loadRemoteTab', function (e, callback) {
                        var $$ = $(this).addClass(settings.loadingClass), span = $('span', this)[0], tabTitle = span.innerHTML;
                        if (settings.spinner) {
                            // TODO if spinner is image
                            span.innerHTML = '<em>' + settings.spinner + '</em>'; // WARNING: html(...) crashes Safari with jQuery 1.1.2
                        }
                        setTimeout(function () { // Timeout is again required in IE, "wait" for id being restored
                            $(hash).load(url, function () {
                                if (settings.spinner) {
                                    span.innerHTML = tabTitle; // WARNING: html(...) crashes Safari with jQuery 1.1.2
                                }
                                $$.removeClass(settings.loadingClass);
                                callback && callback();
                            });
                        }, 0);
                    });

                });
            }

            // set up containers
            var containers = $('div.' + settings.containerClass, container);
            containers = containers.size() && containers || $('>' + settings.tabStruct, container); // fallback to default structure

            // attach classes for styling if not present
            nav.is('.' + settings.navClass) || nav.addClass(settings.navClass);
            containers.each(function () {
                var $$ = $(this);
                $$.is('.' + settings.containerClass) || $$.addClass(settings.containerClass);
            });

            // try to retrieve active tab from class in HTML
            var hasSelectedClass = $('li', nav).index($('li.' + settings.selectedClass, nav)[0]);
            if (hasSelectedClass >= 0) {
                settings.initial = hasSelectedClass;
            }

            // try to retrieve active tab from hash in url, will override class in HTML
            if (location.hash) {
                tabs.each(function (i) {
                    if (this.hash == location.hash) {
                        settings.initial = i;
                        // prevent page scroll to fragment
                        if (($.browser.msie || $.browser.opera) && !settings.remote) {
                            var toShow = $(location.hash);
                            var toShowId = toShow.attr('id');
                            toShow.attr('id', '');
                            setTimeout(function () {
                                toShow.attr('id', toShowId); // restore id
                            }, 500);
                        }
                        unFocus();
                        return false; // break
                    }
                });
            }
            if ($.browser.msie) {
                unFocus(); // fix IE focussing bottom of the page for some unknown reason
            }

            // highlight tab accordingly
            containers.filter(':eq(' + settings.initial + ')').show().end().not(':eq(' + settings.initial + ')').addClass(settings.hideClass);
            $('li', nav).removeClass(settings.selectedClass).eq(settings.initial).addClass(settings.selectedClass); // we need to remove classes eventually if hash takes precedence over class
            // trigger load of initial tab
            tabs.eq(settings.initial).trigger('loadRemoteTab').end();

            // setup auto height
            if (settings.fxAutoHeight) {
                // helper
                var _setAutoHeight = function (reset) {
                    // get tab heights in top to bottom ordered array
                    var heights = $.map(containers.get(), function (el) {
                        var h, jq = $(el);
                        if (reset) {
                            if ($.browser.msie6) {
                                el.style.removeExpression('behaviour');
                                el.style.height = '';
                                el.minHeight = null;
                            }
                            h = jq.css({ 'min-height': '' }).height(); // use jQuery's height() to get hidden element values
                        } else {
                            h = jq.height(); // use jQuery's height() to get hidden element values
                        }
                        return h;
                    }).sort(function (a, b) {
                        return b - a;
                    });
                    if ($.browser.msie6) {
                        containers.each(function () {
                            this.minHeight = heights[0] + 'px';
                            this.style.setExpression('behaviour', 'this.style.height = this.minHeight ? this.minHeight : "1px"'); // using an expression to not make print styles useless
                        });
                    } else {
                        containers.css({ 'min-height': heights[0] + 'px' });
                    }
                };
                // call once for initialization
                _setAutoHeight();
                // trigger auto height adjustment if needed
                var cachedWidth = container.offsetWidth;
                var cachedHeight = container.offsetHeight;
                var watchFontSize = $('#tabs-watch-font-size').get(0) || $('<span id="tabs-watch-font-size">M</span>').css({ display: 'block', position: 'absolute', visibility: 'hidden' }).appendTo(document.body).get(0);
                var cachedFontSize = watchFontSize.offsetHeight;
                setInterval(function () {
                    var currentWidth = container.offsetWidth;
                    var currentHeight = container.offsetHeight;
                    var currentFontSize = watchFontSize.offsetHeight;
                    if (currentHeight > cachedHeight || currentWidth != cachedWidth || currentFontSize != cachedFontSize) {
                        _setAutoHeight((currentWidth > cachedWidth || currentFontSize < cachedFontSize)); // if heights gets smaller reset min-height
                        cachedWidth = currentWidth;
                        cachedHeight = currentHeight;
                        cachedFontSize = currentFontSize;
                    }
                }, 50);
            }

            // setup animations
            var showAnim = {}, hideAnim = {}, showSpeed = settings.fxShowSpeed || settings.fxSpeed, hideSpeed = settings.fxHideSpeed || settings.fxSpeed;
            if (settings.fxSlide || settings.fxFade) {
                if (settings.fxSlide) {
                    showAnim['height'] = 'show';
                    hideAnim['height'] = 'hide';
                }
                if (settings.fxFade) {
                    showAnim['opacity'] = 'show';
                    hideAnim['opacity'] = 'hide';
                }
            } else {
                if (settings.fxShow) {
                    showAnim = settings.fxShow;
                } else { // use some kind of animation to prevent browser scrolling to the tab
                    showAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox
                    showSpeed = 1; // as little as 1 is sufficient
                }
                if (settings.fxHide) {
                    hideAnim = settings.fxHide;
                } else { // use some kind of animation to prevent browser scrolling to the tab
                    hideAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox
                    hideSpeed = 1; // as little as 1 is sufficient
                }
            }

            // callbacks
            var onClick = settings.onClick, onHide = settings.onHide, onShow = settings.onShow;

            // attach activateTab event, required for activating a tab programmatically
            tabs.bind('triggerTab', function () {

                // if the tab is already selected or disabled or animation is still running stop here
                var li = $(this).parents('li:eq(0)');
                if (container.locked || li.is('.' + settings.selectedClass) || li.is('.' + settings.disabledClass)) {
                    return false;
                }

                var hash = this.hash;

                if ($.browser.msie) {

                    $(this).trigger('click');
                    if (settings.bookmarkable) {
                        $.ajaxHistory.update(hash);
                        location.hash = hash.replace('#', '');
                    }

                } else if ($.browser.safari) {

                    // Simply setting location.hash puts Safari into the eternal load state... ugh! Submit a form instead.
                    var tempForm = $('<form action="' + hash + '"><div><input type="submit" value="h" /></div></form>').get(0); // no need to append it to the body
                    tempForm.submit(); // does not trigger the form's submit event...
                    $(this).trigger('click'); // ...thus do stuff here
                    if (settings.bookmarkable) {
                        $.ajaxHistory.update(hash);
                    }

                } else {
                    if (settings.bookmarkable) {
                        location.hash = hash.replace('#', '');
                    } else {
                        $(this).trigger('click');
                    }

                }

            });

            // attach disable event, required for disabling a tab
            tabs.bind('disableTab', function () {
                var li = $(this).parents('li:eq(0)');
                if ($.browser.safari) { /* fix opacity of tab after disabling in Safari... */
                    li.animate({ opacity: 0 }, 1, function () {
                        li.css({ opacity: '' });
                    });
                }
                li.addClass(settings.disabledClass);

            });

            // disabled from settings
            if (settings.disabled && settings.disabled.length) {
                for (var i = 0, k = settings.disabled.length; i < k; i++) {
                    tabs.eq(--settings.disabled[i]).trigger('disableTab').end();
                }
            };

            // attach enable event, required for reenabling a tab
            tabs.bind('enableTab', function () {
                var li = $(this).parents('li:eq(0)');
                li.removeClass(settings.disabledClass);
                if ($.browser.safari) { /* fix disappearing tab after enabling in Safari... */
                    li.animate({ opacity: 1 }, 1, function () {
                        li.css({ opacity: '' });
                    });
                }
            });

            // attach click event
            tabs.bind('click', function (e) {

                var trueClick = e.clientX; // add to history only if true click occured, not a triggered click
                var clicked = this, li = $(this).parents('li:eq(0)'), toShow = $(this.hash), toHide = containers.filter(':visible');

                // if animation is still running, tab is selected or disabled or onClick callback returns false stop here
                // check if onClick returns false last so that it is not executed for a disabled tab
                if (container['locked'] || li.is('.' + settings.selectedClass) || li.is('.' + settings.disabledClass) || typeof onClick == 'function' && onClick(this, toShow[0], toHide[0]) === false) {
                    this.blur();
                    return false;
                }

                container['locked'] = true;

                // show new tab
                if (toShow.size()) {

                    // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled
                    if ($.browser.msie && settings.bookmarkable) {
                        var toShowId = this.hash.replace('#', '');
                        toShow.attr('id', '');
                        setTimeout(function () {
                            toShow.attr('id', toShowId); // restore id
                        }, 0);
                    }

                    var resetCSS = { display: '', overflow: '', height: '' };
                    if (!$.browser.msie) { // not in IE to prevent ClearType font issue
                        resetCSS['opacity'] = '';
                    }

                    // switch tab, animation prevents browser scrolling to the fragment
                    function switchTab() {
                        if (settings.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click
                            $.ajaxHistory.update(clicked.hash);
                        }
                        toHide.animate(hideAnim, hideSpeed, function () { //
                            $(clicked).parents('li:eq(0)').addClass(settings.selectedClass).siblings().removeClass(settings.selectedClass);
                            toHide.addClass(settings.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.                        
                            if (typeof onHide == 'function') {
                                onHide(clicked, toShow[0], toHide[0]);
                            }
                            if (!(settings.fxSlide || settings.fxFade || settings.fxShow)) {
                                toShow.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab containers
                            }
                            toShow.animate(showAnim, showSpeed, function () {
                                toShow.removeClass(settings.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
                                if ($.browser.msie) {
                                    toHide[0].style.filter = '';
                                    toShow[0].style.filter = '';
                                }
                                if (typeof onShow == 'function') {
                                    onShow(clicked, toShow[0], toHide[0]);
                                }
                                container['locked'] = null;
                            });
                        });
                    }

                    if (!settings.remote) {
                        switchTab();
                    } else {
                        $(clicked).trigger('loadRemoteTab', [switchTab]);
                    }

                } else {
                    alert('There is no such container.');
                }

                // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash
                var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0;
                var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0;
                setTimeout(function () {
                    window.scrollTo(scrollX, scrollY);
                }, 0);

                this.blur(); // prevent IE from keeping other link focussed when using the back button

                return settings.bookmarkable && !!trueClick; // convert undefined to Boolean for IE

            });

            // enable history support if bookmarking and history is turned on
            if (settings.bookmarkable) {
                $.ajaxHistory.initialize(function () {
                    tabs.eq(settings.initial).trigger('click').end();
                });
            }

        });

    };

    /**
    * Activate a tab programmatically with the given position (no zero-based index)
    * or its id, e.g. the URL's fragment identifier/hash representing a tab, as if the tab
    * itself were clicked.
    *
    * @example $('#container').triggerTab(2);
    * @desc Activate the second tab of the tab interface contained in <div id="container">.
    * @example $('#container').triggerTab(1);
    * @desc Activate the first tab of the tab interface contained in <div id="container">.
    * @example $('#container').triggerTab();
    * @desc Activate the first tab of the tab interface contained in <div id="container">.
    * @example $('#container').triggerTab('fragment-2');
    * @desc Activate a tab via its URL fragment identifier representation.
    *
    * @param String|Number tab Either a string that matches the id of the tab (the URL's
    *                          fragment identifier/hash representing a tab) or an integer
    *                          specifying the position of the tab (no zero-based index) to
    *                          be activated. If this parameter is omitted, the first tab
    *                          will be activated.
    * @type jQuery
    *
    * @name triggerTab
    * @cat Plugins/Tabs
    * @author Klaus Hartl/klaus.hartl@stilbuero.de
    */

    /**
    * Disable a tab, so that clicking it has no effect.
    *
    * @example $('#container').disableTab(2);
    * @desc Disable the second tab of the tab interface contained in <div id="container">.
    *
    * @param String|Number tab Either a string that matches the id of the tab (the URL's
    *                          fragment identifier/hash representing a tab) or an integer
    *                          specifying the position of the tab (no zero-based index) to
    *                          be disabled. If this parameter is omitted, the first tab
    *                          will be disabled.
    * @type jQuery
    *
    * @name disableTab
    * @cat Plugins/Tabs
    * @author Klaus Hartl/klaus.hartl@stilbuero.de
    */

    /**
    * Enable a tab that has been disabled.
    *
    * @example $('#container').enableTab(2);
    * @desc Enable the second tab of the tab interface contained in <div id="container">.
    *
    * @param String|Number tab Either a string that matches the id of the tab (the URL's
    *                          fragment identifier/hash representing a tab) or an integer
    *                          specifying the position of the tab (no zero-based index) to
    *                          be enabled. If this parameter is omitted, the first tab
    *                          will be enabled.
    * @type jQuery
    *
    * @name enableTab
    * @cat Plugins/Tabs
    * @author Klaus Hartl/klaus.hartl@stilbuero.de
    */

    var tabEvents = ['triggerTab', 'disableTab', 'enableTab'];
    for (var i = 0; i < tabEvents.length; i++) {
        $.fn[tabEvents[i]] = (function (tabEvent) {
            return function (tab) {
                return this.each(function () {
                    var nav = $('ul.tabs-nav', this);
                    nav = nav.size() && nav || $('>ul:eq(0)', this); // fallback to default structure
                    var a;
                    if (!tab || typeof tab == 'number') {
                        a = $('li a', nav).eq((tab && tab > 0 && tab - 1 || 0)); // fall back to 0
                    } else if (typeof tab == 'string') {
                        a = $('li a[@href$="#' + tab + '"]', nav);
                    }
                    a.trigger(tabEvent);
                });
            };
        })(tabEvents[i]);
    }

    /**
    * Get the position of the currently selected tab (no zero-based index).
    *
    * @example $('#container').activeTab();
    * @desc Get the position of the currently selected tab of an interface
    * contained in <div id="container">.
    *
    * @type Number
    *
    * @name activeTab
    * @cat Plugins/Tabs
    * @author Klaus Hartl/klaus.hartl@stilbuero.de
    */

    $.fn.activeTab = function () {
        var selectedTabs = [];
        this.each(function () {
            var nav = $('ul.tabs-nav', this);
            nav = nav.size() && nav || $('>ul:eq(0)', this); //fallback to default structure
            var lis = $('li', nav);
            selectedTabs.push(lis.index(lis.filter('.tabs-selected')[0]) + 1);
        });
        return selectedTabs[0];
    };

})(jQuery);
