Source: ListPager.js

/**
 * @module nyc/ListPager
 */

import $ from 'jquery'

import Container from 'nyc/Container'

/**
 * @desc A class to page through sub-lists of a list of objects rendered as HTML
 * @public
 * @class
 * @extends module:nyc/Container~Container
 * @fires module:nyc/ListPager~ListPager#change
 */
class ListPager extends Container {
  /**
   * @desc Create an instance of ListPager
   * @public
   * @constructor
   * @param {module:nyc/ListPager~ListPager.Options} options Constructor options
   */
  constructor(options) {
    super(options.target)
    /**
     * @private
     * @member {string}
     */
    this.itemType = options.itemType || 'facilities'
    this.getContainer().addClass('lst-pg')
      .append($(ListPager.HTML))
      .attr({
        role: 'region',
        'aria-label': `List of ${this.itemType}`
      })
      /**
     * @private
     * @member {Array<ListPager.Item>}
     */
    this.items = options.items || []
    /**
     * @private
     * @member {jQuery}
     */
    this.list = this.find('.list')
    /**
     * @private
     * @member {number}
     */
    this.index = 0
    /**
     * @private
     * @member {number}
     */
    this.pageSize = options.pageSize || 10
    /**
     * @private
     * @member {jQuery}
     */
    this.moreBtn = this.find('button').click($.proxy(this.more, this))
    this.reset(this.items)
  }
  /**
   * @desc Resets the pager with new items and show the first page
   * @public
   * @method
   * @param {Array<module:nyc/ListPager~ListPager.Item>=} items The items to page through
   * @return {Array<module:nyc/ListPager~ListPager.Item>} List of items on the next page
   */
  reset(items) {
    this.list.empty()
    this.items = items || []
    this.index = 0
    this.moreBtn.fadeIn()
    return this.next(true)
  }
  /**
   * @desc Renders and returns next page of items
   * @public
   * @method
   * @param {boolean} [first=false] Transfer focus to the first item
   * @param {number} [pageSize=10] The length of the items for the next page
   * @return {Array<module:nyc/ListPager~ListPager.Item>} List of items on the next page
   */
  next(first, pageSize) {
    pageSize = pageSize || this.pageSize
    const result = this.items.slice(this.index, this.index + pageSize)
    const last = this.find('.lst-it').last()
    this.index = this.index + pageSize
    if (this.index >= this.items.length - 1) {
      this.moreBtn.fadeOut()
    }
    this.render(result)
    this.info()
    if (first) {
      this.find('.lst-it').first().focus()
    } else {
      last.next().attr('tabindex', 0).focus()
    }
    this.trigger('change', this)
    return result
  }
  /**
   * @private
   * @method
   */
  info() {
    this.find('h2.info')
      .html(`Showing ${this.find('.lst-it').length} of ${this.items.length} ${this.itemType}`)
  }
  /**
   * @private
   * @method
   * @param {Array<module:nyc/ListPager~ListPager.Item>} items List of items
   */
  render(items) {
    items.forEach(item => {
      this.list.append(
        $('<div class="lst-it" role="listitem"></div>').append(item.html())
      )
    })
  }
  /**
   * @private
   * @method
   * @return {Array<module:nyc/ListPager~ListPager.Item>} List of items on the next page
   */
  more() {
    return this.next()
  }
}

/**
 * @desc Constructor options for {@link module:nyc/ListPager~ListPager}
 * @public
 * @typedef {Object}
 * @property {jQuery|Element|string} target The DOM node in which to create the ListPager
 * @param {Array<ListPager.Item>=} items The items to page through
 * @param {string} [itemType=Facilities] The name for the type of items
 * @param {number} [pageSize=10] The number of items per page
 */
ListPager.Options

/**
 * @desc Object containing a rendering function for an item
 * @public
 * @typedef {module:nyc/ListPager~ListPager.Item}
 * @property {function()} html The rendering function for the item
 */
ListPager.Item

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


/**
 * @private
 * @const
 * @type {string}
 */
ListPager.HTML = '<h2 class="info" aria-live="polite"></h2>' +
  '<div class="list" role="list"></div>' +
  '<button class="btn rad-all btn-more">More...</button>'

export default ListPager