Skip to content

Commit 091af84

Browse files
committed
Numerous enhancements & bug fixes re keyboard use of popup windows
- Add support for escape to close popup windows - Refresh current values of width and height when opening resize dialog - Temporarily add role="application" to popup window when user selects "Move" from menu - Fix various other bugs related to window and keyboard focus
1 parent a07918e commit 091af84

13 files changed

Lines changed: 236 additions & 65 deletions

build/ableplayer.dist.js

Lines changed: 78 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ var AblePlayerInstances = [];
5252
AblePlayer.youtubeIframeAPIReady = true;
5353
$('body').trigger('youtubeIframeAPIReady', []);
5454
};
55-
5655
// If there is only one player on the page, dispatch global keydown events to it
5756
// Otherwise, keydowwn events are handled locally (see event.js > handleEventListeners())
5857
$(window).keydown(function(e) {
@@ -3605,6 +3604,7 @@ var AblePlayerInstances = [];
36053604
}
36063605
// add keyboard handlers for navigating within popups
36073606
$menu.on('keydown',function (e) {
3607+
36083608
whichMenu = $(this).attr('id').split('-')[1];
36093609
$thisItem = $(this).find('li:focus');
36103610
if ($thisItem.is(':first-child')) {
@@ -6631,6 +6631,7 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
66316631
});
66326632

66336633
this.$volumeSliderHead.on('keydown',function (e) {
6634+
66346635
// Left arrow or down arrow
66356636
if (e.which === 37 || e.which === 40) {
66366637
thisObj.handleVolume('down');
@@ -7110,6 +7111,17 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
71107111

71117112
this.focusedElementBeforeModal.focus();
71127113
};
7114+
7115+
AccessibleDialog.prototype.getInputs = function () {
7116+
7117+
// return an array of input elements within this dialog
7118+
if (this.modal) {
7119+
var inputs = this.modal.find('input');
7120+
return inputs;
7121+
}
7122+
return false;
7123+
};
7124+
71137125
})(jQuery);
71147126

71157127
(function ($) {
@@ -9096,6 +9108,9 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
90969108
else {
90979109
this.positionDraggableWindow('transcript');
90989110
this.$transcriptArea.show();
9111+
// showing transcriptArea has a cascading effect of showing all content *within* transcriptArea
9112+
// need to re-hide the popup menu
9113+
this.$transcriptPopup.hide();
90999114
this.$transcriptButton.removeClass('buttonOff').attr('aria-label',this.tt.hideTranscript);
91009115
this.$transcriptButton.find('span.able-clipped').text(this.tt.hideTranscript);
91019116
this.prefTranscript = 1;
@@ -9129,6 +9144,9 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
91299144
else {
91309145
this.positionDraggableWindow('sign');
91319146
this.$signWindow.show();
9147+
// showing signWindow has a cascading effect of showing all content *within* signWindow
9148+
// need to re-hide the popup menu
9149+
this.$signPopup.hide();
91329150
this.$signButton.removeClass('buttonOff').attr('aria-label',this.tt.hideSign);
91339151
this.$signButton.find('span.able-clipped').text(this.tt.hideSign);
91349152
this.prefSign = 1;
@@ -10612,7 +10630,6 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1061210630
thisObj = this;
1061310631
this.$transcriptArea = $('<div>', {
1061410632
'class': 'able-transcript-area',
10615-
'tabindex': '-1',
1061610633
'role': 'dialog',
1061710634
'aria-label': this.tt.transcriptTitle
1061810635
});
@@ -11776,14 +11793,24 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1177611793

1177711794
var which, $thisElement;
1177811795

11779-
if (!this.okToHandleKeyPress()) {
11780-
return false;
11781-
}
1178211796
// Convert to lower case.
1178311797
which = e.which;
1178411798
if (which >= 65 && which <= 90) {
1178511799
which += 32;
1178611800
}
11801+
$thisElement = $(document.activeElement);
11802+
11803+
if (which === 27) { // escape
11804+
if ($.contains(this.$transcriptArea[0],$thisElement[0])) {
11805+
// This element is part of transcript area.
11806+
this.handleTranscriptToggle();
11807+
return false;
11808+
}
11809+
}
11810+
if (!this.okToHandleKeyPress()) {
11811+
return false;
11812+
}
11813+
1178711814
// Only use keypress to control player if focus is NOT on a form field or contenteditable element
1178811815
// (or a textarea element with player in stenoMode)
1178911816
if (!(
@@ -11796,7 +11823,6 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1179611823
(e.target.tagName === 'TEXTAREA' && !this.stenoMode) ||
1179711824
e.target.tagName === 'SELECT'
1179811825
)){
11799-
$thisElement = $(document.activeElement);
1180011826
if (which === 27) { // escape
1180111827
this.closePopups();
1180211828
}
@@ -12334,7 +12360,8 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1233412360
});
1233512361

1233612362
// if user presses a key from anywhere on the page, show player controls
12337-
$(document).keydown(function() {
12363+
$(document).keydown(function(e) {
12364+
1233812365
if (thisObj.controlsHidden) {
1233912366
thisObj.fadeControls('in');
1234012367
thisObj.controlsHidden = false;
@@ -12364,6 +12391,7 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1236412391
// handle local keydown events if this isn't the only player on the page;
1236512392
// otherwise these are dispatched by global handler (see ableplayer-base,js)
1236612393
this.$ableDiv.keydown(function (e) {
12394+
1236712395
if (AblePlayer.nextIndex > 1) {
1236812396
thisObj.onPlayerKeyPress(e);
1236912397
}
@@ -12372,7 +12400,7 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1237212400
// transcript is not a child of this.$ableDiv
1237312401
// therefore, must be added separately
1237412402
if (this.$transcriptArea) {
12375-
this.$transcriptArea.keydown(function (e) {
12403+
this.$transcriptArea.on('keydown',function (e) {
1237612404
if (AblePlayer.nextIndex > 1) {
1237712405
thisObj.onPlayerKeyPress(e);
1237812406
}
@@ -12612,7 +12640,14 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1261212640

1261312641
// handle button click
1261412642
$newButton.on('click mousedown keydown',function(e) {
12615-
e.stopPropagation();
12643+
if (thisObj.focusNotClick) {
12644+
return false;
12645+
}
12646+
if (thisObj.dragging) {
12647+
thisObj.dragKeys(which, e);
12648+
return false;
12649+
}
12650+
e.stopPropagation();
1261612651
if (!thisObj.windowMenuClickRegistered && !thisObj.finishingDrag) {
1261712652
// don't set windowMenuClickRegistered yet; that happens in handler function
1261812653
thisObj.handleWindowButtonClick(which, e);
@@ -12761,15 +12796,26 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1276112796
this.windowMenuClickRegistered = true;
1276212797
}
1276312798
else if (e.which === 27) { // escape
12764-
// hide the popup menu
12765-
$windowPopup.hide('fast', function() {
12766-
// also reset the Boolean
12767-
thisObj.windowMenuClickRegistered = false;
12768-
// also restore menu items to their original state
12769-
$windowPopup.find('li').removeClass('able-focus').attr('tabindex','-1');
12770-
// also return focus to window options button
12771-
$windowButton.focus();
12772-
});
12799+
if ($windowPopup.is(':visible')) {
12800+
// close the popup menu
12801+
$windowPopup.hide('fast', function() {
12802+
// also reset the Boolean
12803+
thisObj.windowMenuClickRegistered = false;
12804+
// also restore menu items to their original state
12805+
$windowPopup.find('li').removeClass('able-focus').attr('tabindex','-1');
12806+
// also return focus to window options button
12807+
$windowButton.focus();
12808+
});
12809+
}
12810+
else {
12811+
// popup isn't open. Close the window
12812+
if (which === 'sign') {
12813+
this.handleSignToggle();
12814+
}
12815+
else if (which === 'transcript') {
12816+
this.handleTranscriptToggle();
12817+
}
12818+
}
1277312819
}
1277412820
else {
1277512821
return false;
@@ -12802,7 +12848,7 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1280212848

1280312849
AblePlayer.prototype.handleMenuChoice = function (which, choice, e) {
1280412850

12805-
var thisObj, $window, $windowPopup, $windowButton, resizeDialog, $thisRadio;
12851+
var thisObj, $window, $windowPopup, $windowButton, resizeDialog, width, height, $thisRadio;
1280612852

1280712853
thisObj = this;
1280812854
if (which === 'transcript') {
@@ -12852,6 +12898,11 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1285212898
$windowButton.focus();
1285312899
}
1285412900
if (choice === 'move') {
12901+
12902+
// temporarily add role="application" to activeWindow
12903+
// otherwise, screen readers incercept arrow keys and moving window will not work
12904+
this.$activeWindow.attr('role','application');
12905+
1285512906
if (!this.showedAlert(which)) {
1285612907
this.showAlert(this.tt.windowMoveAlert,which);
1285712908
if (which === 'transcript') {
@@ -12872,6 +12923,12 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1287212923
}
1287312924
else if (choice == 'resize') {
1287412925
// resize through the menu uses a form, not drag
12926+
var resizeFields = resizeDialog.getInputs();
12927+
if (resizeFields) {
12928+
// reset width and height values in form
12929+
resizeFields[0].value = $window.width();
12930+
resizeFields[1].value = $window.height();
12931+
}
1287512932
resizeDialog.show();
1287612933
}
1287712934
else if (choice == 'close') {
@@ -13058,6 +13115,8 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1305813115

1305913116
$(document).off('mousemove mouseup touchmove touchup');
1306013117
this.$activeWindow.off('keydown').removeClass('able-drag');
13118+
// restore activeWindow role from 'application' to 'dialog'
13119+
this.$activeWindow.attr('role','dialog');
1306113120
this.$activeWindow = null;
1306213121

1306313122
if (this.dragDevice === 'keyboard') {
@@ -13160,7 +13219,6 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1316013219

1316113220
$(document).off('mousemove mouseup touchmove touchup');
1316213221
this.$activeWindow.off('keydown');
13163-
1316413222
$windowButton.show().focus();
1316513223
this.resizing = false;
1316613224
this.$activeWindow.removeClass('able-resize');
@@ -13255,7 +13313,6 @@ if (thisObj.useTtml && (trackSrc.endsWith('.xml') || trackText.startsWith('<?xml
1325513313

1325613314
this.$signWindow = $('<div>',{
1325713315
'class' : 'able-sign-window',
13258-
'tabindex': '-1',
1325913316
'role': 'dialog',
1326013317
'aria-label': this.tt.sign
1326113318
});

0 commit comments

Comments
 (0)