bitmovin-player-ui
Version:
Bitmovin Player UI Framework
120 lines (106 loc) • 4.09 kB
text/typescript
import { ToggleButton, ToggleButtonConfig } from '../buttons/ToggleButton';
import { SettingsPanel, SettingsPanelConfig } from './SettingsPanel';
import { UIInstanceManager } from '../../UIManager';
import { Component, ComponentConfig } from '../Component';
import { ArrayUtils } from '../../utils/ArrayUtils';
import { PlayerAPI } from 'bitmovin-player';
import { i18n } from '../../localization/i18n';
/**
* Configuration interface for the {@link SettingsToggleButton}.
*
* @category Configs
*/
export interface SettingsToggleButtonConfig extends ToggleButtonConfig {
/**
* The settings panel whose visibility the button should toggle.
*/
settingsPanel: SettingsPanel<SettingsPanelConfig>;
/**
* Decides if the button should be automatically hidden when the settings panel does not contain any active settings.
* Default: true
*/
autoHideWhenNoActiveSettings?: boolean;
}
/**
* A button that toggles visibility of a settings panel.
*
* @category Buttons
*/
export class SettingsToggleButton extends ToggleButton<SettingsToggleButtonConfig> {
private visibleSettingsPanels: SettingsPanel<SettingsPanelConfig>[] = [];
constructor(config: SettingsToggleButtonConfig) {
super(config);
if (!config.settingsPanel) {
throw new Error('Required SettingsPanel is missing');
}
this.config = this.mergeConfig(
config,
{
cssClass: 'ui-settingstogglebutton',
text: i18n.getLocalizer('settings'),
settingsPanel: null,
autoHideWhenNoActiveSettings: true,
role: 'pop-up button',
},
<SettingsToggleButtonConfig>this.config,
);
/**
* WCAG20 standard defines which popup menu (element id) is owned by the button
*/
this.getDomElement().attr('aria-owns', config.settingsPanel.getActivePage().getConfig().id);
/**
* WCAG20 standard defines that a button has a popup menu bound to it
*/
this.getDomElement().attr('aria-haspopup', 'true');
}
configure(player: PlayerAPI, uimanager: UIInstanceManager): void {
super.configure(player, uimanager);
const config = this.getConfig();
const settingsPanel = config.settingsPanel;
this.onClick.subscribe(() => {
// only hide other `SettingsPanel`s if a new one will be opened
if (!settingsPanel.isShown()) {
// Hide all open SettingsPanels before opening this button's panel
// (We need to iterate a copy because hiding them will automatically remove themselves from the array
// due to the subscribeOnce above)
this.visibleSettingsPanels.slice().forEach(settingsPanel => settingsPanel.hide());
}
settingsPanel.toggleHidden();
});
settingsPanel.onShow.subscribe(() => {
// Set toggle status to on when the settings panel shows
this.on();
});
settingsPanel.onHide.subscribe(() => {
// Set toggle status to off when the settings panel hides
this.off();
});
// Ensure that only one `SettingPanel` is visible at once
// Keep track of shown SettingsPanels
uimanager.onComponentShow.subscribe((sender: Component<ComponentConfig>) => {
if (sender instanceof SettingsPanel) {
this.visibleSettingsPanels.push(sender);
sender.onHide.subscribeOnce(() => ArrayUtils.remove(this.visibleSettingsPanels, sender));
}
});
// Handle automatic hiding of the button if there are no settings for the user to interact with
if (config.autoHideWhenNoActiveSettings) {
// Setup handler to show/hide button when the settings change
const settingsPanelItemsChangedHandler = () => {
if (settingsPanel.rootPageHasActiveSettings()) {
if (this.isHidden()) {
this.show();
}
} else {
if (this.isShown()) {
this.hide();
}
}
};
// Wire the handler to the event
settingsPanel.onSettingsStateChanged.subscribe(settingsPanelItemsChangedHandler);
// Call handler for first init at startup
settingsPanelItemsChangedHandler();
}
}
}