From 6c0bb249184e3ad6f8ce48509b5f9011313a57a3 Mon Sep 17 00:00:00 2001 From: Alexander Schmitz Date: Mon, 24 Aug 2015 08:57:25 -0400 Subject: [PATCH] Tabs: Style updates Ref #14246 --- tests/unit/tabs/common.js | 2 +- tests/unit/tabs/core.js | 68 +++++++++++----------- tests/unit/tabs/events.js | 67 +++++++++++---------- tests/unit/tabs/helper.js | 17 +++--- tests/unit/tabs/methods.js | 74 +++++++++++++---------- tests/unit/tabs/options.js | 116 ++++++++++++++++++------------------- ui/widgets/tabs.js | 22 +++++++ 7 files changed, 202 insertions(+), 164 deletions(-) diff --git a/tests/unit/tabs/common.js b/tests/unit/tabs/common.js index 40c899847..ae4adde5a 100644 --- a/tests/unit/tabs/common.js +++ b/tests/unit/tabs/common.js @@ -26,6 +26,6 @@ common.testWidget( "tabs", { create: null, load: null } -}); +} ); } ); diff --git a/tests/unit/tabs/core.js b/tests/unit/tabs/core.js index 9c62817eb..a2b41e24c 100644 --- a/tests/unit/tabs/core.js +++ b/tests/unit/tabs/core.js @@ -40,9 +40,9 @@ test( "markup structure", function( assert ) { 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({ +$.each( { "deep ul": "#tabs3", "multiple lists, ul first": "#tabs4", "multiple lists, ol first": "#tabs5", @@ -53,8 +53,8 @@ $.each({ var element = $( selector ).tabs(); assert.hasClasses( element, "ui-tabs" ); assert.hasClasses( $( selector + "-list" ), "ui-tabs-nav" ); - }); -}); + } ); +} ); // #5893 - Sublist in the tab list are considered as tab test( "nested list", function() { @@ -62,7 +62,7 @@ test( "nested list", function() { var element = $( "#tabs6" ).tabs(); equal( element.tabs( "instance" ).anchors.length, 2, "should contain 2 tab" ); -}); +} ); test( "disconnected from DOM", function() { expect( 2 ); @@ -70,7 +70,7 @@ test( "disconnected from DOM", function() { var element = $( "#tabs1" ).remove().tabs(); equal( element.find( ".ui-tabs-nav" ).length, 1, "should initialize nav" ); equal( element.find( ".ui-tabs-panel" ).length, 3, "should initialize panels" ); -}); +} ); test( "non-tab list items", function() { expect( 2 ); @@ -79,17 +79,17 @@ test( "non-tab list items", function() { equal( element.tabs( "option", "active" ), 0, "defaults to first tab" ); equal( element.find( ".ui-tabs-nav li.ui-state-active" ).index(), 1, "first actual tab is active" ); -}); +} ); test( "aria-controls", function() { expect( 7 ); var element = $( "#tabs1" ).tabs(), tabs = element.find( ".ui-tabs-nav li" ); - tabs.each(function() { + tabs.each( function() { var tab = $( this ), anchor = tab.find( ".ui-tabs-anchor" ); equal( anchor.prop( "hash" ).substring( 1 ), tab.attr( "aria-controls" ) ); - }); + } ); element = $( "#tabs2" ).tabs(); tabs = element.find( ".ui-tabs-nav li" ); @@ -97,20 +97,20 @@ test( "aria-controls", function() { equal( tabs.eq( 1 ).attr( "aria-controls" ), "inline-style" ); ok( /^ui-id-\d+$/.test( tabs.eq( 2 ).attr( "aria-controls" ) ), "generated id" ); equal( tabs.eq( 3 ).attr( "aria-controls" ), "custom-id" ); -}); +} ); test( "accessibility", function() { expect( 49 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { active: 1, disabled: [ 2 ] - }), + } ), tabs = element.find( ".ui-tabs-nav li" ), anchors = tabs.find( ".ui-tabs-anchor" ), panels = element.find( ".ui-tabs-panel" ); equal( element.find( ".ui-tabs-nav" ).attr( "role" ), "tablist", "tablist role" ); - tabs.each(function( index ) { + tabs.each( function( index ) { var tab = tabs.eq( index ), anchor = anchors.eq( index ), anchorId = anchor.attr( "id" ), @@ -121,7 +121,7 @@ test( "accessibility", function() { equal( anchor.attr( "tabindex" ), -1, "anchor " + index + " tabindex" ); equal( panel.attr( "role" ), "tabpanel", "panel " + index + " role" ); equal( panel.attr( "aria-labelledby" ), anchorId, "panel " + index + " aria-labelledby" ); - }); + } ); equal( tabs.eq( 1 ).attr( "aria-selected" ), "true", "active tab has aria-selected=true" ); equal( tabs.eq( 1 ).attr( "tabindex" ), 0, "active tab has tabindex=0" ); @@ -155,7 +155,7 @@ test( "accessibility", function() { equal( tabs.eq( 2 ).attr( "aria-disabled" ), "true", "disabled tab has aria-disabled=true" ); equal( tabs.eq( 2 ).attr( "aria-expanded" ), "false", "inactive tab has aria-expanded=false" ); equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "inactive panel has aria-hidden=true" ); -}); +} ); asyncTest( "accessibility - ajax", function( assert ) { expect( 6 ); @@ -169,19 +169,19 @@ asyncTest( "accessibility - ajax", function( assert ) { assert.hasClasses( tab, "ui-tabs-loading" ); equal( panel.attr( "aria-busy" ), "true", "panel has aria-busy during load" ); element.one( "tabsload", function() { - setTimeout(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 ); - }); -}); + } ); +} ); asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", function( assert ) { expect( 92 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { collapsible: true - }), + } ), tabs = element.find( ".ui-tabs-nav li" ), panels = element.find( ".ui-tabs-panel" ), keyCode = $.ui.keyCode; @@ -328,10 +328,10 @@ asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", } setTimeout( step1 ); -}); +} ); // Navigation with CTRL and COMMAND (both behave the same) -$.each({ +$.each( { ctrl: "CTRL", meta: "COMMAND" }, function( modifier, label ) { @@ -547,8 +547,8 @@ $.each({ } setTimeout( step1 ); - }); -}); + } ); +} ); asyncTest( "keyboard support - CTRL+UP, ALT+PAGE_DOWN, ALT+PAGE_UP", function( assert ) { expect( 50 ); @@ -640,34 +640,34 @@ asyncTest( "keyboard support - CTRL+UP, ALT+PAGE_DOWN, ALT+PAGE_UP", function( a } setTimeout( step1 ); -}); +} ); test( "#3627 - Ajax tab with url containing a fragment identifier fails to load", function() { expect( 1 ); - $( "#tabs2" ).tabs({ + $( "#tabs2" ).tabs( { active: 2, beforeLoad: function( event, ui ) { event.preventDefault(); ok( /test.html$/.test( ui.ajaxSettings.url ), "should ignore fragment identifier" ); } - }); -}); + } ); +} ); test( "#4033 - IE expands hash to full url and misinterprets tab as ajax", function() { expect( 2 ); - var element = $("
"); - element.appendTo("#qunit-fixture"); - element.tabs({ + var element = $( "
" ); + element.appendTo( "#qunit-fixture" ); + element.tabs( { beforeLoad: function() { event.preventDefault(); ok( false, "should not be an ajax tab" ); } - }); + } ); - equal( element.find(".ui-tabs-nav li").attr("aria-controls"), "tab", "aria-contorls attribute is correct" ); + equal( element.find( ".ui-tabs-nav li" ).attr( "aria-controls" ), "tab", "aria-contorls attribute is correct" ); state( element, 1 ); -}); +} ); } ); diff --git a/tests/unit/tabs/events.js b/tests/unit/tabs/events.js index 307e110fd..736fda503 100644 --- a/tests/unit/tabs/events.js +++ b/tests/unit/tabs/events.js @@ -15,17 +15,17 @@ test( "create", function() { tabs = element.find( "ul li" ), panels = element.children( "div" ); - element.tabs({ + element.tabs( { create: function( event, ui ) { equal( ui.tab.length, 1, "tab length" ); strictEqual( ui.tab[ 0 ], tabs[ 0 ], "tab" ); equal( ui.panel.length, 1, "panel length" ); strictEqual( ui.panel[ 0 ], panels[ 0 ], "panel" ); } - }); + } ); element.tabs( "destroy" ); - element.tabs({ + element.tabs( { active: 2, create: function( event, ui ) { equal( ui.tab.length, 1, "tab length" ); @@ -33,27 +33,27 @@ test( "create", function() { equal( ui.panel.length, 1, "panel length" ); strictEqual( ui.panel[ 0 ], panels[ 2 ], "panel" ); } - }); + } ); element.tabs( "destroy" ); - element.tabs({ + element.tabs( { active: false, collapsible: true, create: function( event, ui ) { equal( ui.tab.length, 0, "tab length" ); equal( ui.panel.length, 0, "panel length" ); } - }); + } ); element.tabs( "destroy" ); -}); +} ); test( "beforeActivate", function() { expect( 38 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { active: false, collapsible: true - }), + } ), tabs = element.find( ".ui-tabs-nav li" ), anchors = tabs.find( ".ui-tabs-anchor" ), panels = element.find( ".ui-tabs-panel" ); @@ -68,7 +68,7 @@ test( "beforeActivate", function() { equal( ui.newPanel.length, 1, "newPanel length" ); strictEqual( ui.newPanel[ 0 ], panels[ 0 ], "newPanel" ); state( element, 0, 0, 0 ); - }); + } ); element.tabs( "option", "active", 0 ); state( element, 1, 0, 0 ); @@ -84,7 +84,7 @@ test( "beforeActivate", function() { equal( ui.newPanel.length, 1, "newPanel length" ); strictEqual( ui.newPanel[ 0 ], panels[ 1 ], "newPanel" ); state( element, 1, 0, 0 ); - }); + } ); anchors.eq( 1 ).trigger( "click" ); state( element, 0, 1, 0 ); @@ -98,7 +98,7 @@ test( "beforeActivate", function() { equal( ui.newTab.length, 0, "newTab length" ); equal( ui.newPanel.length, 0, "newPanel length" ); state( element, 0, 1, 0 ); - }); + } ); element.tabs( "option", "active", false ); state( element, 0, 0, 0 ); @@ -113,18 +113,18 @@ test( "beforeActivate", function() { strictEqual( ui.newPanel[ 0 ], panels[ 1 ], "newPanel" ); event.preventDefault(); state( element, 0, 0, 0 ); - }); + } ); element.tabs( "option", "active", 1 ); state( element, 0, 0, 0 ); -}); +} ); test( "activate", function() { expect( 30 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { active: false, collapsible: true - }), + } ), tabs = element.find( ".ui-tabs-nav li" ), anchors = element.find( ".ui-tabs-anchor" ), panels = element.find( ".ui-tabs-panel" ); @@ -139,7 +139,7 @@ test( "activate", function() { equal( ui.newPanel.length, 1, "newPanel length" ); strictEqual( ui.newPanel[ 0 ], panels[ 0 ], "newPanel" ); state( element, 1, 0, 0 ); - }); + } ); element.tabs( "option", "active", 0 ); state( element, 1, 0, 0 ); @@ -155,7 +155,7 @@ test( "activate", function() { equal( ui.newPanel.length, 1, "newPanel length" ); strictEqual( ui.newPanel[ 0 ], panels[ 1 ], "newPanel" ); state( element, 0, 1, 0 ); - }); + } ); anchors.eq( 1 ).trigger( "click" ); state( element, 0, 1, 0 ); @@ -169,7 +169,7 @@ test( "activate", function() { equal( ui.newTab.length, 0, "newTab length" ); equal( ui.newPanel.length, 0, "newPanel length" ); state( element, 0, 0, 0 ); - }); + } ); element.tabs( "option", "active", false ); state( element, 0, 0, 0 ); @@ -177,12 +177,12 @@ test( "activate", function() { element.one( "tabsbeforeactivate", function( event ) { ok( true, "tabsbeforeactivate" ); event.preventDefault(); - }); + } ); element.one( "tabsactivate", function() { ok( false, "tabsactivate" ); - }); + } ); element.tabs( "option", "active", 1 ); -}); +} ); test( "beforeLoad", function() { expect( 32 ); @@ -206,8 +206,8 @@ test( "beforeLoad", function() { equal( ui.panel.html(), "", "panel html" ); event.preventDefault(); state( element, 0, 0, 1, 0, 0 ); - }); - element.tabs({ active: 2 }); + } ); + element.tabs( { active: 2 } ); state( element, 0, 0, 1, 0, 0 ); equal( panel.html(), "", "panel html after" ); element.tabs( "destroy" ); @@ -228,7 +228,7 @@ test( "beforeLoad", function() { equal( ui.panel.html(), "", "panel html" ); event.preventDefault(); state( element, 1, 0, 0, 0, 0 ); - }); + } ); element.tabs(); element.tabs( "option", "active", 2 ); state( element, 0, 0, 1, 0, 0 ); @@ -250,12 +250,13 @@ test( "beforeLoad", function() { ui.panel.html( "

