Skip to content

Commit fd4ee2a

Browse files
committed
Make the tabIndex hook first a propHook and add it to attrHooks for back-compat reasons. Fixes #9979.
1 parent 3cfb134 commit fd4ee2a

File tree

2 files changed

+75
-15
lines changed

2 files changed

+75
-15
lines changed

src/attributes.js

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -405,19 +405,6 @@ jQuery.extend({
405405
}
406406
}
407407
},
408-
tabIndex: {
409-
get: function( elem ) {
410-
// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
411-
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
412-
var attributeNode = elem.getAttributeNode("tabIndex");
413-
414-
return attributeNode && attributeNode.specified ?
415-
parseInt( attributeNode.value, 10 ) :
416-
rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
417-
0 :
418-
undefined;
419-
}
420-
},
421408
// Use the value property for back compat
422409
// Use the formHook for button elements in IE6/7 (#1954)
423410
value: {
@@ -480,7 +467,7 @@ jQuery.extend({
480467
}
481468

482469
} else {
483-
if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {
470+
if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
484471
return ret;
485472

486473
} else {
@@ -489,9 +476,26 @@ jQuery.extend({
489476
}
490477
},
491478

492-
propHooks: {}
479+
propHooks: {
480+
tabIndex: {
481+
get: function( elem ) {
482+
// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
483+
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
484+
var attributeNode = elem.getAttributeNode("tabIndex");
485+
486+
return attributeNode && attributeNode.specified ?
487+
parseInt( attributeNode.value, 10 ) :
488+
rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
489+
0 :
490+
undefined;
491+
}
492+
}
493+
}
493494
});
494495

496+
// Add the tabindex propHook to attrHooks for back-compat
497+
jQuery.attrHooks.tabIndex = jQuery.propHooks.tabIndex;
498+
495499
// Hook for boolean attributes
496500
boolHook = {
497501
get: function( elem, name ) {
@@ -604,6 +608,7 @@ if ( !jQuery.support.optSelected ) {
604608
parent.parentNode.selectedIndex;
605609
}
606610
}
611+
return null;
607612
}
608613
});
609614
}

test/unit/attributes.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,61 @@ test("prop(String, Object)", function() {
527527
jQuery( document ).removeProp("nonexisting");
528528
});
529529

530+
test("prop('tabindex')", function() {
531+
expect(8);
532+
533+
// elements not natively tabbable
534+
equals(jQuery("#listWithTabIndex").prop("tabindex"), 5, "not natively tabbable, with tabindex set to 0");
535+
equals(jQuery("#divWithNoTabIndex").prop("tabindex"), undefined, "not natively tabbable, no tabindex set");
536+
537+
// anchor with href
538+
equals(jQuery("#linkWithNoTabIndex").prop("tabindex"), 0, "anchor with href, no tabindex set");
539+
equals(jQuery("#linkWithTabIndex").prop("tabindex"), 2, "anchor with href, tabindex set to 2");
540+
equals(jQuery("#linkWithNegativeTabIndex").prop("tabindex"), -1, "anchor with href, tabindex set to -1");
541+
542+
// anchor without href
543+
equals(jQuery("#linkWithNoHrefWithNoTabIndex").prop("tabindex"), undefined, "anchor without href, no tabindex set");
544+
equals(jQuery("#linkWithNoHrefWithTabIndex").prop("tabindex"), 1, "anchor without href, tabindex set to 2");
545+
equals(jQuery("#linkWithNoHrefWithNegativeTabIndex").prop("tabindex"), -1, "anchor without href, no tabindex set");
546+
});
547+
548+
test("prop('tabindex', value)", function() {
549+
expect(9);
550+
551+
var element = jQuery("#divWithNoTabIndex");
552+
equals(element.prop("tabindex"), undefined, "start with no tabindex");
553+
554+
// set a positive string
555+
element.prop("tabindex", "1");
556+
equals(element.prop("tabindex"), 1, "set tabindex to 1 (string)");
557+
558+
// set a zero string
559+
element.prop("tabindex", "0");
560+
equals(element.prop("tabindex"), 0, "set tabindex to 0 (string)");
561+
562+
// set a negative string
563+
element.prop("tabindex", "-1");
564+
equals(element.prop("tabindex"), -1, "set tabindex to -1 (string)");
565+
566+
// set a positive number
567+
element.prop("tabindex", 1);
568+
equals(element.prop("tabindex"), 1, "set tabindex to 1 (number)");
569+
570+
// set a zero number
571+
element.prop("tabindex", 0);
572+
equals(element.prop("tabindex"), 0, "set tabindex to 0 (number)");
573+
574+
// set a negative number
575+
element.prop("tabindex", -1);
576+
equals(element.prop("tabindex"), -1, "set tabindex to -1 (number)");
577+
578+
element = jQuery("#linkWithTabIndex");
579+
equals(element.prop("tabindex"), 2, "start with tabindex 2");
580+
581+
element.prop("tabindex", -1);
582+
equals(element.prop("tabindex"), -1, "set negative tabindex");
583+
});
584+
530585
test("removeProp(String)", function() {
531586
expect(6);
532587
var attributeNode = document.createAttribute("irrelevant"),

0 commit comments

Comments
 (0)