/**
 * @파일 메뉴.js
 */
'../component.js'에서 컴포넌트 가져오기;
'글로벌/문서'에서 문서 가져오기;
import * as Dom from '../utils/dom.js';
import * as Events from '../utils/events.js';
'키코드'에서 키코드 가져오기;

/**
 * Menu 컴포넌트는 자막과 팝업 메뉴를 만드는 데 사용됩니다.
 * 캡션 선택 메뉴.
 *
 * @extends 컴포넌트
 */
클래스 메뉴 확장 구성 요소 {

  /**
   * 이 클래스의 인스턴스를 만듭니다.
   *
   * @param {플레이어} 플레이어
   * 이 구성 요소가 연결되어야 하는 플레이어
   *
   * @param {객체} [옵션]
   * 옵션 이름 및 값의 개체
   *
   */
  생성자(플레이어, 옵션) {
    super(플레이어, 옵션);

    if (옵션) {
      this.menuButton_ = options.menuButton;
    }

    this.focusedChild_ = -1;

    this.on('키다운', (e) => this.handleKeyDown(e));

    // 모든 메뉴 항목 인스턴스는 메뉴 컨테이너에서 제공하는 동일한 흐림 처리기를 공유합니다.
    this.boundHandleBlur_ = (e) => this.handleBlur(e);
    this.boundHandleTapClick_ = (e) => this.handleTapClick(e);
  }

  /**
   * {@link MenuItem}에 이벤트 리스너를 추가합니다.
   *
   * @param {객체} 컴포넌트
   * 리스너를 추가할 `MenuItem`의 인스턴스.
   *
   */
  addEventListenerForItem(구성 요소) {
    if (!(컴포넌트의 컴포넌트 인스턴스)) {
      반품;
    }

    this.on(component, 'blur', this.boundHandleBlur_);
    this.on(구성요소, ['탭', '클릭'], this.boundHandleTapClick_);
  }

  /**
   * {@link MenuItem}에서 이벤트 리스너를 제거합니다.
   *
   * @param {객체} 컴포넌트
   * 리스너를 제거하기 위한 `MenuItem`의 인스턴스.
   *
   */
  removeEventListenerForItem(구성 요소) {
    if (!(컴포넌트의 컴포넌트 인스턴스)) {
      반품;
    }

    this.off(컴포넌트, '블러', this.boundHandleBlur_);
    this.off(컴포넌트, ['탭', '클릭'], this.boundHandleTapClick_);
  }

  /**
   * 이 메서드는 컴포넌트가 추가되면 간접적으로 호출됩니다.
   * 컴포넌트가 `addItem`에 의해 새 메뉴 인스턴스에 추가되기 전에.
   * 이 경우 원래 메뉴 인스턴스는 구성 요소를 제거합니다.
   * `removeChild` 호출.
   *
   * @param {객체} 컴포넌트
   * `MenuItem`의 인스턴스
   */
  removeChild(구성 요소) {
    if (구성 요소 유형 === '문자열') {
      구성 요소 = this.getChild(구성 요소);
    }

    this.removeEventListenerForItem(구성 요소);
    super.removeChild(구성요소);
  }

  /**
   * 메뉴에 {@link MenuItem}을 추가합니다.
   *
   * @param {객체|문자열} 구성요소
   * 추가할 `MenuItem`의 이름 또는 인스턴스입니다.
   *
   */
  addItem(구성 요소) {
    const childComponent = this.addChild(구성 요소);

    경우 (자식 구성 요소) {
      this.addEventListenerForItem(childComponent);
    }
  }

  /**
   * `Menu`의 DOM 요소를 만듭니다.
   *
   * @return {요소}
   * 생성된 요소
   */
  createEl() {
    const contentElType = this.options_.contentElType || '울';

    this.contentEl_ = Dom.createEl(contentElType, {
      className: 'vjs-menu-content'
    });

    this.contentEl_.setAttribute('역할', '메뉴');

    const el = super.createEl('div', {
      추가: this.contentEl_,
      className: 'vjs 메뉴'
    });

    el.appendChild(this.contentEl_);

    // 클릭이 버블링되는 것을 방지합니다. 메뉴 버튼에 필요,
    // 여기서 부모에 대한 클릭이 중요합니다.
    Events.on(el, '클릭', function(event) {
      event.preventDefault();
      event.stopImmediatePropagation();
    });

    반환 엘;
  }

  폐기() {
    this.contentEl_ = null;
    this.boundHandleBlur_ = null;
    this.boundHandleTapClick_ = null;

    super.dispose();
  }

  /**
   * `MenuItem`이 포커스를 잃을 때 호출됩니다.
   *
   * @param {EventTarget~Event} 이벤트
   * 이 함수를 호출하게 만든 `blur` 이벤트.
   *
   * @듣기 흐림
   */
  handleBlur(이벤트) {
    const relatedTarget = event.relatedTarget || document.activeElement;

    // 사용자가 메뉴 외부를 클릭하면 메뉴 팝업 닫기
    if (!this.children().some((요소) => {
      return element.el() === relatedTarget;
    })) {
      const btn = this.menuButton_;

      만약 (btn && btn.버튼누름_ && relatedTarget !== btn.el().firstChild) {
        btn.unpressButton();
      }
    }
  }

  /**
   * `MenuItem`이 클릭되거나 탭될 때 호출됩니다.
   *
   * @param {EventTarget~Event} 이벤트
   * 이 함수를 호출한 `click` 또는 `tap` 이벤트.
   *
   * @listens 클릭, 탭
   */
  handleTapClick(이벤트) {
    // 연결된 MenuButton을 누르고 포커스를 다시 이동합니다.
    if (this.menuButton_) {
      this.menuButton_.unpressButton();

      const childComponents = this.children();

      if (!Array.isArray(childComponents)) {
        반품;
      }

      const foundComponent = childComponents.filter(구성 요소 => component.el() === event.target)[0];

      if (!foundComponent) {
        반품;
      }

      // 항목이 캡션 설정 항목인 경우 메뉴 버튼에 초점을 맞추지 않음
      // 포커스가 다른 곳으로 이동하기 때문에
      if (foundComponent.name() !== 'CaptionSettingsMenuItem') {
        this.menuButton_.focus();
      }
    }
  }

  /**
   * 이 메뉴에서 `keydown` 이벤트를 처리합니다. 이 리스너는 생성자에 추가됩니다.
   *
   * @param {EventTarget~Event} 이벤트
   * 메뉴에서 발생한 `keydown` 이벤트.
   *
   * @listens 키다운
   */
  handleKeyDown(이벤트) {

    // 왼쪽 및 아래쪽 화살표
    if (keycode.isEventKey(event, 'Left') || keycode.isEventKey(event, 'Down')) {
      event.preventDefault();
      event.stopPropagation();
      this.stepForward();

    // 위쪽 및 오른쪽 화살표
    } 그렇지 않으면 (keycode.isEventKey(event, 'Right') || keycode.isEventKey(event, 'Up')) {
      event.preventDefault();
      event.stopPropagation();
      this.stepBack();
    }
  }

  /**
   * 키보드 사용자를 위한 다음(하위) 메뉴 항목으로 이동합니다.
   */
  앞으로 단계() {
    let stepChild = 0;

    if (this.focusedChild_ !== 정의되지 않음) {
      stepChild = this.focusedChild_ + 1;
    }
    this.focus(stepChild);
  }

  /**
   * 키보드 사용자의 경우 이전(상위) 메뉴 항목으로 이동합니다.
   */
  스텝백() {
    let stepChild = 0;

    if (this.focusedChild_ !== 정의되지 않음) {
      stepChild = this.focusedChild_ - 1;
    }
    this.focus(stepChild);
  }

  /**
   * `메뉴`에서 {@link MenuItem}에 포커스를 설정합니다.
   *
   * @param {객체|문자열} [항목=0]
   * 자식 항목의 인덱스는 포커스를 설정합니다.
   */
  포커스(항목 = 0) {
    const children = this.children().slice();
    const haveTitle = children.length && children[0].hasClass('vjs-menu-title');

    if (haveTitle) {
      children.shift();
    }

    if (어린이.길이 > 0) {
      만약 (항목 < 0) {
        항목 = 0;
      } 그렇지 않으면 (항목 > = 어린이.길이) {
        항목 = children.length - 1;
      }

      this.focusedChild_ = 항목;

      children[item].el_.focus();
    }
  }
}

Component.registerComponent('메뉴', 메뉴);
기본 메뉴 내보내기;