Skip to content

Commit 01cefa1

Browse files
author
Terrill Thompson
committed
Add tooltips using aria-label
1 parent ac74ea7 commit 01cefa1

7 files changed

Lines changed: 236 additions & 102 deletions

File tree

‎build/ableplayer.js‎

Lines changed: 113 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@
591591
this.loadCurrentPreferences();
592592
this.injectPlayerCode();
593593
this.setupTracks().then(function () {
594-
thisObj.setupTooltips();
594+
thisObj.setupPopupMenus();
595595
thisObj.initDescription();
596596
thisObj.initializing = false;
597597
thisObj.initPlayer();
@@ -2250,26 +2250,27 @@
22502250
});
22512251
};
22522252

2253-
// Create tooltip with appropriate CSS styling and add to body.
2254-
AblePlayer.prototype.createTooltip = function () {
2253+
// Create popup menu with appropriate CSS styling and add to body
2254+
// (e.g., for captions and chapters menus)
2255+
AblePlayer.prototype.createPopupMenu = function () {
22552256
var thisObj = this;
22562257
var tooltip = $('<div>');
2257-
tooltip.attr('role', 'tooltip');
2258+
// tooltip.attr('role', 'tooltip'); // not really a tooltip
22582259
tooltip.addClass('able-tooltip');
22592260

2260-
// If tabbing off the tooltip, close it.
2261+
// If tabbing off the menu, close it.
22612262
tooltip.keydown(function (e) {
22622263
// Tab
22632264
if (e.which === 9) {
22642265
if (e.shiftKey) {
22652266
if (tooltip.find('button').first().is(':focus')) {
2266-
thisObj.closeTooltips();
2267+
thisObj.closePopupMenus();
22672268
e.preventDefault();
22682269
}
22692270
}
22702271
else {
22712272
if (tooltip.find('button').last().is(':focus')) {
2272-
thisObj.closeTooltips();
2273+
thisObj.closePopupMenus();
22732274
e.preventDefault();
22742275
}
22752276
}
@@ -2281,26 +2282,26 @@
22812282
return tooltip;
22822283
};
22832284

2284-
AblePlayer.prototype.closeTooltips = function () {
2285-
if (this.chaptersTooltip && this.chaptersTooltip.is(':visible')) {
2286-
this.chaptersTooltip.hide();
2285+
AblePlayer.prototype.closePopupMenus = function () {
2286+
if (this.chaptersPopupMenu && this.chaptersPopupMenu.is(':visible')) {
2287+
this.chaptersPopupMenu.hide();
22872288
this.$chaptersButton.focus();
22882289
}
2289-
if (this.captionsTooltip && this.captionsTooltip.is(':visible')) {
2290-
this.captionsTooltip.hide();
2290+
if (this.captionsPopupMenu && this.captionsPopupMenu.is(':visible')) {
2291+
this.captionsPopupMenu.hide();
22912292
this.$ccButton.focus();
22922293
}
22932294
};
22942295

2295-
// Create and fill in the tooltip forms for various controls.
2296-
AblePlayer.prototype.setupTooltips = function () {
2297-
this.setupCaptionsTooltip();
2298-
this.setupChaptersTooltip();
2296+
// Create and fill in the popup menu forms for various controls.
2297+
AblePlayer.prototype.setupPopupMenus = function () {
2298+
this.setupCaptionsPopupMenu();
2299+
this.setupChaptersPopupMenu();
22992300
};
23002301

2301-
AblePlayer.prototype.setupCaptionsTooltip = function () {
2302+
AblePlayer.prototype.setupCaptionsPopupMenu = function () {
23022303
var thisObj = this;
2303-
this.captionsTooltip = this.createTooltip();
2304+
this.captionsPopupMenu = this.createPopupMenu();
23042305

23052306
for (var ii in this.captions) {
23062307
var track = this.captions[ii];
@@ -2309,8 +2310,8 @@
23092310
trackButton.attr('tabindex', 0);
23102311
trackButton.click(this.getCaptionClickFunction(track));
23112312

2312-
this.captionsTooltip.append(trackButton);
2313-
this.captionsTooltip.append('<br>');
2313+
this.captionsPopupMenu.append(trackButton);
2314+
this.captionsPopupMenu.append('<br>');
23142315
}
23152316

23162317
// Captions Off option
@@ -2319,12 +2320,12 @@
23192320
offButton.html(this.tt.captionsOff);
23202321
offButton.click(this.getCaptionOffFunction());
23212322

2322-
this.captionsTooltip.append(offButton);
2323+
this.captionsPopupMenu.append(offButton);
23232324
};
23242325

2325-
AblePlayer.prototype.setupChaptersTooltip = function () {
2326+
AblePlayer.prototype.setupChaptersPopupMenu = function () {
23262327
var thisObj = this;
2327-
this.chaptersTooltip = this.createTooltip();
2328+
this.chaptersPopupMenu = this.createPopupMenu();
23282329

23292330
for (var ii in this.chapters) {
23302331
var chapterButton = $('<button>');
@@ -2333,14 +2334,14 @@
23332334
var getClickFunction = function (time) {
23342335
return function () {
23352336
thisObj.seekTo(time);
2336-
thisObj.chaptersTooltip.hide();
2337+
thisObj.chaptersPopupMenu.hide();
23372338
thisObj.$chaptersButton.focus();
23382339
}
23392340
}
23402341
chapterButton.click(getClickFunction(this.chapters[ii].start));
23412342

2342-
this.chaptersTooltip.append(chapterButton);
2343-
this.chaptersTooltip.append('<br>');
2343+
this.chaptersPopupMenu.append(chapterButton);
2344+
this.chaptersPopupMenu.append('<br>');
23442345
}
23452346
};
23462347

@@ -2561,18 +2562,29 @@
25612562
// some controls are aligned on the left, and others on the right
25622563

25632564
var useSpeedButtons, useFullScreen,
2564-
i, j, controls, controllerSpan, control,
2565+
i, j, controls, controllerSpan, tooltipId, tooltipDiv, tooltipX, tooltipY, control,
25652566
buttonImg, buttonImgSrc, buttonTitle, newButton, iconClass, buttonIcon,
25662567
leftWidth, rightWidth, totalWidth, leftWidthStyle, rightWidthStyle,
25672568
controllerStyles, vidcapStyles;
25682569

2570+
var thisObj = this;
2571+
25692572
var baseSliderWidth = 100;
25702573

25712574
// Initializes the layout into the this.controlLayout variable.
25722575
var controlLayout = this.calculateControlLayout();
25732576

25742577
var sectionByOrder = {0: 'ul', 1:'ur', 2:'bl', 3:'br'};
2575-
// now step separately through left and right controls
2578+
2579+
// add an empty div to serve as a tooltip
2580+
tooltipId = this.mediaId + '-tooltip';
2581+
tooltipDiv = $('<div>',{
2582+
'id': tooltipId,
2583+
'class': 'able-tooltip'
2584+
});
2585+
this.$controllerDiv.append(tooltipDiv);
2586+
2587+
// step separately through left and right controls
25762588
for (i = 0; i <= 3; i++) {
25772589
controls = controlLayout[sectionByOrder[i]];
25782590
if ((i % 2) === 0) {
@@ -2586,6 +2598,7 @@
25862598
});
25872599
}
25882600
this.$controllerDiv.append(controllerSpan);
2601+
25892602
for (j=0; j<controls.length; j++) {
25902603
control = controls[j];
25912604
if (control === 'seek') {
@@ -2658,11 +2671,65 @@
26582671
});
26592672
newButton.append(buttonImg);
26602673
}
2661-
// now add the visibly-hidden label for screen readers that don't support aria-label on the button
2674+
// add the visibly-hidden label for screen readers that don't support aria-label on the button
26622675
var buttonLabel = $('<span>',{
26632676
'class': 'able-clipped'
26642677
}).text(buttonTitle);
26652678
newButton.append(buttonLabel);
2679+
// add an event listener that displays a tooltip on mouseenter or focus
2680+
newButton.on('mouseenter focus',function(event) {
2681+
var label = $(this).attr('aria-label');
2682+
// get position of this button
2683+
var position = $(this).position();
2684+
var buttonHeight = $(this).height();
2685+
var buttonWidth = $(this).width();
2686+
var tooltipY = position.top - buttonHeight - 15;
2687+
var centerTooltip = true;
2688+
if ($(this).closest('span').hasClass('able-right-controls')) {
2689+
// this control is on the right side
2690+
if ($(this).is(':last-child')) {
2691+
// this is the last control on the right
2692+
// position tooltip using the "right" property
2693+
centerTooltip = false;
2694+
// var tooltipX = thisObj.playerWidth - position.left - buttonWidth;
2695+
var tooltipX = 0;
2696+
var tooltipStyle = {
2697+
left: '',
2698+
right: tooltipX + 'px',
2699+
top: tooltipY + 'px'
2700+
};
2701+
}
2702+
}
2703+
else {
2704+
// this control is on the left side
2705+
if ($(this).is(':first-child')) {
2706+
// this is the first control on the left
2707+
centerTooltip = false;
2708+
var tooltipX = position.left;
2709+
var tooltipStyle = {
2710+
left: tooltipX + 'px',
2711+
right: '',
2712+
top: tooltipY + 'px'
2713+
};
2714+
}
2715+
}
2716+
if (centerTooltip) {
2717+
// populate tooltip, then calculate its width before showing it
2718+
var tooltipWidth = $('#' + tooltipId).text(label).width();
2719+
// center the tooltip horizontally over the button
2720+
var tooltipX = position.left - tooltipWidth/2;
2721+
var tooltipStyle = {
2722+
left: tooltipX + 'px',
2723+
right: '',
2724+
top: tooltipY + 'px'
2725+
};
2726+
}
2727+
2728+
$('#' + tooltipId).text(label).css(tooltipStyle).show();
2729+
$(this).on('mouseleave blur',function() {
2730+
$('#' + tooltipId).text('').hide();
2731+
})
2732+
});
26662733

26672734
if (control === 'captions') {
26682735
if (!this.prefCaptions || this.prefCaptions !== 1) {
@@ -4688,33 +4755,33 @@
46884755
this.refreshControls();
46894756
}
46904757
else {
4691-
if (this.captionsTooltip.is(':visible')) {
4692-
this.captionsTooltip.hide();
4758+
if (this.captionsPopupMenu.is(':visible')) {
4759+
this.captionsPopupMenu.hide();
46934760
this.$ccButton.focus();
46944761
}
46954762
else {
4696-
this.closeTooltips();
4697-
this.captionsTooltip.show();
4698-
this.captionsTooltip.css('top', this.$ccButton.offset().top - this.captionsTooltip.outerHeight());
4699-
this.captionsTooltip.css('left', this.$ccButton.offset().left)
4763+
this.closePopupMenus();
4764+
this.captionsPopupMenu.show();
4765+
this.captionsPopupMenu.css('top', this.$ccButton.offset().top - this.captionsPopupMenu.outerHeight());
4766+
this.captionsPopupMenu.css('left', this.$ccButton.offset().left)
47004767
// Focus the first chapter.
4701-
this.captionsTooltip.children().first().focus();
4768+
this.captionsPopupMenu.children().first().focus();
47024769
}
47034770
}
47044771
};
47054772

47064773
AblePlayer.prototype.handleChapters = function () {
4707-
if (this.chaptersTooltip.is(':visible')) {
4708-
this.chaptersTooltip.hide();
4774+
if (this.chaptersPopupMenu.is(':visible')) {
4775+
this.chaptersPopupMenu.hide();
47094776
this.$chaptersButton.focus();
47104777
}
47114778
else {
4712-
this.closeTooltips();
4713-
this.chaptersTooltip.show();
4714-
this.chaptersTooltip.css('top', this.$chaptersButton.offset().top - this.chaptersTooltip.outerHeight());
4715-
this.chaptersTooltip.css('left', this.$chaptersButton.offset().left)
4779+
this.closePopupMenus();
4780+
this.chaptersPopupMenu.show();
4781+
this.chaptersPopupMenu.css('top', this.$chaptersButton.offset().top - this.chaptersPopupMenu.outerHeight());
4782+
this.chaptersPopupMenu.css('left', this.$chaptersButton.offset().left)
47164783
// Focus the first chapter.
4717-
this.chaptersTooltip.children().first().focus();
4784+
this.chaptersPopupMenu.children().first().focus();
47184785
}
47194786
};
47204787

@@ -4946,7 +5013,7 @@
49465013
thisObj.currentDescription = -1;
49475014
}
49485015
}
4949-
thisObj.captionsTooltip.hide();
5016+
thisObj.captionsPopupMenu.hide();
49505017
thisObj.$ccButton.focus();
49515018
thisObj.refreshControls();
49525019
thisObj.updateCaption();
@@ -4960,7 +5027,7 @@
49605027
return function () {
49615028
thisObj.captionsOn = false;
49625029
thisObj.currentCaption = -1;
4963-
thisObj.captionsTooltip.hide();
5030+
thisObj.captionsPopupMenu.hide();
49645031
thisObj.$ccButton.focus();
49655032
thisObj.refreshControls();
49665033
thisObj.updateCaption();
@@ -5795,7 +5862,7 @@
57955862
}
57965863

57975864
if (which === 27) { // Escape - TODO: Not listed in help file, should it be?
5798-
this.closeTooltips();
5865+
this.closePopupMenus();
57995866
}
58005867
else if (which === 32) { // spacebar = play/pause
58015868
if (!($('.able-controller button').is(':focus'))) {

0 commit comments

Comments
 (0)