first commit
This commit is contained in:
191
media/vendor/joomla-custom-elements/js/joomla-alert.js
vendored
Normal file
191
media/vendor/joomla-custom-elements/js/joomla-alert.js
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
class AlertElement extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// Bindings
|
||||
this.close = this.close.bind(this);
|
||||
this.destroyCloseButton = this.destroyCloseButton.bind(this);
|
||||
this.createCloseButton = this.createCloseButton.bind(this);
|
||||
this.onMutation = this.onMutation.bind(this);
|
||||
|
||||
this.observer = new MutationObserver(this.onMutation);
|
||||
this.observer.observe(this, { attributes: false, childList: true, subtree: true });
|
||||
|
||||
// Handle the fade in animation
|
||||
this.addEventListener('animationend', (event) => {
|
||||
if (event.animationName === 'joomla-alert-fade-in' && event.target === this) {
|
||||
this.dispatchEvent(new CustomEvent('joomla.alert.shown'));
|
||||
this.style.removeProperty('animationName');
|
||||
}
|
||||
});
|
||||
|
||||
// Handle the fade out animation
|
||||
this.addEventListener('animationend', (event) => {
|
||||
if (event.animationName === 'joomla-alert-fade-out' && event.target === this) {
|
||||
this.dispatchEvent(new CustomEvent('joomla.alert.closed'));
|
||||
this.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Attributes to monitor */
|
||||
static get observedAttributes() { return ['type', 'role', 'dismiss', 'auto-dismiss', 'close-text']; }
|
||||
|
||||
get type() { return this.getAttribute('type'); }
|
||||
|
||||
set type(value) { this.setAttribute('type', value); }
|
||||
|
||||
get role() { return this.getAttribute('role'); }
|
||||
|
||||
set role(value) { this.setAttribute('role', value); }
|
||||
|
||||
get closeText() { return this.getAttribute('close-text'); }
|
||||
|
||||
set closeText(value) { this.setAttribute('close-text', value); }
|
||||
|
||||
get dismiss() { return this.getAttribute('dismiss'); }
|
||||
|
||||
set dismiss(value) { this.setAttribute('dismiss', value); }
|
||||
|
||||
get autodismiss() { return this.getAttribute('auto-dismiss'); }
|
||||
|
||||
set autodismiss(value) { this.setAttribute('auto-dismiss', value); }
|
||||
|
||||
/* Lifecycle, element appended to the DOM */
|
||||
connectedCallback() {
|
||||
this.dispatchEvent(new CustomEvent('joomla.alert.show'));
|
||||
this.style.animationName = 'joomla-alert-fade-in';
|
||||
|
||||
// Default to info
|
||||
if (!this.type || !['info', 'warning', 'danger', 'success'].includes(this.type)) {
|
||||
this.setAttribute('type', 'info');
|
||||
}
|
||||
// Default to alert
|
||||
if (!this.role || !['alert', 'alertdialog'].includes(this.role)) {
|
||||
this.setAttribute('role', 'alert');
|
||||
}
|
||||
|
||||
// Hydrate the button
|
||||
if (this.firstElementChild && this.firstElementChild.tagName === 'BUTTON') {
|
||||
this.button = this.firstElementChild;
|
||||
if (this.button.classList.contains('joomla-alert--close')) {
|
||||
this.button.classList.add('joomla-alert--close');
|
||||
}
|
||||
if (this.button.innerHTML === '') {
|
||||
this.button.innerHTML = '<span aria-hidden="true">×</span>';
|
||||
}
|
||||
if (!this.button.hasAttribute('aria-label')) {
|
||||
this.button.setAttribute('aria-label', this.closeText);
|
||||
}
|
||||
}
|
||||
|
||||
// Append button
|
||||
if (this.hasAttribute('dismiss') && !this.button) {
|
||||
this.createCloseButton();
|
||||
}
|
||||
|
||||
if (this.hasAttribute('auto-dismiss')) {
|
||||
this.autoDismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/* Lifecycle, element removed from the DOM */
|
||||
disconnectedCallback() {
|
||||
if (this.button) {
|
||||
this.button.removeEventListener('click', this.close);
|
||||
}
|
||||
this.observer.disconnect();
|
||||
}
|
||||
|
||||
/* Respond to attribute changes */
|
||||
attributeChangedCallback(attr, oldValue, newValue) {
|
||||
switch (attr) {
|
||||
case 'type':
|
||||
if (!newValue || (newValue && ['info', 'warning', 'danger', 'success'].indexOf(newValue) === -1)) {
|
||||
this.type = 'info';
|
||||
}
|
||||
break;
|
||||
case 'role':
|
||||
if (!newValue || (newValue && ['alert', 'alertdialog'].indexOf(newValue) === -1)) {
|
||||
this.role = 'alert';
|
||||
}
|
||||
break;
|
||||
case 'dismiss':
|
||||
if ((!newValue || newValue === '') && (!oldValue || oldValue === '')) {
|
||||
if (this.button && !this.hasAttribute('dismiss')) {
|
||||
this.destroyCloseButton();
|
||||
} else if (!this.button && this.hasAttribute('dismiss')) {
|
||||
this.createCloseButton();
|
||||
}
|
||||
} else if (this.button && newValue === 'false') {
|
||||
this.destroyCloseButton();
|
||||
} else if (!this.button && newValue !== 'false') {
|
||||
this.createCloseButton();
|
||||
}
|
||||
break;
|
||||
case 'close-text':
|
||||
if (!newValue || newValue !== oldValue) {
|
||||
if (this.button) {
|
||||
this.button.setAttribute('aria-label', newValue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'auto-dismiss':
|
||||
this.autoDismiss();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Observe added elements */
|
||||
onMutation(mutationsList) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const mutation of mutationsList) {
|
||||
if (mutation.type === 'childList') {
|
||||
if (mutation.addedNodes.length) {
|
||||
// Make sure that the button is always the first element
|
||||
if (this.button && this.firstElementChild !== this.button) {
|
||||
this.prepend(this.button);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Method to close the alert */
|
||||
close() {
|
||||
this.dispatchEvent(new CustomEvent('joomla.alert.close'));
|
||||
this.style.animationName = 'joomla-alert-fade-out';
|
||||
}
|
||||
|
||||
/* Method to create the close button */
|
||||
createCloseButton() {
|
||||
this.button = document.createElement('button');
|
||||
this.button.setAttribute('type', 'button');
|
||||
this.button.classList.add('joomla-alert--close');
|
||||
this.button.innerHTML = '<span aria-hidden="true">×</span>';
|
||||
this.button.setAttribute('aria-label', this.closeText);
|
||||
this.insertAdjacentElement('afterbegin', this.button);
|
||||
|
||||
/* Add the required listener */
|
||||
this.button.addEventListener('click', this.close);
|
||||
}
|
||||
|
||||
/* Method to remove the close button */
|
||||
destroyCloseButton() {
|
||||
if (this.button) {
|
||||
this.button.removeEventListener('click', this.close);
|
||||
this.button.parentNode.removeChild(this.button);
|
||||
this.button = null;
|
||||
}
|
||||
}
|
||||
|
||||
/* Method to auto-dismiss */
|
||||
autoDismiss() {
|
||||
const timer = parseInt(this.getAttribute('auto-dismiss'), 10);
|
||||
setTimeout(this.close, timer >= 10 ? timer : 3000);
|
||||
}
|
||||
}
|
||||
|
||||
if (!customElements.get('joomla-alert')) {
|
||||
customElements.define('joomla-alert', AlertElement);
|
||||
}
|
||||
1
media/vendor/joomla-custom-elements/js/joomla-alert.min.js
vendored
Normal file
1
media/vendor/joomla-custom-elements/js/joomla-alert.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
class t extends HTMLElement{constructor(){super(),this.close=this.close.bind(this),this.destroyCloseButton=this.destroyCloseButton.bind(this),this.createCloseButton=this.createCloseButton.bind(this),this.onMutation=this.onMutation.bind(this),this.observer=new MutationObserver(this.onMutation),this.observer.observe(this,{attributes:!1,childList:!0,subtree:!0}),this.addEventListener("animationend",(t=>{"joomla-alert-fade-in"===t.animationName&&t.target===this&&(this.dispatchEvent(new CustomEvent("joomla.alert.shown")),this.style.removeProperty("animationName"))})),this.addEventListener("animationend",(t=>{"joomla-alert-fade-out"===t.animationName&&t.target===this&&(this.dispatchEvent(new CustomEvent("joomla.alert.closed")),this.remove())}))}static get observedAttributes(){return["type","role","dismiss","auto-dismiss","close-text"]}get type(){return this.getAttribute("type")}set type(t){this.setAttribute("type",t)}get role(){return this.getAttribute("role")}set role(t){this.setAttribute("role",t)}get closeText(){return this.getAttribute("close-text")}set closeText(t){this.setAttribute("close-text",t)}get dismiss(){return this.getAttribute("dismiss")}set dismiss(t){this.setAttribute("dismiss",t)}get autodismiss(){return this.getAttribute("auto-dismiss")}set autodismiss(t){this.setAttribute("auto-dismiss",t)}connectedCallback(){this.dispatchEvent(new CustomEvent("joomla.alert.show")),this.style.animationName="joomla-alert-fade-in",this.type&&["info","warning","danger","success"].includes(this.type)||this.setAttribute("type","info"),this.role&&["alert","alertdialog"].includes(this.role)||this.setAttribute("role","alert"),this.firstElementChild&&"BUTTON"===this.firstElementChild.tagName&&(this.button=this.firstElementChild,this.button.classList.contains("joomla-alert--close")&&this.button.classList.add("joomla-alert--close"),""===this.button.innerHTML&&(this.button.innerHTML='<span aria-hidden="true">×</span>'),this.button.hasAttribute("aria-label")||this.button.setAttribute("aria-label",this.closeText)),this.hasAttribute("dismiss")&&!this.button&&this.createCloseButton(),this.hasAttribute("auto-dismiss")&&this.autoDismiss()}disconnectedCallback(){this.button&&this.button.removeEventListener("click",this.close),this.observer.disconnect()}attributeChangedCallback(t,e,s){switch(t){case"type":(!s||s&&-1===["info","warning","danger","success"].indexOf(s))&&(this.type="info");break;case"role":(!s||s&&-1===["alert","alertdialog"].indexOf(s))&&(this.role="alert");break;case"dismiss":s&&""!==s||e&&""!==e?this.button&&"false"===s?this.destroyCloseButton():this.button||"false"===s||this.createCloseButton():this.button&&!this.hasAttribute("dismiss")?this.destroyCloseButton():!this.button&&this.hasAttribute("dismiss")&&this.createCloseButton();break;case"close-text":s&&s===e||this.button&&this.button.setAttribute("aria-label",s);break;case"auto-dismiss":this.autoDismiss()}}onMutation(t){for(const e of t)"childList"===e.type&&e.addedNodes.length&&this.button&&this.firstElementChild!==this.button&&this.prepend(this.button)}close(){this.dispatchEvent(new CustomEvent("joomla.alert.close")),this.style.animationName="joomla-alert-fade-out"}createCloseButton(){this.button=document.createElement("button"),this.button.setAttribute("type","button"),this.button.classList.add("joomla-alert--close"),this.button.innerHTML='<span aria-hidden="true">×</span>',this.button.setAttribute("aria-label",this.closeText),this.insertAdjacentElement("afterbegin",this.button),this.button.addEventListener("click",this.close)}destroyCloseButton(){this.button&&(this.button.removeEventListener("click",this.close),this.button.parentNode.removeChild(this.button),this.button=null)}autoDismiss(){const t=parseInt(this.getAttribute("auto-dismiss"),10);setTimeout(this.close,t>=10?t:3e3)}}customElements.get("joomla-alert")||customElements.define("joomla-alert",t);
|
||||
BIN
media/vendor/joomla-custom-elements/js/joomla-alert.min.js.gz
vendored
Normal file
BIN
media/vendor/joomla-custom-elements/js/joomla-alert.min.js.gz
vendored
Normal file
Binary file not shown.
487
media/vendor/joomla-custom-elements/js/joomla-tab.js
vendored
Normal file
487
media/vendor/joomla-custom-elements/js/joomla-tab.js
vendored
Normal file
@ -0,0 +1,487 @@
|
||||
class TabElement extends HTMLElement {}
|
||||
|
||||
customElements.define('joomla-tab-element', TabElement);
|
||||
|
||||
class TabsElement extends HTMLElement {
|
||||
/* Attributes to monitor */
|
||||
static get observedAttributes() { return ['recall', 'orientation', 'view', 'breakpoint']; }
|
||||
|
||||
get recall() { return this.getAttribute('recall'); }
|
||||
|
||||
set recall(value) { this.setAttribute('recall', value); }
|
||||
|
||||
get view() { return this.getAttribute('view'); }
|
||||
|
||||
set view(value) { this.setAttribute('view', value); }
|
||||
|
||||
get orientation() { return this.getAttribute('orientation'); }
|
||||
|
||||
set orientation(value) { this.setAttribute('orientation', value); }
|
||||
|
||||
get breakpoint() { return parseInt(this.getAttribute('breakpoint'), 10); }
|
||||
|
||||
set breakpoint(value) { this.setAttribute('breakpoint', value); }
|
||||
|
||||
/* Lifecycle, element created */
|
||||
constructor() {
|
||||
super();
|
||||
this.tabs = [];
|
||||
this.tabsElements = [];
|
||||
this.previousActive = null;
|
||||
|
||||
this.onMutation = this.onMutation.bind(this);
|
||||
this.keyBehaviour = this.keyBehaviour.bind(this);
|
||||
this.activateTab = this.activateTab.bind(this);
|
||||
this.deactivateTabs = this.deactivateTabs.bind(this);
|
||||
this.checkView = this.checkView.bind(this);
|
||||
|
||||
this.observer = new MutationObserver(this.onMutation);
|
||||
this.observer.observe(this, { attributes: false, childList: true, subtree: true });
|
||||
}
|
||||
|
||||
/* Lifecycle, element appended to the DOM */
|
||||
connectedCallback() {
|
||||
if (!this.orientation || (this.orientation && !['horizontal', 'vertical'].includes(this.orientation))) {
|
||||
this.orientation = 'horizontal';
|
||||
}
|
||||
|
||||
if (!this.view || (this.view && !['tabs', 'accordion'].includes(this.view))) {
|
||||
this.view = 'tabs';
|
||||
}
|
||||
|
||||
// get tab elements
|
||||
this.tabsElements = [].slice.call(this.children).filter((el) => el.tagName.toLowerCase() === 'joomla-tab-element');
|
||||
|
||||
// Sanity checks
|
||||
if (!this.tabsElements.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isNested = this.parentNode.closest('joomla-tab') instanceof HTMLElement;
|
||||
|
||||
this.hydrate();
|
||||
if (this.hasAttribute('recall') && !this.isNested) {
|
||||
this.activateFromState();
|
||||
}
|
||||
|
||||
// Activate tab from the URL hash
|
||||
if (window.location.hash) {
|
||||
const hash = window.location.hash.substr(1);
|
||||
const tabToactivate = this.tabs.filter((tab) => tab.tab.id === hash);
|
||||
if (tabToactivate.length) {
|
||||
this.activateTab(tabToactivate[0].tab, false);
|
||||
}
|
||||
}
|
||||
|
||||
// If no active tab activate the first one
|
||||
if (!this.tabs.filter((tab) => tab.tab.hasAttribute('active')).length) {
|
||||
this.activateTab(this.tabs[0].tab, false);
|
||||
}
|
||||
|
||||
this.addEventListener('keyup', this.keyBehaviour);
|
||||
|
||||
if (this.breakpoint) {
|
||||
// Convert tabs to accordian
|
||||
this.checkView();
|
||||
window.addEventListener('resize', () => {
|
||||
this.checkView();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* Lifecycle, element removed from the DOM */
|
||||
disconnectedCallback() {
|
||||
this.tabs.map((tab) => {
|
||||
tab.tabButton.removeEventListener('click', this.activateTab);
|
||||
tab.accordionButton.removeEventListener('click', this.activateTab);
|
||||
return tab;
|
||||
});
|
||||
this.removeEventListener('keyup', this.keyBehaviour);
|
||||
}
|
||||
|
||||
/* Respond to attribute changes */
|
||||
attributeChangedCallback(attr, oldValue, newValue) {
|
||||
switch (attr) {
|
||||
case 'view':
|
||||
if (!newValue || (newValue && !['tabs', 'accordion'].includes(newValue))) {
|
||||
this.view = 'tabs';
|
||||
}
|
||||
if (newValue === 'tabs' && newValue !== oldValue) {
|
||||
if (this.tabButtonContainer) this.tabButtonContainer.removeAttribute('hidden');
|
||||
this.tabs.map((tab) => tab.accordionButton.setAttribute('hidden', ''));
|
||||
} else if (newValue === 'accordion' && newValue !== oldValue) {
|
||||
if (this.tabButtonContainer) this.tabButtonContainer.setAttribute('hidden', '');
|
||||
this.tabs.map((tab) => tab.accordionButton.removeAttribute('hidden'));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hydrate() {
|
||||
// Ensure the tab links container exists
|
||||
this.tabButtonContainer = document.createElement('div');
|
||||
this.tabButtonContainer.setAttribute('role', 'tablist');
|
||||
this.insertAdjacentElement('afterbegin', this.tabButtonContainer);
|
||||
|
||||
if (this.view === 'accordion') {
|
||||
this.tabButtonContainer.setAttribute('hidden', '');
|
||||
}
|
||||
|
||||
this.tabsElements.map((tab) => {
|
||||
// Create Accordion button
|
||||
const accordionButton = document.createElement('button');
|
||||
accordionButton.setAttribute('aria-expanded', !!tab.hasAttribute('active'));
|
||||
accordionButton.setAttribute('aria-controls', tab.id);
|
||||
accordionButton.setAttribute('type', 'button');
|
||||
accordionButton.innerHTML = `<span class="accordion-title">${tab.getAttribute('name')}<span class="accordion-icon"></span></span>`;
|
||||
tab.insertAdjacentElement('beforebegin', accordionButton);
|
||||
|
||||
if (this.view === 'tabs') {
|
||||
accordionButton.setAttribute('hidden', '');
|
||||
}
|
||||
|
||||
accordionButton.addEventListener('click', this.activateTab);
|
||||
|
||||
// Create tab button
|
||||
const tabButton = document.createElement('button');
|
||||
tabButton.setAttribute('aria-expanded', !!tab.hasAttribute('active'));
|
||||
tabButton.setAttribute('aria-controls', tab.id);
|
||||
tabButton.setAttribute('role', 'tab');
|
||||
tabButton.setAttribute('type', 'button');
|
||||
tabButton.innerHTML = `${tab.getAttribute('name')}`;
|
||||
this.tabButtonContainer.appendChild(tabButton);
|
||||
|
||||
tabButton.addEventListener('click', this.activateTab);
|
||||
|
||||
if (this.view === 'tabs') {
|
||||
tab.setAttribute('role', 'tabpanel');
|
||||
} else {
|
||||
tab.setAttribute('role', 'region');
|
||||
}
|
||||
|
||||
this.tabs.push({
|
||||
tab,
|
||||
tabButton,
|
||||
accordionButton,
|
||||
});
|
||||
|
||||
return tab;
|
||||
});
|
||||
}
|
||||
|
||||
/* Update on mutation */
|
||||
onMutation(mutationsList) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const mutation of mutationsList) {
|
||||
if (mutation.type === 'childList') {
|
||||
if (mutation.addedNodes.length) {
|
||||
[].slice.call(mutation.addedNodes).map((inserted) => this.createNavs(inserted));
|
||||
// Add the tab buttons
|
||||
}
|
||||
if (mutation.removedNodes.length) {
|
||||
// Remove the tab buttons
|
||||
[].slice.call(mutation.addedNodes).map((inserted) => this.removeNavs(inserted));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keyBehaviour(e) {
|
||||
// Only the tabs/accordion buttons, no ⌘ or Alt modifier
|
||||
if (![...this.tabs.map((el) => el.tabButton), ...this.tabs.map((el) => el.accordionButton)]
|
||||
.includes(document.activeElement)
|
||||
|| e.metaKey
|
||||
|| e.altKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
let previousTabItem;
|
||||
let nextTabItem;
|
||||
if (this.view === 'tabs') {
|
||||
const currentTabIndex = this.tabs.findIndex((tab) => tab.tab.hasAttribute('active'));
|
||||
previousTabItem = currentTabIndex - 1 >= 0
|
||||
? this.tabs[currentTabIndex - 1] : this.tabs[this.tabs.length - 1];
|
||||
nextTabItem = currentTabIndex + 1 <= this.tabs.length - 1
|
||||
? this.tabs[currentTabIndex + 1] : this.tabs[0];
|
||||
} else {
|
||||
const currentTabIndex = this.tabs.map((el) => el.accordionButton)
|
||||
.findIndex((tab) => tab === document.activeElement);
|
||||
previousTabItem = currentTabIndex - 1 >= 0
|
||||
? this.tabs[currentTabIndex - 1] : this.tabs[this.tabs.length - 1];
|
||||
nextTabItem = currentTabIndex + 1 <= this.tabs.length - 1
|
||||
? this.tabs[currentTabIndex + 1] : this.tabs[0];
|
||||
}
|
||||
|
||||
// catch left/right and up/down arrow key events
|
||||
switch (e.keyCode) {
|
||||
case 37:
|
||||
case 38:
|
||||
if (this.view === 'tabs') {
|
||||
previousTabItem.tabButton.click();
|
||||
previousTabItem.tabButton.focus();
|
||||
} else {
|
||||
previousTabItem.accordionButton.focus();
|
||||
}
|
||||
e.preventDefault();
|
||||
break;
|
||||
case 39:
|
||||
case 40:
|
||||
if (this.view === 'tabs') {
|
||||
nextTabItem.tabButton.click();
|
||||
nextTabItem.tabButton.focus();
|
||||
} else {
|
||||
nextTabItem.accordionButton.focus();
|
||||
}
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
deactivateTabs() {
|
||||
this.tabs.map((tabObj) => {
|
||||
tabObj.accordionButton.removeAttribute('aria-disabled');
|
||||
tabObj.tabButton.removeAttribute('aria-expanded');
|
||||
tabObj.accordionButton.setAttribute('aria-expanded', false);
|
||||
|
||||
if (tabObj.tab.hasAttribute('active')) {
|
||||
this.dispatchCustomEvent('joomla.tab.hide', this.view === 'tabs' ? tabObj.tabButton : tabObj.accordionButton, this.previousActive);
|
||||
tabObj.tab.removeAttribute('active');
|
||||
tabObj.tab.setAttribute('tabindex', '-1');
|
||||
// Emit hidden event
|
||||
this.dispatchCustomEvent('joomla.tab.hidden', this.view === 'tabs' ? tabObj.tabButton : tabObj.accordionButton, this.previousActive);
|
||||
this.previousActive = this.view === 'tabs' ? tabObj.tabButton : tabObj.accordionButton;
|
||||
}
|
||||
return tabObj;
|
||||
});
|
||||
}
|
||||
|
||||
activateTab(input, state = true) {
|
||||
let currentTrigger;
|
||||
if (input.currentTarget) {
|
||||
currentTrigger = this.tabs.find((tab) => ((this.view === 'tabs' ? tab.tabButton : tab.accordionButton) === input.currentTarget));
|
||||
} else if (input instanceof HTMLElement) {
|
||||
currentTrigger = this.tabs.find((tab) => tab.tab === input);
|
||||
} else if (Number.isInteger(input)) {
|
||||
currentTrigger = this.tabs[input];
|
||||
}
|
||||
|
||||
if (currentTrigger) {
|
||||
// Accordion can close the active panel
|
||||
if (this.view === 'accordion' && this.tabs.find((tab) => tab.accordionButton.getAttribute('aria-expanded') === 'true') === currentTrigger) {
|
||||
if (currentTrigger.tab.hasAttribute('active')) {
|
||||
currentTrigger.tab.removeAttribute('active');
|
||||
return;
|
||||
}
|
||||
currentTrigger.tab.setAttribute('active', '');
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove current active
|
||||
this.deactivateTabs();
|
||||
// Set new active
|
||||
currentTrigger.tabButton.setAttribute('aria-expanded', true);
|
||||
currentTrigger.accordionButton.setAttribute('aria-expanded', true);
|
||||
currentTrigger.accordionButton.setAttribute('aria-disabled', true);
|
||||
currentTrigger.tab.setAttribute('active', '');
|
||||
currentTrigger.tabButton.removeAttribute('tabindex');
|
||||
this.dispatchCustomEvent('joomla.tab.show', this.view === 'tabs' ? currentTrigger.tabButton : currentTrigger.accordionButton, this.previousActive);
|
||||
if (state) {
|
||||
if (this.view === 'tabs') {
|
||||
currentTrigger.tabButton.focus();
|
||||
} else {
|
||||
currentTrigger.accordionButton.focus();
|
||||
}
|
||||
}
|
||||
if (state) this.saveState(currentTrigger.tab.id);
|
||||
this.dispatchCustomEvent('joomla.tab.shown', this.view === 'tabs' ? currentTrigger.tabButton : currentTrigger.accordionButton, this.previousActive);
|
||||
}
|
||||
}
|
||||
|
||||
// Create navigation elements for inserted tabs
|
||||
createNavs(tab) {
|
||||
if ((tab instanceof Element && tab.tagName.toLowerCase() !== 'joomla-tab-element') || ![].some.call(this.children, (el) => el === tab).length || !tab.getAttribute('name') || !tab.getAttribute('id')) return;
|
||||
const tabs = [].slice.call(this.children).filter((el) => el.tagName.toLowerCase() === 'joomla-tab-element');
|
||||
const index = tabs.findIndex((tb) => tb === tab);
|
||||
|
||||
// Create Accordion button
|
||||
const accordionButton = document.createElement('button');
|
||||
accordionButton.setAttribute('aria-expanded', !!tab.hasAttribute('active'));
|
||||
accordionButton.setAttribute('aria-controls', tab.id);
|
||||
accordionButton.setAttribute('type', 'button');
|
||||
accordionButton.innerHTML = `<span class="accordion-title">${tab.getAttribute('name')}<span class="accordion-icon"></span></span>`;
|
||||
tab.insertAdjacentElement('beforebegin', accordionButton);
|
||||
|
||||
if (this.view === 'tabs') {
|
||||
accordionButton.setAttribute('hidden', '');
|
||||
}
|
||||
|
||||
accordionButton.addEventListener('click', this.activateTab);
|
||||
|
||||
// Create tab button
|
||||
const tabButton = document.createElement('button');
|
||||
tabButton.setAttribute('aria-expanded', !!tab.hasAttribute('active'));
|
||||
tabButton.setAttribute('aria-controls', tab.id);
|
||||
tabButton.setAttribute('role', 'tab');
|
||||
tabButton.setAttribute('type', 'button');
|
||||
tabButton.innerHTML = `${tab.getAttribute('name')}`;
|
||||
if (tabs.length - 1 === index) {
|
||||
// last
|
||||
this.tabButtonContainer.appendChild(tabButton);
|
||||
this.tabs.push({
|
||||
tab,
|
||||
tabButton,
|
||||
accordionButton,
|
||||
});
|
||||
} else if (index === 0) {
|
||||
// first
|
||||
this.tabButtonContainer.insertAdjacentElement('afterbegin', tabButton);
|
||||
this.tabs.slice(0, 0, {
|
||||
tab,
|
||||
tabButton,
|
||||
accordionButton,
|
||||
});
|
||||
} else {
|
||||
// Middle
|
||||
this.tabs[index - 1].tabButton.insertAdjacentElement('afterend', tabButton);
|
||||
this.tabs.slice(index - 1, 0, {
|
||||
tab,
|
||||
tabButton,
|
||||
accordionButton,
|
||||
});
|
||||
}
|
||||
|
||||
tabButton.addEventListener('click', this.activateTab);
|
||||
}
|
||||
|
||||
// Remove navigation elements for removed tabs
|
||||
removeNavs(tab) {
|
||||
if ((tab instanceof Element && tab.tagName.toLowerCase() !== 'joomla-tab-element') || ![].some.call(this.children, (el) => el === tab).length || !tab.getAttribute('name') || !tab.getAttribute('id')) return;
|
||||
const accordionButton = tab.previousSilbingElement;
|
||||
if (accordionButton && accordionButton.tagName.toLowerCase() === 'button') {
|
||||
accordionButton.removeEventListener('click', this.keyBehaviour);
|
||||
accordionButton.parentNode.removeChild(accordionButton);
|
||||
}
|
||||
const tabButton = this.tabButtonContainer.querySelector(`[aria-controls=${accordionButton.id}]`);
|
||||
if (tabButton) {
|
||||
tabButton.removeEventListener('click', this.keyBehaviour);
|
||||
tabButton.parentNode.removeChild(tabButton);
|
||||
}
|
||||
const index = this.tabs.findIndex((tb) => tb.tabs === tab);
|
||||
if (index - 1 === 0) {
|
||||
this.tabs.shift();
|
||||
} else if (index - 1 === this.tabs.length) {
|
||||
this.tabs.pop();
|
||||
} else {
|
||||
this.tabs.splice(index - 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Method to convert tabs to accordion and vice versa depending on screen size */
|
||||
checkView() {
|
||||
if (!this.breakpoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (document.body.getBoundingClientRect().width > this.breakpoint) {
|
||||
if (this.view === 'tabs') {
|
||||
return;
|
||||
}
|
||||
this.tabButtonContainer.removeAttribute('hidden');
|
||||
this.tabs.map((tab) => {
|
||||
tab.accordionButton.setAttribute('hidden', '');
|
||||
tab.accordionButton.setAttribute('role', 'tabpanel');
|
||||
if (tab.accordionButton.getAttribute('aria-expanded') === 'true') {
|
||||
tab.tab.setAttribute('active', '');
|
||||
}
|
||||
return tab;
|
||||
});
|
||||
this.setAttribute('view', 'tabs');
|
||||
} else {
|
||||
if (this.view === 'accordion') {
|
||||
return;
|
||||
}
|
||||
this.tabButtonContainer.setAttribute('hidden', '');
|
||||
this.tabs.map((tab) => {
|
||||
tab.accordionButton.removeAttribute('hidden');
|
||||
tab.accordionButton.setAttribute('role', 'region');
|
||||
return tab;
|
||||
});
|
||||
this.setAttribute('view', 'accordion');
|
||||
}
|
||||
}
|
||||
|
||||
getStorageKey() {
|
||||
return window.location.href.toString().split(window.location.host)[1].replace(/&return=[a-zA-Z0-9%]+/, '').split('#')[0];
|
||||
}
|
||||
|
||||
saveState(value) {
|
||||
const storageKey = this.getStorageKey();
|
||||
sessionStorage.setItem(storageKey, value);
|
||||
}
|
||||
|
||||
activateFromState() {
|
||||
this.hasNested = this.querySelector('joomla-tab') instanceof HTMLElement;
|
||||
// Use the sessionStorage state!
|
||||
const href = sessionStorage.getItem(this.getStorageKey());
|
||||
if (href) {
|
||||
const currentTabIndex = this.tabs.findIndex((tab) => tab.tab.id === href);
|
||||
|
||||
if (currentTabIndex >= 0) {
|
||||
this.activateTab(currentTabIndex, false);
|
||||
} else if (this.hasNested) {
|
||||
const childTabs = this.querySelector('joomla-tab');
|
||||
if (childTabs) {
|
||||
const activeTabs = [].slice.call(this.querySelectorAll('joomla-tab-element'))
|
||||
.reverse()
|
||||
.filter((activeTabEl) => activeTabEl.id === href);
|
||||
if (activeTabs.length) {
|
||||
// Activate the deepest tab
|
||||
let activeTab = activeTabs[0].closest('joomla-tab');
|
||||
[].slice.call(activeTab.querySelectorAll('joomla-tab-element'))
|
||||
.forEach((tabEl) => {
|
||||
tabEl.removeAttribute('active');
|
||||
if (tabEl.id === href) {
|
||||
tabEl.setAttribute('active', '');
|
||||
}
|
||||
});
|
||||
|
||||
// Activate all parent tabs
|
||||
while (activeTab.parentNode.closest('joomla-tab') !== this) {
|
||||
const parentTabContainer = activeTab.closest('joomla-tab');
|
||||
const parentTabEl = activeTab.parentNode.closest('joomla-tab-element');
|
||||
[].slice.call(parentTabContainer.querySelectorAll('joomla-tab-element'))
|
||||
// eslint-disable-next-line no-loop-func
|
||||
.forEach((tabEl) => {
|
||||
tabEl.removeAttribute('active');
|
||||
if (parentTabEl === tabEl) {
|
||||
tabEl.setAttribute('active', '');
|
||||
activeTab = parentTabEl;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[].slice.call(this.children)
|
||||
.filter((el) => el.tagName.toLowerCase() === 'joomla-tab-element')
|
||||
.forEach((tabEl) => {
|
||||
tabEl.removeAttribute('active');
|
||||
const isActiveChild = tabEl.querySelector('joomla-tab-element[active]');
|
||||
|
||||
if (isActiveChild) {
|
||||
this.activateTab(tabEl, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Method to dispatch events */
|
||||
dispatchCustomEvent(eventName, element, related) {
|
||||
const OriginalCustomEvent = new CustomEvent(eventName, { bubbles: true, cancelable: true });
|
||||
OriginalCustomEvent.relatedTarget = related;
|
||||
element.dispatchEvent(OriginalCustomEvent);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('joomla-tab', TabsElement);
|
||||
1
media/vendor/joomla-custom-elements/js/joomla-tab.min.js
vendored
Normal file
1
media/vendor/joomla-custom-elements/js/joomla-tab.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
media/vendor/joomla-custom-elements/js/joomla-tab.min.js.gz
vendored
Normal file
BIN
media/vendor/joomla-custom-elements/js/joomla-tab.min.js.gz
vendored
Normal file
Binary file not shown.
Reference in New Issue
Block a user