]> source.dussan.org Git - jquery-ui.git/commitdiff
Core: Better support for areas in :focusable and :tabbable selectors. Partial fix...
authorScott González <scott.gonzalez@gmail.com>
Thu, 22 Jul 2010 14:33:42 +0000 (10:33 -0400)
committerScott González <scott.gonzalez@gmail.com>
Thu, 22 Jul 2010 14:33:42 +0000 (10:33 -0400)
tests/unit/core/core.html
tests/unit/core/selector.js
ui/jquery.ui.core.js

index ee2f5fdfa9442cc9dca9c55658fa0de5c9ac38af..ec557700135c83db91653d03e0fdec1fa97a6c07 100644 (file)
 
 <div id="main" style="position: absolute; top: -10000px; left: -10000px;">
 
+       <img src="images/jqueryui_32x32.png" usemap="#mymap" width="10", height="10">
+       <map name="mymap">
+               <area shape="rect" coords="0,0,1,1" id="areaCoordsNoHref">
+               <area shape="rect" coords="1,1,2,2" href="foo.html" id="areaCoordsHref">
+               <area shape="rect" coords="0,0,0,0" href="foo.html" id="areaCoordsNoSizeHref">
+               <area href="foo.html" id="areaNoCoordsHref">
+       </map>
+       <map name="mymap2">
+               <area shape="rect" coords="1,1,2,2" href="foo.html" id="areaNoImg">
+       </map>
+       
        <div>
                <input id="visibleAncestor-inputTypeNone" />
                <input type="text" id="visibleAncestor-inputTypeText" />
                <object id="visibleAncestor-object">xxx</object>
                <a href="#" id="visibleAncestor-anchorWithHref">anchor</a>
                <a id="visibleAncestor-anchorWithoutHref">anchor</a>
-               <map>
-                       <area href="#" id="visibleAncestor-areaWithHref" alt="" />
-                       <area id="visibleAncestor-areaWithoutHref" alt="" />
-               </map>
                <span id="visibleAncestor-span">x</span>
                <div id="visibleAncestor-div">x</div>
                <span id="visibleAncestor-spanWithTabindex" tabindex="1">x</span>
