joomla-ui-custom-elements
Version:
Joomla UI components as custom elements
2 lines (1 loc) • 7.69 kB
JavaScript
customElements.define("joomla-panels",class extends HTMLElement{static get observedAttributes(){return["recall","orientation","view","responsive","collapse-width"]}get recall(){return this.getAttribute("recall")}set recall(t){return this.setAttribute("recall",t)}get view(){return this.getAttribute("view")}set view(t){this.setAttribute("view",t)}get orientation(){return this.getAttribute("orientation")||"horizontal"}set orientation(t){this.setAttribute("orientation",t)}get responsive(){return this.getAttribute("responsive")}set responsive(t){this.setAttribute("responsive",t)}get collapseWidth(){return this.getAttribute("collapse-width")}set collapseWidth(t){this.setAttribute("collapse-width",t)}constructor(){super(),this.hasActive=!1,this.currentActive="",this.hasNested=!1,this.isNested=!1,this.tabs=[],this.tabsLinks=[],this.panels=[],this.tabLinkHash=[]}connectedCallback(){if((!this.orientation||this.orientation&&-1===["horizontal","vertical"].indexOf(this.orientation))&&this.setAttribute("orientation","horizontal"),this.view=this.getAttribute("view")||"tabs",this.recall=this.recall||"false",this.responsive=this.getAttribute("responsive")||"false",this.collapseWidth=this.getAttribute("collapseWidth")||0,this.panels=[].slice.call(this.querySelectorAll("section")),!this.panels.length)throw new Error("`Joomla-panels` require one ore more panels!");if(this.findAncestorByTagNme(this,"joomla-tab")&&(this.isNested=!0),this.querySelector("joomla-tab")&&(this.hasNested=!0),this.recall){const t=sessionStorage.getItem(this.getStorageKey());t&&!/@\[/.test(t)&&this.tabLinkHash.push(t),this.setTabState()}"ul"!==this.firstElementChild.tagName&&this.createNavigation(),this.panels.forEach((t=>{t.setAttribute("role","tabpanel"),this.tabs.push(`#tab-${t.id}`),t.hasAttribute("active")&&(this.hasActive=!0,this.currentActive=t.id,this.querySelector(`#tab-${t.id}`).setAttribute("aria-selected","true"),this.querySelector(`#tab-${t.id}`).setAttribute("active",""),this.querySelector(`#tab-${t.id}`).setAttribute("tabindex","0"))})),this.hasActive||(this.tabsLinks[0].setAttribute("active",""),this.hasActive=!0,this.currentActive=this.panels[0].id,this.tabsLinks[0].setAttribute("aria-selected","true"),this.tabsLinks[0].setAttribute("tabindex","0"),this.tabsLinks[0].setAttribute("active",""),this.panels[0].setAttribute("active","")),window.location.href.match(/#tab-/),"accordion"===this.view&&this.toAccordion.bind(this)(),"true"===this.responsive&&(this.changeView.bind(this),window.addEventListener("resize",this.changeView.bind(this)))}disconnectedCallback(){const t=this,e=this.querySelector("ul");[].slice.call(e.querySelectorAll("a")).forEach((e=>{e.removeEventListener("click",t.activateTabFromLink,!0)})),e.removeEventListener("keydown",t.keyBehaviour,!0)}createNavigation(){const t=this;let e="";"ul"!==this.firstElementChild.tagName.toLowerCase()&&(e=document.createElement("ul")),e.setAttribute("role","tablist"),this.panels.forEach((i=>{if(!i.id)throw new Error("`joomla-panels` All panels require an ID");if(i.parentNode!==this)return;const s=i.getAttribute("active")||!1,a=document.createElement("li"),r=document.createElement("a");a.setAttribute("role","presentation"),r.setAttribute("role","tab"),r.setAttribute("aria-controls",i.id),r.setAttribute("aria-selected",s?"true":"false"),r.setAttribute("tabindex",s?"0":"-1"),r.setAttribute("href",`#${i.id}`),r.setAttribute("id",`tab-${i.id}`),r.innerHTML=i.getAttribute("name"),s&&r.setAttribute("active",""),r.addEventListener("click",t.activateTabFromLink.bind(t)),this.tabsLinks.push(r),a.append(r),e.append(a),i.setAttribute("aria-labelledby",`tab-${i.id}`),s||i.setAttribute("aria-hidden","true")})),this.insertAdjacentElement("afterbegin",e),this.querySelector("ul").addEventListener("keydown",this.keyBehaviour.bind(this))}hideCurrent(){if(this.currentActive){const t=this.querySelector(`a[aria-controls="${this.currentActive}"]`);this.dispatchCustomEvent("joomla.tab.hide",t,this.querySelector(`#tab-${this.currentActive}`)),t.removeAttribute("active"),t.setAttribute("tabindex","-1"),this.querySelector(`#${this.currentActive}`).removeAttribute("active"),this.querySelector(`#${this.currentActive}`).setAttribute("aria-hidden","true"),t.removeAttribute("aria-selected"),this.dispatchCustomEvent("joomla.tab.hidden",t,this.querySelector(`#tab-${this.currentActive}`))}}activateTabFromLink(t){t.preventDefault();const e=this.currentActive;this.hasActive&&this.hideCurrent(),this.dispatchCustomEvent("joomla.tab.show",t.target,this.querySelector(`#tab-${e}`)),t.target.setAttribute("active",""),t.target.setAttribute("aria-selected","true"),t.target.setAttribute("tabindex","0"),this.querySelector(t.target.hash).setAttribute("active",""),this.querySelector(t.target.hash).removeAttribute("aria-hidden"),this.currentActive=t.target.hash.substring(1),this.dispatchCustomEvent("joomla.tab.shown",t.target,this.querySelector(`#tab-${e}`)),this.saveState(`#tab-${t.target.hash.substring(1)}`)}showTab(t){document.querySelector(`#tab-${t.id}`).click()}show(t){t.click()}keyBehaviour(t){const e=this.querySelector(`#tab-${this.currentActive}`),i=e.parentNode.previousElementSibling||e.parentNode.parentNode.lastElementChild,s=e.parentNode.nextElementSibling||e.parentNode.parentNode.firstElementChild;if(!t.metaKey&&!t.altKey&&-1!==this.tabs.indexOf(`#${document.activeElement.id}`))switch(t.keyCode){case 37:case 38:t.preventDefault(),t.stopPropagation(),i.querySelector("a").click(),i.querySelector("a").focus();break;case 39:case 40:t.preventDefault(),t.stopPropagation(),s.querySelector("a").click(),s.querySelector("a").focus()}}getStorageKey(){return window.location.href.toString().split(window.location.host)[1].replace(/&return=[a-zA-Z0-9%]+/,"").split("#")[0]}saveState(t){const e=this.getStorageKey();sessionStorage.setItem(e,t)}setTabState(){const t=this,e=this.tabsLinks;if(this.hasNested){if(this.tabLinkHash.length&&""!==this.tabLinkHash[0]){const t=this.tabLinkHash[0].substring(5),e=this.querySelector(`${t}`);if(e){const t=this.findAncestorByTagNme(e,"joomla-tab");if(this.findAncestorByTagNme(t,"joomla-tab")){const e=this.findAncestorByTagNme(t,"section");e&&this.tabLinkHash.push(`#tab-${e.id}`)}}}e.forEach((e=>{if(this.tabLinkHash.length){const t=`#tab-${e.id}`;-1===this.tabLinkHash.indexOf(t)?e.removeAttribute("active"):e.setAttribute("active","")}e.parentNode===t&&this.tabsLinks.push(e)}))}else e.forEach((t=>{if(this.tabLinkHash.length){const e=`#tab-${t.hash}`;this.tabLinkHash.indexOf(e)>-1?t.removeAttribute("active"):t.setAttribute("active","")}})),this.tabsLinks=e}toTabs(){const t=this;for(let t=0,e=this.panels.length;t<e;++t)this.panels[t].parentNode.parentNode.parentNode===this&&this.tabsLinks.push(this.panels[t]);this.tabsLinks.length&&this.tabsLinks.forEach((e=>{t.appendChild(e)}))}toAccordion(){const t=this;this.panels.length&&this.panels.forEach((e=>{t.querySelector('a[aria-controls="'+e.id+'"]').parentNode.appendChild(e)}))}changeView(){if(window.outerWidth>920){if("tabs"===this.view)return;this.toTabs.bind(this),this.view="tabs"}else{if("accordion"===this.view)return;this.toAccordion.bind(this),this.view="accordion"}}activateUriHash(){const t=window.location.href.match(/#\S[^&]*/),e=this.querySelector(t[0]);if(e){const t=this.findAncestorByTagNme(e,"joomla-tab"),i=this.findAncestorByTagNme(t,"joomla-tab");if(i){const s=this.findAncestorByTagNme(t,"section");i.showTab(s),this.show(e)}else this.showTab(e)}}findAncestorByTagNme(t,e){for(;(t=t.parentElement)&&t.nodeName.toLowerCase()!==e;);return t}dispatchCustomEvent(t,e,i){const s=new CustomEvent(t,{bubbles:!0,cancelable:!0});i&&(s.relatedTarget=i),e.dispatchEvent(s),e.removeEventListener(t,e)}});