testing

" ); event.preventDefault(); state( element, 0, 0, 1, 0, 0 ); - }); + } ); element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 3 ).trigger( "click" ); state( element, 0, 0, 0, 1, 0 ); + // .toLowerCase() is needed to convert

to

in old IEs equal( panel.html().toLowerCase(), "

testing

", "panel html after" ); -}); +} ); asyncTest( "load", function() { expect( 21 ); @@ -277,10 +278,11 @@ asyncTest( "load", function() { equal( ui.panel.find( "p" ).length, 1, "panel html" ); state( element, 0, 0, 1, 0, 0 ); tabsload1(); - }); - element.tabs({ active: 2 }); + } ); + element.tabs( { active: 2 } ); function tabsload1() { + // .option() element.one( "tabsload", function( event, ui ) { tab = element.find( ".ui-tabs-nav li" ).eq( 3 ); @@ -295,11 +297,12 @@ asyncTest( "load", function() { equal( ui.panel.find( "p" ).length, 1, "panel html" ); state( element, 0, 0, 0, 1, 0 ); tabsload2(); - }); + } ); element.tabs( "option", "active", 3 ); } function tabsload2() { + // click, change panel content element.one( "tabsload", function( event, ui ) { tab = element.find( ".ui-tabs-nav li" ).eq( 4 ); @@ -314,9 +317,9 @@ asyncTest( "load", function() { equal( ui.panel.find( "p" ).length, 1, "panel html" ); state( element, 0, 0, 0, 0, 1 ); start(); - }); + } ); element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 4 ).trigger( "click" ); } -}); +} ); } ); diff --git a/tests/unit/tabs/helper.js b/tests/unit/tabs/helper.js index 132061753..073895f5f 100644 --- a/tests/unit/tabs/helper.js +++ b/tests/unit/tabs/helper.js @@ -15,7 +15,7 @@ return $.extend( helper, { if ( internalState === true ) { internalState = $.map( new Array( tabs.find( ".ui-tabs-nav li" ).length ), function( _, index ) { return index; - }); + } ); } expected = $.map( new Array( tabs.find ( ".ui-tabs-nav li" ).length ), function( _, index ) { @@ -24,9 +24,9 @@ return $.extend( helper, { } else { return $.inArray( index, state ) !== -1 ? 1 : 0; } - }); + } ); - actual = tabs.find( ".ui-tabs-nav li" ).map(function( index ) { + actual = tabs.find( ".ui-tabs-nav li" ).map( function( index ) { var tab = $( this ), tabIsDisabled = tab.hasClass( "ui-state-disabled" ); @@ -36,23 +36,24 @@ return $.extend( helper, { if ( !tabIsDisabled && $.inArray( index, internalState ) === -1 ) { return 0; } + // mixed state - invalid return -1; - }).get(); + } ).get(); deepEqual( tabs.tabs( "option", "disabled" ), state ); deepEqual( actual, expected ); }, equalHeight: function( tabs, height ) { - tabs.find( ".ui-tabs-panel" ).each(function() { + tabs.find( ".ui-tabs-panel" ).each( function() { equal( $( this ).outerHeight(), height ); - }); + } ); }, state: function( tabs ) { var expected = $.makeArray( arguments ).slice( 1 ), - actual = tabs.find( ".ui-tabs-nav li" ).map(function() { + actual = tabs.find( ".ui-tabs-nav li" ).map( function() { var tab = $( this ), panel = $( $.ui.tabs.prototype._sanitizeSelector( "#" + tab.attr( "aria-controls" ) ) ), @@ -66,7 +67,7 @@ return $.extend( helper, { return 0; } return -1; // mixed state - invalid - }).get(); + } ).get(); deepEqual( actual, expected ); } } ); diff --git a/tests/unit/tabs/methods.js b/tests/unit/tabs/methods.js index d904ac530..ef7c09ba7 100644 --- a/tests/unit/tabs/methods.js +++ b/tests/unit/tabs/methods.js @@ -13,95 +13,103 @@ test( "destroy", function( assert ) { expect( 2 ); assert.domEqual( "#tabs1", function() { $( "#tabs1" ).tabs().tabs( "destroy" ); - }); + } ); assert.domEqual( "#tabs2", function() { $( "#tabs2" ).tabs().tabs( "destroy" ); - }); -}); + } ); +} ); asyncTest( "destroy - ajax", function( assert ) { expect( 1 ); assert.domEqual( "#tabs2", function( done ) { - var element = $( "#tabs2" ).tabs({ + var element = $( "#tabs2" ).tabs( { load: function() { - setTimeout(function() { + setTimeout( function() { element.tabs( "destroy" ); done(); start(); - }); + } ); } - }); + } ); element.tabs( "option", "active", 2 ); - }); -}); + } ); +} ); test( "enable", function() { expect( 8 ); - var element = $( "#tabs1" ).tabs({ disabled: true }); + var element = $( "#tabs1" ).tabs( { disabled: true } ); disabled( element, true ); element.tabs( "enable" ); disabled( element, false ); element.tabs( "destroy" ); - element.tabs({ disabled: [ 0, 1 ] }); + element.tabs( { disabled: [ 0, 1 ] } ); disabled( element, [ 0, 1 ] ); element.tabs( "enable" ); disabled( element, false ); -}); +} ); test( "enable( index )", function() { expect( 10 ); - var element = $( "#tabs1" ).tabs({ disabled: true }); + var element = $( "#tabs1" ).tabs( { disabled: true } ); disabled( element, true ); + // fully disabled -> partially disabled element.tabs( "enable", 1 ); disabled( element, [ 0, 2 ] ); + // partially disabled -> partially disabled element.tabs( "enable", 2 ); disabled( element, [ 0 ] ); + // already enabled tab, no change element.tabs( "enable", 2 ); disabled( element, [ 0 ] ); + // partially disabled -> fully enabled element.tabs( "enable", 0 ); disabled( element, false ); -}); +} ); test( "disable", function() { expect( 8 ); - var element = $( "#tabs1" ).tabs({ disabled: false }); + var element = $( "#tabs1" ).tabs( { disabled: false } ); disabled( element, false ); element.tabs( "disable" ); disabled( element, true ); element.tabs( "destroy" ); - element.tabs({ disabled: [ 0, 1 ] }); + element.tabs( { disabled: [ 0, 1 ] } ); disabled( element, [ 0, 1 ] ); element.tabs( "disable" ); disabled( element, true ); -}); +} ); test( "disable( index )", function() { expect( 10 ); - var element = $( "#tabs1" ).tabs({ disabled: false }); + var element = $( "#tabs1" ).tabs( { disabled: false } ); disabled( element, false ); + // fully enabled -> partially disabled element.tabs( "disable", 1 ); disabled( element, [ 1 ] ); + // partially disabled -> partially disabled element.tabs( "disable", 2 ); disabled( element, [ 1, 2 ] ); + // already disabled tab, no change element.tabs( "disable", 2 ); disabled( element, [ 1, 2 ] ); + // partially disabled -> fully disabled element.tabs( "disable", 0 ); disabled( element, true ); -}); +} ); test( "refresh", function() { expect( 27 ); @@ -170,15 +178,15 @@ test( "refresh", function() { element.tabs( "refresh" ); state( element, 1 ); disabled( element, false ); -}); +} ); test( "refresh - looping", function() { expect( 6 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { disabled: [ 0 ], active: 1 - }); + } ); state( element, 0, 1, 0 ); disabled( element, [ 0 ] ); @@ -190,7 +198,7 @@ test( "refresh - looping", function() { element.tabs( "refresh" ); state( element, 0, 1 ); disabled( element, [ 0 ] ); -}); +} ); asyncTest( "load", function() { expect( 30 ); @@ -210,8 +218,9 @@ asyncTest( "load", function() { equal( ui.panel.length, 1, "panel length" ); strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); state( element, 1, 0, 0, 0, 0 ); - }); + } ); element.one( "tabsload", function( event, ui ) { + // TODO: remove wrapping in 2.0 var uiTab = $( ui.tab ), uiPanel = $( ui.panel ), @@ -227,24 +236,26 @@ asyncTest( "load", function() { equal( uiPanel.find( "p" ).length, 1, "panel html" ); state( element, 1, 0, 0, 0, 0 ); setTimeout( tabsload1 ); - }); + } ); element.tabs( "load", 3 ); state( element, 1, 0, 0, 0, 0 ); function tabsload1() { + // no need to test details of event (tested in events tests) element.one( "tabsbeforeload", function() { ok( true, "tabsbeforeload invoked" ); - }); + } ); element.one( "tabsload", function() { ok( true, "tabsload invoked" ); setTimeout( tabsload2 ); - }); + } ); element.tabs( "option", "active", 3 ); state( element, 0, 0, 0, 1, 0 ); } function tabsload2() { + // reload content of active tab element.one( "tabsbeforeload", function( event, ui ) { var tab = element.find( ".ui-tabs-nav li" ).eq( 3 ), @@ -257,8 +268,9 @@ asyncTest( "load", function() { equal( ui.panel.length, 1, "panel length" ); strictEqual( ui.panel[ 0 ], panel[ 0 ], "panel" ); state( element, 0, 0, 0, 1, 0 ); - }); + } ); element.one( "tabsload", function( event, ui ) { + // TODO: remove wrapping in 2.0 var uiTab = $( ui.tab ), uiPanel = $( ui.panel ), @@ -273,11 +285,11 @@ asyncTest( "load", function() { strictEqual( uiPanel[ 0 ], panel[ 0 ], "panel" ); state( element, 0, 0, 0, 1, 0 ); start(); - }); + } ); element.tabs( "load", 3 ); state( element, 0, 0, 0, 1, 0 ); } -}); +} ); test( "widget", function() { expect( 2 ); @@ -285,6 +297,6 @@ test( "widget", function() { widgetElement = element.tabs( "widget" ); equal( widgetElement.length, 1, "one element" ); strictEqual( widgetElement[ 0 ], element[ 0 ], "same element" ); -}); +} ); } ); diff --git a/tests/unit/tabs/options.js b/tests/unit/tabs/options.js index f615e165e..f9d9857b1 100644 --- a/tests/unit/tabs/options.js +++ b/tests/unit/tabs/options.js @@ -30,15 +30,15 @@ test( "{ active: default }", function() { state( element, 0, 0, 0, 1, 0 ); element.tabs( "destroy" ); location.hash = "#"; -}); +} ); test( "{ active: false }", function() { expect( 7 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { active: false, collapsible: true - }); + } ); state( element, 0, 0, 0 ); equal( element.find( ".ui-tabs-nav .ui-state-active" ).length, 0, "no tabs selected" ); strictEqual( element.tabs( "option", "active" ), false ); @@ -48,19 +48,19 @@ test( "{ active: false }", function() { equal( element.tabs( "option", "active" ), 0 ); element.tabs( "destroy" ); - element.tabs({ + element.tabs( { active: false - }); + } ); state( element, 1, 0, 0 ); strictEqual( element.tabs( "option", "active" ), 0 ); -}); +} ); test( "{ active: Number }", function() { expect( 8 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { active: 2 - }); + } ); equal( element.tabs( "option", "active" ), 2 ); state( element, 0, 0, 1 ); @@ -75,14 +75,14 @@ test( "{ active: Number }", function() { element.tabs( "option", "active", 10 ); equal( element.tabs( "option", "active" ), 1 ); state( element, 0, 1, 0 ); -}); +} ); test( "{ active: -Number }", function() { expect( 8 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { active: -1 - }); + } ); equal( element.tabs( "option", "active" ), 2 ); state( element, 0, 0, 1 ); @@ -97,7 +97,7 @@ test( "{ active: -Number }", function() { element.tabs( "option", "active", -3 ); equal( element.tabs( "option", "active" ), 0 ); state( element, 1, 0, 0 ); -}); +} ); test( "active - mismatched tab/panel order", function() { expect( 3 ); @@ -109,15 +109,15 @@ test( "active - mismatched tab/panel order", function() { element.tabs( "option", "active", 0 ); state( element, 1, 0 ); location.hash = "#"; -}); +} ); test( "collapsible", function( assert ) { expect( 13 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { active: 1, collapsible: true - }); + } ); assert.hasClasses( element, "ui-tabs-collapsible" ); element.tabs( "option", "active", false ); equal( element.tabs( "option", "active" ), false ); @@ -138,10 +138,10 @@ test( "collapsible", function( assert ) { assert.hasClasses( element, "ui-tabs-collapsible" ); - element.tabs({ + element.tabs( { active: 1, collapsible: false - }); + } ); element.tabs( "option", "active", false ); equal( element.tabs( "option", "active" ), 1 ); state( element, 0, 1, 0 ); @@ -150,7 +150,7 @@ test( "collapsible", function( assert ) { equal( element.tabs( "option", "active" ), 1 ); state( element, 0, 1, 0 ); -}); +} ); test( "disabled", function( assert ) { expect( 23 ); @@ -195,14 +195,14 @@ test( "disabled", function( assert ) { // Enable all tabs element.tabs( "option", "disabled", [] ); disabled( element, false ); -}); +} ); test( "{ event: null }", function() { expect( 5 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { event: null - }); + } ); state( element, 1, 0, 0 ); element.tabs( "option", "active", 1 ); @@ -213,14 +213,14 @@ test( "{ event: null }", function() { element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 2 ).trigger( "click" ); equal( element.tabs( "option", "active" ), 1 ); state( element, 0, 1, 0 ); -}); +} ); test( "{ event: custom }", function() { expect( 11 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { event: "custom1 custom2" - }); + } ); state( element, 1, 0, 0 ); element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 1 ).trigger( "custom1" ); @@ -246,88 +246,88 @@ test( "{ event: custom }", function() { element.find( ".ui-tabs-nav .ui-tabs-anchor" ).eq( 1 ).trigger( "custom3" ); equal( element.tabs( "option", "active" ), 1 ); state( element, 0, 1, 0 ); -}); +} ); test( "{ heightStyle: 'auto' }", function() { expect( 2 ); - var element = $( "#tabs8" ).tabs({ heightStyle: "auto" }); + var element = $( "#tabs8" ).tabs( { heightStyle: "auto" } ); equalHeight( element, 45 ); -}); +} ); test( "{ heightStyle: 'content' }", function() { expect( 2 ); - var element = $( "#tabs8" ).tabs({ heightStyle: "content" }), - sizes = element.find( ".ui-tabs-panel" ).map(function() { + var element = $( "#tabs8" ).tabs( { heightStyle: "content" } ), + sizes = element.find( ".ui-tabs-panel" ).map( function() { return $( this ).height(); - }).get(); + } ).get(); equal( sizes[ 0 ], 45 ); equal( sizes[ 1 ], 15 ); -}); +} ); test( "{ heightStyle: 'fill' }", function() { expect( 4 ); $( "#tabs8Wrapper" ).height( 500 ); - var element = $( "#tabs8" ).tabs({ heightStyle: "fill" }); + var element = $( "#tabs8" ).tabs( { heightStyle: "fill" } ); equalHeight( element, 485 ); element.tabs( "destroy" ); - element = $( "#tabs8" ).css({ + element = $( "#tabs8" ).css( { "border": "1px solid black", "padding": "1px 0" - }); - element.tabs({ heightStyle: "fill" }); + } ); + element.tabs( { heightStyle: "fill" } ); equalHeight( element, 481 ); -}); +} ); test( "{ heightStyle: 'fill' } with sibling", function() { expect( 2 ); $( "#tabs8Wrapper" ).height( 500 ); $( "

Lorem Ipsum

" ) - .css({ + .css( { height: 50, marginTop: 20, marginBottom: 30 - }) + } ) .prependTo( "#tabs8Wrapper" ); - var element = $( "#tabs8" ).tabs({ heightStyle: "fill" }); + var element = $( "#tabs8" ).tabs( { heightStyle: "fill" } ); equalHeight( element, 385 ); -}); +} ); test( "{ heightStyle: 'fill' } with multiple siblings", function() { expect( 2 ); $( "#tabs8Wrapper" ).height( 500 ); $( "

Lorem Ipsum

" ) - .css({ + .css( { height: 50, marginTop: 20, marginBottom: 30 - }) + } ) .prependTo( "#tabs8Wrapper" ); $( "

Lorem Ipsum

" ) - .css({ + .css( { height: 50, marginTop: 20, marginBottom: 30, position: "absolute" - }) + } ) .prependTo( "#tabs8Wrapper" ); $( "

Lorem Ipsum

" ) - .css({ + .css( { height: 25, marginTop: 10, marginBottom: 15 - }) + } ) .prependTo( "#tabs8Wrapper" ); - var element = $( "#tabs8" ).tabs({ heightStyle: "fill" }); + var element = $( "#tabs8" ).tabs( { heightStyle: "fill" } ); equalHeight( element, 335 ); -}); +} ); test( "hide and show: false", function() { expect( 3 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { show: false, hide: false - }), + } ), widget = element.tabs( "instance" ), panels = element.find( ".ui-tabs-panel" ); widget._show = function() { @@ -341,34 +341,34 @@ test( "hide and show: false", function() { element.tabs( "option", "active", 1 ); ok( panels.eq( 0 ).is( ":hidden" ), "first panel hidden" ); ok( panels.eq( 1 ).is( ":visible" ), "second panel visible" ); -}); +} ); asyncTest( "hide and show - animation", function() { expect( 5 ); - var element = $( "#tabs1" ).tabs({ + var element = $( "#tabs1" ).tabs( { show: "drop", hide: 2000 - }), + } ), widget = element.tabs( "instance" ), panels = element.find( ".ui-tabs-panel" ); widget._show = function( element, options, callback ) { strictEqual( element[ 0 ], panels[ 1 ], "correct element in _show()" ); equal( options, "drop", "correct options in _show()" ); - setTimeout(function() { + setTimeout( function() { callback(); - }); + } ); }; widget._hide = function( element, options, callback ) { strictEqual( element[ 0 ], panels[ 0 ], "correct element in _hide()" ); equal( options, 2000, "correct options in _hide()" ); - setTimeout(function() { + setTimeout( function() { callback(); start(); - }); + } ); }; ok( panels.eq( 0 ).is( ":visible" ), "first panel visible" ); element.tabs( "option", "active", 1 ); -}); +} ); } ); diff --git a/ui/widgets/tabs.js b/ui/widgets/tabs.js index 034dcc3aa..ff3a64ec8 100644 --- a/ui/widgets/tabs.js +++ b/ui/widgets/tabs.js @@ -123,6 +123,7 @@ $.widget( "ui.tabs", { locationHash = location.hash.substring( 1 ); if ( active === null ) { + // check the fragment identifier in the URL if ( locationHash ) { this.tabs.each( function( i, tab ) { @@ -193,15 +194,18 @@ $.widget( "ui.tabs", { selectedIndex = 0; break; case $.ui.keyCode.SPACE: + // Activate only, no collapsing event.preventDefault(); clearTimeout( this.activating ); this._activate( selectedIndex ); return; case $.ui.keyCode.ENTER: + // Toggle (cancel delayed activation, allow collapsing) event.preventDefault(); clearTimeout( this.activating ); + // Determine if we should collapse or activate this._activate( selectedIndex === this.options.active ? false : selectedIndex ); return; @@ -281,12 +285,14 @@ $.widget( "ui.tabs", { _setOption: function( key, value ) { if ( key === "active" ) { + // _activate() will handle invalid values and update this.options this._activate( value ); return; } if ( key === "disabled" ) { + // don't use the widget factory's disabled handling this._setupDisabled( value ); return; @@ -332,18 +338,23 @@ $.widget( "ui.tabs", { if ( options.active === false || !this.anchors.length ) { options.active = false; this.active = $(); + // was active, but active tab is gone } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { + // all remaining tabs are disabled if ( this.tabs.length === options.disabled.length ) { options.active = false; this.active = $(); + // activate previous tab } else { this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); } + // was active, active tab still exists } else { + // make sure active index is correct options.active = this.tabs.index( this.active ); } @@ -445,8 +456,10 @@ $.widget( "ui.tabs", { selector = anchor.hash; panelId = selector.substring( 1 ); panel = that.element.find( that._sanitizeSelector( selector ) ); + // remote tab } else { + // If the tab doesn't already have aria-controls, // generate an id by using a throw-away element panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id; @@ -529,6 +542,7 @@ $.widget( "ui.tabs", { } this._off( this.anchors.add( this.tabs ).add( this.panels ) ); + // Always prevent the default action, even when disabled this._on( true, this.anchors, { click: function( event ) { @@ -597,12 +611,16 @@ $.widget( "ui.tabs", { event.preventDefault(); if ( tab.hasClass( "ui-state-disabled" ) || + // tab is already loading tab.hasClass( "ui-tabs-loading" ) || + // can't switch durning an animation this.running || + // click on active header, but not collapsible ( clickedIsActive && !options.collapsible ) || + // allow canceling activation ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { return; @@ -668,6 +686,7 @@ $.widget( "ui.tabs", { "aria-selected": "false", "aria-expanded": "false" } ); + // If we're switching tabs, remove the old tab from the tab order. // If we're opening from collapsed state, remove the previous tab from the tab order. // If we're collapsing, then keep the collapsing tab in the tab order. @@ -715,6 +734,7 @@ $.widget( "ui.tabs", { }, _getIndex: function( index ) { + // meta-function to give users option to provide a href string instead of a numerical index. if ( typeof index === "string" ) { index = this.anchors.index( this.anchors.filter( "[href$='" + $.ui.escapeSelector( index ) + "']" ) ); @@ -848,6 +868,7 @@ $.widget( "ui.tabs", { this.xhr .done( function( response, status, jqXHR ) { + // support: jQuery <1.8 // http://bugs.jquery.com/ticket/11778 setTimeout( function() { @@ -858,6 +879,7 @@ $.widget( "ui.tabs", { }, 1 ); } ) .fail( function( jqXHR, status ) { + // support: jQuery <1.8 // http://bugs.jquery.com/ticket/11778 setTimeout( function() {