Skip to content

Commit 50d910b

Browse files
committed
Focusable: Detect disabled fieldsets
Fixes #14970 Closes jquerygh-1705
1 parent fbc79e1 commit 50d910b

File tree

3 files changed

+39
-9
lines changed

3 files changed

+39
-9
lines changed

tests/unit/core/core.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@
3838
<input>
3939
</form>
4040

41+
<form>
42+
<fieldset id="enabledFieldset">
43+
<input>
44+
</fieldset>
45+
<fieldset id="disabledFieldset" disabled="disabled">
46+
<input>
47+
</fieldset>
48+
</form>
49+
4150
<div>
4251
<input id="visibleAncestor-inputTypeNone">
4352
<input type="text" id="visibleAncestor-inputTypeText">

tests/unit/core/selector.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,12 @@ QUnit.test( "data", function( assert ) {
8989
} );
9090

9191
QUnit.test( "focusable - visible, enabled elements", function( assert ) {
92-
assert.expect( 20 );
92+
assert.expect( 22 );
9393

9494
assert.isNotFocusable( "#formNoTabindex", "form" );
9595
assert.isFocusable( "#formTabindex", "form with tabindex" );
96+
assert.isFocusable( "#enabledFieldset input", "input in enabled fieldset" );
97+
assert.isNotFocusable( "#disabledFieldset input", "input in disabled fieldset" );
9698
assert.isFocusable( "#visibleAncestor-inputTypeNone", "input, no type" );
9799
assert.isFocusable( "#visibleAncestor-inputTypeText", "input, type text" );
98100
assert.isFocusable( "#visibleAncestor-inputTypeCheckbox", "input, type checkbox" );
@@ -184,10 +186,12 @@ QUnit.test( "focusable - dimensionless parent with overflow", function( assert )
184186
} );
185187

186188
QUnit.test( "tabbable - visible, enabled elements", function( assert ) {
187-
assert.expect( 18 );
189+
assert.expect( 20 );
188190

189191
assert.isNotTabbable( "#formNoTabindex", "form" );
190192
assert.isTabbable( "#formTabindex", "form with tabindex" );
193+
assert.isTabbable( "#enabledFieldset input", "input in enabled fieldset" );
194+
assert.isNotTabbable( "#disabledFieldset input", "input in disabled fieldset" );
191195
assert.isTabbable( "#visibleAncestor-inputTypeNone", "input, no type" );
192196
assert.isTabbable( "#visibleAncestor-inputTypeText", "input, type text" );
193197
assert.isTabbable( "#visibleAncestor-inputTypeCheckbox", "input, type checkbox" );

ui/focusable.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@
2626

2727
// Selectors
2828
$.ui.focusable = function( element, hasTabindex ) {
29-
var map, mapName, img,
29+
var map, mapName, img, focusableIfVisible, fieldset,
3030
nodeName = element.nodeName.toLowerCase();
31+
3132
if ( "area" === nodeName ) {
3233
map = element.parentNode;
3334
mapName = map.name;
@@ -37,12 +38,28 @@ $.ui.focusable = function( element, hasTabindex ) {
3738
img = $( "img[usemap='#" + mapName + "']" );
3839
return img.length > 0 && img.is( ":visible" );
3940
}
40-
return ( /^(input|select|textarea|button|object)$/.test( nodeName ) ?
41-
!element.disabled :
42-
"a" === nodeName ?
43-
element.href || hasTabindex :
44-
hasTabindex ) &&
45-
$( element ).is( ":visible" ) && visible( $( element ) );
41+
42+
if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
43+
focusableIfVisible = !element.disabled;
44+
45+
if ( focusableIfVisible ) {
46+
47+
// Form controls within a disabled fieldset are disabled.
48+
// However, controls within the fieldset's legend do not get disabled.
49+
// Since controls generally aren't placed inside legends, we skip
50+
// this portion of the check.
51+
fieldset = $( element ).closest( "fieldset" )[ 0 ];
52+
if ( fieldset ) {
53+
focusableIfVisible = !fieldset.disabled;
54+
}
55+
}
56+
} else if ( "a" === nodeName ) {
57+
focusableIfVisible = element.href || hasTabindex;
58+
} else {
59+
focusableIfVisible = hasTabindex;
60+
}
61+
62+
return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
4663
};
4764

4865
// Support: IE 8 only

0 commit comments

Comments
 (0)