/**
 * @archivo menú.js
 * /
importar componente desde '../component.js';
importar documento desde 'global/document';
importar * como Dom desde '../utils/dom.js';
importar * como Eventos desde '../utils/events.js';
importar código clave desde 'código clave';

/**
 * El componente Menú se utiliza para crear menús emergentes, incluidos subtítulos y
 * menús de selección de subtítulos.
 *
 * Componente @extiende
 * /
El menú de clase extiende el componente {

  /**
   * Crear una instancia de esta clase.
   *
   * @param {Jugador} jugador
   * el reproductor al que debe adjuntarse este componente
   *
   * @param {Objeto} [opciones]
   * Objeto de nombres y valores de opciones
   *
   * /
  constructor(jugador, opciones) {
    super(jugador, opciones);

    si (opciones) {
      this.menuButton_ = opciones.menuButton;
    }

    this.focusedChild_ = -1;

    this.on('teclado abajo', (e) => this.handleKeyDown(e));

    // Todas las instancias de elementos de menú comparten el mismo controlador de desenfoque proporcionado por el contenedor de menú.
    this.boundHandleBlur_ = (e) => este.handleBlur(e);
    this.boundHandleTapClick_ = (e) => this.handleTapClick(e);
  }

  /**
   * Agregue detectores de eventos al {@link MenuItem}.
   *
   * @param {Objeto} componente
   * La instancia del `MenuItem` para agregar oyentes.
   *
   * /
  addEventListenerForItem(componente) {
    if (!(componente instancia de Componente)) {
      devolver;
    }

    this.on(componente, 'desenfoque', this.boundHandleBlur_);
    this.on(componente, ['toque', 'clic'], this.boundHandleTapClick_);
  }

  /**
   * Eliminar detectores de eventos del {@link MenuItem}.
   *
   * @param {Objeto} componente
   * La instancia de `MenuItem` para eliminar oyentes.
   *
   * /
  removeEventListenerForItem(componente) {
    if (!(componente instancia de Componente)) {
      devolver;
    }

    this.off(componente, 'desenfoque', this.boundHandleBlur_);
    this.off(componente, ['toque', 'clic'], this.boundHandleTapClick_);
  }

  /**
   * Este método se llamará indirectamente cuando se haya agregado el componente
   * antes de que el componente se agregue a la nueva instancia de menú mediante `addItem`.
   * En este caso, la instancia del menú original eliminará el componente
   * llamando a `removeChild`.
   *
   * @param {Objeto} componente
   * La instancia del `MenuItem`
   * /
  removeChild(componente) {
    if (tipo de componente === 'cadena') {
      componente = this.getChild(componente);
    }

    this.removeEventListenerForItem(componente);
    super.removeChild(componente);
  }

  /**
   * Agrega un {@link MenuItem} al menú.
   *
   * @param {Objeto|cadena} componente
   * El nombre o instancia del `MenuItem` para agregar.
   *
   * /
  añadirItem(componente) {
    const childComponent = this.addChild(componente);

    si (componente secundario) {
      this.addEventListenerForItem(childComponent);
    }
  }

  /**
   * Crear el elemento DOM `Menu`s.
   *
   * @return {Elemento}
   * el elemento que fue creado
   * /
  crearEl() {
    const contentElType = this.options_.contentElType || 'ul';

    this.contentEl_ = Dom.createEl(contentElType, {
      className: 'vjs-menú-contenido'
    });

    this.contentEl_.setAttribute('rol', 'menú');

    const el = super.createEl('div', {
      agregar: this.contentEl_,
      className: 'vjs-menú'
    });

    el.appendChild(this.contentEl_);

    // Evite que los clics se incrementen. Necesario para los botones de menú,
    // donde un clic en el padre es significativo
    Eventos.on(el, 'clic', función(evento) {
      event.preventDefault();
      event.stopImmediatePropagation();
    });

    volver el;
  }

  disponer () {
    this.contentEl_ = null;
    this.boundHandleBlur_ = null;
    this.boundHandleTapClick_ = null;

    super.dispose();
  }

  /**
   * Llamado cuando un `MenuItem` pierde el foco.
   *
   * @param {EventTarget~Evento} evento
   * El evento `blur` que provocó la llamada de esta función.
   *
   * @escucha borrosa
   * /
  handleBlur(evento) {
    const objetivo relacionado = evento.objetivo relacionado || documento.elementoactivo;

    // Cerrar el menú emergente cuando un usuario hace clic fuera del menú
    if (!this.children().algunos((elemento) => {
      return elemento.el() === objetivo relacionado;
    })) {
      const btn = this.menuButton_;

      si (btn && btn.buttonPressed_ && objetivo relacionado !== btn.el().firstChild) {
        btn.unpressButton();
      }
    }
  }

  /**
   * Se llama cuando se hace clic o se toca un `MenuItem`.
   *
   * @param {EventTarget~Evento} evento
   * El evento `clic` o `toque` que provocó la llamada de esta función.
   *
   * @escucha clic, toque
   * /
  handleTapClick(evento) {
    // Quite la presión del MenuButton asociado y vuelva a enfocarlo
    if (este.menuButton_) {
      este.menuButton_.unpressButton();

      const childComponents = this.children();

      if (!Array.isArray(childComponents)) {
        devolver;
      }

      const foundComponent = childComponents.filter(componente => componente.el() === evento.objetivo)[0];

      si (! componente encontrado) {
        devolver;
      }

      // no enfocar el botón de menú si el elemento es un elemento de configuración de subtítulos
      // porque el foco se moverá a otra parte
      if (foundComponent.name() !== 'CaptionSettingsMenuItem') {
        este.menuButton_.focus();
      }
    }
  }

  /**
   * Manejar un evento `keydown` en este menú. Este agente de escucha se añade al constructor.
   *
   * @param {EventTarget~Evento} evento
   * Un evento `keydown` que ocurrió en el menú.
   *
   * @escucha tecla abajo
   * /
  handleKeyDown(evento) {

    // Flechas izquierda y abajo
    if (keycode.isEventKey(evento, 'Izquierda') || keycode.isEventKey(evento, 'Abajo')) {
      event.preventDefault();
      event.stopPropagation();
      esto.pasoAdelante();

    // Flechas arriba y derecha
    } else if (keycode.isEventKey(event, 'Right') || keycode.isEventKey(event, 'Up')) {
      event.preventDefault();
      event.stopPropagation();
      esto.pasoAtrás();
    }
  }

  /**
   * Pasar al elemento de menú siguiente (inferior) para usuarios de teclado.
   * /
  un paso adelante() {
    dejar hijastro = 0;

    if (this.focusedChild_ !== indefinido) {
      hijastro = this.focusedChild_ + 1;
    }
    this.focus(hijastro);
  }

  /**
   * Mover al elemento de menú anterior (superior) para usuarios de teclado.
   * /
  Paso atrás() {
    dejar hijastro = 0;

    if (this.focusedChild_ !== indefinido) {
      hijastro = this.focusedChild_ - 1;
    }
    this.focus(hijastro);
  }

  /**
   * Establece el foco en un {@link MenuItem} en el `Menú`.
   *
   * @param {Objeto|cadena} [elemento=0]
   * Índice de enfoque de conjunto de elementos secundarios.
   * /
  enfoque (elemento = 0) {
    const niños = esto.niños().slice();
    const haveTitle = niños.longitud && children[0].hasClass('vjs-menu-title');

    si (tener título) {
      niños.shift();
    }

    if (niños.longitud > 0) {
      si (elemento < 0) {
        artículo = 0;
      } más si (elemento > = niños.longitud) {
        elemento = niños.longitud - 1;
      }

      this.focusedChild_ = artículo;

      niños[elemento].el_.focus();
    }
  }
}

Componente.registerComponent('Menú', Menú);
Exportar menú predeterminado;