/**
* @file menú-botón.js
* /
importar botón desde '../button.js';
importar componente desde '../component.js';
importar menú desde './menu.js';
importar * como Dom desde '../utils/dom.js';
importar * como Eventos desde '../utils/events.js';
importar {toTitleCase} desde '../utils/string-cases.js';
importar { IS_IOS } desde '../utils/browser.js';
importar documento desde 'global/document';
importar código clave desde 'código clave';
/**
* Una clase `MenuButton` para cualquier ventana emergente {@link Menu}.
*
* Componente @extiende
* /
class MenuButton extiende Componente {
/**
* Crea una instancia de esta clase.
*
* @param {Jugador} jugador
* El `Jugador` al que se debe adjuntar esta clase.
*
* @param {Objeto} [opciones={}]
* El almacén de clave/valor de las opciones del jugador.
* /
constructor(jugador, opciones = {}) {
super(jugador, opciones);
this.menuButton_ = new Button(jugador, opciones);
este.menuButton_.controlText(este.controlText_);
this.menuButton_.el_.setAttribute('aria-haspopup', 'true');
// Agregar valores de buildCSSClass al botón, no al envoltorio
const buttonClass = Button.prototype.buildCSSClass();
this.menuButton_.el_.className = this.buildCSSClass() + ' ' + buttonClass;
this.menuButton_.removeClass('vjs-control');
this.addChild(this.menuButton_);
esta.actualización();
esto.habilitado_ = verdadero;
const handleClick = (e) => this.handleClick(e);
this.handleMenuKeyUp_ = (e) => this.handleMenuKeyUp(e);
this.on(this.menuButton_, 'tocar', handleClick);
this.on(this.menuButton_, 'clic', handleClick);
this.on(this.menuButton_, 'keydown', (e) => this.handleKeyDown(e));
this.on(this.menuButton_, 'mouseenter', () => {
this.addClass('vjs-hover');
este.menú.mostrar();
Events.on(document, 'keyup', this.handleMenuKeyUp_);
});
this.on('mouseleave', (e) => this.handleMouseLeave(e));
this.on('teclado abajo', (e) => this.handleSubmenuKeyDown(e));
}
/**
* Actualice el menú según el estado actual de sus elementos.
* /
actualizar() {
const menu = this.createMenu();
si (este.menú) {
este.menu.dispose();
this.removeChild(this.menu);
}
este.menu = menú;
this.addChild(menú);
/**
* Seguimiento del estado del botón de menú
*
* @tipo {Booleano}
* @privado
* /
this.buttonPressed_ = false;
this.menuButton_.el_.setAttribute('aria-expanded', 'false');
si (este.elementos && este.artículos.longitud < = this.hideThreshold_) {
esto. ocultar ();
this.menu.contentEl_.removeAttribute('rol');
} else {
este espectáculo();
this.menu.contentEl_.setAttribute('rol', 'menú');
}
}
/**
* Cree el menú y agréguele todos los elementos.
*
* @return {Menú}
* El menú construido
* /
crearMenu() {
const menu = new Menu(this.player_, { menuButton: this });
/**
* Ocultar el menú si el número de elementos es menor o igual a este umbral. esto por defecto
* a 0 y cada vez que agreguemos elementos que se pueden ocultar en el menú, lo incrementaremos. Listamos
* aquí porque cada vez que ejecutamos `createMenu` necesitamos restablecer el valor.
*
* @protegido
* @teclea un número}
* /
este.hideThreshold_ = 0;
// Agregar un elemento de la lista de títulos en la parte superior
if (esta.opciones_.título) {
const tituloEl = Dom.createEl('li', {
className: 'vjs-menú-título',
textContent: toTitleCase(this.options_.title),
índice de tabulación: -1
});
const titleComponent = new Component(this.player_, {el: titleEl});
menu.addItem(componentetítulo);
}
this.items = this.createItems();
si (este.elementos) {
// Agregar elementos de menú al menú
para (sea i = 0; i < this.items.length; i++) {
menu.addItem(this.items[i]);
}
}
menú de retorno;
}
/**
* Crear la lista de elementos del menú. Específico para cada subclase.
*
* @abstracto
* /
crear elementos () {}
/**
* Crear el elemento DOM `MenuButtons`.
*
* @return {Elemento}
* El elemento que se crea.
* /
crearEl() {
return super.createEl('div', {
nombre de clase: this.buildWrapperCSSClass()
}, {
});
}
/**
* Permitir que los subcomponentes apilen nombres de clase CSS para el elemento contenedor
*
* @return {cadena}
* El envoltorio construido DOM `className`
* /
buildWrapperCSSClass() {
let menuButtonClass = 'vjs-menu-button';
// Si se pasa la opción en línea, queremos usar estilos diferentes por completo.
if (this.options_.inline === verdadero) {
menuButtonClass += '-en línea';
} else {
menuButtonClass += '-popup';
}
// HACER: Arregle el CSS para que esto no sea necesario
const buttonClass = Button.prototype.buildCSSClass();
return `vjs-menu-button ${menuButtonClass} ${buttonClass} ${super.buildCSSClass()}`;
}
/**
* Construye el DOM predeterminado `className`.
*
* @return {cadena}
* El DOM `className` para este objeto.
* /
construirClaseCSS() {
let menuButtonClass = 'vjs-menu-button';
// Si se pasa la opción en línea, queremos usar estilos diferentes por completo.
if (this.options_.inline === verdadero) {
menuButtonClass += '-en línea';
} else {
menuButtonClass += '-popup';
}
return `vjs-menu-button ${menuButtonClass} ${super.buildCSSClass()}`;
}
/**
* Obtener o establecer el texto de control localizado que se utilizará para la accesibilidad.
*
* > NOTA: Esto vendrá del elemento interno `menuButton_`.
*
* @param {cadena} [texto]
* Texto de control para el elemento.
*
* @param {Elemento} [el=this.menuButton_.el()]
* Elemento para configurar el título.
*
* @return {cadena}
* - El texto de control al obtener
* /
controlText(texto, el = this.menuButton_.el()) {
devuelve este.menuButton_.controlText(texto, el);
}
/**
* Deseche el "botón de menú" y todos los componentes secundarios.
* /
disponer () {
this.handleMouseLeave();
super.dispose();
}
/**
* Manejar un clic en un `MenuButton`.
* Consulte {@link ClickableComponent#handleClick} para conocer las instancias en las que se llama.
*
* @param {EventTarget~Evento} evento
* El evento `keydown`, `top` o `click` que hizo que esta función se desactivara
* llamado.
*
* @escucha toca
* @escucha clic
* /
handleClick(evento) {
if (este.botonPresionado_) {
este.unpressButton();
} else {
este.presioneBoton();
}
}
/**
* Manejar `mouseleave` para `MenuButton`.
*
* @param {EventTarget~Evento} evento
* El evento `mouseleave` que provocó la llamada de esta función.
*
* @escucha mouseleave
* /
handleMouseLeave(evento) {
this.removeClass('vjs-hover');
Events.off(document, 'keyup', this.handleMenuKeyUp_);
}
/**
* Establecer el enfoque en el botón real, no en este elemento
* /
enfocar() {
este.menuButton_.focus();
}
/**
* Eliminar el foco del botón real, no de este elemento
* /
difuminar() {
este.menuButton_.blur();
}
/**
* Manejar las teclas de tabulador, escape, flecha abajo y flecha arriba para `MenuButton`. Ver
* {@link ClickableComponent#handleKeyDown} para instancias donde se llama esto.
*
* @param {EventTarget~Evento} evento
* El evento `keydown` que hizo que se llamara a esta función.
*
* @escucha tecla abajo
* /
handleKeyDown(evento) {
// Escape o Tab despresiona el 'botón'
if (keycode.isEventKey(evento, 'Esc') || keycode.isEventKey(evento, 'Tab')) {
if (este.botonPresionado_) {
este.unpressButton();
}
// No prevenga Predeterminado para la tecla Tabulador: aún queremos perder el foco
if (!keycode.isEventKey(evento, 'Tab')) {
event.preventDefault();
// Vuelva a poner el foco en el botón del botón de menú
este.menuButton_.focus();
}
// Flecha arriba o flecha abajo también 'presiona' el botón para abrir el menú
} else if (keycode.isEventKey(evento, 'Arriba') || keycode.isEventKey(evento, 'Abajo')) {
if (!this.buttonPressed_) {
event.preventDefault();
este.presioneBoton();
}
}
}
/**
* Manejar un evento `keyup` en un `MenuButton`. El oyente para esto se agrega en
* el constructor.
*
* @param {EventTarget~Evento} evento
* Evento de pulsación de tecla
*
* @escucha teclado
* /
handleMenuKeyUp(evento) {
// Escape oculta el menú emergente
if (keycode.isEventKey(evento, 'Esc') || keycode.isEventKey(evento, 'Tab')) {
this.removeClass('vjs-hover');
}
}
/**
* Este nombre de método ahora se delega a `handleSubmenuKeyDown`. Esto significa
* cualquiera que llame a `handleSubmenuKeyPress` no verá sus llamadas a métodos
* para de trabajar.
*
* @param {EventTarget~Evento} evento
* El evento que provocó la llamada de esta función.
* /
handleSubmenuKeyPress(evento) {
this.handleSubmenuKeyDown(evento);
}
/**
* Manejar un evento `keydown` en un submenú. El oyente para esto se agrega en
* el constructor.
*
* @param {EventTarget~Evento} evento
* Evento de pulsación de tecla
*
* @escucha tecla abajo
* /
handleSubmenuKeyDown(evento) {
// Escape o Tab despresiona el 'botón'
if (keycode.isEventKey(evento, 'Esc') || keycode.isEventKey(evento, 'Tab')) {
if (este.botonPresionado_) {
este.unpressButton();
}
// No prevenga Predeterminado para la tecla Tabulador: aún queremos perder el foco
if (!keycode.isEventKey(evento, 'Tab')) {
event.preventDefault();
// Vuelva a poner el foco en el botón del botón de menú
este.menuButton_.focus();
}
} else {
// NOTA: Este es un caso especial en el que no pasamos desapercibidos
// eventos keydown hasta el controlador de componentes, porque es
// acaba de entender el manejo del teclado del `MenuItem`
// en el `Menú` que ya pasa las teclas no utilizadas.
}
}
/**
* Poner el `MenuButton` actual en un estado presionado.
* /
presiona el botón() {
si (esto.habilitado_) {
this.buttonPressed_ = verdadero;
este.menú.mostrar();
this.menu.lockMostrando();
this.menuButton_.el_.setAttribute('aria-expanded', 'true');
// establezca el enfoque en el submenú, excepto en iOS, donde resulta en
// comportamiento de desplazamiento no deseado cuando el jugador está en un iframe
si (IS_IOS && Dom.isInFrame()) {
//Regresa temprano para que el menu no este enfocado
devolver;
}
este.menú.focus();
}
}
/**
* Saca el `MenuButton` actual de un estado presionado.
* /
despresionarBoton() {
si (esto.habilitado_) {
this.buttonPressed_ = false;
this.menu.unlockMostrando();
este.menu.hide();
this.menuButton_.el_.setAttribute('aria-expanded', 'false');
}
}
/**
* Deshabilite el `MenuButton`. No permita que se haga clic en él.
* /
desactivar() {
este.unpressButton();
esto.habilitado_ = falso;
this.addClass('vjs-disabled');
este.menuButton_.disable();
}
/**
* Habilite el `MenuButton`. Permita que se haga clic en él.
* /
permitir() {
esto.habilitado_ = verdadero;
this.removeClass('vjs-disabled');
este.menuButton_.enable();
}
}
Componente.registerComponent('MenuButton', MenuButton);
exportar el botón de menú predeterminado;