Skip to content

Commit dbb36d2

Browse files
Troels NilssonTroels Nilsson
authored andcommitted
Shadow DOM fixes
Update JQuery to 3.2.1 (which has some shadow DOM fixes) show()/hide() works slightly different in JQuery 3.2.1, so display: none in CSS doesn't always work as expected Added AblePlayer.getActiveDOMElement() get the *actual* DOM element with focus - document.activeElement isn't enough (JQuery still has a bug here when using shadow DOMs) Added AblePlayer.localGetElementById(element, id) to get the element with the given id in the DOM where element is a member Used .find() on a local parent a few places instead of searching globally with $()
1 parent 45c841b commit dbb36d2

43 files changed

Lines changed: 182 additions & 95 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

build/ableplayer.dist.js

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,32 @@
435435
});
436436
};
437437

438+
AblePlayer.getActiveDOMElement = function () {
439+
var activeElement = document.activeElement;
440+
441+
// For shadow DOMs we need to keep digging down through the DOMs
442+
while (activeElement.shadowRoot && activeElement.shadowRoot.activeElement) {
443+
activeElement = activeElement.shadowRoot.activeElement;
444+
}
445+
446+
return activeElement;
447+
};
448+
449+
AblePlayer.localGetElementById = function(element, id) {
450+
if (element.getRootNode)
451+
{
452+
// Use getRootNode() and querySelector() where supported (for shadow DOM support)
453+
return $(element.getRootNode().querySelector('#' + id));
454+
}
455+
else
456+
{
457+
// If getRootNode is not supported it should be safe to use document.getElementById (since there is no shadow DOM support)
458+
return $(document.getElementById(id));
459+
}
460+
};
461+
462+
463+
438464
AblePlayer.youtubeIframeAPIReady = false;
439465
AblePlayer.loadingYoutubeIframeAPI = false;
440466
})(jQuery);
@@ -3185,6 +3211,7 @@
31853211

31863212
this.$alertBox = $('<div role="alert"></div>');
31873213
this.$alertBox.addClass('able-alert');
3214+
this.$alertBox.hide();
31883215
this.$alertBox.appendTo(this.$ableDiv);
31893216
if (this.mediaType == 'audio') {
31903217
top = -10;
@@ -3229,7 +3256,7 @@
32293256
$popup = $('<div>',{
32303257
'id': this.mediaId + '-' + which + '-menu',
32313258
'class': 'able-popup'
3232-
});
3259+
}).hide();
32333260
if (which === 'chapters' || which === 'prefs' || which === 'sign-window' || which === 'transcript-window') {
32343261
$popup.addClass('able-popup-no-radio');
32353262
}
@@ -3273,7 +3300,7 @@
32733300
$prevButton.parent().addClass('able-focus');
32743301
}
32753302
else if (e.which === 32 || e.which === 13) { // space or enter
3276-
$('input:focus').click();
3303+
$thisListItem.find('input:focus').click();
32773304
}
32783305
else if (e.which === 27) { // Escape
32793306
$thisListItem.removeClass('able-focus');
@@ -3731,7 +3758,7 @@
37313758
this.$tooltipDiv = $('<div>',{
37323759
'id': tooltipId,
37333760
'class': 'able-tooltip'
3734-
});
3761+
}).hide();
37353762
this.$controllerDiv.append(this.$tooltipDiv);
37363763

37373764
// step separately through left and right controls
@@ -3954,7 +3981,7 @@
39543981
}
39553982
if (centerTooltip) {
39563983
// populate tooltip, then calculate its width before showing it
3957-
var tooltipWidth = $('#' + tooltipId).text(label).width();
3984+
var tooltipWidth = AblePlayer.localGetElementById(newButton[0], tooltipId).text(label).width();
39583985
// center the tooltip horizontally over the button
39593986
var tooltipX = position.left - tooltipWidth/2;
39603987
var tooltipStyle = {
@@ -3963,10 +3990,10 @@
39633990
top: tooltipY + 'px'
39643991
};
39653992
}
3966-
var tooltip = $('#' + tooltipId).text(label).css(tooltipStyle);
3993+
var tooltip = AblePlayer.localGetElementById(newButton[0], tooltipId).text(label).css(tooltipStyle);
39673994
thisObj.showTooltip(tooltip);
39683995
$(this).on('mouseleave blur',function() {
3969-
$('#' + tooltipId).text('').hide();
3996+
AblePlayer.localGetElementById(newButton[0], tooltipId).text('').hide();
39703997
})
39713998
});
39723999

