From 2da2ae5070e976c23ea4e19ff705dcba822838d8 Mon Sep 17 00:00:00 2001 From: kborchers Date: Fri, 1 Jun 2012 00:03:16 -0500 Subject: Menu: Properly remove submenu carat icons and menu dividers during destroy and add a test for this functionality --- tests/unit/menu/menu_methods.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tests') diff --git a/tests/unit/menu/menu_methods.js b/tests/unit/menu/menu_methods.js index c17986816..3a7b2d8fe 100644 --- a/tests/unit/menu/menu_methods.js +++ b/tests/unit/menu/menu_methods.js @@ -46,6 +46,9 @@ test("destroy", function() { domEqual("#menu1", function() { $("#menu1").menu().menu("destroy"); }); + domEqual("#menu2", function() { + $("#menu2").menu().menu("destroy"); + }); domEqual("#menu5", function() { $("#menu5").menu().menu("destroy"); }); -- cgit v1.2.3 From 47a427e5a78e0a00026f93983945f9cdb7853f5f Mon Sep 17 00:00:00 2001 From: Scott González Date: Fri, 8 Jun 2012 10:45:10 -0400 Subject: Tabs: ARIA tests. --- tests/unit/tabs/tabs_core.js | 59 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index fb3c306e6..111ee082a 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -63,8 +63,63 @@ test( "aria-controls", function() { }); test( "accessibility", function() { - // TODO: add tests - expect( 0 ); + expect( 49 ); + 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 ) { + var tab = tabs.eq( index ), + anchor = anchors.eq( index ), + anchorId = anchor.attr( "id" ), + panel = panels.eq( index ); + equal( tab.attr( "role" ), "tab", "tab " + index + " role" ); + equal( tab.attr( "aria-labelledby" ), anchorId, "tab " + index + " aria-labelledby" ); + equal( anchor.attr( "role" ), "presentation", "anchor " + index + " role" ); + 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" ); + equal( tabs.eq( 1 ).attr( "aria-disabled" ), null, "enabled tab does not have aria-disabled" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "true", "active panel has aria-expanded=true" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "false", "active panel has aria-hidden=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "tabindex" ), -1, "inactive tab has tabindex=-1" ); + equal( tabs.eq( 0 ).attr( "aria-disabled" ), null, "enabled tab does not have aria-disabled" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "inactive panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "inactive panel has aria-hidden=true" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( tabs.eq( 2 ).attr( "tabindex" ), -1, "inactive tab has tabindex=-1" ); + equal( tabs.eq( 2 ).attr( "aria-disabled" ), "true", "disabled tab has aria-disabled=true" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "inactive panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "inactive panel has aria-hidden=true" ); + + element.tabs( "option", "active", 0 ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "active tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "tabindex" ), 0, "active tab has tabindex=0" ); + equal( tabs.eq( 0 ).attr( "aria-disabled" ), null, "enabled tab does not have aria-disabled" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "active panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "active panel has aria-hidden=false" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( tabs.eq( 1 ).attr( "tabindex" ), -1, "inactive tab has tabindex=-1" ); + equal( tabs.eq( 1 ).attr( "aria-disabled" ), null, "enabled tab does not have aria-disabled" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "inactive panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "inactive panel has aria-hidden=true" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( tabs.eq( 2 ).attr( "tabindex" ), -1, "inactive tab has tabindex=-1" ); + equal( tabs.eq( 2 ).attr( "aria-disabled" ), "true", "disabled tab has aria-disabled=true" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "inactive panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "inactive panel has aria-hidden=true" ); + + // TODO: aria-live and aria-busy tests for ajax tabs }); test( "#3627 - Ajax tab with url containing a fragment identifier fails to load", function() { -- cgit v1.2.3 From 4cacb4bbcea9e2332f5ef6fd7fd6ad01d822d998 Mon Sep 17 00:00:00 2001 From: Scott González Date: Fri, 8 Jun 2012 20:58:19 -0400 Subject: Tabs: Basic keyboard support tests. --- tests/unit/tabs/tabs_core.js | 153 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) (limited to 'tests') diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index 111ee082a..55f96573e 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -122,6 +122,159 @@ test( "accessibility", function() { // TODO: aria-live and aria-busy tests for ajax tabs }); +asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", function() { + expect( 90 ); + var element = $( "#tabs1" ).tabs({ + active: 0, + collapsible: true + }), + tabs = element.find( ".ui-tabs-nav li" ), + anchors = tabs.find( ".ui-tabs-anchor" ), + panels = element.find( ".ui-tabs-panel" ), + keyCode = $.ui.keyCode; + + element.data( "tabs" ).delay = 50; + + equal( tabs.filter( ".ui-state-focus" ).length, 0, "no tabs focused on init" ); + tabs.eq( 0 ).simulate( "focus" ); + + // down, right, down (wrap), up (wrap) + function step1() { + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "first tab has focus" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.DOWN } ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "DOWN moves focus to next tab" ); + ok( !tabs.eq( 0 ).is( ".ui-state-focus" ), "first tab is no longer focused" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "true", "second tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "first tab has aria-selected=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is still hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + tabs.eq( 1 ).simulate( "keydown", { keyCode: keyCode.RIGHT } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "RIGHT moves focus to next tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "second tab has aria-selected=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.DOWN } ); + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "DOWN wraps focus to first tab" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.UP } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "UP wraps focus to last tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "first tab has aria-selected=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step2, 100 ); + } + + // left, home, space + function step2() { + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.LEFT } ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "LEFT moves focus to previous tab" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "true", "second tab has aria-selected=true" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is still hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is still visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + + tabs.eq( 1 ).simulate( "keydown", { keyCode: keyCode.HOME } ); + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "HOME moves focus to first tab" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "second tab has aria-selected=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is still hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is still visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + + // SPACE activates, cancels delay + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.SPACE } ); + setTimeout( step3, 1 ); + } + + // end, enter + function step3() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.END } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "END moves focus to last tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "first tab has aria-selected=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + // ENTER activates, cancels delay + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.ENTER } ); + setTimeout( step4, 1 ); + } + + // enter (collapse) + function step4() { + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + + // ENTER collapses if active + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.ENTER } ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + start(); + } + + setTimeout( step1, 1 ); +}); + test( "#3627 - Ajax tab with url containing a fragment identifier fails to load", function() { expect( 1 ); -- cgit v1.2.3 From e1eeed6b4f8503632ae9afb4b5e07216e7518318 Mon Sep 17 00:00:00 2001 From: Scott González Date: Fri, 8 Jun 2012 21:36:23 -0400 Subject: Tabs: CTRL navigation tests. --- tests/unit/tabs/tabs_core.js | 203 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index 55f96573e..25ee9c031 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -123,13 +123,12 @@ test( "accessibility", function() { }); asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", function() { - expect( 90 ); + expect( 92 ); var element = $( "#tabs1" ).tabs({ active: 0, collapsible: true }), tabs = element.find( ".ui-tabs-nav li" ), - anchors = tabs.find( ".ui-tabs-anchor" ), panels = element.find( ".ui-tabs-panel" ), keyCode = $.ui.keyCode; @@ -192,6 +191,7 @@ asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", // left, home, space function step2() { equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "first tab has aria-selected=false" ); ok( panels.eq( 2 ).is( ":visible" ), "third panel is visible" ); equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); @@ -229,6 +229,7 @@ asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", // end, enter function step3() { equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); @@ -269,7 +270,203 @@ asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); - start(); + setTimeout( start, 1 ); + } + + setTimeout( step1, 1 ); +}); + +asyncTest( "keyboard support - CTRL navigation", function() { + expect( 115 ); + var element = $( "#tabs1" ).tabs({ + active: 0, + collapsible: true + }), + tabs = element.find( ".ui-tabs-nav li" ), + panels = element.find( ".ui-tabs-panel" ), + keyCode = $.ui.keyCode; + + element.data( "tabs" ).delay = 50; + + equal( tabs.filter( ".ui-state-focus" ).length, 0, "no tabs focused on init" ); + tabs.eq( 0 ).simulate( "focus" ); + + // down + function step1() { + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "first tab has focus" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.DOWN, ctrlKey: true } ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "DOWN moves focus to next tab" ); + ok( !tabs.eq( 0 ).is( ".ui-state-focus" ), "first tab is no longer focused" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "second tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is still hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step2, 100 ); + } + + // right + function step2() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + + tabs.eq( 1 ).simulate( "keydown", { keyCode: keyCode.RIGHT, ctrlKey: true } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "RIGHT moves focus to next tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step3, 100 ); + } + + // down (wrap) + function step3() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.DOWN, ctrlKey: true } ); + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "DOWN wraps focus to first tab" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step4, 100 ); + } + + // up (wrap) + function step4() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.UP, ctrlKey: true } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "UP wraps focus to last tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step5, 100 ); + } + + // left + function step5() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.LEFT, ctrlKey: true } ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "LEFT moves focus to previous tab" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "second tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is still hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step6, 100 ); + } + + // home + function step6() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + + tabs.eq( 1 ).simulate( "keydown", { keyCode: keyCode.HOME, ctrlKey: true } ); + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "HOME moves focus to first tab" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "false", "second tab has aria-selected=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is still hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step7, 100 ); + } + + // end + function step7() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + tabs.eq( 0 ).simulate( "keydown", { keyCode: keyCode.END, ctrlKey: true } ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "END moves focus to last tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "false", "third tab has aria-selected=false" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is still hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is still visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + + setTimeout( step8, 100 ); + } + + // space + function step8() { + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.SPACE } ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "false", "first tab has aria-selected=false" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + + setTimeout( start, 1 ); } setTimeout( step1, 1 ); -- cgit v1.2.3 From db5f95fcdf37dbf540bb7ac88a4e2229cceda049 Mon Sep 17 00:00:00 2001 From: Scott González Date: Fri, 8 Jun 2012 22:21:14 -0400 Subject: Tabs: Panel keyboard support tests. --- tests/unit/tabs/tabs_core.js | 98 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 5 deletions(-) (limited to 'tests') diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index 25ee9c031..b69ad406c 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -125,7 +125,6 @@ test( "accessibility", function() { asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", function() { expect( 92 ); var element = $( "#tabs1" ).tabs({ - active: 0, collapsible: true }), tabs = element.find( ".ui-tabs-nav li" ), @@ -278,10 +277,7 @@ asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", asyncTest( "keyboard support - CTRL navigation", function() { expect( 115 ); - var element = $( "#tabs1" ).tabs({ - active: 0, - collapsible: true - }), + var element = $( "#tabs1" ).tabs(), tabs = element.find( ".ui-tabs-nav li" ), panels = element.find( ".ui-tabs-panel" ), keyCode = $.ui.keyCode; @@ -472,6 +468,98 @@ asyncTest( "keyboard support - CTRL navigation", function() { setTimeout( step1, 1 ); }); +asyncTest( "keyboard support - CTRL+UP, ALT+PAGE_DOWN, ALT+PAGE_UP", function() { + expect( 50 ); + var element = $( "#tabs1" ).tabs(), + tabs = element.find( ".ui-tabs-nav li" ), + panels = element.find( ".ui-tabs-panel" ), + keyCode = $.ui.keyCode; + + equal( tabs.filter( ".ui-state-focus" ).length, 0, "no tabs focused on init" ); + panels.attr( "tabindex", -1 ); + panels.eq( 0 ).simulate( "focus" ); + + function step1() { + strictEqual( document.activeElement, panels[ 0 ], "first panel is activeElement" ); + + panels.eq( 0 ).simulate( "keydown", { keyCode: keyCode.PAGE_DOWN, altKey: true } ); + strictEqual( document.activeElement, tabs[ 1 ], "second tab is activeElement" ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "ALT+PAGE_DOWN moves focus to next tab" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "true", "second tab has aria-selected=true" ); + ok( panels.eq( 1 ).is( ":visible" ), "second panel is visible" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "true", "second panel has aria-expanded=true" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "false", "second panel has aria-hidden=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + + tabs.eq( 1 ).simulate( "keydown", { keyCode: keyCode.PAGE_DOWN, altKey: true } ); + strictEqual( document.activeElement, tabs[ 2 ], "third tab is activeElement" ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "ALT+PAGE_DOWN moves focus to next tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + ok( panels.eq( 1 ).is( ":hidden" ), "second panel is hidden" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "false", "second panel has aria-expanded=false" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "true", "second panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.PAGE_DOWN, altKey: true } ); + strictEqual( document.activeElement, tabs[ 0 ], "first tab is activeElement" ); + ok( tabs.eq( 0 ).is( ".ui-state-focus" ), "ALT+PAGE_DOWN wraps focus to first tab" ); + equal( tabs.eq( 0 ).attr( "aria-selected" ), "true", "first tab has aria-selected=true" ); + ok( panels.eq( 0 ).is( ":visible" ), "first panel is visible" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "true", "first panel has aria-expanded=true" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "false", "first panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + panels.eq( 0 ).simulate( "focus" ); + setTimeout( step2, 1 ); + } + + function step2() { + strictEqual( document.activeElement, panels[ 0 ], "first panel is activeElement" ); + + panels.eq( 0 ).simulate( "keydown", { keyCode: keyCode.PAGE_UP, altKey: true } ); + strictEqual( document.activeElement, tabs[ 2 ], "third tab is activeElement" ); + ok( tabs.eq( 2 ).is( ".ui-state-focus" ), "ALT+PAGE_UP wraps focus to last tab" ); + equal( tabs.eq( 2 ).attr( "aria-selected" ), "true", "third tab has aria-selected=true" ); + ok( panels.eq( 2 ).is( ":visible" ), "third panel is visible" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "true", "third panel has aria-expanded=true" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "false", "third panel has aria-hidden=false" ); + ok( panels.eq( 0 ).is( ":hidden" ), "first panel is hidden" ); + equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); + equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); + + tabs.eq( 2 ).simulate( "keydown", { keyCode: keyCode.PAGE_UP, altKey: true } ); + strictEqual( document.activeElement, tabs[ 1 ], "second tab is activeElement" ); + ok( tabs.eq( 1 ).is( ".ui-state-focus" ), "ALT+PAGE_UP moves focus to previous tab" ); + equal( tabs.eq( 1 ).attr( "aria-selected" ), "true", "second tab has aria-selected=true" ); + ok( panels.eq( 1 ).is( ":visible" ), "second panel is visible" ); + equal( panels.eq( 1 ).attr( "aria-expanded" ), "true", "second panel has aria-expanded=true" ); + equal( panels.eq( 1 ).attr( "aria-hidden" ), "false", "second panel has aria-hidden=false" ); + ok( panels.eq( 2 ).is( ":hidden" ), "third panel is hidden" ); + equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); + equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); + + panels.eq( 1 ).simulate( "focus" ); + setTimeout( step3, 1 ); + } + + function step3() { + strictEqual( document.activeElement, panels[ 1 ], "second panel is activeElement" ); + + panels.eq( 1 ).simulate( "keydown", { keyCode: keyCode.UP, ctrlKey: true } ); + strictEqual( document.activeElement, tabs[ 1 ], "second tab is activeElement" ); + + setTimeout( start, 1 ); + } + + setTimeout( step1, 1 ); +}); + test( "#3627 - Ajax tab with url containing a fragment identifier fails to load", function() { expect( 1 ); -- cgit v1.2.3 From aa1e8b5e6ce0b5012deb98dd30a93c89491dfa3f Mon Sep 17 00:00:00 2001 From: Scott González Date: Sat, 9 Jun 2012 20:12:03 -0400 Subject: Tests: Check .data() and event bindings in domEqual(). --- tests/unit/testsuite.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tests') diff --git a/tests/unit/testsuite.js b/tests/unit/testsuite.js index 3c8ec04c4..59bda7df8 100644 --- a/tests/unit/testsuite.js +++ b/tests/unit/testsuite.js @@ -188,6 +188,9 @@ window.domEqual = function( selector, modifier, message ) { var value = elem.attr( attr ); result[ attr ] = value !== undefined ? value : ""; }); + result.events = $._data( elem[ 0 ], "events" ); + result.data = $.extend( {}, elem.data() ); + delete result.data[ $.expando ]; children = elem.children(); if ( children.length ) { result.children = elem.children().map(function( ind ) { -- cgit v1.2.3 From 8c82edb40ca946f160089191d5bbe564159c7593 Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 11 Jun 2012 16:21:12 -0400 Subject: Tabs tests: Don't call start directly from setTimeout because Firefox <13 is dumb. --- tests/unit/tabs/tabs_core.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/unit/tabs/tabs_core.js b/tests/unit/tabs/tabs_core.js index b69ad406c..fd9cc7d63 100644 --- a/tests/unit/tabs/tabs_core.js +++ b/tests/unit/tabs/tabs_core.js @@ -269,7 +269,11 @@ asyncTest( "keyboard support - LEFT, RIGHT, UP, DOWN, HOME, END, SPACE, ENTER", equal( panels.eq( 2 ).attr( "aria-expanded" ), "false", "third panel has aria-expanded=false" ); equal( panels.eq( 2 ).attr( "aria-hidden" ), "true", "third panel has aria-hidden=true" ); - setTimeout( start, 1 ); + // support: Firefox 12 + // Firefox <13 passes arguments so we can't use setTimeout( start, 1 ) + setTimeout(function() { + start(); + }, 1 ); } setTimeout( step1, 1 ); @@ -462,7 +466,11 @@ asyncTest( "keyboard support - CTRL navigation", function() { equal( panels.eq( 0 ).attr( "aria-expanded" ), "false", "first panel has aria-expanded=false" ); equal( panels.eq( 0 ).attr( "aria-hidden" ), "true", "first panel has aria-hidden=true" ); - setTimeout( start, 1 ); + // support: Firefox 12 + // Firefox <13 passes arguments so we can't use setTimeout( start, 1 ) + setTimeout(function() { + start(); + }, 1 ); } setTimeout( step1, 1 ); @@ -554,7 +562,11 @@ asyncTest( "keyboard support - CTRL+UP, ALT+PAGE_DOWN, ALT+PAGE_UP", function() panels.eq( 1 ).simulate( "keydown", { keyCode: keyCode.UP, ctrlKey: true } ); strictEqual( document.activeElement, tabs[ 1 ], "second tab is activeElement" ); - setTimeout( start, 1 ); + // support: Firefox 12 + // Firefox <13 passes arguments so we can't use setTimeout( start, 1 ) + setTimeout(function() { + start(); + }, 1 ); } setTimeout( step1, 1 ); -- cgit v1.2.3 From f1031b3f3a94698f62074c00b43a5ac36bb80a8c Mon Sep 17 00:00:00 2001 From: Scott González Date: Mon, 11 Jun 2012 17:24:27 -0400 Subject: Accordion tests: Fixed typos. --- tests/unit/accordion/accordion_core.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'tests') diff --git a/tests/unit/accordion/accordion_core.js b/tests/unit/accordion/accordion_core.js index 7a1d56c18..101cb83b1 100644 --- a/tests/unit/accordion/accordion_core.js +++ b/tests/unit/accordion/accordion_core.js @@ -48,31 +48,31 @@ test( "accessibility", function () { equal( headers.eq( 1 ).attr( "aria-selected" ), "true", "active tab has aria-selected=true" ); equal( headers.eq( 1 ).next().attr( "aria-expanded" ), "true", "active tabpanel has aria-expanded=true" ); equal( headers.eq( 1 ).next().attr( "aria-hidden" ), "false", "active tabpanel has aria-hidden=false" ); - equal( headers.eq( 0 ).attr( "tabindex" ), -1, "active header has tabindex=-1" ); - equal( headers.eq( 0 ).attr( "aria-selected" ), "false", "active tab has aria-selected=false" ); - equal( headers.eq( 0 ).next().attr( "aria-expanded" ), "false", "active tabpanel has aria-expanded=false" ); - equal( headers.eq( 0 ).next().attr( "aria-hidden" ), "true", "active tabpanel has aria-hidden=true" ); - equal( headers.eq( 2 ).attr( "tabindex" ), -1, "active header has tabindex=-1" ); - equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "active tab has aria-selected=false" ); - equal( headers.eq( 2 ).next().attr( "aria-expanded" ), "false", "active tabpanel has aria-expanded=false" ); - equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "active tabpanel has aria-hidden=true" ); + equal( headers.eq( 0 ).attr( "tabindex" ), -1, "inactive header has tabindex=-1" ); + equal( headers.eq( 0 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( headers.eq( 0 ).next().attr( "aria-expanded" ), "false", "inactive tabpanel has aria-expanded=false" ); + equal( headers.eq( 0 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel has aria-hidden=true" ); + equal( headers.eq( 2 ).attr( "tabindex" ), -1, "inactive header has tabindex=-1" ); + equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( headers.eq( 2 ).next().attr( "aria-expanded" ), "false", "inactive tabpanel has aria-expanded=false" ); + equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel has aria-hidden=true" ); element.accordion( "option", "active", 0 ); equal( headers.eq( 0 ).attr( "tabindex" ), 0, "active header has tabindex=0" ); equal( headers.eq( 0 ).attr( "aria-selected" ), "true", "active tab has aria-selected=true" ); equal( headers.eq( 0 ).next().attr( "aria-expanded" ), "true", "active tabpanel has aria-expanded=true" ); equal( headers.eq( 0 ).next().attr( "aria-hidden" ), "false", "active tabpanel has aria-hidden=false" ); - equal( headers.eq( 1 ).attr( "tabindex" ), -1, "active header has tabindex=-1" ); - equal( headers.eq( 1 ).attr( "aria-selected" ), "false", "active tab has aria-selected=false" ); - equal( headers.eq( 1 ).next().attr( "aria-expanded" ), "false", "active tabpanel has aria-expanded=false" ); - equal( headers.eq( 1 ).next().attr( "aria-hidden" ), "true", "active tabpanel has aria-hidden=true" ); - equal( headers.eq( 2 ).attr( "tabindex" ), -1, "active header has tabindex=-1" ); - equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "active tab has aria-selected=false" ); - equal( headers.eq( 2 ).next().attr( "aria-expanded" ), "false", "active tabpanel has aria-expanded=false" ); - equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "active tabpanel has aria-hidden=true" ); + equal( headers.eq( 1 ).attr( "tabindex" ), -1, "inactive header has tabindex=-1" ); + equal( headers.eq( 1 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( headers.eq( 1 ).next().attr( "aria-expanded" ), "false", "inactive tabpanel has aria-expanded=false" ); + equal( headers.eq( 1 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel has aria-hidden=true" ); + equal( headers.eq( 2 ).attr( "tabindex" ), -1, "inactive header has tabindex=-1" ); + equal( headers.eq( 2 ).attr( "aria-selected" ), "false", "inactive tab has aria-selected=false" ); + equal( headers.eq( 2 ).next().attr( "aria-expanded" ), "false", "inactive tabpanel has aria-expanded=false" ); + equal( headers.eq( 2 ).next().attr( "aria-hidden" ), "true", "inactive tabpanel has aria-hidden=true" ); }); -asyncTest( "keybaord support", function() { +asyncTest( "keyboard support", function() { expect( 13 ); var element = $( "#list1" ).accordion(), headers = element.find( ".ui-accordion-header" ), -- cgit v1.2.3 From 9ebeb0616a5ca556e507aecbe360f5dcec238737 Mon Sep 17 00:00:00 2001 From: Scott González Date: Tue, 12 Jun 2012 10:07:16 -0400 Subject: Tabs: Walk previous tabs (and loop) in refresh() in case the tab we're trying to activate is disabled. --- tests/unit/tabs/tabs_methods.js | 20 ++++++++++++++++++++ ui/jquery.ui.tabs.js | 16 +++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/unit/tabs/tabs_methods.js b/tests/unit/tabs/tabs_methods.js index ed3e73745..e48d353e7 100644 --- a/tests/unit/tabs/tabs_methods.js +++ b/tests/unit/tabs/tabs_methods.js @@ -148,6 +148,26 @@ test( "refresh", function() { disabled( element, false ); }); +test( "refresh - looping", function() { + expect( 6 ); + + var element = $( "#tabs1" ).tabs({ + disabled: [ 0 ], + active: 1 + }); + state( element, 0, 1, 0 ); + disabled( element, [ 0 ] ); + + // remove active, jump to previous + // previous is disabled, just back one more + // reached first tab, move to end + // activate last tab + element.find( ".ui-tabs-nav li" ).eq( 2 ).remove(); + element.tabs( "refresh" ); + state( element, 0, 1 ); + disabled( element, [ 0 ] ); +}); + asyncTest( "load", function() { expect( 30 ); diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 8c7bd207b..e71b2a244 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -229,7 +229,7 @@ $.widget( "ui.tabs", { } }, - _focusNextTab: function( index, goingForward ) { + _findNextTab: function( index, goingForward ) { var lastTabIndex = this.tabs.length - 1; function constrain() { @@ -246,6 +246,11 @@ $.widget( "ui.tabs", { index = goingForward ? index + 1 : index - 1; } + return index; + }, + + _focusNextTab: function( index, goingForward ) { + index = this._findNextTab( index, goingForward ); this.tabs.eq( index ).focus(); return index; }, @@ -309,9 +314,14 @@ $.widget( "ui.tabs", { 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 - next = options.active - 1; - this._activate( next >= 0 ? next : 0 ); + } 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 -- cgit v1.2.3 From 9608e981498846b3727cc4dad723a7fa7252fd86 Mon Sep 17 00:00:00 2001 From: Scott González Date: Wed, 13 Jun 2012 08:00:45 -0400 Subject: Widget: Rename _bind() to _on(). Partial fix for #7795 - Widget: _on and _off. --- demos/widget/default.html | 6 +++--- tests/unit/widget/widget_core.js | 14 +++++++------- ui/jquery.ui.accordion.js | 6 +++--- ui/jquery.ui.autocomplete.js | 6 +++--- ui/jquery.ui.menu.js | 7 +++---- ui/jquery.ui.slider.js | 2 +- ui/jquery.ui.spinner.js | 4 ++-- ui/jquery.ui.tabs.js | 8 ++++---- ui/jquery.ui.tooltip.js | 4 ++-- ui/jquery.ui.widget.js | 10 +++++----- 10 files changed, 33 insertions(+), 34 deletions(-) (limited to 'tests') diff --git a/demos/widget/default.html b/demos/widget/default.html index f39825034..8d08256ce 100644 --- a/demos/widget/default.html +++ b/demos/widget/default.html @@ -56,8 +56,8 @@ .button(); // bind click events on the changer button to the random method - this._bind( this.changer, { - // _bind won't call random when widget is disabled + this._on( this.changer, { + // _on won't call random when widget is disabled click: "random" }); this._refresh(); @@ -90,7 +90,7 @@ } }, - // events bound via _bind are removed automatically + // events bound via _on are removed automatically // revert other modifications here _destroy: function() { // remove generated elements diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index aa70e2425..3dfaf1918 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -610,13 +610,13 @@ test( ".widget() - overriden", function() { deepEqual( wrapper[0], $( "
" ).testWidget().testWidget( "widget" )[0] ); }); -test( "._bind() to element (default)", function() { +test( "._on() to element (default)", function() { expect( 12 ); var that, widget; $.widget( "ui.testWidget", { _create: function() { that = this; - this._bind({ + this._on({ keyup: this.keyup, keydown: "keydown" }); @@ -650,13 +650,13 @@ test( "._bind() to element (default)", function() { .trigger( "keydown" ); }); -test( "._bind() to descendent", function() { +test( "._on() to descendent", function() { expect( 12 ); var that, widget, descendant; $.widget( "ui.testWidget", { _create: function() { that = this; - this._bind( this.element.find( "strong" ), { + this._on( this.element.find( "strong" ), { keyup: this.keyup, keydown: "keydown" }); @@ -707,7 +707,7 @@ test( "._bind() to descendent", function() { .trigger( "keydown" ); }); -test( "_bind() with delegate", function() { +test( "_on() with delegate", function() { expect( 8 ); $.widget( "ui.testWidget", { _create: function() { @@ -727,7 +727,7 @@ test( "_bind() with delegate", function() { } }; }; - this._bind({ + this._on({ "click": "handler", "click a": "handler" }); @@ -740,7 +740,7 @@ test( "_bind() with delegate", function() { } }; }; - this._bind({ + this._on({ "change form fieldset > input": "handler" }); } diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index 856b3ba4b..4cfc265a3 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -137,8 +137,8 @@ $.widget( "ui.accordion", { }); } - this._bind( this.headers, { keydown: "_keydown" }); - this._bind( this.headers.next(), { keydown: "_panelKeyDown" }); + this._on( this.headers, { keydown: "_keydown" }); + this._on( this.headers.next(), { keydown: "_panelKeyDown" }); this._setupEvents( options.event ); }, @@ -376,7 +376,7 @@ $.widget( "ui.accordion", { $.each( event.split(" "), function( index, eventName ) { events[ eventName ] = "_eventHandler"; }); - this._bind( this.headers, events ); + this._on( this.headers, events ); }, _eventHandler: function( event ) { diff --git a/ui/jquery.ui.autocomplete.js b/ui/jquery.ui.autocomplete.js index 2fb7e395c..f73fff96d 100644 --- a/ui/jquery.ui.autocomplete.js +++ b/ui/jquery.ui.autocomplete.js @@ -63,7 +63,7 @@ $.widget( "ui.autocomplete", { .addClass( "ui-autocomplete-input" ) .attr( "autocomplete", "off" ); - this._bind({ + this._on({ keydown: function( event ) { if ( this.element.prop( "readOnly" ) ) { suppressKeyPress = true; @@ -190,7 +190,7 @@ $.widget( "ui.autocomplete", { .zIndex( this.element.zIndex() + 1 ) .hide() .data( "menu" ); - this._bind( this.menu.element, { + this._on( this.menu.element, { mousedown: function( event ) { // prevent moving focus out of the text field event.preventDefault(); @@ -297,7 +297,7 @@ $.widget( "ui.autocomplete", { // turning off autocomplete prevents the browser from remembering the // value when navigating through history, so we re-enable autocomplete // if the page is unloaded before the widget is destroyed. #7790 - this._bind( this.window, { + this._on( this.window, { beforeunload: function() { this.element.removeAttr( "autocomplete" ); } diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 986cca168..eb0be494c 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -43,7 +43,7 @@ $.widget( "ui.menu", { tabIndex: 0 }) // need to catch all clicks on disabled menu - // not possible through _bind + // not possible through _on .bind( "click.menu", $.proxy(function( event ) { if ( this.options.disabled ) { event.preventDefault(); @@ -56,7 +56,7 @@ $.widget( "ui.menu", { .attr( "aria-disabled", "true" ); } - this._bind({ + this._on({ // Prevent focus from sticking to links inside menu after clicking // them (focus should always stay on UL during navigation). "mousedown .ui-menu-item > a": function( event ) { @@ -122,8 +122,7 @@ $.widget( "ui.menu", { this.refresh(); // TODO: We probably shouldn't bind to document for each menu. - // TODO: This isn't being cleaned up on destroy. - this._bind( this.document, { + this._on( this.document, { click: function( event ) { if ( !$( event.target ).closest( ".ui-menu" ).length ) { this.collapseAll( event ); diff --git a/ui/jquery.ui.slider.js b/ui/jquery.ui.slider.js index c302bfe8b..e44d20f7c 100644 --- a/ui/jquery.ui.slider.js +++ b/ui/jquery.ui.slider.js @@ -114,7 +114,7 @@ $.widget( "ui.slider", $.ui.mouse, { $( this ).data( "ui-slider-handle-index", i ); }); - this._bind( this.handles, { + this._on( this.handles, { keydown: function( event ) { var allowed, curVal, newVal, step, index = $( event.target ).data( "ui-slider-handle-index" ); diff --git a/ui/jquery.ui.spinner.js b/ui/jquery.ui.spinner.js index b01feec9a..d6ebc6d87 100644 --- a/ui/jquery.ui.spinner.js +++ b/ui/jquery.ui.spinner.js @@ -54,13 +54,13 @@ $.widget( "ui.spinner", { this._value( this.element.val(), true ); this._draw(); - this._bind( this._events ); + this._on( this._events ); this._refresh(); // turning off autocomplete prevents the browser from remembering the // value when navigating through history, so we re-enable autocomplete // if the page is unloaded before the widget is destroyed. #7790 - this._bind( this.window, { + this._on( this.window, { beforeunload: function() { this.element.removeAttr( "autocomplete" ); } diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index f3b27cf9d..5878a56a1 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -481,9 +481,9 @@ $.widget( "ui.tabs", { } this.anchors.add( this.tabs ).add( this.panels ).unbind( ".tabs" ); - this._bind( this.anchors, events ); - this._bind( this.tabs, { keydown: "_tabKeydown" } ); - this._bind( this.panels, { keydown: "_panelKeydown" } ); + this._on( this.anchors, events ); + this._on( this.tabs, { keydown: "_tabKeydown" } ); + this._on( this.panels, { keydown: "_panelKeydown" } ); this._focusable( this.tabs ); this._hoverable( this.tabs ); @@ -943,7 +943,7 @@ if ( $.uiBackCompat !== false ) { }, _create: function() { this._super(); - this._bind({ + this._on({ tabsbeforeload: function( event, ui ) { if ( !this.options.spinner ) { return; diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 752c95687..6a7aab706 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -61,7 +61,7 @@ $.widget( "ui.tooltip", { }, _create: function() { - this._bind({ + this._on({ mouseover: "open", focusin: "open" }); @@ -185,7 +185,7 @@ $.widget( "ui.tooltip", { this._trigger( "open", event, { tooltip: tooltip } ); - this._bind( target, { + this._on( target, { mouseleave: "close", focusout: "close", keyup: function( event ) { diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index e317d3841..410b7003a 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -224,7 +224,7 @@ $.Widget.prototype = { // TODO remove dual storage $.data( element, this.widgetName, this ); $.data( element, this.widgetFullName, this ); - this._bind({ remove: "destroy" }); + this._on({ remove: "destroy" }); this.document = $( element.style ? // element within the document element.ownerDocument : @@ -245,7 +245,7 @@ $.Widget.prototype = { destroy: function() { this._destroy(); // we can probably remove the unbind calls in 2.0 - // all event bindings should go through this._bind() + // all event bindings should go through this._on() this.element .unbind( "." + this.widgetName ) // 1.9 BC for #7810 @@ -342,7 +342,7 @@ $.Widget.prototype = { return this._setOption( "disabled", true ); }, - _bind: function( element, handlers ) { + _on: function( element, handlers ) { // no element argument, shuffle and use this.element if ( !handlers ) { handlers = element; @@ -395,7 +395,7 @@ $.Widget.prototype = { _hoverable: function( element ) { this.hoverable = this.hoverable.add( element ); - this._bind( element, { + this._on( element, { mouseenter: function( event ) { $( event.currentTarget ).addClass( "ui-state-hover" ); }, @@ -407,7 +407,7 @@ $.Widget.prototype = { _focusable: function( element ) { this.focusable = this.focusable.add( element ); - this._bind( element, { + this._on( element, { focusin: function( event ) { $( event.currentTarget ).addClass( "ui-state-focus" ); }, -- cgit v1.2.3 From 386bb7214b0d52a9e88c3c2158b4b9894dca6b1c Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Wed, 13 Jun 2012 23:06:34 +0200 Subject: Spinner: Fix ghost log call in events unit test, never shows up in browser for some reason --- tests/unit/spinner/spinner_events.js | 1 + 1 file changed, 1 insertion(+) (limited to 'tests') diff --git a/tests/unit/spinner/spinner_events.js b/tests/unit/spinner/spinner_events.js index 72b185528..64f510de0 100644 --- a/tests/unit/spinner/spinner_events.js +++ b/tests/unit/spinner/spinner_events.js @@ -220,6 +220,7 @@ asyncTest( "change", function() { shouldChange( false, "min, value not changed" ); element.spinner( "option", "min", 200 ); + shouldChange( true, "cleanup" ); start(); }); }); -- cgit v1.2.3 From 28b14ec47cfeb3c58e44f35170cdd8a9270aceae Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Sun, 10 Jun 2012 20:55:04 +0200 Subject: Generate a uuid for each widget for unique namespaces. Fixes #8385 - Widget: _bind() on elements such as document are dangerous --- tests/unit/widget/widget_core.js | 25 ++++++++++++++++++++++--- ui/jquery.ui.widget.js | 12 +++++++----- 2 files changed, 29 insertions(+), 8 deletions(-) (limited to 'tests') diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 3dfaf1918..1e40c4080 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -711,9 +711,10 @@ test( "_on() with delegate", function() { expect( 8 ); $.widget( "ui.testWidget", { _create: function() { + var uuid = this.uuid; this.element = { bind: function( event, handler ) { - equal( event, "click.testWidget" ); + equal( event, "click.testWidget" + uuid ); ok( $.isFunction(handler) ); }, trigger: $.noop @@ -722,7 +723,7 @@ test( "_on() with delegate", function() { return { delegate: function( selector, event, handler ) { equal( selector, "a" ); - equal( event, "click.testWidget" ); + equal( event, "click.testWidget" + uuid ); ok( $.isFunction(handler) ); } }; @@ -735,7 +736,7 @@ test( "_on() with delegate", function() { return { delegate: function( selector, event, handler ) { equal( selector, "form fieldset > input" ); - equal( event, "change.testWidget" ); + equal( event, "change.testWidget" + uuid ); ok( $.isFunction(handler) ); } }; @@ -748,6 +749,24 @@ test( "_on() with delegate", function() { $.ui.testWidget(); }); +test( "_bind() to common element", function() { + expect( 1 ); + $.widget( "ui.testWidget", { + _create: function() { + this._bind( this.document, { + "customevent": "_handler" + }); + }, + _handler: function() { + ok( true, "handler triggered" ); + } + }); + var widget = $( "#widget" ).testWidget().data( "testWidget" ); + $( "#widget-wrapper" ).testWidget(); + widget.destroy(); + $( document ).trigger( "customevent" ); +}); + test( "._hoverable()", function() { $.widget( "ui.testWidget", { _create: function() { diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 410b7003a..d5e68683e 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -9,7 +9,8 @@ */ (function( $, undefined ) { -var slice = Array.prototype.slice, +var uuid = 0, + slice = Array.prototype.slice, _cleanData = $.cleanData; $.cleanData = function( elems ) { for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { @@ -214,6 +215,7 @@ $.Widget.prototype = { this.options, this._getCreateOptions(), options ); + this.uuid = uuid++; this.bindings = $(); this.hoverable = $(); @@ -247,7 +249,7 @@ $.Widget.prototype = { // we can probably remove the unbind calls in 2.0 // all event bindings should go through this._on() this.element - .unbind( "." + this.widgetName ) + .unbind( "." + this.widgetName + this.uuid ) // 1.9 BC for #7810 // TODO remove dual storage .removeData( this.widgetName ) @@ -256,14 +258,14 @@ $.Widget.prototype = { // http://bugs.jquery.com/ticket/9413 .removeData( $.camelCase( this.widgetFullName ) ); this.widget() - .unbind( "." + this.widgetName ) + .unbind( "." + this.widgetName + this.uuid ) .removeAttr( "aria-disabled" ) .removeClass( this.widgetFullName + "-disabled " + "ui-state-disabled" ); // clean up events and states - this.bindings.unbind( "." + this.widgetName ); + this.bindings.unbind( "." + this.widgetName + this.uuid ); this.hoverable.removeClass( "ui-state-hover" ); this.focusable.removeClass( "ui-state-focus" ); }, @@ -374,7 +376,7 @@ $.Widget.prototype = { } var match = event.match( /^(\w+)\s*(.*)$/ ), - eventName = match[1] + "." + instance.widgetName, + eventName = match[1] + "." + instance.widgetName + instance.uuid, selector = match[2]; if ( selector ) { instance.widget().delegate( selector, eventName, handlerProxy ); -- cgit v1.2.3 From 00d4beb0ca4a99933bb7e786a1dd50618c180a0b Mon Sep 17 00:00:00 2001 From: Scott González Date: Thu, 14 Jun 2012 10:51:29 -0400 Subject: Widget: Create eventNamespace property instead of constantly rebuilding it. --- tests/unit/widget/widget_core.js | 4 ++-- ui/jquery.ui.widget.js | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'tests') diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 1e40c4080..24ae9c567 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -749,11 +749,11 @@ test( "_on() with delegate", function() { $.ui.testWidget(); }); -test( "_bind() to common element", function() { +test( "_on() to common element", function() { expect( 1 ); $.widget( "ui.testWidget", { _create: function() { - this._bind( this.document, { + this._on( this.document, { "customevent": "_handler" }); }, diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index d5e68683e..22049cbb8 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -211,11 +211,12 @@ $.Widget.prototype = { _createWidget: function( options, element ) { element = $( element || this.defaultElement || this )[ 0 ]; this.element = $( element ); + this.uuid = uuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; this.options = $.widget.extend( {}, this.options, this._getCreateOptions(), options ); - this.uuid = uuid++; this.bindings = $(); this.hoverable = $(); @@ -249,7 +250,7 @@ $.Widget.prototype = { // we can probably remove the unbind calls in 2.0 // all event bindings should go through this._on() this.element - .unbind( "." + this.widgetName + this.uuid ) + .unbind( this.eventNamespace ) // 1.9 BC for #7810 // TODO remove dual storage .removeData( this.widgetName ) @@ -258,14 +259,14 @@ $.Widget.prototype = { // http://bugs.jquery.com/ticket/9413 .removeData( $.camelCase( this.widgetFullName ) ); this.widget() - .unbind( "." + this.widgetName + this.uuid ) + .unbind( this.eventNamespace ) .removeAttr( "aria-disabled" ) .removeClass( this.widgetFullName + "-disabled " + "ui-state-disabled" ); // clean up events and states - this.bindings.unbind( "." + this.widgetName + this.uuid ); + this.bindings.unbind( this.eventNamespace ); this.hoverable.removeClass( "ui-state-hover" ); this.focusable.removeClass( "ui-state-focus" ); }, @@ -376,7 +377,7 @@ $.Widget.prototype = { } var match = event.match( /^(\w+)\s*(.*)$/ ), - eventName = match[1] + "." + instance.widgetName + instance.uuid, + eventName = match[1] + instance.eventNamespace, selector = match[2]; if ( selector ) { instance.widget().delegate( selector, eventName, handlerProxy ); -- cgit v1.2.3 From ff39bed57a05ca060033187b8aecebafab357f78 Mon Sep 17 00:00:00 2001 From: Scott González Date: Thu, 14 Jun 2012 12:33:16 -0400 Subject: Widget: Added _off() for removing event handlers. Fixes #7795 - Widget: _on and _off. --- tests/unit/widget/widget_core.js | 77 ++++++++++++++++++++++++++++++++++++++++ ui/jquery.ui.accordion.js | 3 +- ui/jquery.ui.button.js | 32 ++++++++--------- ui/jquery.ui.dialog.js | 6 ++-- ui/jquery.ui.menu.js | 4 +-- ui/jquery.ui.tabs.js | 6 ++-- ui/jquery.ui.tooltip.js | 2 +- ui/jquery.ui.widget.js | 5 +++ 8 files changed, 108 insertions(+), 27 deletions(-) (limited to 'tests') diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 24ae9c567..abfb0d9de 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -767,6 +767,83 @@ test( "_on() to common element", function() { $( document ).trigger( "customevent" ); }); +test( "_off() - single event", function() { + expect( 3 ); + + $.widget( "ui.testWidget", {} ); + var shouldTriggerWidget, shouldTriggerOther, + element = $( "#widget" ), + widget = element.testWidget().data( "testWidget" ); + widget._on( element, { foo: function() { + ok( shouldTriggerWidget, "foo called from _on" ); + }}); + element.bind( "foo", function() { + ok( shouldTriggerOther, "foo called from bind" ); + }); + shouldTriggerWidget = true; + shouldTriggerOther = true; + element.trigger( "foo" ); + shouldTriggerWidget = false; + widget._off( element, "foo" ); + element.trigger( "foo" ); +}); + +test( "_off() - multiple events", function() { + expect( 6 ); + + $.widget( "ui.testWidget", {} ); + var shouldTriggerWidget, shouldTriggerOther, + element = $( "#widget" ), + widget = element.testWidget().data( "testWidget" ); + widget._on( element, { + foo: function() { + ok( shouldTriggerWidget, "foo called from _on" ); + }, + bar: function() { + ok( shouldTriggerWidget, "bar called from _on" ); + } + }); + element.bind( "foo bar", function( event ) { + ok( shouldTriggerOther, event.type + " called from bind" ); + }); + shouldTriggerWidget = true; + shouldTriggerOther = true; + element.trigger( "foo" ); + element.trigger( "bar" ); + shouldTriggerWidget = false; + widget._off( element, "foo bar" ); + element.trigger( "foo" ); + element.trigger( "bar" ); +}); + +test( "_off() - all events", function() { + expect( 6 ); + + $.widget( "ui.testWidget", {} ); + var shouldTriggerWidget, shouldTriggerOther, + element = $( "#widget" ), + widget = element.testWidget().data( "testWidget" ); + widget._on( element, { + foo: function() { + ok( shouldTriggerWidget, "foo called from _on" ); + }, + bar: function() { + ok( shouldTriggerWidget, "bar called from _on" ); + } + }); + element.bind( "foo bar", function( event ) { + ok( shouldTriggerOther, event.type + " called from bind" ); + }); + shouldTriggerWidget = true; + shouldTriggerOther = true; + element.trigger( "foo" ); + element.trigger( "bar" ); + shouldTriggerWidget = false; + widget._off( element ); + element.trigger( "foo" ); + element.trigger( "bar" ); +}); + test( "._hoverable()", function() { $.widget( "ui.testWidget", { _create: function() { diff --git a/ui/jquery.ui.accordion.js b/ui/jquery.ui.accordion.js index 4cfc265a3..e8a10b746 100644 --- a/ui/jquery.ui.accordion.js +++ b/ui/jquery.ui.accordion.js @@ -219,8 +219,7 @@ $.widget( "ui.accordion", { if ( key === "event" ) { if ( this.options.event ) { - this.headers.unbind( - this.options.event.split( " " ).join( ".accordion " ) + ".accordion" ); + this._off( this.headers, this.options.event ); } this._setupEvents( value ); } diff --git a/ui/jquery.ui.button.js b/ui/jquery.ui.button.js index 810191775..0c72e9c4b 100644 --- a/ui/jquery.ui.button.js +++ b/ui/jquery.ui.button.js @@ -54,8 +54,8 @@ $.widget( "ui.button", { }, _create: function() { this.element.closest( "form" ) - .unbind( "reset.button" ) - .bind( "reset.button", formResetHandler ); + .unbind( "reset" + this.eventNamespace ) + .bind( "reset" + this.eventNamespace, formResetHandler ); if ( typeof this.options.disabled !== "boolean" ) { this.options.disabled = !!this.element.prop( "disabled" ); @@ -79,7 +79,7 @@ $.widget( "ui.button", { this.buttonElement .addClass( baseClasses ) .attr( "role", "button" ) - .bind( "mouseenter.button", function() { + .bind( "mouseenter" + this.eventNamespace, function() { if ( options.disabled ) { return; } @@ -88,13 +88,13 @@ $.widget( "ui.button", { $( this ).addClass( "ui-state-active" ); } }) - .bind( "mouseleave.button", function() { + .bind( "mouseleave" + this.eventNamespace, function() { if ( options.disabled ) { return; } $( this ).removeClass( hoverClass ); }) - .bind( "click.button", function( event ) { + .bind( "click" + this.eventNamespace, function( event ) { if ( options.disabled ) { event.preventDefault(); event.stopImmediatePropagation(); @@ -102,16 +102,16 @@ $.widget( "ui.button", { }); this.element - .bind( "focus.button", function() { + .bind( "focus" + this.eventNamespace, function() { // no need to check disabled, focus won't be triggered anyway that.buttonElement.addClass( focusClass ); }) - .bind( "blur.button", function() { + .bind( "blur" + this.eventNamespace, function() { that.buttonElement.removeClass( focusClass ); }); if ( toggleButton ) { - this.element.bind( "change.button", function() { + this.element.bind( "change" + this.eventNamespace, function() { if ( clickDragged ) { return; } @@ -121,7 +121,7 @@ $.widget( "ui.button", { // prevents issue where button state changes but checkbox/radio checked state // does not in Firefox (see ticket #6970) this.buttonElement - .bind( "mousedown.button", function( event ) { + .bind( "mousedown" + this.eventNamespace, function( event ) { if ( options.disabled ) { return; } @@ -129,7 +129,7 @@ $.widget( "ui.button", { startXPos = event.pageX; startYPos = event.pageY; }) - .bind( "mouseup.button", function( event ) { + .bind( "mouseup" + this.eventNamespace, function( event ) { if ( options.disabled ) { return; } @@ -140,7 +140,7 @@ $.widget( "ui.button", { } if ( this.type === "checkbox" ) { - this.buttonElement.bind( "click.button", function() { + this.buttonElement.bind( "click" + this.eventNamespace, function() { if ( options.disabled || clickDragged ) { return false; } @@ -148,7 +148,7 @@ $.widget( "ui.button", { that.buttonElement.attr( "aria-pressed", that.element[0].checked ); }); } else if ( this.type === "radio" ) { - this.buttonElement.bind( "click.button", function() { + this.buttonElement.bind( "click" + this.eventNamespace, function() { if ( options.disabled || clickDragged ) { return false; } @@ -166,7 +166,7 @@ $.widget( "ui.button", { }); } else { this.buttonElement - .bind( "mousedown.button", function() { + .bind( "mousedown" + this.eventNamespace, function() { if ( options.disabled ) { return false; } @@ -176,13 +176,13 @@ $.widget( "ui.button", { lastActive = null; }); }) - .bind( "mouseup.button", function() { + .bind( "mouseup" + this.eventNamespace, function() { if ( options.disabled ) { return false; } $( this ).removeClass( "ui-state-active" ); }) - .bind( "keydown.button", function(event) { + .bind( "keydown" + this.eventNamespace, function(event) { if ( options.disabled ) { return false; } @@ -190,7 +190,7 @@ $.widget( "ui.button", { $( this ).addClass( "ui-state-active" ); } }) - .bind( "keyup.button", function() { + .bind( "keyup" + this.eventNamespace, function() { $( this ).removeClass( "ui-state-active" ); }); diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index 4ef8a20cb..a22eef806 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -224,7 +224,7 @@ $.widget("ui.dialog", { if ( this.overlay ) { this.overlay.destroy(); } - this.uiDialog.unbind( "keypress.ui-dialog" ); + this._off( this.uiDialog, "keypress" ); if ( this.options.hide ) { this.uiDialog.hide( this.options.hide, function() { @@ -310,7 +310,7 @@ $.widget("ui.dialog", { // prevent tabbing out of modal dialogs if ( options.modal ) { - uiDialog.bind( "keydown.ui-dialog", function( event ) { + this._on( uiDialog, { keydown: function( event ) { if ( event.keyCode !== $.ui.keyCode.TAB ) { return; } @@ -326,7 +326,7 @@ $.widget("ui.dialog", { last.focus( 1 ); return false; } - }); + }}); } // set focus to the first tabbable element in the content area or the first button diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index eb0be494c..616389ba2 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -44,7 +44,7 @@ $.widget( "ui.menu", { }) // need to catch all clicks on disabled menu // not possible through _on - .bind( "click.menu", $.proxy(function( event ) { + .bind( "click" + this.eventNamespace, $.proxy(function( event ) { if ( this.options.disabled ) { event.preventDefault(); } @@ -168,7 +168,7 @@ $.widget( "ui.menu", { this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); // unbind currentEventTarget click event handler - $( currentEventTarget ).unbind( "click.menu" ); + this._off( $( currentEventTarget ), "click" ); }, _keydown: function( event ) { diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js index 21736641f..aed4ba8fb 100644 --- a/ui/jquery.ui.tabs.js +++ b/ui/jquery.ui.tabs.js @@ -58,7 +58,7 @@ $.widget( "ui.tabs", { .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) .toggleClass( "ui-tabs-collapsible", options.collapsible ) // Prevent users from focusing disabled tabs via click - .delegate( ".ui-tabs-nav > li", "mousedown.tabs", function( event ) { + .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) { if ( $( this ).is( ".ui-state-disabled" ) ) { event.preventDefault(); } @@ -69,7 +69,7 @@ $.widget( "ui.tabs", { // We don't have to worry about focusing the previously focused // element since clicking on a non-focusable element should focus // the body anyway. - .delegate( ".ui-tabs-anchor", "focus.tabs", function() { + .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { this.blur(); } @@ -480,7 +480,7 @@ $.widget( "ui.tabs", { }); } - this.anchors.add( this.tabs ).add( this.panels ).unbind( ".tabs" ); + this._off( this.anchors.add( this.tabs ).add( this.panels ) ); this._on( this.anchors, events ); this._on( this.tabs, { keydown: "_tabKeydown" } ); this._on( this.panels, { keydown: "_panelKeydown" } ); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 6a7aab706..c4bdbb0d7 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -233,7 +233,7 @@ $.widget( "ui.tooltip", { }); target.removeData( "tooltip-open" ); - target.unbind( "mouseleave.tooltip focusout.tooltip keyup.tooltip" ); + this._off( target, "mouseleave focusout keyup" ); this.closing = true; this._trigger( "close", event, { tooltip: tooltip } ); diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 22049cbb8..5366beefe 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -387,6 +387,11 @@ $.Widget.prototype = { }); }, + _off: function( element, eventName ) { + eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; + element.unbind( eventName ).undelegate( eventName ); + }, + _delay: function( handler, delay ) { function handlerProxy() { return ( typeof handler === "string" ? instance[ handler ] : handler ) -- cgit v1.2.3 From 5c2cf39dff34b4598b214b1a2a1f3b48d15f0366 Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Thu, 14 Jun 2012 01:02:11 +0200 Subject: Tooltip: Add track option --- demos/tooltip/tracking.html | 22 +--------------------- tests/unit/tooltip/tooltip_common.js | 1 + ui/jquery.ui.tooltip.js | 29 ++++++++++++++++++++++++----- 3 files changed, 26 insertions(+), 26 deletions(-) (limited to 'tests') diff --git a/demos/tooltip/tracking.html b/demos/tooltip/tracking.html index 033bc9766..ab0237da6 100644 --- a/demos/tooltip/tracking.html +++ b/demos/tooltip/tracking.html @@ -19,27 +19,7 @@ diff --git a/tests/unit/tooltip/tooltip_common.js b/tests/unit/tooltip/tooltip_common.js index d12ee9519..6d503aecd 100644 --- a/tests/unit/tooltip/tooltip_common.js +++ b/tests/unit/tooltip/tooltip_common.js @@ -11,6 +11,7 @@ TestHelpers.commonWidgetTests( "tooltip", { }, show: true, tooltipClass: null, + track: false, // callbacks close: null, diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index c4bdbb0d7..2c80f328c 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -54,6 +54,7 @@ $.widget( "ui.tooltip", { }, show: true, tooltipClass: null, + track: false, // callbacks close: null, @@ -145,13 +146,14 @@ $.widget( "ui.tooltip", { }, _open: function( event, target, content ) { + var tooltip, positionOption; if ( !content ) { return; } // Content can be updated multiple times. If the tooltip already // exists, then just update the content and bail. - var tooltip = this._find( target ); + tooltip = this._find( target ); if ( tooltip.length ) { tooltip.find( ".ui-tooltip-content" ).html( content ); return; @@ -175,11 +177,25 @@ $.widget( "ui.tooltip", { tooltip = this._tooltip( target ); addDescribedBy( target, tooltip.attr( "id" ) ); tooltip.find( ".ui-tooltip-content" ).html( content ); - tooltip - .position( $.extend({ + + function position( event ) { + positionOption.of = event; + tooltip.position( positionOption ); + } + if ( this.options.track && /^mouse/.test( event.originalEvent.type ) ) { + positionOption = $.extend( {}, this.options.position ); + this._on( this.document, { + mousemove: position + }); + // trigger once to override element-relative positioning + position( event ); + } else { + tooltip.position( $.extend({ of: target - }, this.options.position ) ) - .hide(); + }, this.options.position ) ); + } + + tooltip.hide(); this._show( tooltip, this.options.show ); @@ -235,6 +251,9 @@ $.widget( "ui.tooltip", { target.removeData( "tooltip-open" ); this._off( target, "mouseleave focusout keyup" ); + // TODO use _off + this.document.unbind( "mousemove.tooltip" ); + this.closing = true; this._trigger( "close", event, { tooltip: tooltip } ); this.closing = false; -- cgit v1.2.3 From 92fb5567a25080f2064710fc24f0c6c073424cf3 Mon Sep 17 00:00:00 2001 From: Scott González Date: Fri, 15 Jun 2012 12:47:12 -0400 Subject: Effects: Renamed all files. --- demos/addClass/default.html | 2 +- demos/animate/default.html | 2 +- demos/datepicker/animation.html | 14 +- demos/dialog/animated.html | 6 +- demos/dialog/modal-form.html | 2 +- demos/effect/default.html | 28 +- demos/effect/easing.html | 2 +- demos/hide/default.html | 24 +- demos/index.html | 26 +- demos/removeClass/default.html | 2 +- demos/show/default.html | 24 +- demos/switchClass/default.html | 2 +- demos/toggle/default.html | 24 +- demos/toggleClass/default.html | 2 +- demos/tooltip/custom-animation.html | 4 +- demos/tooltip/video-player.html | 4 +- grunt.js | 2 +- tests/unit/effects/effects.html | 28 +- tests/visual/addClass/queue.html | 2 +- tests/visual/effects/all.html | 28 +- tests/visual/effects/scale.html | 4 +- tests/visual/tooltip/animations.html | 10 +- ui/jquery.effects.blind.js | 81 ---- ui/jquery.effects.bounce.js | 112 ------ ui/jquery.effects.clip.js | 66 ---- ui/jquery.effects.core.js | 739 ----------------------------------- ui/jquery.effects.drop.js | 64 --- ui/jquery.effects.explode.js | 96 ----- ui/jquery.effects.fade.js | 29 -- ui/jquery.effects.fold.js | 75 ---- ui/jquery.effects.highlight.js | 49 --- ui/jquery.effects.pulsate.js | 62 --- ui/jquery.effects.scale.js | 290 -------------- ui/jquery.effects.shake.js | 73 ---- ui/jquery.effects.slide.js | 65 --- ui/jquery.effects.transfer.js | 46 --- ui/jquery.ui.effect-blind.js | 81 ++++ ui/jquery.ui.effect-bounce.js | 112 ++++++ ui/jquery.ui.effect-clip.js | 66 ++++ ui/jquery.ui.effect-drop.js | 64 +++ ui/jquery.ui.effect-explode.js | 96 +++++ ui/jquery.ui.effect-fade.js | 29 ++ ui/jquery.ui.effect-fold.js | 75 ++++ ui/jquery.ui.effect-highlight.js | 49 +++ ui/jquery.ui.effect-pulsate.js | 62 +++ ui/jquery.ui.effect-scale.js | 290 ++++++++++++++ ui/jquery.ui.effect-shake.js | 73 ++++ ui/jquery.ui.effect-slide.js | 65 +++ ui/jquery.ui.effect-transfer.js | 46 +++ ui/jquery.ui.effect.js | 739 +++++++++++++++++++++++++++++++++++ 50 files changed, 1968 insertions(+), 1968 deletions(-) delete mode 100644 ui/jquery.effects.blind.js delete mode 100644 ui/jquery.effects.bounce.js delete mode 100644 ui/jquery.effects.clip.js delete mode 100644 ui/jquery.effects.core.js delete mode 100644 ui/jquery.effects.drop.js delete mode 100644 ui/jquery.effects.explode.js delete mode 100644 ui/jquery.effects.fade.js delete mode 100644 ui/jquery.effects.fold.js delete mode 100644 ui/jquery.effects.highlight.js delete mode 100644 ui/jquery.effects.pulsate.js delete mode 100644 ui/jquery.effects.scale.js delete mode 100644 ui/jquery.effects.shake.js delete mode 100644 ui/jquery.effects.slide.js delete mode 100644 ui/jquery.effects.transfer.js create mode 100644 ui/jquery.ui.effect-blind.js create mode 100644 ui/jquery.ui.effect-bounce.js create mode 100644 ui/jquery.ui.effect-clip.js create mode 100644 ui/jquery.ui.effect-drop.js create mode 100644 ui/jquery.ui.effect-explode.js create mode 100644 ui/jquery.ui.effect-fade.js create mode 100644 ui/jquery.ui.effect-fold.js create mode 100644 ui/jquery.ui.effect-highlight.js create mode 100644 ui/jquery.ui.effect-pulsate.js create mode 100644 ui/jquery.ui.effect-scale.js create mode 100644 ui/jquery.ui.effect-shake.js create mode 100644 ui/jquery.ui.effect-slide.js create mode 100644 ui/jquery.ui.effect-transfer.js create mode 100644 ui/jquery.ui.effect.js (limited to 'tests') diff --git a/demos/addClass/default.html b/demos/addClass/default.html index 98f7c8c50..9d4b71455 100644 --- a/demos/addClass/default.html +++ b/demos/addClass/default.html @@ -5,7 +5,7 @@ jQuery UI Effects - addClass demo - +