import $ from "jquery";
import EventEmitter from "./EventEmitter";
/**
* @function Tabs.on
* @param {"before-tab-hide" | "after-tab-hide" | "before-tab-show" | "after-tab-show"} event The event name
* @param {function} listener The event listener
*/
/**
* A class to manage tabs
* @class
* @extends EventEmitter
* @fires Tabs~before-tab-hide
* @example
* const tabs = new Tabs($('.tabs');
*/
class Tabs extends EventEmitter {
/**
* @constructor
* @param {jQuery} $el - The element contains the tabs
*/
constructor($el) {
super();
this.$tabs = $el.find("[role=tab]");
this.$panels = this.$tabs.map(function () {
const controls = $(this).attr("aria-controls");
const $panel = $(`#${controls}`);
if (!$panel.length) {
console.warn(`Tab panel '${controls}' not found`);
}
return $panel;
});
this.$tabs.on("click", this.#showTab.bind(this));
let index = this.$tabs.filter('[aria-selected="true"]').index();
this.$tabs.on("keydown", (e) => {
if (e.key !== "ArrowRight" && e.key !== "ArrowLeft") {
return;
}
this.$tabs[index].setAttribute("tabindex", -1);
if (e.key === "ArrowRight") {
index++;
if (index >= this.$tabs.length) {
index = 0;
}
} else {
index--;
if (index < 0) {
index = this.$tabs.length - 1;
}
}
this.$tabs[index].setAttribute("tabindex", 0);
this.$tabs[index].focus();
});
}
#showTab(e) {
const $currentPanel = this.$panels.filter(function () {
const attr = $(this).attr("hidden");
return !attr;
});
const $futurePanel = $(`#${$(e.target).attr("aria-controls")}`);
// Update tabs state
this.$tabs.attr({ "aria-selected": "false" });
$(e.target).attr({ "aria-selected": "true" });
/**
* Before tab hide event
*
* @event Tabs#before-tab-hide
* @property {Event} e - The event object
* @property {jQuery} $panel - The panel which is about to hide.
*/
this.emit("before-tab-hide", e, $currentPanel);
// Hide all panels
this.$panels.each(function () {
this[0].setAttribute("hidden", "true");
});
/**
* After tab hide event
*
* @event Tabs#after-tab-hide
* @property {Event} e - The event object
* @property {jQuery} $panel - The panel which was hidden.
*/
this.emit("after-tab-hide", e, $currentPanel);
/**
* Before tab show event
*
* @event Tabs#before-tab-show
* @property {Event} e - The event object
* @property {jQuery} $panel - The panel which is about to show.
*/
this.emit("before-tab-show", e, $futurePanel);
// Show the selected panel
$futurePanel[0].removeAttribute("hidden");
/**
* After tab show event
*
* @event Tabs#after-tab-show
* @property {Event} e - The event object
* @property {jQuery} $panel - The panel which was shown.
*/
this.emit("after-tab-show", e, $futurePanel);
}
}
export { Tabs as default };
Source