]> source.dussan.org Git - jquery-ui.git/commitdiff
Tabs: Better handling of active option and various cleanup.
authorScott González <scott.gonzalez@gmail.com>
Tue, 5 Apr 2011 20:53:52 +0000 (16:53 -0400)
committerScott González <scott.gonzalez@gmail.com>
Tue, 5 Apr 2011 20:53:52 +0000 (16:53 -0400)
tests/unit/tabs/tabs_defaults.js
tests/unit/tabs/tabs_defaults_deprecated.js
tests/unit/tabs/tabs_deprecated.js
tests/unit/tabs/tabs_events.js
tests/unit/tabs/tabs_methods.js
tests/unit/tabs/tabs_options.js
ui/jquery.ui.tabs.js

index d64316f9fdb84d8571421f6f0339eec4d26836b4..e15d618de6e7e4c9b5f0f7cdba207b3d6297ebb7 100644 (file)
@@ -1,7 +1,7 @@
 commonWidgetTests( "tabs", {
        defaults: {
                activate: null,
-//             active: null,
+               active: null,
                beforeLoad: null,
                beforeActivate: null,
                collapsible: false,
index c496e72f5f0d8a335cf2db890d0469bbe2062246..2d9772c6d070b24cdb131fdf20548f0f726e586c 100644 (file)
@@ -1,7 +1,7 @@
 commonWidgetTests( "tabs", {
        defaults: {
                activate: null,
-//             active: null,
+               active: null,
                add: null,
                ajaxOptions: null,
                beforeLoad: null,
index 535358636df21e9b059dff94db28b98d8dd1fdb4..9c816734a1c587a30a94ee56cab7bd43e5d5f9ee 100644 (file)
@@ -102,7 +102,7 @@ test('spinner', function() {
 });
 
 test('selected', function() {
-       expect(11);
+       expect(10);
 
        el = $('#tabs1').tabs();
        equals(el.tabs('option', 'selected'), 0, 'should be 0 by default');
@@ -127,10 +127,6 @@ test('selected', function() {
        equals( $('li.ui-tabs-selected', el).length, 0, 'no tab should be selected' );
        equals( $('div:hidden', '#tabs1').length, 3, 'all panels should be hidden' );
 
-       el.tabs('destroy');
-       el.tabs({ selected: null });
-       equals(el.tabs('option', 'selected'), -1, 'should be -1 for all tabs unselected with value null (deprecated)');
-
        el.tabs('destroy');
        el.tabs({ selected: 1 });
        equals(el.tabs('option', 'selected'), 1, 'should be specified tab');
index ef0297653ad673aaa359e7a735263b2f68a021a7..2e54407de7e1cb9d71f7c1c44044502ace488320 100644 (file)
@@ -6,8 +6,7 @@ test( "beforeActivate", function() {
        expect( 38 );
 
        var element = $( "#tabs1" ).tabs({
-                       // TODO: should be false
-                       active: -1,
+                       active: false,
                        collapsible: true
                }),
                tabs = element.find( ".ui-tabs-nav a" ),
@@ -15,13 +14,13 @@ test( "beforeActivate", function() {
 
        // from collapsed
        element.one( "tabsbeforeactivate", function( event, ui ) {
-               ok( !( "originalEvent" in event ) );
-               equals( ui.oldTab.size(), 0 );
-               equals( ui.oldPanel.size(), 0 );
-               equals( ui.newTab.size(), 1 );
-               strictEqual( ui.newTab[ 0 ], tabs[ 0 ] );
-               equals( ui.newPanel.size(), 1 );
-               strictEqual( ui.newPanel[ 0 ], panels[ 0 ] );
+               ok( !( "originalEvent" in event ), "originalEvent" );
+               equals( ui.oldTab.size(), 0, "oldTab size" );
+               equals( ui.oldPanel.size(), 0, "oldPanel size" );
+               equals( ui.newTab.size(), 1, "newTab size" );
+               strictEqual( ui.newTab[ 0 ], tabs[ 0 ], "newTab" );
+               equals( ui.newPanel.size(), 1, "newPanel size" );
+               strictEqual( ui.newPanel[ 0 ], panels[ 0 ], "newPanel" );
                tabs_state( element, 0, 0, 0 );
        });
        element.tabs( "option", "active", 0 );
@@ -29,15 +28,15 @@ test( "beforeActivate", function() {
 
        // switching tabs
        element.one( "tabsbeforeactivate", function( event, ui ) {
-               equals( event.originalEvent.type, "click" );
-               equals( ui.oldTab.size(), 1 );
-               strictEqual( ui.oldTab[ 0 ], tabs[ 0 ] );
-               equals( ui.oldPanel.size(), 1 );
-               strictEqual( ui.oldPanel[ 0 ], panels[ 0 ] );
-               equals( ui.newTab.size(), 1 );
-               strictEqual( ui.newTab[ 0 ], tabs[ 1 ] );
-               equals( ui.newPanel.size(), 1 );
-               strictEqual( ui.newPanel[ 0 ], panels[ 1 ] );
+               equals( event.originalEvent.type, "click", "originalEvent" );
+               equals( ui.oldTab.size(), 1, "oldTab size" );
+               strictEqual( ui.oldTab[ 0 ], tabs[ 0 ], "oldTab" );
+               equals( ui.oldPanel.size(), 1, "oldPanel size" );
+               strictEqual( ui.oldPanel[ 0 ], panels[ 0 ], "oldPanel" );
+               equals( ui.newTab.size(), 1, "newTab size" );
+               strictEqual( ui.newTab[ 0 ], tabs[ 1 ], "newTab" );
+               equals( ui.newPanel.size(), 1, "newPanel size" );
+               strictEqual( ui.newPanel[ 0 ], panels[ 1 ], "newPanel" );
                tabs_state( element, 1, 0, 0 );
        });
        tabs.eq( 1 ).click();
@@ -45,13 +44,13 @@ test( "beforeActivate", function() {
 
        // collapsing
        element.one( "tabsbeforeactivate", function( event, ui ) {
-               ok( !( "originalEvent" in event ) );
-               equals( ui.oldTab.size(), 1 );
-               strictEqual( ui.oldTab[ 0 ], tabs[ 1 ] );
-               equals( ui.oldPanel.size(), 1 );
-               strictEqual( ui.oldPanel[ 0 ], panels[ 1 ] );
-               equals( ui.newTab.size(), 0 );
-               equals( ui.newPanel.size(), 0 );
+               ok( !( "originalEvent" in event ), "originalEvent" );
+               equals( ui.oldTab.size(), 1, "oldTab size" );
+               strictEqual( ui.oldTab[ 0 ], tabs[ 1 ], "oldTab" );
+               equals( ui.oldPanel.size(), 1, "oldPanel size" );
+               strictEqual( ui.oldPanel[ 0 ], panels[ 1 ], "oldPanel" );
+               equals( ui.newTab.size(), 0, "newTab size" );
+               equals( ui.newPanel.size(), 0, "newPanel size" );
                tabs_state( element, 0, 1, 0 );
        });
        element.tabs( "option", "active", false );
@@ -59,13 +58,13 @@ test( "beforeActivate", function() {
 
        // prevent activation
        element.one( "tabsbeforeactivate", function( event, ui ) {
-               ok( !( "originalEvent" in event ) );
-               equals( ui.oldTab.size(), 0 );
-               equals( ui.oldPanel.size(), 0 );
-               equals( ui.newTab.size(), 1 );
-               strictEqual( ui.newTab[ 0 ], tabs[ 1 ] );
-               equals( ui.newPanel.size(), 1 );
-               strictEqual( ui.newPanel[ 0 ], panels[ 1 ] );
+               ok( !( "originalEvent" in event ), "originalEvent" );
+               equals( ui.oldTab.size(), 0, "oldTab size" );
+               equals( ui.oldPanel.size(), 0, "oldTab" );
+               equals( ui.newTab.size(), 1, "newTab size" );
+               strictEqual( ui.newTab[ 0 ], tabs[ 1 ], "newTab" );
+               equals( ui.newPanel.size(), 1, "newPanel size" );
+               strictEqual( ui.newPanel[ 0 ], panels[ 1 ], "newPanel" );
                event.preventDefault();
                tabs_state( element, 0, 0, 0 );
        });
@@ -77,8 +76,7 @@ test( "activate", function() {
        expect( 30 );
 
        var element = $( "#tabs1" ).tabs({
-                       // TODO: should be false
-                       active: -1,
+                       active: false,
                        collapsible: true
                }),
                tabs = element.find( ".ui-tabs-nav a" ),
@@ -86,13 +84,13 @@ test( "activate", function() {
 
        // from collapsed
        element.one( "tabsactivate", function( event, ui ) {
-               ok( !( "originalEvent" in event ) );
-               equals( ui.oldTab.size(), 0 );
-               equals( ui.oldPanel.size(), 0 );
-               equals( ui.newTab.size(), 1 );
-               strictEqual( ui.newTab[ 0 ], tabs[ 0 ] );
-               equals( ui.newPanel.size(), 1 );
-               strictEqual( ui.newPanel[ 0 ], panels[ 0 ] );
+               ok( !( "originalEvent" in event ), "originalEvent" );
+               equals( ui.oldTab.size(), 0, "oldTab size" );
+               equals( ui.oldPanel.size(), 0, "oldPanel size" );
+               equals( ui.newTab.size(), 1, "newTab size" );
+               strictEqual( ui.newTab[ 0 ], tabs[ 0 ], "newTab" );
+               equals( ui.newPanel.size(), 1, "newPanel size" );
+               strictEqual( ui.newPanel[ 0 ], panels[ 0 ], "newPanel" );
                tabs_state( element, 1, 0, 0 );
        });
        element.tabs( "option", "active", 0 );
@@ -100,15 +98,15 @@ test( "activate", function() {
 
        // switching tabs
        element.one( "tabsactivate", function( event, ui ) {
-               equals( event.originalEvent.type, "click" );
-               equals( ui.oldTab.size(), 1 );
-               strictEqual( ui.oldTab[ 0 ], tabs[ 0 ] );
-               equals( ui.oldPanel.size(), 1 );
-               strictEqual( ui.oldPanel[ 0 ], panels[ 0 ] );
-               equals( ui.newTab.size(), 1 );
-               strictEqual( ui.newTab[ 0 ], tabs[ 1 ] );
-               equals( ui.newPanel.size(), 1 );
-               strictEqual( ui.newPanel[ 0 ], panels[ 1 ] );
+               equals( event.originalEvent.type, "click", "originalEvent" );
+               equals( ui.oldTab.size(), 1, "oldTab size" );
+               strictEqual( ui.oldTab[ 0 ], tabs[ 0 ], "oldTab" );
+               equals( ui.oldPanel.size(), 1, "oldPanel size" );
+               strictEqual( ui.oldPanel[ 0 ], panels[ 0 ], "oldPanel" );
+               equals( ui.newTab.size(), 1, "newTab size" );
+               strictEqual( ui.newTab[ 0 ], tabs[ 1 ], "newTab" );
+               equals( ui.newPanel.size(), 1, "newPanel size" );
+               strictEqual( ui.newPanel[ 0 ], panels[ 1 ], "newPanel" );
                tabs_state( element, 0, 1, 0 );
        });
        tabs.eq( 1 ).click();
@@ -116,13 +114,13 @@ test( "activate", function() {
 
        // collapsing
        element.one( "tabsactivate", function( event, ui ) {
-               ok( !( "originalEvent" in event ) );
-               equals( ui.oldTab.size(), 1 );
-               strictEqual( ui.oldTab[ 0 ], tabs[ 1 ] );
-               equals( ui.oldPanel.size(), 1 );
-               strictEqual( ui.oldPanel[ 0 ], panels[ 1 ] );
-               equals( ui.newTab.size(), 0 );
-               equals( ui.newPanel.size(), 0 );
+               ok( !( "originalEvent" in event ), "originalEvent" );
+               equals( ui.oldTab.size(), 1, "oldTab size" );
+               strictEqual( ui.oldTab[ 0 ], tabs[ 1 ], "oldTab" );
+               equals( ui.oldPanel.size(), 1, "oldPanel size" );
+               strictEqual( ui.oldPanel[ 0 ], panels[ 1 ], "oldPanel" );
+               equals( ui.newTab.size(), 0, "newTab size" );
+               equals( ui.newPanel.size(), 0, "newPanel size" );
                tabs_state( element, 0, 0, 0 );
        });
        element.tabs( "option", "active", false );
@@ -130,11 +128,11 @@ test( "activate", function() {
 
        // prevent activation
        element.one( "tabsbeforeactivate", function( event ) {
-               ok( true );
+               ok( true, "tabsbeforeactivate" );
                event.preventDefault();
        });
        element.one( "tabsactivate", function() {
-               ok( false );
+               ok( false, "tabsactivate" );
        });
        element.tabs( "option", "active", 1 );
 });
@@ -171,7 +169,7 @@ test( "beforeLoad", function() {
        tabs_state( element, 0, 0, 1, 0 );
        equals( panel.html(), "", "panel html after" );
 
-       // click
+       // click, change panel content
        element.one( "tabsbeforeload", function( event, ui ) {
                tab = element.find( ".ui-tabs-nav a" ).eq( 3 );
                panelId = tab.attr( "aria-controls" );
@@ -193,8 +191,8 @@ test( "beforeLoad", function() {
        equals( panel.html(), "<p>testing</p>", "panel html after" );
 });
 
-test('load', function() {
-       ok(false, "missing test - untested code is broken code.");
+test( "load", function() {
+       ok( false, "missing test - untested code is broken code." );
 });
 
-})(jQuery);
+}( jQuery ) );
index c33bebe65daf1598d6432a18ce8d452840a28231..8fcd2a848f643a3aa5b6f8f57a1bca8d9db96704 100644 (file)
@@ -136,7 +136,7 @@ test('refresh', function() {
        var el = $('<div id="tabs"><ul></ul></div>').tabs(),
                ul = el.find('ul');
 
-       equals(el.tabs('option', 'active'), -1, 'Initially empty, no active tab');
+       equals(el.tabs('option', 'active'), false, 'Initially empty, no active tab');
 
        ul.append('<li><a href="data/test.html">Test 1</a></li>');
        el.tabs('refresh');
index 98cd3b4ca20b2eca03369b4394e83c4671b5b55a..49c77521eb6221b41a6823083e89333c8bbe4848 100644 (file)
@@ -53,14 +53,14 @@ test('active', function() {
        equals(el.tabs('option', 'active'), 0, 'should be 0 by default');
 
        el.tabs('destroy');
-       el.tabs({ active: -1 });
-       equals(el.tabs('option', 'active'), -1, 'should be -1 for all tabs deactive');
+       el.tabs({ active: false });
+       equals(el.tabs('option', 'active'), false, 'should be false for all tabs deactive');
        equals( $('li.ui-tabs-selected', el).length, 0, 'no tab should be active' );
        equals( $('div:hidden', '#tabs1').length, 3, 'all panels should be hidden' );
 
        el.tabs('destroy');
        el.tabs({ active: null });
-       equals(el.tabs('option', 'active'), -1, 'should be -1 for all tabs deactive with value null (deprecated)');
+       equals(el.tabs('option', 'active'), false, 'should be false for all tabs deactive with value null (deprecated)');
 
        el.tabs('destroy');
        el.tabs({ active: 1 });
index 99e1b65381f3ad2c50dbb7ac2a8c7b21dc17d761..c16fe94c06ec4b9d763b10cd4b1d7ab21640240f 100755 (executable)
@@ -27,10 +27,9 @@ function getNextListId() {
 $.widget( "ui.tabs", {
        options: {
                activate: null,
-               // TODO: uncomment (requires fixing code related to active option)
-//             active: null,
-               beforeLoad: null,
+               active: null,
                beforeActivate: null,
+               beforeLoad: null,
                collapsible: false,
                event: "click",
                fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
@@ -38,52 +37,58 @@ $.widget( "ui.tabs", {
        },
 
        _create: function() {
-               var self = this,
-                       o = this.options;
+               var that = this,
+                       options = that.options,
+                       active = options.active;
 
-               this.running = false;
+               that.running = false;
 
-               this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
+               that.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
 
-               this._processTabs();
+               that._processTabs();
 
-               // Selected tab
-               // use "selected" option or try to retrieve:
-               // 1. from fragment identifier in url
-               // 2. from selected class attribute on <li>
-               if ( o.active === undefined ) {
+               if ( active === null ) {
+                       // check the fragment identifier in the URL
                        if ( location.hash ) {
-                               this.anchors.each(function( i, a ) {
-                                       if ( a.hash == location.hash ) {
-                                               o.active = i;
+                               that.anchors.each(function( i, tab ) {
+                                       if ( tab.hash === location.hash ) {
+                                               active = i;
                                                return false;
                                        }
                                });
                        }
-                       if ( typeof o.active !== "number" && this.lis.filter( ".ui-tabs-active" ).length ) {
-                               o.active = this.lis.index( this.lis.filter( ".ui-tabs-active" ) );
+
+                       // check for a tab marked active via a class
+                       if ( active === null ) {
+                               active = that.lis.filter( ".ui-tabs-active" ).index();
+                       }
+
+                       // no active tab, set to false
+                       if ( active === null || active === -1 ) {
+                               active = that.lis.length ? 0 : false;
                        }
-                       o.active = o.active || ( this.lis.length ? 0 : -1 );
-               } else if ( o.active === null ) { // usage of null is deprecated, TODO remove in next release
-                       o.active = -1;
                }
 
-               // sanity check - default to first tab...
-               o.active = ( ( o.active >= 0 && this.anchors[ o.active ] ) || o.active < 0 )
-                       ? o.active
-                       : 0;
+               // handle numbers: negative, out of range
+               if ( active !== false ) {
+                       active = this.lis.eq( active ).index();
+                       if ( active === -1 ) {
+                               active = options.collapsible ? false : 0;
+                       }
+               }
+               options.active = active;
 
                // Take disabling tabs via class attribute from HTML
                // into account and update option properly.
-               if ( $.isArray( o.disabled ) ) {
-                       o.disabled = $.unique( o.disabled.concat(
+               if ( $.isArray( options.disabled ) ) {
+                       options.disabled = $.unique( options.disabled.concat(
                                $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
-                                       return self.lis.index( n );
+                                       return that.lis.index( n );
                                })
                        ) ).sort();
                }
 
-               this._setupFx( o.fx );
+               this._setupFx( options.fx );
 
                this._refresh();
 
@@ -91,30 +96,24 @@ $.widget( "ui.tabs", {
                this.panels.hide();
                this.lis.removeClass( "ui-tabs-active ui-state-active" );
                // check for length avoids error when initializing empty list
-               if ( o.active >= 0 && this.anchors.length ) {
-                       this.active = this._findActive( o.active );
-                       var panel = self._getPanelForTab( this.active );
+               if ( options.active !== false && this.anchors.length ) {
+                       this.active = this._findActive( options.active );
+                       var panel = that._getPanelForTab( this.active );
 
                        panel.show();
 
-                       this.lis.eq( o.active ).addClass( "ui-tabs-active ui-state-active" );
+                       this.lis.eq( options.active ).addClass( "ui-tabs-active ui-state-active" );
 
                        // TODO: we need to remove this or add it to accordion
                        // seems to be expected behavior that the activate callback is fired
-                       self.element.queue( "tabs", function() {
-                               self._trigger( "activate", null, self._ui( self.active[ 0 ], panel[ 0 ] ) );
+                       that.element.queue( "tabs", function() {
+                               that._trigger( "activate", null, that._ui( that.active[ 0 ], panel[ 0 ] ) );
                        });
 
-                       this.load( o.active );
+                       this.load( options.active );
                } else {
                        this.active = $();
                }
-
-               // clean up to avoid memory leaks in certain versions of IE 6
-               $( window ).bind( "unload.tabs", function() {
-                       self.lis.add( self.anchors ).unbind( ".tabs" );
-                       self.lis = self.anchors = self.panels = null;
-               });
        },
 
        _setOption: function( key, value ) {
@@ -163,36 +162,27 @@ $.widget( "ui.tabs", {
        },
 
        _refresh: function() {
-               var self = this,
-                       o = this.options;
-
-               this.element
-                       .toggleClass( "ui-tabs-collapsible", o.collapsible );
-
-               this.list
-                       .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
-
-               this.lis
-                       .addClass( "ui-state-default ui-corner-top" );
+               var that = this,
+                       options = that.options;
 
-               this.panels
-                       .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
+               this.element.toggleClass( "ui-tabs-collapsible", options.collapsible );
+               this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
+               this.lis.addClass( "ui-state-default ui-corner-top" );
+               this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
 
-               if ( !o.disabled.length ) {
-                       o.disabled = false;
+               if ( !options.disabled.length ) {
+                       options.disabled = false;
                }
 
                // disable tabs
                for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
-                       $( li ).toggleClass( "ui-state-disabled", $.inArray( i, o.disabled ) != -1 );
+                       $( li ).toggleClass( "ui-state-disabled", $.inArray( i, options.disabled ) !== -1 );
                }
 
-               this._setupEvents( o.event );
+               this._setupEvents( options.event );
 
                // remove all handlers, may run on existing tabs
                this.lis.unbind( ".tabs" );
-
-
                this._focusable( this.lis );
                this._hoverable( this.lis );
        },
@@ -907,11 +897,14 @@ if ( $.uiBackCompat !== false ) {
 
                prototype._create = function() {
                        var options = this.options;
-                       if ( options.active === undefined && options.selected !== undefined ) {
-                               options.active = options.selected;
+                       if ( options.active === null && options.selected !== undefined ) {
+                               options.active = options.selected === -1 ? false : options.selected;
                        }
                        _create.call( this );
                        options.selected = options.active;
+                       if ( options.selected === false ) {
+                               options.selected = -1;
+                       }
                };
 
                prototype._setOption = function( key, value ) {
@@ -921,13 +914,22 @@ if ( $.uiBackCompat !== false ) {
                        }
                        _setOption.apply( this, arguments );
                        if ( key === "active" ) {
-                               options.selected = options.active ;
+                               if ( key === - 1 ) {
+                                       key = false;
+                               }
+                               options.selected = options.active;
+                               if ( options.selected === false ) {
+                                       options.selected = -1;
+                               }
                        }
                };
 
                prototype._eventHandler = function( event ) {
                        _eventHandler.apply( this, arguments );
-                       this.options.selected = this.options.active ;
+                       this.options.selected = this.options.active;
+                       if ( this.options.selected === false ) {
+                               this.options.selected = -1;
+                       }
                };
        }( jQuery, jQuery.ui.tabs.prototype ) );