File: D:/HostingSpaces/SBogers47/leden.ehbocranendonck.nl/resources/assets/js/kms/entity/tabs.js
class TabsController {
/**
* The tab controller can obviously control tabs.
* You just have to have a couple of divs that hold the content. These divs must all have a class name that
* corresponds to the value of constructor parameter tabContentIdAndClassAndPrefix. And they all must have an id
* that also starts with the value of tabContentIdAndClassAndPrefix followed by the tab slug.
*
* You can specify if you have an hidden input field that needs to be updated with the curent tab slug. You do that
* with the tabSlugInputSelector.
*
* Content tab divs and buttons will also receive an active state class to make them visible / stand out when present
* or hidden / to background. You can specify this class name with the activeClass parameter.
*
* The tabButtonGroupSelector selects an element that holds the tab buttons to switch tabs. This element must have an
* ul element that holds li elements containing a elements.
*
* The reactToUrlHashChange parameter controls if the controller should react if the hash part of the url did change.
*
* @param tabContentIdAndClassAndPrefix string
* @param tabButtonGroupSelector string
* @param activeClass string
* @param reactToUrlHashChange
* @param tabSlugInputSelector string
*/
constructor(tabContentIdAndClassAndPrefix = 'tab', tabButtonGroupSelector = '.tab-buttons', activeClass = 'active', reactToUrlHashChange = false, tabSlugInputSelector = undefined) {
let input = document.querySelector(this.tabSlugInputId);
this.tabButtonGroupSelector = tabButtonGroupSelector;
this.tabContentDivsClassAndIdPrefix = tabContentIdAndClassAndPrefix;
this.tabSlugInputId = tabSlugInputSelector;
this.activeClass = activeClass;
this.reactToUrlHashChange = reactToUrlHashChange;
this.openTabFromHiddenSlugInput();
if(reactToUrlHashChange) this.addListenerForHashChange(reactToUrlHashChange);
}
/**
* Looks at the hidden input and opens the correct tab
*/
openTabFromHiddenSlugInput()
{
if(this.tabSlugInputId === undefined) return;
let input = document.querySelector(this.tabSlugInputId);
if(!input) return;
this.openTab(input.value);
}
/**
* Opens the tab by using the tab slug
*
* @param tabSlug
*/
openTab(tabSlug) {
//Remove trailing / on the left hand side
tabSlug = this.removeLeftHandSlashInSlug(tabSlug);
if (!tabSlug) { return; }
this.updateTabSlugInput(tabSlug);
this.showTabContentForTabWithSlug(tabSlug);
this.makeTabButtonActiveForSlug(tabSlug);
}
/**
* Removes a / at the beginning of a tab slug
*
* @param tabSlug
*/
removeLeftHandSlashInSlug(tabSlug) {
return tabSlug.replace(/^\/(.*)/, '$1');
}
/**
* Updates a usually hidden input field holding the tab slug with a new slug
*
* @param newSlug string
*/
updateTabSlugInput(newSlug)
{
if(this.tabSlugInputId === undefined) return;
let element = document.querySelector(this.tabSlugInputId);
if(element) element.value = newSlug;
}
makeTabButtonActiveForSlug(slug)
{
$('.entity-tabs >ul >li').removeClass('active');
$('.entity-tabs >ul >li a[href="#' + slug + '"]').parent().addClass('active');
}
/**
* Shows the tab content div with the specified slug and hides the other content div tabs.
* It does this by adding and removing classes (the active class you specified in the constructor)
*
* @param slug string
*/
showTabContentForTabWithSlug(slug)
{
//Remove the active class from all tab content classes
let items = document.querySelectorAll('.'+this.tabContentDivsClassAndIdPrefix);
let length = items.length;
for(let index = 0; index < length; index++) {
let element = items[index];
element.classList.remove(this.activeClass)
}
//Add the active class to the tab that has the correct slug appended to the IdPrefix
let activeTab = document.querySelector("#"+this.tabContentDivsClassAndIdPrefix+"-"+slug);
if(!activeTab) { console.error("TabsController: Could not make content tab active. It should have an ID with: #"+this.tabContentDivsClassAndIdPrefix+"-"+slug); return; }
activeTab.classList.add(this.activeClass);
}
/**
* Adds or disables listening for hashchange events to update tabs
*
* @param boolean
*/
addListenerForHashChange(boolean)
{
if(boolean) {
window.addEventListener('hashchange', this.hashChanged.bind(this));
window.addEventListener('load', this.hashChanged.bind(this));
} else {
window.removeEventListener('hashchange', this.hashChanged);
window.removeEventListener('load', this.hashChanged);
}
}
/**
* Called automatically by an internal listener (controlled by the addListenerForHashChange method)
*/
hashChanged(event)
{
let tabSlug = window.location.hash.substring(1);
if (tabSlug) {
this.openTab(tabSlug);
return;
}
let tabSlugElement = document.querySelector(this.tabSlugInputId);
if(!tabSlugElement) return;
this.openTab(tabSlugElement.value);
}
}