mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-25 17:45:03 +03:00
abd8b3b43a
Without listing them individually, the controls CSS now applies the correct styles to all submenus. This makes it easier for apps to subclass SettingsMenu without needing to add explicit CSS to achieve the same styling as the built-in menus. Closes #2925 Change-Id: Ie1e1536dc4806576d7ed22dfc8feb17abaa72152
239 lines
6.6 KiB
JavaScript
239 lines
6.6 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
|
|
goog.provide('shaka.ui.OverflowMenu');
|
|
|
|
goog.require('goog.asserts');
|
|
goog.require('shaka.ads.AdManager');
|
|
goog.require('shaka.log');
|
|
goog.require('shaka.ui.Constants');
|
|
goog.require('shaka.ui.Controls');
|
|
goog.require('shaka.ui.Element');
|
|
goog.require('shaka.ui.Enums');
|
|
goog.require('shaka.ui.Locales');
|
|
goog.require('shaka.ui.Localization');
|
|
goog.require('shaka.ui.Utils');
|
|
goog.require('shaka.util.Dom');
|
|
goog.require('shaka.util.Iterables');
|
|
|
|
|
|
/**
|
|
* @extends {shaka.ui.Element}
|
|
* @final
|
|
* @export
|
|
*/
|
|
shaka.ui.OverflowMenu = class extends shaka.ui.Element {
|
|
/**
|
|
* @param {!HTMLElement} parent
|
|
* @param {!shaka.ui.Controls} controls
|
|
*/
|
|
constructor(parent, controls) {
|
|
super(parent, controls);
|
|
|
|
/** @private {!shaka.extern.UIConfiguration} */
|
|
this.config_ = this.controls.getConfig();
|
|
|
|
/** @private {HTMLElement} */
|
|
this.controlsContainer_ = this.controls.getControlsContainer();
|
|
|
|
/** @private {!Array.<shaka.extern.IUIElement>} */
|
|
this.children_ = [];
|
|
|
|
this.addOverflowMenuButton_();
|
|
|
|
this.addOverflowMenu_();
|
|
|
|
this.createChildren_();
|
|
|
|
|
|
const backToOverflowMenuButtons =
|
|
this.controls.getVideoContainer().getElementsByClassName(
|
|
'shaka-back-to-overflow-button');
|
|
|
|
for (const button of backToOverflowMenuButtons) {
|
|
this.eventManager.listen(button, 'click', () => {
|
|
// Hide the submenus, display the overflow menu
|
|
this.controls.hideSettingsMenus();
|
|
shaka.ui.Utils.setDisplay(this.overflowMenu_, true);
|
|
|
|
// If there are back to overflow menu buttons, there must be
|
|
// overflow menu buttons, but oh well
|
|
if (this.overflowMenu_.childNodes.length) {
|
|
/** @type {!HTMLElement} */ (this.overflowMenu_.childNodes[0])
|
|
.focus();
|
|
}
|
|
|
|
// Make sure controls are displayed
|
|
this.controls.computeOpacity();
|
|
});
|
|
}
|
|
|
|
this.eventManager.listen(
|
|
this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
|
|
this.updateAriaLabel_();
|
|
});
|
|
|
|
this.eventManager.listen(
|
|
this.localization, shaka.ui.Localization.LOCALE_CHANGED, () => {
|
|
this.updateAriaLabel_();
|
|
});
|
|
|
|
this.eventManager.listen(
|
|
this.adManager, shaka.ads.AdManager.AD_STARTED, () => {
|
|
shaka.ui.Utils.setDisplay(this.overflowMenuButton_, false);
|
|
});
|
|
|
|
this.eventManager.listen(
|
|
this.adManager, shaka.ads.AdManager.AD_STOPPED, () => {
|
|
shaka.ui.Utils.setDisplay(this.overflowMenuButton_, true);
|
|
});
|
|
|
|
|
|
this.eventManager.listen(
|
|
this.controls, 'submenuopen', () => {
|
|
// Hide the main overflow menu if one of the sub menus has
|
|
// been opened.
|
|
shaka.ui.Utils.setDisplay(this.overflowMenu_, false);
|
|
});
|
|
|
|
|
|
this.eventManager.listen(
|
|
this.overflowMenu_, 'touchstart', (event) => {
|
|
this.controls.setLastTouchEventTime(Date.now());
|
|
event.stopPropagation();
|
|
});
|
|
|
|
this.eventManager.listen(this.overflowMenuButton_, 'click', () => {
|
|
this.onOverflowMenuButtonClick_();
|
|
});
|
|
|
|
this.updateAriaLabel_();
|
|
}
|
|
|
|
/** @override */
|
|
release() {
|
|
this.controlsContainer_ = null;
|
|
|
|
for (const element of this.children_) {
|
|
element.release();
|
|
}
|
|
|
|
this.children_ = [];
|
|
super.release();
|
|
}
|
|
|
|
/**
|
|
* @param {string} name
|
|
* @param {!shaka.extern.IUIElement.Factory} factory
|
|
* @export
|
|
*/
|
|
static registerElement(name, factory) {
|
|
shaka.ui.OverflowMenu.elementNamesToFactories_.set(name, factory);
|
|
}
|
|
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
addOverflowMenu_() {
|
|
/** @private {!HTMLElement} */
|
|
this.overflowMenu_ = shaka.util.Dom.createHTMLElement('div');
|
|
this.overflowMenu_.classList.add('shaka-overflow-menu');
|
|
this.overflowMenu_.classList.add('shaka-no-propagation');
|
|
this.overflowMenu_.classList.add('shaka-show-controls-on-mouse-over');
|
|
this.overflowMenu_.classList.add('shaka-hidden');
|
|
this.controlsContainer_.appendChild(this.overflowMenu_);
|
|
}
|
|
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
addOverflowMenuButton_() {
|
|
/** @private {!HTMLButtonElement} */
|
|
this.overflowMenuButton_ = shaka.util.Dom.createButton();
|
|
this.overflowMenuButton_.classList.add('shaka-overflow-menu-button');
|
|
this.overflowMenuButton_.classList.add('shaka-no-propagation');
|
|
this.overflowMenuButton_.classList.add('material-icons-round');
|
|
this.overflowMenuButton_.textContent =
|
|
shaka.ui.Enums.MaterialDesignIcons.OPEN_OVERFLOW;
|
|
this.parent.appendChild(this.overflowMenuButton_);
|
|
}
|
|
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
createChildren_() {
|
|
for (const name of this.config_.overflowMenuButtons) {
|
|
if (shaka.ui.OverflowMenu.elementNamesToFactories_.get(name)) {
|
|
const factory =
|
|
shaka.ui.OverflowMenu.elementNamesToFactories_.get(name);
|
|
goog.asserts.assert(this.controls, 'Controls should not be null!');
|
|
this.children_.push(factory.create(this.overflowMenu_, this.controls));
|
|
} else {
|
|
shaka.log.alwaysWarn('Unrecognized overflow menu element requested:',
|
|
name);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/** @private */
|
|
onOverflowMenuButtonClick_() {
|
|
if (this.controls.anySettingsMenusAreOpen()) {
|
|
this.controls.hideSettingsMenus();
|
|
} else {
|
|
shaka.ui.Utils.setDisplay(this.overflowMenu_, true);
|
|
this.controls.computeOpacity();
|
|
|
|
// If overflow menu has currently visible buttons, focus on the
|
|
// first one, when the menu opens.
|
|
const isDisplayed =
|
|
(element) => element.classList.contains('shaka-hidden') == false;
|
|
|
|
const Iterables = shaka.util.Iterables;
|
|
if (Iterables.some(this.overflowMenu_.childNodes, isDisplayed)) {
|
|
// Focus on the first visible child of the overflow menu
|
|
const visibleElements =
|
|
Iterables.filter(this.overflowMenu_.childNodes, isDisplayed);
|
|
/** @type {!HTMLElement} */ (visibleElements[0]).focus();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
updateAriaLabel_() {
|
|
const LocIds = shaka.ui.Locales.Ids;
|
|
this.overflowMenuButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
|
|
this.localization.resolve(LocIds.MORE_SETTINGS));
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @implements {shaka.extern.IUIElement.Factory}
|
|
* @final
|
|
*/
|
|
shaka.ui.OverflowMenu.Factory = class {
|
|
/** @override */
|
|
create(rootElement, controls) {
|
|
return new shaka.ui.OverflowMenu(rootElement, controls);
|
|
}
|
|
};
|
|
|
|
shaka.ui.Controls.registerElement(
|
|
'overflow_menu', new shaka.ui.OverflowMenu.Factory());
|
|
|
|
|
|
/** @private {!Map.<string, !shaka.extern.IUIElement.Factory>} */
|
|
shaka.ui.OverflowMenu.elementNamesToFactories_ = new Map();
|
|
|