@@ -4541,7 +4568,7 @@
45414568
this.$captionsWrapper = $('<div>',{
45424569
'class': 'able-captions-wrapper',
45434570
'aria-hidden': 'true'
4544-
});
4571+
}).hide();
45454572
if (this.prefCaptionsPosition === 'below') {
45464573
this.$captionsWrapper.addClass('able-captions-below');
45474574
}
@@ -5289,6 +5316,7 @@
52895316

52905317
this.timeTooltip.attr('role', 'tooltip');
52915318
this.timeTooltip.addClass('able-tooltip');
5319+
this.timeTooltip.hide();
52925320

52935321
this.bodyDiv.append(this.loadedDiv);
52945322
this.bodyDiv.append(this.playedDiv);
@@ -5699,11 +5727,11 @@
56995727
'id': volumeSliderId,
57005728
'class': 'able-volume-slider',
57015729
'aria-hidden': 'true'
5702-
});
5730+
}).hide();
57035731
this.$volumeSliderTooltip = $('<div>',{
57045732
'class': 'able-tooltip',
57055733
'role': 'tooltip'
5706-
});
5734+
}).hide();
57075735
this.$volumeSliderTrack = $('<div>',{
57085736
'class': 'able-volume-track'
57095737
});
@@ -9078,7 +9106,7 @@
90789106
thisObj.handleTranscriptLockToggle(thisObj.$autoScrollTranscriptCheckbox.prop('checked'));
90799107
});
90809108

9081-
this.$transcriptDiv.bind('mousewheel DOMMouseScroll click scroll', function (event) {
9109+
this.$transcriptDiv.on('mousewheel DOMMouseScroll click scroll', function (event) {
90829110
// Propagation is stopped in transcript click handler, so clicks are on the scrollbar
90839111
// or outside of a clickable span.
90849112
if (!thisObj.scrollingTranscript) {
@@ -9992,14 +10020,16 @@
999210020

999310021
// returns true unless user's focus is on a UI element
999410022
// that is likely to need supported keystrokes, including space
9995-
var activeElement = $(document.activeElement).prop('tagName');
9996-
if (activeElement === 'INPUT') {
10023+
10024+
var activeElement = AblePlayer.getActiveDOMElement();
10025+
10026+
if ($(activeElement).prop('tagName') === 'INPUT') {
999710027
return false;
999810028
}
999910029
else {
1000010030
return true;
1000110031
}
10002-
}
10032+
};
1000310033

1000410034
AblePlayer.prototype.onPlayerKeyPress = function (e) {
1000510035
// handle keystrokes (using DHTML Style Guide recommended key combinations)
@@ -10022,7 +10052,7 @@
1002210052
this.closePopups();
1002310053
}
1002410054
else if (which === 32) { // spacebar = play/pause
10025-
if (!($('.able-controller button').is(':focus'))) {
10055+
if (this.$ableWrapper.find('.able-controller button:focus').length === 0) {
1002610056
// only toggle play if a button does not have focus
1002710057
// if a button has focus, space should activate that button
1002810058
this.handlePlay();
@@ -10481,6 +10511,7 @@
1048110511
// create an alert div and add it to window
1048210512
$windowAlert = $('<div role="alert"></div>');
1048310513
$windowAlert.addClass('able-alert');
10514+
$windowAlert.hide();
1048410515
$windowAlert.appendTo(this.$activeWindow);
1048510516
$windowAlert.css({
1048610517
top: $window.offset().top
@@ -10523,7 +10554,7 @@
1052310554
$tooltip = $('<div>',{
1052410555
'class' : 'able-tooltip',
1052510556
'id' : tooltipId
10526-
});
10557+
}).hide();
1052710558
$newButton.on('mouseenter focus',function(event) {
1052810559
var label = $(this).attr('aria-label');
1052910560
// get position of this button
@@ -10537,10 +10568,10 @@
1053710568
right: tooltipX + 'px',
1053810569
top: tooltipY + 'px'
1053910570
};
10540-
var tooltip = $('#' + tooltipId).text(label).css(tooltipStyle);
10571+
var tooltip = AblePlayer.localGetElementById($newButton[0], tooltipId).text(label).css(tooltipStyle);
1054110572
thisObj.showTooltip(tooltip);
1054210573
$(this).on('mouseleave blur',function() {
10543-
$('#' + tooltipId).text('').hide();
10574+
AblePlayer.localGetElementById($newButton[0], tooltipId).text('').hide();
1054410575
});
1054510576
});
1054610577

build/ableplayer.js

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,32 @@
435435
});
436436
};
437437

438+
AblePlayer.getActiveDOMElement = function () {
439+
var activeElement = document.activeElement;
440+
441+
// For shadow DOMs we need to keep digging down through the DOMs
442+
while (activeElement.shadowRoot && activeElement.shadowRoot.activeElement) {
443+
activeElement = activeElement.shadowRoot.activeElement;
444+
}
445+
446+
return activeElement;
447+
};
448+
449+
AblePlayer.localGetElementById = function(element, id) {
450+
if (element.getRootNode)
451+
{
452+
// Use getRootNode() and querySelector() where supported (for shadow DOM support)
453+
return $(element.getRootNode().querySelector('#' + id));
454+
}
455+
else
456+
{
457+
// If getRootNode is not supported it should be safe to use document.getElementById (since there is no shadow DOM support)
458+
return $(document.getElementById(id));
459+
}
460+
};
461+
462+
463+
438464
AblePlayer.youtubeIframeAPIReady = false;
439465
AblePlayer.loadingYoutubeIframeAPI = false;
440466
})(jQuery);
@@ -3185,6 +3211,7 @@
31853211

31863212
this.$alertBox = $('<div role="alert"></div>');
31873213
this.$alertBox.addClass('able-alert');
3214+
this.$alertBox.hide();
31883215
this.$alertBox.appendTo(this.$ableDiv);
31893216
if (this.mediaType == 'audio') {
31903217
top = -10;
@@ -3229,7 +3256,7 @@
32293256
$popup = $('<div>',{
32303257
'id': this.mediaId + '-' + which + '-menu',
32313258
'class': 'able-popup'
3232-
});
3259+
}).hide();
32333260
if (which === 'chapters' || which === 'prefs' || which === 'sign-window' || which === 'transcript-window') {
32343261
$popup.addClass('able-popup-no-radio');
32353262
}
@@ -3273,7 +3300,7 @@
32733300
$prevButton.parent().addClass('able-focus');
32743301
}
32753302
else if (e.which === 32 || e.which === 13) { // space or enter
3276-
$('input:focus').click();
3303+
$thisListItem.find('input:focus').click();
32773304
}
32783305
else if (e.which === 27) { // Escape
32793306
$thisListItem.removeClass('able-focus');
@@ -3731,7 +3758,7 @@
37313758
this.$tooltipDiv = $('<div>',{
37323759
'id': tooltipId,
37333760
'class': 'able-tooltip'
3734-
});
3761+
}).hide();
37353762
this.$controllerDiv.append(this.$tooltipDiv);
37363763

