Source: Slider.js

/**
 * @module nyc/Slider
 */

import $ from 'jquery'

import nyc from 'nyc'
import Container from 'nyc/Container'

/**
 * @desc A class to provide a numeric slider
 * @public
 * @class
 * @extends module:nyc/Container~Container
 * @fires module:nyc/Slider~Slider#change
 */
class Slider extends Container {
  /**
   * @desc Create an instance of Slider
   * @constructor
   * @param {module:nyc/Slider~Slider.Options} options Constructor options
   */
  constructor(options) {
    super(options.target)
    let units = options.units
    const id = nyc.nextId('slider')
    const label = $('<label></label>')
      .html(options.label || '')
      .attr('for', id)
    this.text = $('<input type="text" class="rad-all">')
      .attr('value', options.value || options.min)
      .change($.proxy(this.change, this))
      .keydown($.proxy(this.key, this))
      .focus(event => $(event.target).select())
    this.range = $('<input type="range">').attr({
      id: id,
      min: options.min,
      max: options.max,
      step: options.step || 1,
      value: this.text.val()
    }).change($.proxy(this.change, this))
    units = units ? $(`<span>${units}</span>`) : undefined
    this.append(label)
      .append(this.text)
      .append(units)
      .append(this.range)
      .addClass('sld')
  }
  /**
   * @public
   * @method
   * @desc Get or set the input value
   * @param {number=} value The value of the slider input value
   * @return {string|JQuery} Returns the slider jQuery input element or its value
   */
  val(value) {
    if (typeof value === 'undefined') {
      return this.range.val() * 1
    }
    this.range.val(value)
    this.text.val(value)
    return this
  }
  /**
   * @private
   * @method
   * @param {jQuery.Event} event The event object
   * @return {boolean} Is the key a bad key?
   */
  badKey(event) {
    const key = event.keyCode
    return (key < 96 || key > 105) && /* not a number from num keypad with num lock on */
      ($.inArray(key, [8, 9, 37, 38, 39, 40, 46]) === -1 && /* not backspace, tab, arrows or delete */
      isNaN(String.fromCharCode(event.which || key))) /* not a number */
  }
  /**
   * @private
   * @method
   * @param {jQuery.Event} event The event object
   */
  key(event) {
    if (this.badKey(event)) {
      event.preventDefault()
    } else {
      if (event.keyCode === 38) {
        this.val((this.val() * 1) + (this.range.attr('step') * 1))
      } else if (event.keyCode === 40) {
        this.val(this.val() - this.range.attr('step'))
      } else if (event.keyCode === 13) {
        this.val(this.text.val())
        this.change()
      }
    }
  }
  /**
   * @private
   * @method
   */
  change() {
    this.text.val(this.range.val())
    this.trigger('change', this)
  }
}

/**
 * @desc The change event
 * @event module:nyc/Slider~Slider#change
 * @type {module:nyc/Slider~Slider}
 */

/**
 * @desc Constructor options for {@link module:nyc/Slider~Slider}
 * @public
 * @typedef {Object}
 * @property {jQuery|Element|string} target The target DOM node for creating the slider control
 * @property {number} min The minimum value
 * @property {number} max The maximum value
 * @property {number} [step=1] The step value
 * @property {number=} value The value
 * @property {string=} units The units
 * @property {string=} label The label
 */
Slider.Options;

export default Slider