Skip to content

Commit b6cc9dd

Browse files
committed
Tooltip: Handle multiple aria-describedby values.
1 parent d7359be commit b6cc9dd

File tree

6 files changed

+58
-20
lines changed

6 files changed

+58
-20
lines changed

tests/unit/tooltip/tooltip.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ <h2 id="qunit-userAgent"></h2>
4141
<div>
4242
<a id="tooltipped1" href="#" title="anchortitle">anchor</a>
4343
<input title="inputtitle">
44+
<span id="multiple-describedby" aria-describedby="fixture-span" title="...">aria-describedby</span>
4445
<span id="fixture-span" title="title-text">span</span>
4546
</div>
4647

tests/unit/tooltip/tooltip_core.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,37 @@
33
module( "tooltip: core" );
44

55
test( "markup structure", function() {
6-
expect( 6 );
6+
expect( 7 );
77
var element = $( "#tooltipped1" ).tooltip(),
88
tooltip = $( ".ui-tooltip" );
99

1010
equal( element.attr( "aria-describedby" ), undefined, "no aria-describedby on init" );
1111
equal( tooltip.length, 0, "no tooltip on init" );
1212

1313
element.tooltip( "open" );
14-
tooltip = $( "#" + element.attr( "aria-describedby" ) );
14+
tooltip = $( "#" + element.data( "ui-tooltip-id" ) );
1515
equal( tooltip.length, 1, "tooltip exists" );
16+
equal( element.attr( "aria-describedby"), tooltip.attr( "id" ), "aria-describedby" );
1617
ok( tooltip.hasClass( "ui-tooltip" ), "tooltip is .ui-tooltip" );
1718
equal( tooltip.length, 1, ".ui-tooltip exists" );
1819
equal( tooltip.find( ".ui-tooltip-content" ).length, 1,
1920
".ui-tooltip-content exists" );
2021
});
2122

2223
test( "accessibility", function() {
23-
// TODO: add tests
24-
expect( 0 );
24+
// TODO: full tests
25+
expect( 2 );
26+
27+
var tooltipId,
28+
element = $( "#multiple-describedby" ).tooltip();
29+
30+
element.tooltip( "open" );
31+
tooltipId = element.data( "ui-tooltip-id" );
32+
equal( element.attr( "aria-describedby" ), "fixture-span " + tooltipId,
33+
"multiple describedby when open" );
34+
element.tooltip( "close" );
35+
equal( element.attr( "aria-describedby" ), "fixture-span",
36+
"correct describedby when closed" );
2537
});
2638

2739
}( jQuery ) );

tests/unit/tooltip/tooltip_events.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ test( "programmatic triggers", function() {
1111
tooltip = ui.tooltip;
1212
ok( !( "originalEvent" in event ), "open" );
1313
strictEqual( ui.tooltip[0],
14-
$( "#" + element.attr( "aria-describedby" ) )[0], "ui.tooltip" );
14+
$( "#" + element.data( "ui-tooltip-id" ) )[0], "ui.tooltip" );
1515
});
1616
element.tooltip( "open" );
1717