37373764
// step separately through left and right controls
@@ -3954,7 +3981,7 @@
39543981
}
39553982
if (centerTooltip) {
39563983
// populate tooltip, then calculate its width before showing it
3957-
var tooltipWidth = $('#' + tooltipId).text(label).width();
3984+
var tooltipWidth = AblePlayer.localGetElementById(newButton[0], tooltipId).text(label).width();
39583985
// center the tooltip horizontally over the button
39593986
var tooltipX = position.left - tooltipWidth/2;
39603987
var tooltipStyle = {
@@ -3963,10 +3990,10 @@
39633990
top: tooltipY + 'px'
39643991
};
39653992
}
3966-
var tooltip = $('#' + tooltipId).text(label).css(tooltipStyle);
3993+
var tooltip = AblePlayer.localGetElementById(newButton[0], tooltipId).text(label).css(tooltipStyle);
39673994
thisObj.showTooltip(tooltip);
39683995
$(this).on('mouseleave blur',function() {
3969-
$('#' + tooltipId).text('').hide();
3996+
AblePlayer.localGetElementById(newButton[0], tooltipId).text('').hide();
39703997
})
39713998
});
39723999

@@ -4541,7 +4568,7 @@
45414568
this.$captionsWrapper = $('<div>',{
45424569
'class': 'able-captions-wrapper',
45434570
'aria-hidden': 'true'
4544-
});
4571+
}).hide();
45454572
if (this.prefCaptionsPosition === 'below') {
45464573
this.$captionsWrapper.addClass('able-captions-below');
45474574
}
@@ -5289,6 +5316,7 @@ console.log('resizeYouTubePlayer at POS Y1');
52895316

