diff options
author | Alexander Schmitz <arschmitz@gmail.com> | 2014-12-03 11:28:56 -0500 |
---|---|---|
committer | Alexander Schmitz <arschmitz@gmail.com> | 2015-03-11 16:05:28 -0400 |
commit | aaddfbfa8b3bdb0374540d7dd1e13a708bdb00aa (patch) | |
tree | daeb063d0950a4c217a88870305238f0d9a08749 | |
parent | 28dccda3776c586052d787dd77e0abdbf1b68a0d (diff) | |
download | jquery-ui-aaddfbfa8b3bdb0374540d7dd1e13a708bdb00aa.tar.gz jquery-ui-aaddfbfa8b3bdb0374540d7dd1e13a708bdb00aa.zip |
Tabs: Add classes option
Ref #7053
Ref gh-1411
-rw-r--r-- | tests/unit/tabs/tabs.html | 1 | ||||
-rw-r--r-- | tests/unit/tabs/tabs_common.js | 7 | ||||
-rw-r--r-- | tests/unit/tabs/tabs_core.js | 40 | ||||
-rw-r--r-- | tests/unit/tabs/tabs_methods.js | 16 | ||||
-rw-r--r-- | tests/unit/tabs/tabs_options.js | 38 | ||||
-rw-r--r-- | ui/tabs.js | 73 |
6 files changed, 112 insertions, 63 deletions
diff --git a/tests/unit/tabs/tabs.html b/tests/unit/tabs/tabs.html index 778639eb3..e2bccec99 100644 --- a/tests/unit/tabs/tabs.html +++ b/tests/unit/tabs/tabs.html @@ -9,6 +9,7 @@ <script src="../../../external/qunit/qunit.js"></script> <script src="../../../external/jquery-simulate/jquery.simulate.js"></script> <script src="../testsuite.js"></script> + <script src="../../../external/qunit-assert-classes/qunit-assert-classes.js"></script> <script> TestHelpers.loadResources({ css: [ "core", "tabs" ], diff --git a/tests/unit/tabs/tabs_common.js b/tests/unit/tabs/tabs_common.js index 8f6bbc67b..c43d8ff09 100644 --- a/tests/unit/tabs/tabs_common.js +++ b/tests/unit/tabs/tabs_common.js @@ -1,7 +1,12 @@ TestHelpers.commonWidgetTests( "tabs", { defaults: { active: null, - classes: {}, + classes: { + "ui-tabs": "ui-corner-all", + "ui-tabs-nav": "ui-corner-all", + "ui-tab": "ui-corner-top", + "ui-tabs-panel": "ui-corner-bottom" + }, collapsible: false, disabled: false, event: "click", diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index ab3c81175..b003fa61e 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -4,13 +4,32 @@ var state = TestHelpers.tabs.state; module( "tabs: core" ); -test( "markup structure", function() { - expect( 3 ); - var element = $( "#tabs1" ).tabs(); - ok( element.hasClass( "ui-tabs" ), "main element is .ui-tabs" ); - ok( element.find( "ul" ).hasClass( "ui-tabs-nav" ), "list item is .ui-tabs-nav" ); - equal( element.find( ".ui-tabs-panel" ).length, 3, - ".ui-tabs-panel elements exist, correct number" ); +test( "markup structure", function( assert ) { + expect( 17 ); + var element = $( "#tabs1" ).tabs(), + tabList = element.find( "ul, ol" ), + tabs = tabList.find( "li" ), + active = tabs.eq( 0 ), + anchors = tabs.find( "a" ), + panels = element.find( ".ui-tabs-panel" ); + + assert.hasClasses( element, "ui-tabs ui-widget ui-widget-content" ); + assert.lacksClasses( element, "ui-tabs-collapsible" ); + assert.hasClasses( tabList, "ui-tabs-nav ui-widget-header" ); + equal( tabList.length, 1, "The widget contains exactly one tab list" ); + assert.hasClasses( tabs[ 0 ], "ui-tab" ); + assert.hasClasses( tabs[ 1 ], "ui-tab" ); + assert.hasClasses( tabs[ 2 ], "ui-tab" ); + equal( tabs.length, 3, "There are exactly three tabs" ); + assert.hasClasses( anchors[ 0 ], "ui-tabs-anchor" ); + assert.hasClasses( anchors[ 1 ], "ui-tabs-anchor" ); + assert.hasClasses( anchors[ 2 ], "ui-tabs-anchor" ); + equal( anchors.length, 3, "There are exactly 3 anchors" ); + assert.hasClasses( active, "ui-tabs-active" ); + assert.hasClasses( panels[ 0 ], "ui-tabs-panel ui-widget-content" ); + assert.hasClasses( panels[ 1 ], "ui-tabs-panel ui-widget-content" ); + assert.hasClasses( panels[ 2 ], "ui-tabs-panel ui-widget-content" ); + equal( panels.length, 3, "There are exactly 3 tab panels" ); }); $.each({ @@ -129,18 +148,21 @@ test( "accessibility", function() { equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "inactive panel has aria-hidden=true" ); }); -asyncTest( "accessibility - ajax", function() { - expect( 4 ); +asyncTest( "accessibility - ajax", function( assert ) { + expect( 6 ); var element = $( "#tabs2" ).tabs(), + tab = element.find( ".ui-tabs-nav li" ).eq( 3 ), panel = $( "#custom-id" ); equal( panel.attr( "aria-live" ), "polite", "remote panel has aria-live" ); equal( panel.attr( "aria-busy" ), null, "does not have aria-busy on init" ); element.tabs( "option", "active", 3 ); + assert.hasClasses( tab, "ui-tabs-loading" ); equal( panel.attr( "aria-busy" ), "true", "panel has aria-busy during load" ); element.one( "tabsload", function() { setTimeout(function() { equal( panel.attr( "aria-busy" ), null, "panel does not have aria-busy after load" ); + assert.lacksClasses( tab, "ui-tabs-loading" ); start(); }, 1 ); }); diff --git a/tests/unit/tabs/tabs_methods.js b/tests/unit/tabs/tabs_methods.js index 073430b77..b9b5bee9f 100644 --- a/tests/unit/tabs/tabs_methods.js +++ b/tests/unit/tabs/tabs_methods.js @@ -15,6 +15,22 @@ test( "destroy", function() { }); }); +asyncTest( "destroy - ajax", function() { + expect( 1 ); + domEqual( "#tabs2", function( done ) { + var element = $( "#tabs2" ).tabs({ + load: function() { + setTimeout(function() { + element.tabs( "destroy" ); + done(); + start(); + }); + } + }); + element.tabs( "option", "active", 2 ); + }); +}); + test( "enable", function() { expect( 8 ); diff --git a/tests/unit/tabs/tabs_options.js b/tests/unit/tabs/tabs_options.js index 56e32b7da..3983721d5 100644 --- a/tests/unit/tabs/tabs_options.js +++ b/tests/unit/tabs/tabs_options.js @@ -107,28 +107,14 @@ test( "active - mismatched tab/panel order", function() { location.hash = "#"; }); -test( "{ collapsible: false }", function() { - expect( 4 ); - - var element = $( "#tabs1" ).tabs({ - active: 1 - }); - element.tabs( "option", "active", false ); - equal( element.tabs( "option", "active" ), 1 ); - state( element, 0, 1, 0 ); - - element.find( ".ui-state-active .ui-tabs-anchor" ).eq( 1 ).click(); - equal( element.tabs( "option", "active" ), 1 ); - state( element, 0, 1, 0 ); -}); - -test( "{ collapsible: true }", function() { - expect( 6 ); +test( "collapsible", function() { + expect( 13 ); var element = $( "#tabs1" ).tabs({ active: 1, collapsible: true }); + ok( element.hasClass( "ui-tabs-collapsible" ), "main element is .ui-tabs-collapsible" ); element.tabs( "option", "active", false ); equal( element.tabs( "option", "active" ), false ); @@ -141,6 +127,24 @@ test( "{ collapsible: true }", function() { element.find( ".ui-state-active .ui-tabs-anchor" ).click(); equal( element.tabs( "option", "active" ), false ); state( element, 0, 0, 0 ); + + element.tabs( "option", "collapsible", false ); + ok( !element.hasClass( "ui-tabs-collapsible" ), "main element is not .ui-tabs-collapsible" ); + + element.tabs( "option", "collapsible", true ); + ok( element.hasClass( "ui-tabs-collapsible" ), "main element is .ui-tabs-collapsible" ); + + element.tabs({ + active: 1, + collapsible: false + }); + element.tabs( "option", "active", false ); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); + + element.find( ".ui-state-active .ui-tabs-anchor" ).eq( 1 ).click(); + equal( element.tabs( "option", "active" ), 1 ); + state( element, 0, 1, 0 ); }); test( "disabled", function() { diff --git a/ui/tabs.js b/ui/tabs.js index 6d826b14a..366ebbb51 100644 --- a/ui/tabs.js +++ b/ui/tabs.js @@ -37,6 +37,12 @@ return $.widget( "ui.tabs", { delay: 300, options: { active: null, + classes: { + "ui-tabs": "ui-corner-all", + "ui-tabs-nav": "ui-corner-all", + "ui-tab": "ui-corner-top", + "ui-tabs-panel": "ui-corner-bottom" + }, collapsible: false, event: "click", heightStyle: "content", @@ -77,9 +83,8 @@ return $.widget( "ui.tabs", { this.running = false; - this.element - .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) - .toggleClass( "ui-tabs-collapsible", options.collapsible ); + this._addClass( "ui-tabs", "ui-widget ui-widget-content" ); + this._toggleClass( "ui-tabs-collapsible", null, options.collapsible ); this._processTabs(); options.active = this._initialActive(); @@ -286,7 +291,8 @@ return $.widget( "ui.tabs", { this._super( key, value); if ( key === "collapsible" ) { - this.element.toggleClass( "ui-tabs-collapsible", value ); + this._toggleClass( "ui-tabs-collapsible", null, value ); + // Setting collapsible: false while collapsed; open first panel if ( !value && this.options.active === false ) { this._activate( 0 ); @@ -362,12 +368,12 @@ return $.widget( "ui.tabs", { this.tabs.eq( 0 ).attr( "tabIndex", 0 ); } else { this.active - .addClass( "ui-tabs-active ui-state-active" ) .attr({ "aria-selected": "true", "aria-expanded": "true", tabIndex: 0 }); + this._addClass( this.active, "ui-tabs-active", "ui-state-active" ); this._getPanelForTab( this.active ) .show() .attr({ @@ -382,11 +388,12 @@ return $.widget( "ui.tabs", { prevAnchors = this.anchors, prevPanels = this.panels; - this.tablist = this._getList() - .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) - .attr( "role", "tablist" ) + this.tablist = this._getList().attr( "role", "tablist" ); + this._addClass( this.tablist, "ui-tabs-nav", + "ui-helper-reset ui-helper-clearfix ui-widget-header" ); - // Prevent users from focusing disabled tabs via click + // Prevent users from focusing disabled tabs via click + this.tablist .delegate( "> li", "mousedown" + this.eventNamespace, function( event ) { if ( $( this ).is( ".ui-state-disabled" ) ) { event.preventDefault(); @@ -406,20 +413,20 @@ return $.widget( "ui.tabs", { }); this.tabs = this.tablist.find( "> li:has(a[href])" ) - .addClass( "ui-state-default ui-corner-top" ) .attr({ role: "tab", tabIndex: -1 }); + this._addClass( this.tabs, "ui-tab", "ui-state-default" ); this.anchors = this.tabs.map(function() { return $( "a", this )[ 0 ]; }) - .addClass( "ui-tabs-anchor" ) .attr({ role: "presentation", tabIndex: -1 }); + this._addClass( this.anchors, "ui-tabs-anchor" ); this.panels = $(); @@ -461,9 +468,8 @@ return $.widget( "ui.tabs", { panel.attr( "aria-labelledby", anchorId ); }); - this.panels - .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) - .attr( "role", "tabpanel" ); + this.panels.attr( "role", "tabpanel" ); + this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" ); // Avoid memory leaks (#10056) if ( prevTabs ) { @@ -481,11 +487,12 @@ return $.widget( "ui.tabs", { _createPanel: function( id ) { return $( "<div>" ) .attr( "id", id ) - .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) .data( "ui-tabs-destroy", true ); }, _setupDisabled: function( disabled ) { + var currentItem, li, i; + if ( $.isArray( disabled ) ) { if ( !disabled.length ) { disabled = false; @@ -495,15 +502,14 @@ return $.widget( "ui.tabs", { } // disable tabs - for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { + for ( i = 0; ( li = this.tabs[ i ] ); i++ ) { + currentItem = $( li ); if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { - $( li ) - .addClass( "ui-state-disabled" ) - .attr( "aria-disabled", "true" ); + currentItem.attr( "aria-disabled", "true" ); + this._addClass( currentItem, null, "ui-state-disabled" ); } else { - $( li ) - .removeClass( "ui-state-disabled" ) - .removeAttr( "aria-disabled" ); + currentItem.removeAttr( "aria-disabled" ); + this._removeClass( currentItem, null, "ui-state-disabled" ); } } @@ -629,7 +635,7 @@ return $.widget( "ui.tabs", { } function show() { - eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); + that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" ); if ( toShow.length && that.options.show ) { that._show( toShow, that.options.show, complete ); @@ -642,11 +648,13 @@ return $.widget( "ui.tabs", { // start out by hiding, then showing, then completing if ( toHide.length && this.options.hide ) { this._hide( toHide, this.options.hide, function() { - eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + that._removeClass( eventData.oldTab.closest( "li" ), + "ui-tabs-active", "ui-state-active" ); show(); }); } else { - eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + this._removeClass( eventData.oldTab.closest( "li" ), + "ui-tabs-active", "ui-state-active" ); toHide.hide(); show(); } @@ -716,27 +724,20 @@ return $.widget( "ui.tabs", { this.xhr.abort(); } - this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); - this.tablist - .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) - .removeAttr( "role" ); + .removeAttr( "role" ) + .unbind( this.eventNamespace ); this.anchors - .removeClass( "ui-tabs-anchor" ) .removeAttr( "role" ) .removeAttr( "tabIndex" ) .removeUniqueId(); - this.tablist.unbind( this.eventNamespace ); - this.tabs.add( this.panels ).each(function() { if ( $.data( this, "ui-tabs-destroy" ) ) { $( this ).remove(); } else { $( this ) - .removeClass( "ui-state-default ui-state-active ui-state-disabled " + - "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) .removeAttr( "tabIndex" ) .removeAttr( "aria-live" ) .removeAttr( "aria-busy" ) @@ -827,7 +828,7 @@ return $.widget( "ui.tabs", { that.panels.stop( false, true ); } - tab.removeClass( "ui-tabs-loading" ); + that._removeClass( tab, "ui-tabs-loading" ); panel.removeAttr( "aria-busy" ); if ( jqXHR === that.xhr ) { @@ -846,7 +847,7 @@ return $.widget( "ui.tabs", { // jQuery <1.8 returns false if the request is canceled in beforeSend, // but as of 1.8, $.ajax() always returns a jqXHR object. if ( this.xhr && this.xhr.statusText !== "canceled" ) { - tab.addClass( "ui-tabs-loading" ); + this._addClass( tab, "ui-tabs-loading" ); panel.attr( "aria-busy", "true" ); this.xhr |