/**
 * @file 菜單按鈕.js
 */
從 '../button.js' 導入按鈕;
從 '../component.js' 導入組件;
從 './menu.js' 導入菜單;
import * as Dom from '../utils/dom.js';
import * as Events from '../utils/events.js';
從 '../utils/string-cases.js' 導入 {toTitleCase};
從'../utils/browser.js'導入{IS_IOS};
從“全局/文檔”導入文檔;
從“鍵碼”導入鍵碼;

/**
 * 任何彈出菜單 {@link Menu} 的 `MenuButton` 類。
 *
 * @extends 組件
 */
類 MenuButton 擴展組件 {

  /**
   * 創建此類的一個實例。
   *
   * @param {Player} 播放器
   * 此類應附加到的 `Player`。
   *
   * @param {對象} [選項={}]
   * 播放器選項的鍵/值存儲。
   */
  構造函數(播放器,選項= {}){
    超級(播放器,選項);

    this.menuButton_ = new Button(player, options);

    this.menuButton_.controlText(this.controlText_);
    this.menuButton_.el_.setAttribute('aria-haspopup', 'true');

    // 將 buildCSSClass 值添加到按鈕,而不是包裝器
    const buttonClass = Button.prototype.buildCSSClass();

    this.menuButton_.el_.className = this.buildCSSClass() + ' ' + buttonClass;
    this.menuButton_.removeClass('vjs-control');

    this.addChild(this.menuButton_);

    這個.更新();

    this.enabled_ = true;

    const handleClick = (e) => this.handleClick(e);

    this.handleMenuKeyUp_ = (e) => this.handleMenuKeyUp(e);

    this.on(this.menuButton_, 'tap', handleClick);
    this.on(this.menuButton_, 'click', handleClick);
    this.on(this.menuButton_, 'keydown', (e) => this.handleKeyDown(e));
    this.on(this.menuButton_, 'mouseenter', () => {
      this.addClass('vjs-懸停');
      這個.menu.show();
      Events.on(文檔, 'keyup', this.handleMenuKeyUp_);
    });
    this.on('mouseleave', (e) => this.handleMouseLeave(e));
    this.on('keydown', (e) => this.handleSubmenuKeyDown(e));
  }

  /**
   * 根據項目的當前狀態更新菜單。
   */
  更新() {
    const menu = this.createMenu();

    如果(這個。菜單){
      這個.menu.dispose();
      this.removeChild(this.menu);
    }

    this.menu = 菜單;
    這個.addChild(菜單);

    /**
     * 跟踪菜單按鈕的狀態
     *
     * @type {布爾}
     * @私人的
     */
    this.buttonPressed_ = false;
    this.menuButton_.el_.setAttribute('aria-expanded', 'false');

    如果(this.items && this.items.length <= this.hideThreshold_){
      這個。隱藏();
      this.menu.contentEl_.removeAttribute('角色');

    }其他{
      這個。顯示();
      this.menu.contentEl_.setAttribute('角色', '菜單');
    }
  }

  /**
   * 創建菜單並向其中添加所有項目。
   *
   * @return {菜單}
   * 構建的菜單
   */
  創建菜單(){
    const menu = new Menu(this.player_, { menuButton: this });

    /**
     * 如果項目數小於或等於此閾值,則隱藏菜單。這默認
     * 到 0,每當我們將可以隱藏的項目添加到菜單時,我們都會增加它。我們列出
     * 在這裡是因為每次我們運行 `createMenu` 時我們都需要重置這個值。
     *
     * @protected
     * @type {數字}
     */
    this.hideThreshold_ = 0;

    // 在頂部添加一個標題列表項
    如果(this.options_.title){
      const titleEl = Dom.createEl('li', {
        className: 'vjs-菜單標題',
        textContent: toTitleCase(this.options_.title),
        選項卡索引:-1
      });

      const titleComponent = new Component(this.player_, {el: titleEl});

      menu.addItem(titleComponent);
    }

    this.items = this.createItems();

    如果(這個。項目){
      // 添加菜單項到菜單
      for (let i = 0; i < this.items.length; i++) {
        menu.addItem(this.items[i]);
      }
    }

    返回菜單;
  }

  /**
   * 創建菜單項列表。具體到每個子類。
   *
   * @抽象的
   */
  創建項目(){}

  /**
   * 創建 `MenuButtons` 的 DOM 元素。
   *
   * @return {元素}
   * 被創建的元素。
   */
  創建El() {
    返回 super.createEl('div', {
      類名:this.buildWrapperCSSClass()
    },{
    });
  }

  /**
   * 允許子組件為 wrapper 元素堆疊 CSS 類名
   *
   * @return {字符串}
   * 構造的包裝器 DOM `className`
   */
  buildWrapperCSSClass() {
    讓 menuButtonClass = 'vjs-menu-button';

    // 如果傳遞了內聯選項,我們希望完全使用不同的樣式。
    如果(this.options_.inline === true){
      menuButtonClass += '-inline';
    }其他{
      menuButtonClass += '-popup';
    }

    // 去做:修復 CSS,這樣就沒有必要了
    const buttonClass = Button.prototype.buildCSSClass();

    返回`vjs-menu-button ${menuButtonClass} ${buttonClass} ${super.buildCSSClass()}`;
  }

  /**
   * 構建默認的 DOM `className`。
   *
   * @return {字符串}
   * 此對象的 DOM `className`。
   */
  buildCSSClass() {
    讓 menuButtonClass = 'vjs-menu-button';

    // 如果傳遞了內聯選項,我們希望完全使用不同的樣式。
    如果(this.options_.inline === true){
      menuButtonClass += '-inline';
    }其他{
      menuButtonClass += '-popup';
    }

    返回`vjs-menu-button ${menuButtonClass} ${super.buildCSSClass()}`;
  }

  /**
   * 獲取或設置將用於輔助功能的本地化控製文本。
   *
   * > 注意:這將來自內部的 `menuButton_` 元素。
   *
   * @param {字符串} [文本]
   * 元素的控製文本。
   *
   * @param {Element} [el=this.menuButton_.el()]
   * 設置標題的元素。
   *
   * @return {字符串}
   * - 獲取時的控製文本
   */
  controlText(text, el = this.menuButton_.el()) {
    返回 this.menuButton_.controlText(text, el);
  }

  /**
   * 處理 `menu-button` 和所有子組件。
   */
  處置(){
    this.handleMouseLeave();
    super.dispose();
  }

  /**
   * 處理對 `MenuButton` 的點擊。
   * 請參閱 {@link ClickableComponent#handleClick} 以了解調用此方法的實例。
   *
   * @param {EventTarget~Event} 事件
   * 導致此功能被執行的 `keydown`、`tap` 或 `click` 事件
   * 打電話。
   *
   * @listens 水龍頭
   * @listens 點擊
   */
  handleClick(事件){
    如果(this.buttonPressed_){
      這個.unpressButton();
    }其他{
      這個.pressButton();
    }
  }

  /**
   * 為 `MenuButton` 處理 `mouseleave`。
   *
   * @param {EventTarget~Event} 事件
   * 導致調用此函數的 `mouseleave` 事件。
   *
   * @listens 鼠標離開
   */
  handleMouseLeave(事件){
    this.removeClass('vjs-hover');
    Events.off(文檔, 'keyup', this.handleMenuKeyUp_);
  }

  /**
   * 將焦點設置到實際的按鈕,而不是這個元素
   */
  重點() {
    這個.menuButton_.focus();
  }

  /**
   * 從實際按鈕上移除焦點,而不是這個元素
   */
  模糊(){
    這個.menuButton_.blur();
  }

  /**
   * 處理 `MenuButton` 的製表符、轉義鍵、向下箭頭和向上箭頭鍵。看
   * {@link ClickableComponent#handleKeyDown} 用於調用它的實例。
   *
   * @param {EventTarget~Event} 事件
   * 導致調用此函數的 `keydown` 事件。
   *
   * @listens 按鍵
   */
  handleKeyDown(事件){

    // Escape 或 Tab 取消按下“按鈕”
    if (keycode.isEventKey(event, 'Esc') || keycode.isEventKey(event, 'Tab')) {
      如果(this.buttonPressed_){
        這個.unpressButton();
      }

      // 不要阻止 Tab 鍵的默認值 - 我們仍然想失去焦點
      如果 (!keycode.isEventKey(event, 'Tab')) {
        事件.preventDefault();
        // 將焦點設置回菜單按鈕的按鈕
        這個.menuButton_.focus();
      }
    // 向上箭頭或向下箭頭也“按下”按鈕以打開菜單
    } else if (keycode.isEventKey(event, 'Up') || keycode.isEventKey(event, 'Down')) {
      如果(!this.buttonPressed_){
        事件.preventDefault();
        這個.pressButton();
      }
    }
  }

  /**
   * 處理 `MenuButton` 上的 `keyup` 事件。為此添加了偵聽器
   * 構造函數。
   *
   * @param {EventTarget~Event} 事件
   * 按鍵事件
   *
   * @listens 按鍵
   */
  handleMenuKeyUp(事件){
    // 退出隱藏彈出菜單
    if (keycode.isEventKey(event, 'Esc') || keycode.isEventKey(event, 'Tab')) {
      this.removeClass('vjs-hover');
    }
  }

  /**
   * 此方法名稱現在委託給 `handleSubmenuKeyDown`。這意味著
   * 任何調用 `handleSubmenuKeyPress` 的人都不會看到他們的方法調用
   * 停止工作。
   *
   * @param {EventTarget~Event} 事件
   * 導致調用此函數的事件。
   */
  handleSubmenuKeyPress(事件){
    this.handleSubmenuKeyDown(事件);
  }

  /**
   * 處理子菜單上的 `keydown` 事件。為此添加了偵聽器
   * 構造函數。
   *
   * @param {EventTarget~Event} 事件
   * 按鍵事件
   *
   * @listens 按鍵
   */
  handleSubmenuKeyDown(事件){
    // Escape 或 Tab 取消按下“按鈕”
    if (keycode.isEventKey(event, 'Esc') || keycode.isEventKey(event, 'Tab')) {
      如果(this.buttonPressed_){
        這個.unpressButton();
      }
      // 不要阻止 Tab 鍵的默認值 - 我們仍然想失去焦點
      如果 (!keycode.isEventKey(event, 'Tab')) {
        事件.preventDefault();
        // 將焦點設置回菜單按鈕的按鈕
        這個.menuButton_.focus();
      }
    }其他{
      // 筆記:這是一個特殊情況,我們不會未經處理就通過
      // 直到組件處理程序的按鍵事件,因為它是
      // 只是結束 `MenuItem` 的按鍵處理
      // 在已經向上傳遞未使用的鍵的 `Menu` 中。
    }
  }

  /**
   * 將當前的 `MenuButton` 置於按下狀態。
   */
  按下按鈕() {
    如果(this.enabled_){
      this.buttonPressed_ = true;
      這個.menu.show();
      這個.menu.lockShowing();
      this.menuButton_.el_.setAttribute('aria-expanded', 'true');

      // 將焦點設置到子菜單中,除了在 iOS 上它會導致
      // 當播放器在 iframe 中時不希望的滾動行為
      如果 (IS_IOS && Dom.isInFrame()) {
        // 提前返回,這樣菜單就沒有焦點
        返回;
      }

      這個.menu.focus();
    }
  }

  /**
   * 使當前的 `MenuButton` 脫離按下狀態。
   */
  unpressButton() {
    如果(this.enabled_){
      this.buttonPressed_ = false;
      這個.menu.unlockShowing();
      這個.menu.hide();
      this.menuButton_.el_.setAttribute('aria-expanded', 'false');
    }
  }

  /**
   * 禁用 `MenuButton`。不要讓它被點擊。
   */
  禁用(){
    這個.unpressButton();

    this.enabled_ = false;
    this.addClass('vjs-disabled');

    this.menuButton_.disable();
  }

  /**
   * 啟用 `MenuButton`。允許它被點擊。
   */
  使能夠() {
    this.enabled_ = true;
    this.removeClass('vjs-disabled');

    this.menuButton_.enable();
  }
}

Component.registerComponent('MenuButton', MenuButton);
導出默認菜單按鈕;