52905317
this.timeTooltip.attr('role', 'tooltip');
52915318
this.timeTooltip.addClass('able-tooltip');
5319+
this.timeTooltip.hide();
52925320

52935321
this.bodyDiv.append(this.loadedDiv);
52945322
this.bodyDiv.append(this.playedDiv);
@@ -5699,11 +5727,11 @@ console.log('resizeYouTubePlayer at POS Y1');
56995727
'id': volumeSliderId,
57005728
'class': 'able-volume-slider',
57015729
'aria-hidden': 'true'
5702-
});
5730+
}).hide();
57035731
this.$volumeSliderTooltip = $('<div>',{
57045732
'class': 'able-tooltip',
57055733
'role': 'tooltip'
5706-
});
5734+
}).hide();
57075735
this.$volumeSliderTrack = $('<div>',{
57085736
'class': 'able-volume-track'
57095737
});
@@ -9078,7 +9106,7 @@ console.log('resizeYouTubePlayer at POS Y1');
90789106
thisObj.handleTranscriptLockToggle(thisObj.$autoScrollTranscriptCheckbox.prop('checked'));
90799107
});
90809108

9081-
this.$transcriptDiv.bind('mousewheel DOMMouseScroll click scroll', function (event) {
9109+
this.$transcriptDiv.on('mousewheel DOMMouseScroll click scroll', function (event) {
90829110
// Propagation is stopped in transcript click handler, so clicks are on the scrollbar
90839111
// or outside of a clickable span.
90849112
if (!thisObj.scrollingTranscript) {
@@ -9992,14 +10020,16 @@ console.log('resizeYouTubePlayer at POS Y1');
999210020

999310021
// returns true unless user's focus is on a UI element
999410022
// that is likely to need supported keystrokes, including space
9995-
var activeElement = $(document.activeElement).prop('tagName');
9996-
if (activeElement === 'INPUT') {
10023+
10024+
var activeElement = AblePlayer.getActiveDOMElement();
10025+
10026+
if ($(activeElement).prop('tagName') === 'INPUT') {
999710027
return false;
999810028
}
999910029
else {
1000010030
return true;
1000110031
}
10002-
}
10032+
};
1000310033

1000410034
AblePlayer.prototype.onPlayerKeyPress = function (e) {
1000510035
// handle keystrokes (using DHTML Style Guide recommended key combinations)
@@ -10022,7 +10052,7 @@ console.log('resizeYouTubePlayer at POS Y1');
1002210052
this.closePopups();
1002310053
}
1002410054
else if (which === 32) { // spacebar = play/pause
10025-
if (!($('.able-controller button').is(':focus'))) {
10055+
if (this.$ableWrapper.find('.able-controller button:focus').length === 0) {
1002610056
// only toggle play if a button does not have focus
1002710057
// if a button has focus, space should activate that button
1002810058
this.handlePlay();
@@ -10481,6 +10511,7 @@ console.log('resizeYouTubePlayer at POS Y1');
1048110511
// create an alert div and add it to window
1048210512
$windowAlert = $('<div role="alert"></div>');
1048310513
$windowAlert.addClass('able-alert');
10514+
$windowAlert.hide();
1048410515
$windowAlert.appendTo(this.$activeWindow);
1048510516
$windowAlert.css({
1048610517
top: $window.offset().top
@@ -10523,7 +10554,7 @@ console.log('resizeYouTubePlayer at POS Y1');
1052310554
$tooltip = $('<div>',{
1052410555
'class' : 'able-tooltip',
1052510556
'id' : tooltipId
10526-
});
10557+
}).hide();
1052710558
$newButton.on('mouseenter focus',function(event) {
1052810559
var label = $(this).attr('aria-label');
1052910560
// get position of this button
@@ -10537,10 +10568,10 @@ console.log('resizeYouTubePlayer at POS Y1');
1053710568
right: tooltipX + 'px',
1053810569
top: tooltipY + 'px'
1053910570
};
10540-
var tooltip = $('#' + tooltipId).text(label).css(tooltipStyle);
10571+
var tooltip = AblePlayer.localGetElementById($newButton[0], tooltipId).text(label).css(tooltipStyle);
1054110572
thisObj.showTooltip(tooltip);
1054210573
$(this).on('mouseleave blur',function() {
10543-
$('#' + tooltipId).text('').hide();
10574+
AblePlayer.localGetElementById($newButton[0], tooltipId).text('').hide();
1054410575
});
1054510576
});
1054610577

0 commit comments

Comments
 (0)