41 lines
8.3 KiB
JavaScript
41 lines
8.3 KiB
JavaScript
;(function(){"use strict";class iDropdown extends HTMLElement{connectedCallback(){this.supportsAnchor=CSS.supports("(top: anchor(bottom)) and (not (-webkit-hyphens: auto))");this.supportsPopover=CSS.supports("selector(:popover-open)");this.supportsAnimationTimeline=CSS.supports("(animation-timeline: scroll())");this.addEventListener("beforetoggle",this);this.addEventListener("toggle",this);if(this.matches(":popover-open")){this.beforetoggleEvent({newState:"open",oldState:"closed"});this.toggleEvent({newState:"open",oldState:"closed"});}}
|
|
handleEvent(e){return this[`${e.type}Event`]&&this[`${e.type}Event`](e);}
|
|
clickEvent(e){let itemClicked=e.target.closest(".iDropdown__items a, .iDropdown__items button");this.handleClick(e,itemClicked);}
|
|
changeEvent(e){let itemClicked=e.target.closest(".iDropdown__items label");this.handleClick(e,itemClicked);}
|
|
handleClick(e,itemClicked){if(!itemClicked)return;if(!itemClicked.closest("[data-i-dropdown-persist]")){setTimeout(()=>{itemClicked.closest("i-dropdown")?.hidePopover();},150);}
|
|
if(itemClicked.closest("[data-i-dropdown-noselect]"))return;const pingItems=itemClicked.closest('[data-action="ipsMenu_ping"]');if(pingItems){e.preventDefault();ips.getAjax()(pingItems.getAttribute('href')).done(()=>{this.trigger.dispatchEvent(new CustomEvent('menuPingSuccessful',{}));});}
|
|
const selectedTextTrigger=this.trigger.closest('[data-role="ipsMenu_selectedText"]'),selectedTextMenu=e.target.closest('[data-role="ipsMenu_selectedText"]');if(selectedTextTrigger&&selectedTextMenu){selectedTextTrigger.innerText=selectedTextMenu.innerText;}
|
|
const selectedIconTrigger=this.trigger.closest('[data-role="ipsMenu_selectedIcon"]'),selectedIconMenu=e.target.closest('[data-role="ipsMenu_selectedIcon"]');if(selectedIconTrigger&&selectedIconMenu){selectedIconTrigger.replaceWith(selectedIconMenu.cloneNode(true));}
|
|
let eventDetail={triggerElem:this.trigger,triggerID:this.trigger.getAttribute("popovertarget"),menuElem:this,originalEvent:e};let selectableList=itemClicked.closest("[data-i-dropdown-selectable]");if(selectableList&&itemClicked.matches("a, button")){if(selectableList.getAttribute("data-i-dropdown-selectable")==="radio"){selectableList.querySelectorAll('[aria-selected="true"]').forEach(el=>el.removeAttribute("aria-selected"));itemClicked.setAttribute("aria-selected","true");}else{if(itemClicked.hasAttribute("aria-selected")){itemClicked.removeAttribute("aria-selected")}else{itemClicked.setAttribute("aria-selected","true")}}}
|
|
if(itemClicked.hasAttribute("data-ipsMenuValue")){eventDetail.selectedItemID=itemClicked.getAttribute("data-ipsMenuValue");}else{let inputValue=itemClicked.querySelector("input[value]");if(inputValue){eventDetail.selectedItemID=inputValue.value;}}
|
|
let selectedListItems=this.querySelectorAll("[aria-selected='true'], :checked"),selectedItemObj={};if(selectedListItems.length){selectedListItems.forEach(el=>{let input=el.closest("label");if(input){el=input;}
|
|
if(!el.id){el.id='ips_uid_'+Math.floor(Math.random()*9999)+1;}
|
|
selectedItemObj[el.getAttribute('id')]=el;})
|
|
eventDetail.selectedItems=selectedItemObj;}
|
|
this.trigger.dispatchEvent(new CustomEvent("menuItemSelected",{detail:eventDetail,bubbles:true}));}
|
|
beforetoggleEvent(e){this.open=e.newState==='open';if(e.newState==="open"){this.removeAttribute("hidden-via-swipe");if(e.source){this.trigger=e.source}else if(document.activeElement.matches("[popovertarget]")){this.trigger=document.activeElement;}else{this.trigger=document.querySelector(`[popovertarget="${this.id}"]`);}
|
|
if(this.hasAttribute("data-i-dropdown-append")){const appendMenuTo=this.getAttribute("data-i-dropdown-append")||"body";document.querySelector(appendMenuTo)?.append(this);}
|
|
if(!this._remoteContentLoaded){this.resetRemoteContent().catch(err=>Debug.error(err)).finally(()=>{if(this.open){this.scrollTop=this.scrollHeight;}});}
|
|
this.positionAnchors(e);if(!this.swipeElement){this.createSwipeElement();}}}
|
|
toggleEvent(e){if(e.newState==="open"){this.scrollTop=this.scrollHeight;this.trigger.ariaExpanded="true";this.swipeObserver.observe(this.swipeElement);this.addEventListener("change",this);this.addEventListener("click",this);if(!this.supportsAnimationTimeline){this.addEventListener("transitionend",this);}
|
|
if(!this.supportsPopover){document.addEventListener("scroll",this,{passive:true});}
|
|
this.trigger.dispatchEvent(new CustomEvent("menuOpened",{detail:{elemID:(this.trigger.id)?this.trigger.id:this.trigger.getAttribute("popovertarget"),menu:this},bubbles:true}));}else{this.swipeObserver.disconnect();if(!this.supportsAnimationTimeline){this.removeEventListener("scroll",this,{passive:true});this.removeEventListener("transitionend",this);}
|
|
if(!this.supportsPopover&&!document.querySelector('i-dropdown[class*=":popover-open"]')){document.removeEventListener("scroll",this,{passive:true});}
|
|
this.trigger.ariaExpanded="false";this.trigger.dispatchEvent(new CustomEvent("menuClosed",{detail:{elemID:(this.trigger.id)?this.trigger.id:this.trigger.getAttribute("popovertarget"),menu:this},bubbles:true}));}}
|
|
transitionendEvent(e){if(e.target===this){this.addEventListener("scroll",this,{passive:true});}}
|
|
scrollEvent(e){requestAnimationFrame(()=>{if(e.target===this){this.style.setProperty('--i-dropdown--backdrop-scroll',Math.floor(this.scrollTop/(this.scrollHeight-this.clientHeight)*100)+"%");}else{this.style.setProperty("--_anchor-scroll",window.scrollY+"px");}});}
|
|
createContentElement(){this.contentElement=this.querySelector(':scope > :is(.iDropdown, [data-i-dropdown-wrapper]) > :is(.iDropdown__content, [data-i-dropdown-content])');if(this.contentElement instanceof HTMLElement){return;}
|
|
let contentWrapper=this.querySelector(`:scope > :is(.iDropdown, [data-i-dropdown-wrapper])`);if(!contentWrapper){this.insertAdjacentHTML("beforeend","<div class='iDropdown' data-i-dropdown-wrapper></div>");contentWrapper=this.querySelector(`:scope > :is(.iDropdown, [data-i-dropdown-wrapper])`);}
|
|
contentWrapper.insertAdjacentHTML("beforeend","<div class='iDropdown__content' data-i-dropdown-content=''></div>");this.contentElement=contentWrapper.querySelector(':scope > :is(.iDropdown__content, [data-i-dropdown-content])');}
|
|
async resetRemoteContent(){if(this.dataset.iDropdownSource){this._remoteContentLoaded=true;if(!this.contentElement){this.createContentElement();}
|
|
this.contentElement.classList.add('ipsLoading','ipsLoading--small');if(!this.open){this._remoteContentLoaded=false;return;}
|
|
try{let res=await ips.fetch(this.dataset.iDropdownSource);if(!this._remoteContentLoaded){return;}
|
|
if(typeof res==='object'){res=res.content;}
|
|
if(typeof res!=='string'){throw new TypeError(`Expected a string as the content type`);}
|
|
this.contentElement.classList.remove('ipsLoading','ipsLoading--small');this.contentElement.innerHTML=res;$(document).trigger('contentChange',[this.contentElement]);}catch(err){this._remoteContentLoaded=false;throw err;}}}
|
|
createSwipeElement(){let addBackdropElements=``;if(!this.querySelector(".iDropdownSwipe")){addBackdropElements+=`<div class='iDropdownSwipe'></div>`;}
|
|
if(!this.querySelector(".iDropdownDismiss")){addBackdropElements+=`<button class="iDropdownDismiss" type="button" popovertarget="${this.id}" popovertargetaction="hide" aria-label="Close"></button>`;}
|
|
this.insertAdjacentHTML("afterbegin",addBackdropElements);this.swipeElement=this.querySelector(".iDropdownSwipe");}
|
|
swipeObserver=new IntersectionObserver(entries=>{entries.forEach(entry=>{if(entry.isIntersecting){this.setAttribute("hidden-via-swipe",true);this.style.removeProperty('--i-dropdown--backdrop-scroll');this.hidePopover();}});},{root:this,threshold:.1})
|
|
positionAnchors(e){if(!this.supportsAnchor){this.triggerPos=this.trigger.getBoundingClientRect();this.style.setProperty("--_anchor-v",window.scrollY+this.triggerPos.bottom+"px");this.style.setProperty("--_anchor-h",this.triggerPos.left+(this.triggerPos.width/2)+"px");this.style.setProperty("--_anchor-height",this.triggerPos.height+"px");this.style.setProperty("--_remaining-height",document.documentElement.scrollHeight-window.scrollY-this.triggerPos.bottom+"px");if(!this.supportsPopover){this.style.setProperty("--_anchor-scroll",window.scrollY+"px");}}else if(!e.source){if(!this.anchorCounter)this.anchorCounter=1;let anchorName=`--${this.id}-${this.anchorCounter++}`;this.trigger.style.setProperty("anchor-name",anchorName);this.style.setProperty("position-anchor",anchorName);}}}
|
|
ips.ui.registerWebComponent("dropdown",iDropdown);Debug.log(`Submitted the web component constructor, iDropdown, for ${"dropdown"}`);})();; |