tests/unit/tooltip/tooltip_methods.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ test( "open/close", function() {
2121
equal( $( ".ui-tooltip" ).length, 0, "no tooltip on init" );
2222

2323
element.tooltip( "open" );
24-
tooltip = $( "#" + element.attr( "aria-describedby" ) );
24+
tooltip = $( "#" + element.data( "ui-tooltip-id" ) );
2525
ok( tooltip.is( ":visible" ) );
2626

2727
element.tooltip( "close" );
@@ -37,7 +37,7 @@ test( "enable/disable", function() {
3737
equal( $( ".ui-tooltip" ).length, 0, "no tooltip on init" );
3838

3939
element.tooltip( "open" );
40-
tooltip = $( "#" + element.attr( "aria-describedby" ) );
40+
tooltip = $( "#" + element.data( "ui-tooltip-id" ) );
4141
ok( tooltip.is( ":visible" ) );
4242

4343
element.tooltip( "disable" );
@@ -51,7 +51,7 @@ test( "enable/disable", function() {
5151
equal( element.attr( "title" ), "anchortitle", "title restored on enable" );
5252

5353
element.tooltip( "open" );
54-
tooltip = $( "#" + element.attr( "aria-describedby" ) );
54+
tooltip = $( "#" + element.data( "ui-tooltip-id" ) );
5555
ok( tooltip.is( ":visible" ) );
5656
$.fx.off = false;
5757
});

tests/unit/tooltip/tooltip_options.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module( "tooltip: options" );
44

55
test( "content: default", function() {
66
var element = $( "#tooltipped1" ).tooltip().tooltip( "open" );
7-
deepEqual( $( "#" + element.attr( "aria-describedby" ) ).text(), "anchortitle" );
7+
deepEqual( $( "#" + element.data( "ui-tooltip-id" ) ).text(), "anchortitle" );
88
});
99

1010
test( "content: return string", function() {
@@ -13,7 +13,7 @@ test( "content: return string", function() {
1313
return "customstring";
1414
}
1515
}).tooltip( "open" );
16-
deepEqual( $( "#" + element.attr( "aria-describedby" ) ).text(), "customstring" );
16+
deepEqual( $( "#" + element.data( "ui-tooltip-id" ) ).text(), "customstring" );
1717
});
1818

1919
test( "content: return jQuery", function() {
@@ -22,19 +22,19 @@ test( "content: return jQuery", function() {
2222
return $( "<div>" ).html( "cu<b>s</b>tomstring" );
2323
}
2424
}).tooltip( "open" );
25-
deepEqual( $( "#" + element.attr( "aria-describedby" ) ).text(), "customstring" );
25+
deepEqual( $( "#" + element.data( "ui-tooltip-id" ) ).text(), "customstring" );
2626
});
2727

2828
asyncTest( "content: sync + async callback", function() {
2929
expect( 2 );
3030
var element = $( "#tooltipped1" ).tooltip({
3131
content: function( response ) {
3232
setTimeout(function() {
33-
deepEqual( $( "#" + element.attr("aria-describedby") ).text(), "loading..." );
33+
deepEqual( $( "#" + element.data("ui-tooltip-id") ).text(), "loading..." );
3434

3535
response( "customstring2" );
3636
setTimeout(function() {
37-
deepEqual( $( "#" + element.attr("aria-describedby") ).text(), "customstring2" );
37+
deepEqual( $( "#" + element.data("ui-tooltip-id") ).text(), "customstring2" );
3838
start();
3939
}, 13 );
4040
}, 13 );
@@ -53,12 +53,12 @@ test( "items", function() {
5353
event = $.Event( "mouseenter" );
5454
event.target = $( "#fixture-span" )[ 0 ];
5555
element.tooltip( "open", event );
56-
deepEqual( $( "#" + $( "#fixture-span" ).attr( "aria-describedby" ) ).text(), "title-text" );
56+
deepEqual( $( "#" + $( "#fixture-span" ).data( "ui-tooltip-id" ) ).text(), "title-text" );
5757

5858
// make sure default [title] doesn't get used
5959
event.target = $( "#tooltipped1" )[ 0 ];
6060
element.tooltip( "open", event );
61-
deepEqual( $( "#tooltipped1" ).attr( "aria-describedby" ), undefined );
61+
deepEqual( $( "#tooltipped1" ).data( "ui-tooltip-id" ), undefined );
6262

6363
element.tooltip( "destroy" );
6464
});
@@ -68,7 +68,7 @@ test( "tooltipClass", function() {
6868
var element = $( "#tooltipped1" ).tooltip({
6969
tooltipClass: "custom"
7070
}).tooltip( "open" );
71-
ok( $( "#" + element.attr( "aria-describedby" ) ).hasClass( "custom" ) );
71+
ok( $( "#" + element.data( "ui-tooltip-id" ) ).hasClass( "custom" ) );
7272
});
7373

7474
}( jQuery ) );

ui/jquery.ui.tooltip.js

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,31 @@
1414

1515
var increments = 0;
1616

17+
function addDescribedBy( elem, id ) {
18+
var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
19+
describedby.push( id );
20+
elem
21+
.data( "ui-tooltip-id", id )
22+
.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
23+
}
24+
25+
function removeDescribedBy( elem ) {
26+
var id = elem.data( "ui-tooltip-id" ),
27+
describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
28+
index = $.inArray( id, describedby );
29+
if ( index !== -1 ) {
30+
describedby.splice( index, 1 );
31+
}
32+
33+
elem.removeData( "ui-tooltip-id" );
34+
describedby = $.trim( describedby.join( " " ) );
35+
if ( describedby ) {
36+
elem.attr( "aria-describedby", describedby );
37+
} else {
38+
elem.removeAttr( "aria-describedby" );
39+
}
40+
}
41+
1742
$.widget( "ui.tooltip", {
1843
version: "@VERSION",
1944
options: {
@@ -93,7 +118,7 @@ $.widget( "ui.tooltip", {
93118
.closest( this.options.items );
94119

95120
// if aria-describedby exists, then the tooltip is already open
96-
if ( !target.length || target.attr( "aria-describedby" ) ) {
121+
if ( !target.length || target.data( "ui-tooltip-id" ) ) {
97122
return;
98123
}
99124

@@ -143,7 +168,7 @@ $.widget( "ui.tooltip", {
143168
var tooltip = this._find( target );
144169
if ( !tooltip.length ) {
145170
tooltip = this._tooltip( target );
146-
target.attr( "aria-describedby", tooltip.attr( "id" ) );
171+
addDescribedBy( target, tooltip.attr( "id" ) );
147172
}
148173
tooltip.find( ".ui-tooltip-content" ).html( content );
149174
tooltip
@@ -195,7 +220,7 @@ $.widget( "ui.tooltip", {
195220
target.attr( "title", target.data( "ui-tooltip-title" ) );
196221
}
197222

198-
target.removeAttr( "aria-describedby" );
223+
removeDescribedBy( target );
199224

200225
tooltip.stop( true );
201226
this._hide( tooltip, this.options.hide, function() {
@@ -232,7 +257,7 @@ $.widget( "ui.tooltip", {
232257
},
233258

234259
_find: function( target ) {
235-
var id = target.attr( "aria-describedby" );
260+
var id = target.data( "ui-tooltip-id" );
236261
return id ? $( "#" + id ) : $();
237262
},
238263

0 commit comments

Comments
 (0)