From 7e4963fdf7ca3120c6c1af1a7b5600953c4f3b6c Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Tue, 29 Jul 2025 22:06:57 -0500 Subject: [PATCH 1/2] Work in Progress prototype This is a prototype to simplify toggling popups. But it's proving to be a hassle, because of how differently these work. --- scripts/control.js | 89 ++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/scripts/control.js b/scripts/control.js index 07e1a5cc..d2f6cfa4 100644 --- a/scripts/control.js +++ b/scripts/control.js @@ -1211,29 +1211,15 @@ this.refreshControls('captions'); } else { + this.togglePopup(this.captionsPopup, this.$ccButton, !this.captionsPopup.is(':visible')); // there is more than one caption track. // clicking on a track is handled via caption.js > getCaptionClickFunction() - if (this.captionsPopup && this.captionsPopup.is(':visible')) { - this.captionsPopup.hide(); - this.hidingPopup = false; - this.$ccButton.attr('aria-expanded', 'false') - this.waitThenFocus(this.$ccButton); - } - else { - this.closePopups(); - if (this.captionsPopup) { - this.captionsPopup.show(); - this.$ccButton.attr('aria-expanded','true'); - - // Gives time to "register" expanded ccButton - setTimeout(function() { - thisObj.captionsPopup.css('top', thisObj.$ccButton.position().top - thisObj.captionsPopup.outerHeight()); - thisObj.captionsPopup.css('left', thisObj.$ccButton.position().left) - // Place focus on the first button (even if another button is checked) - thisObj.captionsPopup.find('li').removeClass('able-focus'); - thisObj.captionsPopup.find('li').first().trigger('focus').addClass('able-focus'); - }, 50); - } + if ( this.captionsPopup.is(':visible') ) { + // Gives time to "register" expanded ccButton + setTimeout(function() { + // Position popup & remove existing able-focus classes. + thisObj.captionsPopup.find('li').removeClass('able-focus'); + }, 50); } } }; @@ -1262,18 +1248,8 @@ this.hidingPopup = false; return false; } - if (this.chaptersPopup.is(':visible')) { - this.chaptersPopup.hide(); - this.hidingPopup = false; - this.$chaptersButton.attr('aria-expanded','false').trigger('focus'); - } - else { - this.closePopups(); - this.chaptersPopup.show(); - this.$chaptersButton.attr('aria-expanded','true'); - this.chaptersPopup.css('top', this.$chaptersButton.position().top - this.chaptersPopup.outerHeight()); - this.chaptersPopup.css('left', this.$chaptersButton.position().left) - + this.togglePopup( this.chaptersPopup, this.$chaptersButton, !this.chaptersPopup.is(':visible') ); + if ( this.chaptersPopup.is(':visible') ) { // Highlight the current chapter, if any chapters are checked // Otherwise, place focus on the first chapter this.chaptersPopup.find('li').removeClass('able-focus'); @@ -1326,9 +1302,8 @@ this.hidingPopup = false; return false; } + this.togglePopup(this.prefsPopup, this.$prefsButton, !this.prefsPopup.is(':visible') ); if (this.prefsPopup.is(':visible')) { - this.prefsPopup.hide(); - this.$prefsButton.attr('aria-expanded','false'); // restore each menu item to original hidden state this.prefsPopup.find('li').removeClass('able-focus').attr('tabindex','-1'); if (!this.showingPrefsDialog) { @@ -1340,17 +1315,9 @@ },100); } else { - this.closePopups(); - this.prefsPopup.show(); - this.$prefsButton.attr('aria-expanded','true'); this.$prefsButton.trigger('focus'); // focus first on prefs button to announce expanded state // give time for focus on button then adjust popup settings and focus setTimeout(function() { - prefsButtonPosition = thisObj.$prefsButton.position(); - prefsMenuRight = thisObj.$ableDiv.width() - 5; - prefsMenuLeft = prefsMenuRight - thisObj.prefsPopup.width(); - thisObj.prefsPopup.css('top', prefsButtonPosition.top - thisObj.prefsPopup.outerHeight()); - thisObj.prefsPopup.css('left', prefsMenuLeft); // remove prior focus and set focus on first item; also change tabindex from -1 to 0 thisObj.prefsPopup.find('li').removeClass('able-focus').attr('tabindex','0'); thisObj.prefsPopup.find('li').first().trigger('focus').addClass('able-focus'); @@ -1658,6 +1625,42 @@ } }; + AblePlayer.prototype.togglePopup = function($popup, $button, show, focusSelector = 'li:first') { + if (show) { + this.closePopups(); + $popup.show(); + $button.attr('aria-expanded', 'true'); + setTimeout(() => { + $popup.find(focusSelector).trigger('focus').addClass('able-focus'); + }, 50); + // Position popup. + var position = isElementOutOfParentBounds( $popup, this.$ableWrapper ); + console.log( position ); + $popup.css('top', $button.position().top - $popup.outerHeight()); + $popup.css('left', $button.position().left ); + } else { + $popup.hide(); + $button.attr('aria-expanded', 'false'); + this.waitThenFocus( $button ); + } + + function isElementOutOfParentBounds($child, $parent) { + let childElement = $child.get(0); + let parentClement = $parent.get(0); + const childRect = childElement.getBoundingClientRect(); + const parentRect = parentElement.getBoundingClientRect(); + + if ( childRect.left > parentRect.left ) { + return ( childRect.left - parentRect.left ) * -1; + } + if ( childRect.right < parentRect.right ) { + return parentRect.right - childRect.right; + } + + return false; + } + }; + AblePlayer.prototype.showTooltip = function($tooltip) { if (($tooltip).is(':animated')) { From dfb03dd93f8b06313fc5441662383d8e1bf0898b Mon Sep 17 00:00:00 2001 From: Joe Dolson Date: Tue, 29 Jul 2025 22:13:42 -0500 Subject: [PATCH 2/2] Works, but it's buggy. --- scripts/control.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/scripts/control.js b/scripts/control.js index d2f6cfa4..731edea2 100644 --- a/scripts/control.js +++ b/scripts/control.js @@ -1635,9 +1635,14 @@ }, 50); // Position popup. var position = isElementOutOfParentBounds( $popup, this.$ableWrapper ); + var leftPosition = $button.position().left; + if ( position ) { + position = -1 * position; + var leftPosition = leftPosition - position - 8; + } console.log( position ); $popup.css('top', $button.position().top - $popup.outerHeight()); - $popup.css('left', $button.position().left ); + $popup.css('left', leftPosition ); } else { $popup.hide(); $button.attr('aria-expanded', 'false'); @@ -1646,14 +1651,17 @@ function isElementOutOfParentBounds($child, $parent) { let childElement = $child.get(0); - let parentClement = $parent.get(0); + let parentElement = $parent.get(0); const childRect = childElement.getBoundingClientRect(); const parentRect = parentElement.getBoundingClientRect(); - if ( childRect.left > parentRect.left ) { - return ( childRect.left - parentRect.left ) * -1; + // Is outside container to the left. + if ( childRect.left < parentRect.left ) { + // I'm not sure there's a case where this would happen. + return ( childRect.left - parentRect.left ); } - if ( childRect.right < parentRect.right ) { + // Is outside container to the right. + if ( childRect.right > parentRect.right ) { return parentRect.right - childRect.right; }