diff --git a/tests/unit/tabs/tabs_defaults.js b/tests/unit/tabs/tabs_defaults.js index d64316f9f..e15d618de 100644 --- a/tests/unit/tabs/tabs_defaults.js +++ b/tests/unit/tabs/tabs_defaults.js @@ -1,7 +1,7 @@ commonWidgetTests( "tabs", { defaults: { activate: null, -// active: null, + active: null, beforeLoad: null, beforeActivate: null, collapsible: false, diff --git a/tests/unit/tabs/tabs_defaults_deprecated.js b/tests/unit/tabs/tabs_defaults_deprecated.js index c496e72f5..2d9772c6d 100644 --- a/tests/unit/tabs/tabs_defaults_deprecated.js +++ b/tests/unit/tabs/tabs_defaults_deprecated.js @@ -1,7 +1,7 @@ commonWidgetTests( "tabs", { defaults: { activate: null, -// active: null, + active: null, add: null, ajaxOptions: null, beforeLoad: null, diff --git a/tests/unit/tabs/tabs_deprecated.js b/tests/unit/tabs/tabs_deprecated.js index 535358636..9c816734a 100644 --- a/tests/unit/tabs/tabs_deprecated.js +++ b/tests/unit/tabs/tabs_deprecated.js @@ -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'); diff --git a/tests/unit/tabs/tabs_events.js b/tests/unit/tabs/tabs_events.js index ef0297653..2e54407de 100644 --- a/tests/unit/tabs/tabs_events.js +++ b/tests/unit/tabs/tabs_events.js @@ -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(), "

testing

", "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 ) ); diff --git a/tests/unit/tabs/tabs_methods.js b/tests/unit/tabs/tabs_methods.js index c33bebe65..8fcd2a848 100644 --- a/tests/unit/tabs/tabs_methods.js +++ b/tests/unit/tabs/tabs_methods.js @@ -136,7 +136,7 @@ test('refresh', function() { var el = $('
').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('
  • Test 1
  • '); el.tabs('refresh'); diff --git a/tests/unit/tabs/tabs_options.js b/tests/unit/tabs/tabs_options.js index 98cd3b4ca..49c77521e 100644 --- a/tests/unit/tabs/tabs_options.js +++ b/tests/unit/tabs/tabs_options.js @@ -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 }); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 99e1b6538..c16fe94c0 100755 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -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
  • - 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; + var that = this, + options = that.options; - this.element - .toggleClass( "ui-tabs-collapsible", o.collapsible ); + 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" ); - 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 ) );