/**
* @module nyc/Tabs
*/
import $ from 'jquery'
import nyc from 'nyc'
import Container from 'nyc/Container'
/**
* @desc A class for creating and managing tabs
* @public
* @class
* @extends module:nyc/Container~Container
*/
class Tabs extends Container {
/**
* @desc Create an instance of Tabs
* @constructor
* @param {module:nyc/Tabs~Tabs.Options} options Constructor options
*/
constructor(options) {
super(options.target)
this.getContainer().append($(Tabs.HTML)).addClass('tabs')
this.btns = this.find('.btns')
this.tabs = this.find('.container')
/**
* @desc The active tab
* @public
* @member {jQuery}
*/
this.active = null
/**
* @private
* @member {jQuery}
*/
this.ready = false
this.render(options.tabs)
}
/**
* @desc Open a tab
* @public
* @method
* @param {jQuery|Element|string} tab Tab panel
*/
open(tab) {
tab = this.find(tab)
this.find('.btns h2').removeClass('active')
this.find('.tab')
.attr('aria-hidden', true)
.removeClass('active')
this.btns.find('.btn')
.removeClass('active')
tab.addClass('active')
.attr('aria-hidden', false)
.attr('tabindex', 1000)
.focus()
this.find('.btn').attr('aria-selected', false)
tab.data('btn').addClass('active')
.attr('aria-selected', true)
.parent().addClass('active')
this.active = tab
this.trigger('change', this)
}
/**
* @private
* @method
* @param {Array<module:nyc/Tabs~Tabs.Tab>} tabs The tabs
*/
render(tabs) {
let opened = false
tabs.forEach((tab, i) => {
const btnId = nyc.nextId('tab-btn')
const tb = $(tab.tab)
.addClass(`tab tab-${i}`)
.attr('aria-labelledby', btnId)
.attr('role', 'tabpanel')
.attr('aria-hidden', true)
const pnlId = tb.attr('id') || nyc.nextId('tab-pnl')
tb.attr('id', pnlId)
const btn = $(Tabs.BTN_HTML)
.attr('id', btnId)
.attr('aria-controls', pnlId)
.attr('aria-selected', false)
.click($.proxy(this.btnClick, this))
.addClass(`btn-tab btn-${i}`)
.data('tab', tb)
.append(tab.title)
tb.data('btn', btn)
this.btns.append($('<h2></h2>').append(btn))
this.tabs.append(tb)
if (tab.active) {
this.open(tb)
opened = true
}
})
if (!opened) {
this.open(tabs[0].tab)
}
this.ready = true
}
/**
* @private
* @method
* @param {jQuery.Event} event Event object
*/
btnClick(event) {
this.open($(event.currentTarget).data('tab'))
}
}
/**
* @desc Contructor options for {@link module:nyc/Tabs~Tabs}
* @public
* @typedef {Object}
* @property {jQuery|Element|string} target The target DOM node for Tabs
* @property {Array<module:nyc/Tabs~Tabs.Tab>} tabs The tabs
*/
Tabs.Options
/**
* @desc Object type to hold a tab definition
* @public
* @typedef {Object}
* @property {jQuery|Element|string} tab The target DOM node for tab
* @property {string} title The tab title
* @property {boolean} [active=false] Active state of the tab
*/
Tabs.Tab
/**
* @private
* @const
* @type {string}
*/
Tabs.HTML = '<div class="btns" role="tablist"></div>' +
'<div class="container" tabindex="-1"></div>'
/**
* @private
* @const
* @type {string}
*/
Tabs.BTN_HTML = '<button class="btn" role="tab"></button>'
export default Tabs