(function (){
const { mergeObjects, matchMedia }=BreakdanceFrontend.utils;
const verticalTabsSelector="is-vertical";
class BreakdanceTabs {
defaultOptions={
activeTab: 1,
horizontalAt: "breakpoint_phone_landscape",
isVertical: false,
openOnHover: false
};
activateTabEventTypes=["click"];
keys={
end: 35,
home: 36,
left: 37,
up: 38,
right: 39,
down: 40,
delete: 46
};
direction={
37: -1,
38: -1,
39: 1,
40: 1
};
constructor(selector, options={}){
this.selector=selector;
this.element=document.querySelector(`${this.selector}`);
this.isBuilder = !!window?.BreakdanceFrontend.utils.isBuilder();
this.options=mergeObjects(this.defaultOptions, options);
this.init();
}
bindListeners(){
if(this.tabs){
this.tabs.forEach((tab, index)=> {
this.addListeners(tab, index);
});
if(this.tabSelect){
this.tabSelect.addEventListener("change", event=> {
this.changeEventListener(event);
});
}}
}
onResizeVertical(){
if(!this.options.isVertical) return;
const breakpoint=this.options.horizontalAt;
const { BASE_BREAKPOINT_ID }=window.BreakdanceFrontend.data;
if((matchMedia(breakpoint)&&this.options.isVertical) ||
(breakpoint===BASE_BREAKPOINT_ID&&this.options.isVertical)
){
this.tabsContainer.classList.remove(verticalTabsSelector);
this.tabList.setAttribute("aria-orientation", "horizontal");
}else{
if(!this.tabsContainer.classList.contains(verticalTabsSelector)){
this.tabsContainer.classList.add(verticalTabsSelector);
this.tabList.setAttribute("aria-orientation", "vertical");
}}
}
addListeners(tab, index){
this.tabs[index].index=index;
this.onClick=this.clickEventListener.bind(this);
this.onKeydown=this.keydownEventListener.bind(this);
this.activateTabEventTypes.forEach((eventType)=> {
tab.addEventListener(eventType, this.onClick);
});
if(this.isBuilder) return;
tab.addEventListener("keydown", this.onKeydown);
}
changeEventListener(event){
const tab=document.querySelector(`#${event.target.value}`);
this.activateTab(tab, false);
}
clickEventListener(event){
const tab=event.target.closest(".js-tab");
this.activateTab(tab, false);
}
keydownEventListener(event){
const key=event.keyCode;
switch (key){
case this.keys.end:
event.preventDefault();
this.activateTab(this.tabs[this.tabs.length - 1], true);
break;
case this.keys.home:
event.preventDefault();
this.activateTab(this.tabs[0], true);
break;
case this.keys.up:
case this.keys.down:
case this.keys.left:
case this.keys.right:
this.determineOrientation(event);
break;
}}
determineOrientation(event){
const key=event.keyCode;
const vertical =
this.tabList.getAttribute("aria-orientation")=="vertical";
let proceed=false;
if(vertical){
if(key===this.keys.up||key===this.keys.down){
event.preventDefault();
proceed=true;
}}else{
if(key===this.keys.left||key===this.keys.right){
proceed=true;
}}
if(proceed){
this.switchTabOnArrowPress(event);
}}
switchTabOnArrowPress(event){
const pressed=event.keyCode;
this.onFocus=this.focusEventHandler.bind(this);
this.tabs.forEach(tab=> {
tab.addEventListener("focus", event=> this.onFocus(event));
});
if(this.direction[pressed]){
const target=event.target;
if(target.index!==undefined){
if(this.tabs[target.index + this.direction[pressed]]){
this.tabs[target.index + this.direction[pressed]].focus();
}else if(pressed===this.keys.left||pressed===this.keys.up){
this.focusLastTab();
}else if(pressed===this.keys.right||pressed==this.keys.down){
this.focusFirstTab();
}}
}}
activateTab(tab, setFocus){
if(tab){
setFocus=setFocus||false;
this.deactivateTabs();
tab.removeAttribute("tabindex");
tab.setAttribute("aria-selected", "true");
tab.classList.add("is-active");
const controls=tab.getAttribute("aria-controls");
if(this.tabSelect){
this.tabSelect.value=tab.getAttribute("id");
this.tabSelect[this.tabSelect.selectedIndex].setAttribute("selected",
"selected"
);
}
const panel=document.getElementById(controls);
if(!panel) return;
panel.classList.add("is-active");
if(setFocus&&!this.isBuilder){
tab.focus();
}
const event=new Event("breakdance_play_animations", { bubbles: true });
panel.parentElement.dispatchEvent(event);
}}
refreshPanelAttributes(){
const firstPanel=document.querySelector(`${this.selector} .js-panel`);
const panelsContainer=firstPanel.closest(".bde-tabs-content-container");
this.panels=panelsContainer.querySelectorAll(":scope > .js-panel, :scope > .bde-advanced-tabs-content > .js-panel"
);
this.panels.forEach((panel, index)=> {
panel.setAttribute("id", `tab-panel-${this.tabsId}-${index + 1}`);
panel.setAttribute("aria-labelledby",
`tab-${this.tabsId}-${index + 1}`
);
});
}
deactivateTabs(){
if(this.tabs){
this.tabs.forEach(tab=> {
tab.setAttribute("tabindex", "-1");
tab.setAttribute("aria-selected", "false");
tab.removeEventListener("focus", event=> this.onFocus(event));
this.activateTabEventTypes.forEach((eventType)=> {
tab.removeEventListener(eventType, event=> this.onClick(event));
});
tab.removeEventListener("keydown", event=> this.onKeydown(event));
tab.classList.remove("is-active");
});
}
if(this.tabSelect){
[...this.tabSelect.options].forEach(option=>
option.removeAttribute("selected")
);
}
if(this.tabSelect){
this.tabSelect.removeEventListener("change", event=>
this.changeEventListener(event)
);
}
if(this.panels){
this.panels.forEach(panel=> {
panel.classList.remove("is-active");
});
}}
focusFirstTab(){
this.tabs[0].focus();
}
focusLastTab(){
this.tabs[this.tabs.length - 1].focus();
}
determineDelay(){
const hasDelay=this.tabList.hasAttribute("data-delay");
const delay=0;
if(hasDelay){
const delayValue=this.tabList.getAttribute("data-delay");
if(delayValue){
this.delay=delayValue;
}else{
this.delay=300;
}}
return delay;
}
focusEventHandler(event){
const target=event.target;
setTimeout(()=> this.checkTabFocus(target), this.delay);
}
checkTabFocus(target){
const focused=document.activeElement;
if(target===focused){
this.activateTab(target, false);
}}
destroy(){
if(!this.tabs) return;
this.deactivateTabs();
this.resetTabstoVerticalLayout();
this.destroyResizeObserver();
}
destroyResizeObserver(){
if(!this.resizeObserver) return;
this.resizeObserver.unobserve(this.element);
}
resetTabstoVerticalLayout(){
this.tabsContainer.classList.remove(verticalTabsSelector);
this.tabList.setAttribute("aria-orientation", "vertical");
}
onResize(callback){
this.resizeObserver=new ResizeObserver(callback);
this.resizeObserver.observe(this.element);
return ()=> {
this.resizeObserver.disconnect();
};}
update(options){
if(options){
this.options=mergeObjects(this.defaultOptions, options);
}
this.destroy();
this.init();
}
updateAndActivateTabFromSelector(selector){
this.refreshPanelAttributes();
const panel=selector.querySelector(".js-panel");
const tabId=panel.getAttribute("aria-labelledby");
if(!tabId) return;
const tab=document.getElementById(tabId);
this.activateTab(tab);
}
init(){
if(!this.element) return;
if(this.options.openOnHover&&!this.isBuilder){
this.activateTabEventTypes.push("mouseover");
}
this.tabList=this.element.querySelector(".js-tablist");
if(!this.tabList) return;
this.tabs=this.tabList.querySelectorAll(".js-tab");
this.tabsContainer=this.tabList.closest(".js-tabs-container");
this.tabsId =
this.tabList&&this.tabList.dataset.tabsId
? this.tabList.dataset.tabsId
: this.selector.match(/\d+$/)[0];
this.tabSelect=this.element.querySelector(".js-tab-select");
this.refreshPanelAttributes();
this.bindListeners();
this.activateTab(this.tabs[this.options.activeTab - 1]);
if(this.options.isVertical){
this.onResize(()=> this.onResizeVertical());
}}
}
window.BreakdanceTabs=BreakdanceTabs;
})();