From b6cc9dd870836b94d6f82729d56e592c548f24ea Mon Sep 17 00:00:00 2001 From: =?utf8?q?Scott=20Gonz=C3=A1lez?= Date: Tue, 22 May 2012 11:06:44 -0400 Subject: [PATCH] Tooltip: Handle multiple aria-describedby values. --- tests/unit/tooltip/tooltip.html | 1 + tests/unit/tooltip/tooltip_core.js | 20 ++++++++++++---- tests/unit/tooltip/tooltip_events.js | 2 +- tests/unit/tooltip/tooltip_methods.js | 6 ++--- tests/unit/tooltip/tooltip_options.js | 16 ++++++------- ui/jquery.ui.tooltip.js | 33 +++++++++++++++++++++++---- 6 files changed, 58 insertions(+), 20 deletions(-) diff --git a/tests/unit/tooltip/tooltip.html b/tests/unit/tooltip/tooltip.html index d20ba8578..f6e60b367 100644 --- a/tests/unit/tooltip/tooltip.html +++ b/tests/unit/tooltip/tooltip.html @@ -41,6 +41,7 @@
anchor + aria-describedby span
diff --git a/tests/unit/tooltip/tooltip_core.js b/tests/unit/tooltip/tooltip_core.js index e2569fb01..e25eb3c13 100644 --- a/tests/unit/tooltip/tooltip_core.js +++ b/tests/unit/tooltip/tooltip_core.js @@ -3,7 +3,7 @@ module( "tooltip: core" ); test( "markup structure", function() { - expect( 6 ); + expect( 7 ); var element = $( "#tooltipped1" ).tooltip(), tooltip = $( ".ui-tooltip" ); @@ -11,8 +11,9 @@ test( "markup structure", function() { equal( tooltip.length, 0, "no tooltip on init" ); element.tooltip( "open" ); - tooltip = $( "#" + element.attr( "aria-describedby" ) ); + tooltip = $( "#" + element.data( "ui-tooltip-id" ) ); equal( tooltip.length, 1, "tooltip exists" ); + equal( element.attr( "aria-describedby"), tooltip.attr( "id" ), "aria-describedby" ); ok( tooltip.hasClass( "ui-tooltip" ), "tooltip is .ui-tooltip" ); equal( tooltip.length, 1, ".ui-tooltip exists" ); equal( tooltip.find( ".ui-tooltip-content" ).length, 1, @@ -20,8 +21,19 @@ test( "markup structure", function() { }); test( "accessibility", function() { - // TODO: add tests - expect( 0 ); + // TODO: full tests + expect( 2 ); + + var tooltipId, + element = $( "#multiple-describedby" ).tooltip(); + + element.tooltip( "open" ); + tooltipId = element.data( "ui-tooltip-id" ); + equal( element.attr( "aria-describedby" ), "fixture-span " + tooltipId, + "multiple describedby when open" ); + element.tooltip( "close" ); + equal( element.attr( "aria-describedby" ), "fixture-span", + "correct describedby when closed" ); }); }( jQuery ) ); diff --git a/tests/unit/tooltip/tooltip_events.js b/tests/unit/tooltip/tooltip_events.js index b1ce92fb2..fc5f1acc5 100644 --- a/tests/unit/tooltip/tooltip_events.js +++ b/tests/unit/tooltip/tooltip_events.js @@ -11,7 +11,7 @@ test( "programmatic triggers", function() { tooltip = ui.tooltip; ok( !( "originalEvent" in event ), "open" ); strictEqual( ui.tooltip[0], - $( "#" + element.attr( "aria-describedby" ) )[0], "ui.tooltip" ); + $( "#" + element.data( "ui-tooltip-id" ) )[0], "ui.tooltip" ); }); element.tooltip( "open" ); diff --git a/tests/unit/tooltip/tooltip_methods.js b/tests/unit/tooltip/tooltip_methods.js index eaab1c0d1..1b8cd2bf2 100644 --- a/tests/unit/tooltip/tooltip_methods.js +++ b/tests/unit/tooltip/tooltip_methods.js @@ -21,7 +21,7 @@ test( "open/close", function() { equal( $( ".ui-tooltip" ).length, 0, "no tooltip on init" ); element.tooltip( "open" ); - tooltip = $( "#" + element.attr( "aria-describedby" ) ); + tooltip = $( "#" + element.data( "ui-tooltip-id" ) ); ok( tooltip.is( ":visible" ) ); element.tooltip( "close" ); @@ -37,7 +37,7 @@ test( "enable/disable", function() { equal( $( ".ui-tooltip" ).length, 0, "no tooltip on init" ); element.tooltip( "open" ); - tooltip = $( "#" + element.attr( "aria-describedby" ) ); + tooltip = $( "#" + element.data( "ui-tooltip-id" ) ); ok( tooltip.is( ":visible" ) ); element.tooltip( "disable" ); @@ -51,7 +51,7 @@ test( "enable/disable", function() { equal( element.attr( "title" ), "anchortitle", "title restored on enable" ); element.tooltip( "open" ); - tooltip = $( "#" + element.attr( "aria-describedby" ) ); + tooltip = $( "#" + element.data( "ui-tooltip-id" ) ); ok( tooltip.is( ":visible" ) ); $.fx.off = false; }); diff --git a/tests/unit/tooltip/tooltip_options.js b/tests/unit/tooltip/tooltip_options.js index 4f994f8de..a4ef9f472 100644 --- a/tests/unit/tooltip/tooltip_options.js +++ b/tests/unit/tooltip/tooltip_options.js @@ -4,7 +4,7 @@ module( "tooltip: options" ); test( "content: default", function() { var element = $( "#tooltipped1" ).tooltip().tooltip( "open" ); - deepEqual( $( "#" + element.attr( "aria-describedby" ) ).text(), "anchortitle" ); + deepEqual( $( "#" + element.data( "ui-tooltip-id" ) ).text(), "anchortitle" ); }); test( "content: return string", function() { @@ -13,7 +13,7 @@ test( "content: return string", function() { return "customstring"; } }).tooltip( "open" ); - deepEqual( $( "#" + element.attr( "aria-describedby" ) ).text(), "customstring" ); + deepEqual( $( "#" + element.data( "ui-tooltip-id" ) ).text(), "customstring" ); }); test( "content: return jQuery", function() { @@ -22,7 +22,7 @@ test( "content: return jQuery", function() { return $( "
" ).html( "customstring" ); } }).tooltip( "open" ); - deepEqual( $( "#" + element.attr( "aria-describedby" ) ).text(), "customstring" ); + deepEqual( $( "#" + element.data( "ui-tooltip-id" ) ).text(), "customstring" ); }); asyncTest( "content: sync + async callback", function() { @@ -30,11 +30,11 @@ asyncTest( "content: sync + async callback", function() { var element = $( "#tooltipped1" ).tooltip({ content: function( response ) { setTimeout(function() { - deepEqual( $( "#" + element.attr("aria-describedby") ).text(), "loading..." ); + deepEqual( $( "#" + element.data("ui-tooltip-id") ).text(), "loading..." ); response( "customstring2" ); setTimeout(function() { - deepEqual( $( "#" + element.attr("aria-describedby") ).text(), "customstring2" ); + deepEqual( $( "#" + element.data("ui-tooltip-id") ).text(), "customstring2" ); start(); }, 13 ); }, 13 ); @@ -53,12 +53,12 @@ test( "items", function() { event = $.Event( "mouseenter" ); event.target = $( "#fixture-span" )[ 0 ]; element.tooltip( "open", event ); - deepEqual( $( "#" + $( "#fixture-span" ).attr( "aria-describedby" ) ).text(), "title-text" ); + deepEqual( $( "#" + $( "#fixture-span" ).data( "ui-tooltip-id" ) ).text(), "title-text" ); // make sure default [title] doesn't get used event.target = $( "#tooltipped1" )[ 0 ]; element.tooltip( "open", event ); - deepEqual( $( "#tooltipped1" ).attr( "aria-describedby" ), undefined ); + deepEqual( $( "#tooltipped1" ).data( "ui-tooltip-id" ), undefined ); element.tooltip( "destroy" ); }); @@ -68,7 +68,7 @@ test( "tooltipClass", function() { var element = $( "#tooltipped1" ).tooltip({ tooltipClass: "custom" }).tooltip( "open" ); - ok( $( "#" + element.attr( "aria-describedby" ) ).hasClass( "custom" ) ); + ok( $( "#" + element.data( "ui-tooltip-id" ) ).hasClass( "custom" ) ); }); }( jQuery ) ); diff --git a/ui/jquery.ui.tooltip.js b/ui/jquery.ui.tooltip.js index 47a377bfd..1d6cd32a8 100644 --- a/ui/jquery.ui.tooltip.js +++ b/ui/jquery.ui.tooltip.js @@ -14,6 +14,31 @@ var increments = 0; +function addDescribedBy( elem, id ) { + var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); + describedby.push( id ); + elem + .data( "ui-tooltip-id", id ) + .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); +} + +function removeDescribedBy( elem ) { + var id = elem.data( "ui-tooltip-id" ), + describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), + index = $.inArray( id, describedby ); + if ( index !== -1 ) { + describedby.splice( index, 1 ); + } + + elem.removeData( "ui-tooltip-id" ); + describedby = $.trim( describedby.join( " " ) ); + if ( describedby ) { + elem.attr( "aria-describedby", describedby ); + } else { + elem.removeAttr( "aria-describedby" ); + } +} + $.widget( "ui.tooltip", { version: "@VERSION", options: { @@ -93,7 +118,7 @@ $.widget( "ui.tooltip", { .closest( this.options.items ); // if aria-describedby exists, then the tooltip is already open - if ( !target.length || target.attr( "aria-describedby" ) ) { + if ( !target.length || target.data( "ui-tooltip-id" ) ) { return; } @@ -143,7 +168,7 @@ $.widget( "ui.tooltip", { var tooltip = this._find( target ); if ( !tooltip.length ) { tooltip = this._tooltip( target ); - target.attr( "aria-describedby", tooltip.attr( "id" ) ); + addDescribedBy( target, tooltip.attr( "id" ) ); } tooltip.find( ".ui-tooltip-content" ).html( content ); tooltip @@ -195,7 +220,7 @@ $.widget( "ui.tooltip", { target.attr( "title", target.data( "ui-tooltip-title" ) ); } - target.removeAttr( "aria-describedby" ); + removeDescribedBy( target ); tooltip.stop( true ); this._hide( tooltip, this.options.hide, function() { @@ -232,7 +257,7 @@ $.widget( "ui.tooltip", { }, _find: function( target ) { - var id = target.attr( "aria-describedby" ); + var id = target.data( "ui-tooltip-id" ); return id ? $( "#" + id ) : $(); }, -- 2.39.5