text: /**
   * @file slider.js
   */
  import Component from '../component.js';
  import * as Dom from '../utils/dom.js';
  import {assign} from '../utils/obj';
  
  /**
   * The base functionality for a slider. Can be vertical or horizontal.
   * For instance the volume bar or the seek bar on a video is a slider.
   *
   * @extends Component
   */
  class Slider extends Component {
  
  /**
   * Create an instance of this class
   *
   * @param {Player} player
   *        The `Player` that this class should be attached to.
   *
   * @param {Object} [options]
   *        The key/value store of player options.
   */
    constructor(player, options) {
      super(player, options);
  
      // Set property names to bar to match with the child Slider class is looking for
      this.bar = this.getChild(this.options_.barName);
  
      // Set a horizontal or vertical class on the slider depending on the slider type
      this.vertical(!!this.options_.vertical);
  
      this.on('mousedown', this.handleMouseDown);
      this.on('touchstart', this.handleMouseDown);
      this.on('focus', this.handleFocus);
      this.on('blur', this.handleBlur);
      this.on('click', this.handleClick);
  
      this.on(player, 'controlsvisible', this.update);
      this.on(player, this.playerEvent, this.update);
    }
  
    /**
     * Create the `Button`s DOM element.
     *
     * @param {string} type
     *        Type of element to create.
     *
     * @param {Object} [props={}]
     *        List of properties in Object form.
     *
     * @param {Object} [attributes={}]
     *        list of attributes in Object form.
     *
     * @return {Element}
     *         The element that gets created.
     */
    createEl(type, props = {}, attributes = {}) {
      // Add the slider element class to all sub classes
      props.className = props.className + ' vjs-slider';
      props = assign({
        tabIndex: 0
      }, props);
  
      attributes = assign({
        'role': 'slider',
        'aria-valuenow': 0,
        'aria-valuemin': 0,
        'aria-valuemax': 100,
        'tabIndex': 0
      }, attributes);
  
      return super.createEl(type, props, attributes);
    }
  
    /**
     * Handle `mousedown` or `touchstart` events on the `Slider`.
     *
     * @param {EventTarget~Event} event
     *        `mousedown` or `touchstart` event that triggered this function
     *
     * @listens mousedown
     * @listens touchstart
     * @fires Slider#slideractive
     */
    handleMouseDown(event) {
      const doc = this.bar.el_.ownerDocument;
  
      event.preventDefault();
      Dom.blockTextSelection();
  
      this.addClass('vjs-sliding');
      /**
       * Triggered when the slider is in an active state
       *
       * @event Slider#slideractive
       * @type {EventTarget~Event}
       */
      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(event);
    }
  
    /**
     * Handle the `mousemove`, `touchmove`, and `mousedown` events on this `Slider`.
     * The `mousemove` and `touchmove` events will only only trigger this function during
     * `mousedown` and `touchstart`. This is due to {@link Slider#handleMouseDown} and
     * {@link Slider#handleMouseUp}.
     *
     * @param {EventTarget~Event} event
     *        `mousedown`, `mousemove`, `touchstart`, or `touchmove` event that triggered
     *        this function
     *
     * @listens mousemove
     * @listens touchmove
     */
    handleMouseMove(event) {}
  
    /**
     * Handle `mouseup` or `touchend` events on the `Slider`.
     *
     * @param {EventTarget~Event} event
     *        `mouseup` or `touchend` event that triggered this function.
     *
     * @listens touchend
     * @listens mouseup
     * @fires Slider#sliderinactive
     */
    handleMouseUp() {
      const doc = this.bar.el_.ownerDocument;
  
      Dom.unblockTextSelection();
  
      this.removeClass('vjs-sliding');
      /**
       * Triggered when the slider is no longer in an active state.
       *
       * @event Slider#sliderinactive
       * @type {EventTarget~Event}
       */
      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();
    }
  
    /**
     * Update the progress bar of the `Slider`.
     */
    update() {
      // In VolumeBar init we have a setTimeout for update that pops and update to the end of the
      // execution stack. The player is destroyed before then update will cause an error
      if (!this.el_) {
        return;
      }
  
      // If scrubbing, we could use a cached value to make the handle keep up with the user's mouse.
      // On HTML5 browsers scrubbing is really smooth, but some flash players are slow, so we might want to utilize this later.
      // var progress =  (this.player_.scrubbing()) ? this.player_.getCache().currentTime / this.player_.duration() : this.player_.currentTime() / this.player_.duration();
      let progress = this.getPercent();
      const bar = this.bar;
  
      // If there's no bar...
      if (!bar) {
        return;
      }
  
      // Protect against no duration and other division issues
      if (typeof progress !== 'number' ||
          progress !== progress ||
          progress < 0 ||
          progress === Infinity) {
        progress = 0;
      }
  
      // Convert to a percentage for setting
      const percentage = (progress * 100).toFixed(2) + '%';
  
      // Set the new bar width or height
      if (this.vertical()) {
        bar.el().style.height = percentage;
      } else {
        bar.el().style.width = percentage;
      }
    }
  
    /**
     * Calculate distance for slider
     *
     * @param {EventTarget~Event} event
     *        The event that caused this function to run.
     *
     * @return {number}
     *         The current position of the Slider.
     *         - postition.x for vertical `Slider`s
     *         - postition.y for horizontal `Slider`s
     */
    calculateDistance(event) {
      const position = Dom.getPointerPosition(this.el_, event);
  
      if (this.vertical()) {
        return position.y;
      }
      return position.x;
    }
  
    /**
     * Handle a `focus` event on this `Slider`.
     *
     * @param {EventTarget~Event} event
     *        The `focus` event that caused this function to run.
     *
     * @listens focus
     */
    handleFocus() {
      this.on(this.bar.el_.ownerDocument, 'keydown', this.handleKeyPress);
    }
  
    /**
     * Handle a `keydown` event on the `Slider`. Watches for left, rigth, up, and down
     * arrow keys. This function will only be called when the slider has focus. See
     * {@link Slider#handleFocus} and {@link Slider#handleBlur}.
     *
     * @param {EventTarget~Event} event
     *        the `keydown` event that caused this function to run.
     *
     * @listens keydown
     */
    handleKeyPress(event) {
      // Left and Down Arrows
      if (event.which === 37 || event.which === 40) {
        event.preventDefault();
        this.stepBack();
  
      // Up and Right Arrows
      } else if (event.which === 38 || event.which === 39) {
        event.preventDefault();
        this.stepForward();
      }
    }
  
    /**
     * Handle a `blur` event on this `Slider`.
     *
     * @param {EventTarget~Event} event
     *        The `blur` event that caused this function to run.
     *
     * @listens blur
     */
  
    handleBlur() {
      this.off(this.bar.el_.ownerDocument, 'keydown', this.handleKeyPress);
    }
  
    /**
     * Listener for click events on slider, used to prevent clicks
     *   from bubbling up to parent elements like button menus.
     *
     * @param {Object} event
     *        Event that caused this object to run
     */
    handleClick(event) {
      event.stopImmediatePropagation();
      event.preventDefault();
    }
  
    /**
     * Get/set if slider is horizontal for vertical
     *
     * @param {boolean} [bool]
     *        - true if slider is vertical,
     *        - false is horizontal
     *
     * @return {boolean|Slider}
     *         - true if slider is vertical, and getting
     *         - false is horizontal, and getting
     *         - a reference to this object when setting
     */
    vertical(bool) {
      if (bool === undefined) {
        return this.vertical_ || false;
      }
  
      this.vertical_ = !!bool;
  
      if (this.vertical_) {
        this.addClass('vjs-slider-vertical');
      } else {
        this.addClass('vjs-slider-horizontal');
      }
  
      return this;
    }
  }
  
  Component.registerComponent('Slider', Slider);
  export default Slider;
  