mirror of
https://github.com/jquery/jquery-ui.git
synced 2024-10-05 01:44:18 +00:00
Tooltip: Improve accessibility by adding content to an aria-live div
Fixes #9610 Closes gh-1118
This commit is contained in:
parent
c9042b960f
commit
b9e438d07c
@ -21,27 +21,47 @@ test( "markup structure", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test( "accessibility", function() {
|
test( "accessibility", function() {
|
||||||
expect( 5 );
|
expect( 15 );
|
||||||
|
|
||||||
var tooltipId,
|
var tooltipId, tooltip,
|
||||||
tooltip,
|
element = $( "#multiple-describedby" ).tooltip(),
|
||||||
element = $( "#multiple-describedby" ).tooltip();
|
liveRegion = element.tooltip( "instance" ).liveRegion;
|
||||||
|
|
||||||
|
equal( liveRegion.find( ">div" ).length, 0 );
|
||||||
|
equal( liveRegion.attr( "role" ), "log" );
|
||||||
|
equal( liveRegion.attr( "aria-live" ), "assertive" );
|
||||||
|
equal( liveRegion.attr( "aria-relevant" ), "additions" );
|
||||||
element.tooltip( "open" );
|
element.tooltip( "open" );
|
||||||
tooltipId = element.data( "ui-tooltip-id" );
|
tooltipId = element.data( "ui-tooltip-id" );
|
||||||
tooltip = $( "#" + tooltipId );
|
tooltip = $( "#" + tooltipId );
|
||||||
equal( tooltip.attr( "role" ), "tooltip", "role" );
|
equal( tooltip.attr( "role" ), "tooltip", "role" );
|
||||||
equal( element.attr( "aria-describedby" ), "fixture-span " + tooltipId,
|
equal( element.attr( "aria-describedby" ), "fixture-span " + tooltipId,
|
||||||
"multiple describedby when open" );
|
"multiple describedby when open" );
|
||||||
|
|
||||||
// strictEqual to distinguish between .removeAttr( "title" ) and .attr( "title", "" )
|
// strictEqual to distinguish between .removeAttr( "title" ) and .attr( "title", "" )
|
||||||
// support: jQuery <1.6.2
|
// support: jQuery <1.6.2
|
||||||
// support: IE <8
|
// support: IE <8
|
||||||
// We should use strictEqual( ..., undefined ) when dropping jQuery 1.6.1 support (or IE6/7)
|
// We should use strictEqual( ..., undefined ) when dropping jQuery 1.6.1 support (or IE6/7)
|
||||||
ok( !element.attr( "title" ), "no title when open" );
|
ok( !element.attr( "title" ), "no title when open" );
|
||||||
|
equal( liveRegion.children().length, 1 );
|
||||||
|
equal( liveRegion.children().last().html(), "..." );
|
||||||
element.tooltip( "close" );
|
element.tooltip( "close" );
|
||||||
equal( element.attr( "aria-describedby" ), "fixture-span",
|
equal( element.attr( "aria-describedby" ), "fixture-span",
|
||||||
"correct describedby when closed" );
|
"correct describedby when closed" );
|
||||||
equal( element.attr( "title" ), "...", "title restored when closed" );
|
equal( element.attr( "title" ), "...", "title restored when closed" );
|
||||||
|
|
||||||
|
element.tooltip( "open" );
|
||||||
|
equal( liveRegion.children().length, 2,
|
||||||
|
"After the second tooltip show, there should be two children" );
|
||||||
|
equal( liveRegion.children().filter( ":visible" ).length, 1,
|
||||||
|
"Only one of the children should be visible" );
|
||||||
|
ok( liveRegion.children().last().is( ":visible" ),
|
||||||
|
"Only the last child should be visible" );
|
||||||
|
element.tooltip( "close" );
|
||||||
|
|
||||||
|
element.tooltip( "destroy" );
|
||||||
|
equal( liveRegion.parent().length, 0,
|
||||||
|
"Tooltip liveregion element should be removed" );
|
||||||
});
|
});
|
||||||
|
|
||||||
test( "delegated removal", function() {
|
test( "delegated removal", function() {
|
||||||
|
@ -41,13 +41,16 @@ test( "content: return string", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test( "content: return jQuery", function() {
|
test( "content: return jQuery", function() {
|
||||||
expect( 1 );
|
expect( 2 );
|
||||||
var element = $( "#tooltipped1" ).tooltip({
|
var element = $( "#tooltipped1" ).tooltip({
|
||||||
content: function() {
|
content: function() {
|
||||||
return $( "<div>" ).html( "cu<b>s</b>tomstring" );
|
return $( "<div id='unique'>" ).html( "cu<b id='bold'>s</b>tomstring" );
|
||||||
}
|
}
|
||||||
}).tooltip( "open" );
|
}).tooltip( "open" ),
|
||||||
|
liveRegion = element.tooltip( "instance" ).liveRegion;
|
||||||
deepEqual( $( "#" + element.data( "ui-tooltip-id" ) ).text(), "customstring" );
|
deepEqual( $( "#" + element.data( "ui-tooltip-id" ) ).text(), "customstring" );
|
||||||
|
equal( liveRegion.children().last().html(), "<div>cu<b>s</b>tomstring</div>",
|
||||||
|
"The accessibility live region will strip the ids but keep the structure" );
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest( "content: sync + async callback", function() {
|
asyncTest( "content: sync + async callback", function() {
|
||||||
|
25
ui/jquery.ui.tooltip.js
vendored
25
ui/jquery.ui.tooltip.js
vendored
@ -82,6 +82,16 @@ $.widget( "ui.tooltip", {
|
|||||||
if ( this.options.disabled ) {
|
if ( this.options.disabled ) {
|
||||||
this._disable();
|
this._disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append the aria-live region so tooltips announce correctly
|
||||||
|
this.liveRegion = $( "<div>" )
|
||||||
|
.attr({
|
||||||
|
role: "log",
|
||||||
|
"aria-live": "assertive",
|
||||||
|
"aria-relevant": "additions"
|
||||||
|
})
|
||||||
|
.addClass( "ui-helper-hidden-accessible" )
|
||||||
|
.appendTo( this.document[ 0 ].body );
|
||||||
},
|
},
|
||||||
|
|
||||||
_setOption: function( key, value ) {
|
_setOption: function( key, value ) {
|
||||||
@ -211,7 +221,7 @@ $.widget( "ui.tooltip", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_open: function( event, target, content ) {
|
_open: function( event, target, content ) {
|
||||||
var tooltip, events, delayedShow,
|
var tooltip, events, delayedShow, a11yContent,
|
||||||
positionOption = $.extend( {}, this.options.position );
|
positionOption = $.extend( {}, this.options.position );
|
||||||
|
|
||||||
if ( !content ) {
|
if ( !content ) {
|
||||||
@ -245,6 +255,18 @@ $.widget( "ui.tooltip", {
|
|||||||
this._addDescribedBy( target, tooltip.attr( "id" ) );
|
this._addDescribedBy( target, tooltip.attr( "id" ) );
|
||||||
tooltip.find( ".ui-tooltip-content" ).html( content );
|
tooltip.find( ".ui-tooltip-content" ).html( content );
|
||||||
|
|
||||||
|
// Support: Voiceover on OS X, JAWS on IE <= 9
|
||||||
|
// JAWS announces deletions even when aria-relevant="additions"
|
||||||
|
// Voiceover will sometimes re-read the entire log region's contents from the beginning
|
||||||
|
this.liveRegion.children().hide();
|
||||||
|
if ( content.clone ) {
|
||||||
|
a11yContent = content.clone();
|
||||||
|
a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
|
||||||
|
} else {
|
||||||
|
a11yContent = content;
|
||||||
|
}
|
||||||
|
$( "<div>" ).html( a11yContent ).appendTo( this.liveRegion );
|
||||||
|
|
||||||
function position( event ) {
|
function position( event ) {
|
||||||
positionOption.of = event;
|
positionOption.of = event;
|
||||||
if ( tooltip.is( ":hidden" ) ) {
|
if ( tooltip.is( ":hidden" ) ) {
|
||||||
@ -394,6 +416,7 @@ $.widget( "ui.tooltip", {
|
|||||||
element.removeData( "ui-tooltip-title" );
|
element.removeData( "ui-tooltip-title" );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.liveRegion.remove();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user