From 8a112e94d8ee2fa217e61bd5d9e92c923bff3ddb Mon Sep 17 00:00:00 2001 From: MattMo Date: Mon, 13 Dec 2021 16:51:32 -0800 Subject: [PATCH] Removed tab link template in favor of tabButton extension. Added tabs api class similar to my route plugin. Cleaned up code and added new functionality. --- ignite-html-tabs.js | 212 +++++++++++++++++++++++--------------------- 1 file changed, 111 insertions(+), 101 deletions(-) diff --git a/ignite-html-tabs.js b/ignite-html-tabs.js index b98d474..044ab2d 100644 --- a/ignite-html-tabs.js +++ b/ignite-html-tabs.js @@ -7,14 +7,16 @@ import { IgniteTemplate, slot, div, html } from "../ignite-html/ignite-template. * @param {String} name The name of the tab. * @param {String} group The tab group to put this tab under, by default this is null. * @param {Boolean} active Whether or not this tab is active by default. - * @returns {IgniteTemplate} This ignite template. + * @returns {IgniteTemplate} Returns this ignite template. */ IgniteTemplate.prototype.tab = function(name, group = null, active = false) { - //Set the starting class based on whether or not the tab is active. + //Add the tab class to this element. + this.class("tab") + + //If active, make this tab active. if (active) { - this.class("tab-active"); - } else { - this.class("tab-inactive"); + this.class("active"); + Tabs.change(name, group); } //What we do is create an IgniteCallback that will get called when @@ -23,17 +25,11 @@ import { IgniteTemplate, slot, div, html } from "../ignite-html/ignite-template. var callback = new IgniteCallback(event => { if (this.element) { if (event.name == name && event.group == group) { - this.element.classList.remove("tab-inactive"); - - if (!this.element.classList.contains("tab-active")) { - this.element.classList.add("tab-active"); + if (!this.element.classList.contains("active")) { + this.element.classList.add("active"); } } else if (event.group == group) { - this.element.classList.remove("tab-active"); - - if (!this.element.classList.contains("tab-inactive")) { - this.element.classList.add("tab-inactive"); - } + this.element.classList.remove("active"); } } }, () => { @@ -49,109 +45,123 @@ import { IgniteTemplate, slot, div, html } from "../ignite-html/ignite-template. return this; } -class TabLink extends IgniteElement { - constructor() { - super(); +/** + * Makes this IgniteTemplate a tab button that will become active or inactive based on the current tab and change tabs when clicked. + * @param {String} name The name of the tab that this button will set to active. + * @param {String} group The tab group the tab belongs to. + * @param {Boolean} active Whether or not this button is active, indicating the tab is active. + * @returns {IgniteTemplate} Returns this ignite template. + */ +IgniteTemplate.prototype.tabButton = function(name, group = null, active = false) { + //Add the tab-btn class to this element. + this.class("tab-btn"); - this.tabChangeListener = e => this.update(e); - window.addEventListener("tabchange", this.tabChangeListener); + //If active, make the button active. + if (active) { + this.class("active"); } - get properties() { - return { - active: false, - name: null, - group: null, - secondary: null - }; - } - - render() { - return this.template - .onClick((event) => this.onClick(event)) - .class(this.active, value => value ? "active" : null) - .child(new slot(this).class(this.active, value => value ? "active" : null)); - } - - update(event) { - //If the name and group match, set this tab link to active. - if (this.name == event.name && this.group == event.group) { - this.active = true; - return; - } - - //See if this event matched any of the secondary tabs. - for(var i = 0; i < this.secondary.length; i++) { - if (this.secondary[i] == event.name && this.group == event.group) { - this.active = true; - return; + //What we do is create an IgniteCallback that will get called when + //the tabchange event is raised. Upon disconnecting the callback we remove + //the event listener. + var callback = new IgniteCallback(event => { + if (this.element) { + //See if the group matches. + if (event.group == group) { + if (event.name == name) { + //Mark this button as active. + if (!this.element.classList.contains("active")) { + this.element.classList.add("active"); + } + } else { + //Mark this button as inactive. + this.element.classList.remove("active"); + } } } - - //Otherwise set this tab to inactive if it's active and the group matches. - if (event.group == this.group && this.active) { - this.active = false; - } - } + }, () => { + window.removeEventListener("tabchange", callback.callback); + }); - onClick(event) { - event.preventDefault(); + //Register our callback to the tabchange event. + window.addEventListener("tabchange", callback.callback); - var changeEvent = new Event("tabchange"); - changeEvent.name = this.name; - changeEvent.group = this.group; + //Add this callback to our template so that upon deconstruction our callback is destroyed correctly. + this._callbacks.push(callback); - window.dispatchEvent(changeEvent); - } + //Setup our on click to change tabs. + this.onClick(() => Tabs.change(name, group)); - cleanup() { - window.removeEventListener("tabchange", this.tabChangeListener); - } -} - -class TabLinkTemplate extends IgniteTemplate { - /** - * Initializes a new tab link template. - * @param {String} name The name of the tab this link is for and will set active to. - * @param {String} group The name of the group this link belongs to, this is optional. - * @param {String|String[]} secondary Optional tabs that also set this link to active if active. - * @param {...any} elements Elements to render within the link. - */ - constructor(name, group, secondary, ...elements) { - super("tab-link", elements); - - //If the secondary tabs is null, set it to an empty array. - if (!secondary) { - secondary = []; - } - - //If the secondary tabs is not an array then wrap it in one. - if (!Array.isArray(secondary)) { - secondary = [secondary]; - } - - this.property("name", name); - this.property("group", group); - this.property("secondary", secondary); - } + return this; } /** - * Fires a change tab event that will cause the given tab to become active. - * @param {String} name The name of the tab to change to. - * @param {String} group The name of the tab group if applicable. + * A api class to help easily work with tabs. */ -function changeTab(name, group = null) { - var changeEvent = new Event("tabchange"); - changeEvent.name = name; - changeEvent.group = group; +class Tabs { + /** + * Changes the given tab to active. + * @param {String} name The name of the tab to change to. + * @param {String} group The name of the group this tab belongs to if any. Default is null. + * @param {Boolean} active Whether or not to make this tab active. Default is true. + */ + static change(name, group = null, active = true) { + //Init the groups if needed. + if (Tabs.groups[group] == undefined) { + Tabs.groups[group] = { }; + } - window.dispatchEvent(changeEvent); + //Init the tabs if needed. + if (group == null && Tabs.tabs[name] == undefined) { + Tabs.tabs[name] = false; + } + + //If this tab is supposed to be active make that happen. + if (active) { + if (group) { + //Reset all tabs + Object.keys(Tabs.groups[group]).forEach(key => Tabs.groups[group][key] = false); + + //Set this tab to active. + Tabs.groups[group][name] = true; + } else { + //Reset all tabs + Object.keys(Tabs.tabs).forEach(key => Tabs.tabs[key] = false); + + //Set this tab to active. + Tabs.groups[group][name] = true; + } + } else { + //Set this tab to inactive. + if (group) { + Tabs.groups[group][name] = false; + } else { + Tabs.tabs[name] = false; + } + } + + //Create a tab change event and fire it. + var changeEvent = new Event("tabchange"); + changeEvent.name = (active ? name : ""); + changeEvent.group = group; + window.dispatchEvent(changeEvent); + } + + /** + * Returns whether or not the given tab is active. + * @param {String} name The name of the tab. + * @param {String} group The name of the group this tab belongs to. Default is null. + */ + static isActive(name, group = null) { + return ((group && Tabs.groups[group] != undefined && Tabs.groups[group][name]) || (group == null && Tabs.tabs[name] != undefined && Tabs.tabs[name])) ? true : false; + } } -customElements.define("tab-link", TabLink); +Tabs.groups = { }; +Tabs.tabs = { }; + +window.Tabs = Tabs; export { - TabLinkTemplate as TabLink, - changeTab as changeTab + Tabs } \ No newline at end of file