index 11490794a8d791ba74f4b38a6825c9f590e8a5fb..e7b7f9b6cd8fce76fbf89b48e326a7163ab8c05a 100644 (file)
@@ -79,7 +79,7 @@ test("data", function() {
 });
 
 test("focusable - visible, enabled elements", function() {
-       expect(18);
+       expect(16);
        
        isFocusable('#visibleAncestor-inputTypeNone', 'input, no type');
        isFocusable('#visibleAncestor-inputTypeText', 'input, type text');
@@ -93,9 +93,6 @@ test("focusable - visible, enabled elements", function() {
        isFocusable('#visibleAncestor-object', 'object');
        isFocusable('#visibleAncestor-anchorWithHref', 'anchor with href');
        isNotFocusable('#visibleAncestor-anchorWithoutHref', 'anchor without href');
-       // fails: $("map").is(":visible") and $("map").is(":hidden") both return true
-       isFocusable('#visibleAncestor-areaWithHref', 'area with href');
-       isNotFocusable('#visibleAncestor-areaWithoutHref', 'area without href');
        isNotFocusable('#visibleAncestor-span', 'span');
        isNotFocusable('#visibleAncestor-div', 'div');
        isFocusable("#visibleAncestor-spanWithTabindex", 'span with tabindex');
@@ -159,8 +156,16 @@ test("focusable - invalid tabindex", function() {
        isNotFocusable('#spanTabindex3foo', 'span, tabindex 3foo');
 });
 
+test("focusable - area elements", function() {
+       isNotFocusable('#areaCoordsNoHref', 'coords but no href');
+       isFocusable('#areaCoordsHref', 'coords and href');
+       isFocusable('#areaCoordsNoSizeHref', 'coords of zero px and href');
+       isFocusable('#areaNoCoordsHref', 'href but no coords');
+       isNotFocusable('#areaNoImg', 'not associated with an image');
+});
+
 test("tabbable - visible, enabled elements", function() {
-       expect(18);
+       expect(16);
        
        isTabbable('#visibleAncestor-inputTypeNone', 'input, no type');
        isTabbable('#visibleAncestor-inputTypeText', 'input, type text');
@@ -174,16 +179,13 @@ test("tabbable - visible, enabled elements", function() {
        isTabbable('#visibleAncestor-object', 'object');
        isTabbable('#visibleAncestor-anchorWithHref', 'anchor with href');
        isNotTabbable('#visibleAncestor-anchorWithoutHref', 'anchor without href');
-       // fails: $("map").is(":visible") and $("map").is(":hidden") both return true
-       isTabbable('#visibleAncestor-areaWithHref', 'area with href');
-       isNotTabbable('#visibleAncestor-areaWithoutHref', 'area without href');
        isNotTabbable('#visibleAncestor-span', 'span');
        isNotTabbable('#visibleAncestor-div', 'div');
        isTabbable("#visibleAncestor-spanWithTabindex", 'span with tabindex');
        isNotTabbable("#visibleAncestor-divWithNegativeTabindex", 'div with tabindex');
 });
 
-test("Tabbable - disabled elements", function() {
+test("tabbable - disabled elements", function() {
        expect(9);
        
        isNotTabbable('#disabledElement-inputTypeNone', 'input, no type');
@@ -197,25 +199,23 @@ test("Tabbable - disabled elements", function() {
        isNotTabbable('#disabledElement-textarea', 'textarea');
 });
 
-test("Tabbable - hidden styles", function() {
+test("tabbable - hidden styles", function() {
        expect(8);
        
        isNotTabbable('#displayNoneAncestor-input', 'input, display: none parent');
        isNotTabbable('#displayNoneAncestor-span', 'span with tabindex, display: none parent');
        
-       // fails: element hidden by parent-visibility-hidden is still visible according to :visible
        isNotTabbable('#visibilityHiddenAncestor-input', 'input, visibility: hidden parent');
        isNotTabbable('#visibilityHiddenAncestor-span', 'span with tabindex, visibility: hidden parent');
        
        isNotTabbable('#displayNone-input', 'input, display: none');
-       // fails: element hidden by parent-visibility-hidden is still visible according to :visible
        isNotTabbable('#visibilityHidden-input', 'input, visibility: hidden');
        
        isNotTabbable('#displayNone-span', 'span with tabindex, display: none');
        isNotTabbable('#visibilityHidden-span', 'span with tabindex, visibility: hidden');
 });
 
-test("Tabbable -  natively tabbable with various tabindex", function() {
+test("tabbable -  natively tabbable with various tabindex", function() {
        expect(4);
        
        isTabbable('#inputTabindex0', 'input, tabindex 0');
@@ -224,7 +224,7 @@ test("Tabbable -  natively tabbable with various tabindex", function() {
        isNotTabbable('#inputTabindex-50', 'input, tabindex -50');
 });
 
-test("Tabbable -  not natively tabbable with various tabindex", function() {
+test("tabbable -  not natively tabbable with various tabindex", function() {
        expect(4);
        
        isTabbable('#spanTabindex0', 'span, tabindex 0');
@@ -233,7 +233,7 @@ test("Tabbable -  not natively tabbable with various tabindex", function() {
        isNotTabbable('#spanTabindex-50', 'span, tabindex -50');
 });
 
-test("Tabbable - invalid tabindex", function() {
+test("tabbable - invalid tabindex", function() {
        expect(4);
        
        isTabbable('#inputTabindexfoo', 'input, tabindex foo');
@@ -242,4 +242,12 @@ test("Tabbable - invalid tabindex", function() {
        isNotTabbable('#spanTabindex3foo', 'span, tabindex 3foo');
 });
 
+test("tabbable - area elements", function() {
+       isNotTabbable('#areaCoordsNoHref', 'coords but no href');
+       isTabbable('#areaCoordsHref', 'coords and href');
+       isTabbable('#areaCoordsNoSizeHref', 'coords of zero px and href');
+       isTabbable('#areaNoCoordsHref', 'href but no coords');
+       isNotTabbable('#areaNoImg', 'not associated with an image');
+});
+
 })(jQuery);
index 0804edab72a41862f8ecb01b4c6d5818ea4e26f5..49b5c003b18aaf2ce1d364feb8603522838e21aa 100644 (file)
@@ -231,6 +231,13 @@ $.each( [ "Width", "Height" ], function( i, name ) {
 });
 
 //Additional selectors
+function visible( element ) {
+       return !$(element).parents().andSelf().filter(function() {
+               return $.curCSS( this, "visibility" ) === "hidden" ||
+                       $.expr.filters.hidden( this );
+       }).length;
+}
+
 $.extend($.expr[':'], {
        data: function(elem, i, match) {
                return !!$.data(elem, match[3]);
@@ -239,17 +246,23 @@ $.extend($.expr[':'], {
        focusable: function(element) {
                var nodeName = element.nodeName.toLowerCase(),
                        tabIndex = $.attr(element, 'tabindex');
+               if ( "area" === nodeName ) {
+                       var map = element.parentNode,
+                               mapName = map.name,
+                               img;
+                       if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
+                               return false;
+                       }
+                       img = $( "img[usemap=#" + mapName + "]" )[0];
+                       return !!img && visible( img );
+               }
                return (/input|select|textarea|button|object/.test(nodeName)
                        ? !element.disabled
-                       : 'a' == nodeName || 'area' == nodeName
+                       : 'a' == nodeName
                                ? element.href || !isNaN(tabIndex)
                                : !isNaN(tabIndex))
                        // the element and all of its ancestors must be visible
-                       // the browser may report that the area is hidden
-                       && !$(element).parents().andSelf().filter(function() {
-                               return $.curCSS( this, "visibility" ) === "hidden" ||
-                                       $.expr.filters.hidden( this );
-                       }).length;
+                       && visible( element );
        },
 
        tabbable: function(element) {