/**
 * @파일 슬라이더.js
 */
'../component.js'에서 컴포넌트 가져오기;
import * as Dom from '../utils/dom.js';
'../utils/obj'에서 {assign} 가져오기;
'../utils/browser.js'에서 {IS_CHROME} 가져오기;
'../utils/clamp.js'에서 클램프 가져오기;
'키코드'에서 키코드 가져오기;

/**
 * 슬라이더의 기본 기능. 수직 또는 수평일 수 있습니다.
 * 예를 들어 동영상의 볼륨 막대 또는 검색 막대는 슬라이더입니다.
 *
 * @extends 컴포넌트
 */
슬라이더 클래스 확장 구성 요소 {

  /**
 * 이 클래스의 인스턴스 생성
 *
 * @param {플레이어} 플레이어
 * 이 클래스가 연결되어야 하는 `Player`.
 *
 * @param {객체} [옵션]
 * 플레이어 옵션의 키/값 저장소.
 */
  생성자(플레이어, 옵션) {
    super(플레이어, 옵션);

    this.handleMouseDown_ = (e) => this.handleMouseDown(e);
    this.handleMouseUp_ = (e) => this.handleMouseUp(e);
    this.handleKeyDown_ = (e) => this.handleKeyDown(e);
    this.handleClick_ = (e) => this.handleClick(e);
    this.handleMouseMove_ = (e) => this.handleMouseMove(e);
    this.update_ = (e) => this.update(e);

    // Slider 클래스가 찾고 있는 자식과 일치하도록 속성 이름을 bar로 설정합니다.
    this.bar = this.getChild(this.options_.barName);

    // 슬라이더 종류에 따라 슬라이더에 수평 또는 수직 클래스를 설정합니다.
    this.vertical(!!this.options_.vertical);

    this.enable();
  }

  /**
   * 현재 이 슬라이더에 컨트롤이 활성화되어 있는지 여부.
   *
   * @return {부울}
   * 컨트롤이 활성화된 경우 true, 그렇지 않은 경우 false
   */
  활성화() {
    this.enabled_를 반환합니다.
  }

  /**
   * 비활성화된 경우 이 슬라이더에 대한 컨트롤을 활성화합니다.
   */
  할 수 있게 하다() {
    if (이.활성화()) {
      반품;
    }

    this.on('마우스다운', this.handleMouseDown_);
    this.on('터치스타트', this.handleMouseDown_);
    this.on('keydown', this.handleKeyDown_);
    this.on('클릭', this.handleClick_);

    // TODO: 더 이상 사용되지 않음, controlsvisible이 실행되지 않는 것 같습니다.
    this.on(this.player_, 'controlsvisible', this.update);

    if (이.플레이어 이벤트) {
      this.on(this.player_, this.playerEvent, this.update);
    }

    this.removeClass('비활성화됨');
    this.setAttribute('tabindex', 0);

    this.enabled_ = 참;
  }

  /**
   * 이 슬라이더에 대한 컨트롤이 활성화된 경우 비활성화
   */
  장애를 입히다() {
    if (!this.enabled()) {
      반품;
    }
    const doc = this.bar.el_.ownerDocument;

    this.off('마우스다운', this.handleMouseDown_);
    this.off('터치스타트', this.handleMouseDown_);
    this.off('키다운', this.handleKeyDown_);
    this.off('클릭', this.handleClick_);
    this.off(this.player_, 'controlsvisible', this.update_);
    this.off(doc, 'mousemove', this.handleMouseMove_);
    this.off(doc, 'mouseup', this.handleMouseUp_);
    this.off(doc, 'touchmove', this.handleMouseMove_);
    this.off(doc, 'touchend', this.handleMouseUp_);
    this.removeAttribute('tabindex');

    this.addClass('비활성화됨');

    if (이.플레이어 이벤트) {
      this.off(this.player_, this.playerEvent, this.update);
    }
    this.enabled_ = 거짓;
  }

  /**
   * `Slider`의 DOM 요소를 만듭니다.
   *
   * @param {문자열} 유형
   * 생성할 요소의 유형.
   *
   * @param {객체} [소품={}]
   * 개체 형식의 속성 목록입니다.
   *
   * @param {객체} [속성={}]
   * 객체 형태의 속성 목록.
   *
   * @return {요소}
   * 생성되는 요소.
   */
  createEl(유형, 소품 = {}, 속성 = {}) {
    // 슬라이더 요소 클래스를 모든 하위 클래스에 추가
    props.className = props.className + 'vjs-slider';
    소품 = 할당({
      탭 인덱스: 0
    }, 소품);

    속성 = 할당({
      '역할': '슬라이더',
      '아리아-valuenow': 0,
      '아리아-valuemin': 0,
      '아리아-valuemax': 100,
      '탭인덱스': 0
    }, 속성);

    return super.createEl(유형, 소품, 속성);
  }

  /**
   * `Slider`에서 `mousedown` 또는 `touchstart` 이벤트를 처리합니다.
   *
   * @param {EventTarget~Event} 이벤트
   * 이 기능을 트리거한 `mousedown` 또는 `touchstart` 이벤트
   *
   * @listens mousedown
   * @listens 터치스타트
   * @fires 슬라이더#slideractive
   */
  handleMouseDown(이벤트) {
    const doc = this.bar.el_.ownerDocument;

    if (event.type === '마우스다운') {
      event.preventDefault();
    }
    // Chrome에서 touchstart 시 preventDefault()를 호출하지 않습니다.
    // 콘솔 경고를 피하기 위해. '터치 액션: 없음' 스타일 사용
    // 대신 의도하지 않은 스크롤을 방지합니다.
    // https://developers.google.com/web/updates/2017/01/scrolling-intervention
    if (event.type === '터치스타트' && !IS_CHROME) {
      event.preventDefault();
    }
    Dom.blockTextSelection();

    this.addClass('vjs-sliding');
    /**
     * 슬라이더가 활성 상태일 때 트리거됨
     *
     * @event 슬라이더#slideractive
     * @type {이벤트대상~이벤트}
     */
    this.trigger('slideractive');

    this.on(doc, 'mousemove', this.handleMouseMove_);
    this.on(doc, 'mouseup', this.handleMouseUp_);
    this.on(doc, 'touchmove', this.handleMouseMove_);
    this.on(doc, 'touchend', this.handleMouseUp_);

    this.handleMouseMove(이벤트, 참);
  }

  /**
   * 이 `Slider`에서 `mousemove`, `touchmove` 및 `mousedown` 이벤트를 처리합니다.
   * `mousemove` 및 `touchmove` 이벤트는 동안에만 이 기능을 트리거합니다.
   * `마우스다운` 및 `터치스타트`. 이는 {@link Slider#handleMouseDown} 및
   * {@link Slider#handleMouseUp}.
   *
   * @param {EventTarget~Event} 이벤트
   * 트리거된 `mousedown`, `mousemove`, `touchstart` 또는 `touchmove` 이벤트
   * 이 기능
   * @param {boolean} mouseDown `handleMouseMove`가 직접 호출되는 경우 true로 설정되어야 하는 플래그입니다. 이것은 우리가 마우스를 눌렀을 때 발생하지 않아야 하지만 일반 마우스 이동 처리기에서 발생해야 하는 일을 건너뛸 수 있게 해줍니다. 기본값은 false입니다.
   *
   * @listens mousemove
   * @listens 터치무브
   */
  handleMouseMove(이벤트) {}

  /**
   * `Slider`에서 `mouseup` 또는 `touchend` 이벤트를 처리합니다.
   *
   * @param {EventTarget~Event} 이벤트
   * 이 기능을 트리거한 `mouseup` 또는 `touchend` 이벤트.
   *
   * @listens 터치엔드
   * @listens mouseup
   * @fires 슬라이더#sliderinactive
   */
  handleMouseUp() {
    const doc = this.bar.el_.ownerDocument;

    Dom.unblockTextSelection();

    this.removeClass('vjs-sliding');
    /**
     * 슬라이더가 더 이상 활성 상태가 아닐 때 트리거됩니다.
     *
     * @event 슬라이더#sliderinactive
     * @type {이벤트대상~이벤트}
     */
    this.trigger('sliderinactive');

    this.off(doc, 'mousemove', this.handleMouseMove_);
    this.off(doc, 'mouseup', this.handleMouseUp_);
    this.off(doc, 'touchmove', this.handleMouseMove_);
    this.off(doc, 'touchend', this.handleMouseUp_);

    this.update();
  }

  /**
   * `슬라이더`의 진행률 표시줄을 업데이트합니다.
   *
   * @return {숫자}
   * 진행률 표시줄이 나타내는 진행률
   * 0에서 1까지의 숫자.
   */
  업데이트() {
    // VolumeBar init에는 팝업 및 업데이트를 위한 setTimeout이 있습니다.
    // 실행 스택의 끝까지. 플레이어는 그 전에 파괴됩니다.
    // 업데이트하면 오류가 발생합니다.
    // 막대가 없으면...
    if (!this.el_ || !this.bar) {
      반품;
    }

    // 0과 1 사이에서 클램프 진행
    // 아래에서 2로 반올림하므로 소수점 이하 네 자리까지만 반올림합니다.
    const 진행 = this.getProgress();

    if (진행 === this.progress_) {
      진행 상황을 반환합니다.
    }

    this.progress_ = 진행;

    this.requestNamedAnimationFrame('슬라이더#업데이트', () => {
      // 새 막대 너비 또는 높이를 설정합니다.
      const sizeKey = this.vertical() ? '높이 너비';

      // css 값에 대한 백분율로 변환
      this.bar.el().style[sizeKey] = (진행률 * 100).toFixed(2) + '%';
    });

    진행 상황을 반환합니다.
  }

  /**
   * 채워야 하는 막대의 백분율을 가져옵니다.
   * 그러나 고정되고 둥글다.
   *
   * @return {숫자}
   * 슬라이더가 채워지는 백분율
   */
  getProgress() {
    return Number(clamp(this.getPercent(), 0, 1).toFixed(4));
  }

  /**
   * 슬라이더의 거리 계산
   *
   * @param {EventTarget~Event} 이벤트
   * 이 기능을 실행하게 만든 이벤트.
   *
   * @return {숫자}
   * 슬라이더의 현재 위치.
   * - 수직 `슬라이더`에 대한 position.x
   * - 수평 `슬라이더`에 대한 position.y
   */
  계산거리(이벤트) {
    const position = Dom.getPointerPosition(this.el_, event);

    if (this.vertical()) {
      반환 위치.y;
    }
    반환 position.x;
  }

  /**
   * `Slider`에서 `keydown` 이벤트를 처리합니다. 왼쪽, 오른쪽, 위쪽 및 아래쪽에 대한 시계
   * 화살표 키. 이 함수는 슬라이더에 포커스가 있을 때만 호출됩니다. 보다
   * {@link Slider#handleFocus} 및 {@link Slider#handleBlur}.
   *
   * @param {EventTarget~Event} 이벤트
   * 이 함수를 실행하게 만든 `keydown` 이벤트.
   *
   * @listens 키다운
   */
  handleKeyDown(이벤트) {

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

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

      // 지원되지 않는 키에 대한 keydown 처리를 전달합니다.
      super.handleKeyDown(이벤트);
    }
  }

  /**
   * 클릭을 방지하는 데 사용되는 슬라이더의 클릭 이벤트에 대한 리스너
   * 버블링에서 버튼 메뉴와 같은 부모 요소까지.
   *
   * @param {객체} 이벤트
   * 이 객체를 실행시킨 이벤트
   */
  handleClick(이벤트) {
    event.stopPropagation();
    event.preventDefault();
  }

  /**
   * 슬라이더가 수직에 대해 수평인지 가져오기/설정
   *
   * @param {부울} [부울]
   * - 슬라이더가 수직이면 true,
   * - false는 수평입니다.
   *
   * @return {부울}
   * - 슬라이더가 수직인 경우 true이고 점점
   * - 슬라이더가 수평이면 false, 점점
   */
  수직(부울) {
    if (부울 === 정의되지 않음) {
      return this.vertical_ || 거짓;
    }

    this.vertical_ = !!부울;

    if (this.vertical_) {
      this.addClass('vjs-slider-vertical');
    } else {
      this.addClass('vjs-slider-horizontal');
    }
  }
}

Component.registerComponent('슬라이더', 슬라이더);
기본 슬라이더 내보내기;