UNPKG

@ezmodus/select-picker

Version:

Improve HTML <select> element to have live search and better selection process. Written with native JavaScript

1 lines 15 kB
(()=>{var e={517:e=>{e.exports={ezmodusSelectPicker:class{dropdown=null;button=null;select=null;menu=null;settings={debug:!1,isMobile:"ontouchstart"in window,multiple:!1,size:1,title:"Select",dropdownTick:!0,selectedCount:1,selectedMax:null,selectedText:"{0} selected",menuHeight:0,menuItemHeight:null,calcMenuWidth:0,menuDynamic:null,searchShow:!1,searchFocus:!0,searchFocusMobile:!1,searchInputPlaceHolder:"Filter...",searchFrom:null,searchNoResultsText:'No results matched "{0}"',clearButtonShow:!1,clearButtonText:"clear selection"};items=[];searchString="";constructor(e,t=null){let s=this;if(this.select=e,this.select.dataset.id=t,this.settings.multiple=e.multiple,this.settings.size=(e.size||void 0)??(parseInt(this.settings.size)?10:null),this.settings.disabled=!!e.disabled,e.title&&(this.settings.title=e.title),Object.entries(e.dataset).forEach((([e,t])=>{switch(e){case"debug":this.settings.debug="true"===t.toLowerCase();break;case"size":this.settings.size=parseInt(t);break;case"tick":this.settings.dropdownTick="false"!==t.toLowerCase();break;case"search":this.settings.searchShow="true"===t.toLowerCase();break;case"searchFocus":this.settings.searchFocus="true"===t.toLowerCase();break;case"searchFocusMobile":this.settings.searchFocusMobile="true"===t.toLowerCase();break;case"searchPlaceholder":this.settings.searchInputPlaceHolder=t;break;case"searchFrom":"values"==t?this.settings.searchFrom="values":"both"==t&&(this.settings.searchFrom="both");break;case"searchNoResults":this.settings.searchNoResultsText=t;break;case"selectedCount":this.settings.selectedCount=parseInt(t);break;case"selectedText":this.settings.selectedText=t;break;case"selectedMax":this.settings.selectedMax=parseInt(t);break;case"clearShow":this.settings.clearButtonShow="true"===t;break;case"clearText":this.settings.clearButtonText=t;break;case"menuItemHeight":this.settings.menuItemHeight=parseInt(t);break;case"dynamic":let e=parseInt(t);this.settings.menuDynamic=e<0?0:e>100?100:e}})),Object.values(e.children).forEach((function(e,t){if("OPTGROUP"!==e.nodeName)s.items.push({group:!1,label:null,total:1,match:1,items:[{elem:e,listelem:null,visible:!0,initial:!!e.selected,selected:!!e.selected,search_value:e.value.toLowerCase(),search_label:e.text.toLowerCase(),search_desc:e.dataset.desc?e.dataset.desc.toLowerCase():""}]});else{let t=e.label,l=e.getElementsByTagName("legend");l.length>0&&(t=l[0].innerText),s.items.push({group:!0,label:t,listelem:null,total:e.getElementsByTagName("option").length,match:e.getElementsByTagName("option").length,items:[]});let i=s.items.length-1;Object.values(e.children).forEach((function(e,t){"OPTION"===e.nodeName&&s.items[i].items.push({elem:e,listelem:null,visible:!0,initial:!!e.selected,selected:!!e.selected,search_value:e.value.toLowerCase(),search_label:e.text.toLowerCase(),search_desc:e.dataset.desc?e.dataset.desc.toLowerCase():""})}))}})),this.render(),this.settings.debug){let e=document.createElement("div");e.id="debugger-"+s.select.dataset.id+"-testarea",e.style.position="relative",s.dropdown.prepend(e),this.debugRender()}let l=this.button;new MutationObserver((function(e){e.forEach((function(e){"attributes"===e.type&&"disabled"===e.attributeName&&(e.target.attributes.disabled?l.classList.add("disabled"):l.classList.remove("disabled"))}))})).observe(e,{attributes:!0})}debugRender(){if(!this.dropdown)return;let e=document.getElementById("debugger-"+this.select.dataset.id+"-testarea");e&&(e.innerHTML="",e.innerText="",this.items.forEach((t=>{if(t.group){let s=document.createElement("div");s.innerText=t.label,s.style.color="#000000",s.style.fontWeight=600,0==t.match&&(s.style.color="#b7575b"),e.appendChild(s),t.items.forEach((t=>{let s=document.createElement("div");if(s.innerText=t.elem.label,t.selected&&(s.innerText+=" (selected)"),s.style.paddingLeft="20px",t.visible||(s.style.color="#b7575b"),void 0!==t.elem.dataset.desc){let e=document.createElement("div");e.innerText=t.elem.dataset.desc,e.style.color="#7d7d7d",s.appendChild(e)}e.appendChild(s)}))}else t.items.forEach((t=>{let s=document.createElement("div");if(s.innerText=t.elem.label,s.style.color="#000000",t.selected&&(s.innerText+=" (selected)"),t.visible||(s.style.color="#b7575b"),void 0!==t.elem.dataset.desc){let e=document.createElement("div");e.innerText=t.elem.dataset.desc,e.style.color="#7d7d7d",s.appendChild(e)}e.appendChild(s)}))})))}handleAriaAttributes(e,t){Object.entries(e.attributes).forEach((([e,s])=>{"role"!=s.nodeName&&-1===s.nodeName.indexOf("aria-")||t.setAttribute(s.nodeName,s.value)}))}selectMenuItem(e,t){let s=this;if("keydown"===t.type){if("Space"!==t.code)return;t.preventDefault()}let l=Object.values(e.select.options).filter((e=>e.selected));e.items.forEach((t=>{t.items.forEach((t=>{if(e.settings.multiple){if(t.listelem===s)if(t.selected)t.elem.selected=null,t.selected=!1,t.listelem.classList.remove("selected");else{let s=e.settings.selectedMax;if(null!==s&&l.length==s)return;t.elem.selected=!0,t.selected=!0,t.listelem.classList.add("selected")}}else t.listelem===s?t.selected?(t.elem.selected=null,t.selected=!1,t.listelem.classList.remove("selected")):(t.elem.selected=!0,t.selected=!0,t.listelem.classList.add("selected")):(t.elem.selected=null,t.selected=!1,t.listelem.classList.remove("selected"))}))})),e.select.dispatchEvent(new Event("change")),e.changeDropdownButton(),e.settings.multiple||e.dropdown.classList.remove("open-menu"),e.settings.debug&&e.debugRender()}addHandlerSelect(e,t){t.addEventListener("keydown",this.selectMenuItem.bind(t,e)),t.addEventListener("click",this.selectMenuItem.bind(t,e))}createDropdownButton(e,t){let s=this,l=document.createElement("button");l.type="button",l.classList.add("ezmodus-dropdown"),l.addEventListener("click",(function(){l.classList.contains("disabled")||e.classList.toggle("open-menu");let t=!1;if(s.settings.isMobile?s.settings.searchShow&&s.settings.searchFocusMobile&&(t=!0):s.settings.searchShow&&s.settings.searchFocus&&(t=!0),e.classList.contains("open-menu")&&t){let t=e.querySelector('input[type="search"]');setTimeout((()=>{t.focus()}),75)}})),t.classList.forEach((function(e){"ezmodus-select-picker"!==e&&l.classList.add(e)}));let i=document.createElement("span");if(i.classList.add("text"),i.innerText=this.title,l.appendChild(i),s.settings.dropdownTick){let e=document.createElement("i");e.classList.add("tick"),l.appendChild(e)}return l}createClearButton(){let e=this,t=document.createElement("div");t.classList.add("ezmodus-clear");let s=document.createElement("button");return s.type="button",s.name="clear",s.innerHTML=e.settings.clearButtonText,s.addEventListener("click",(function(t){Object.values(e.select.options).filter((e=>e.selected)).length&&e.items.forEach((e=>{e.items.forEach((e=>{e.selected=!1,e.elem.selected=null,e.listelem.classList.remove("selected")}))})),e.changeDropdownButton()})),t.appendChild(s),t}createMenuGroup(e){let t=document.createElement("li");t.tabIndex=-1,t.classList.add("group");let s=document.createElement("span");s.classList.add("text"),s.innerHTML=e.label;let l=document.createElement("div");return l.classList.add("item-wrapper"),l.append(s),t.append(l),t}createMenuItem(e,t){let s=document.createElement("li");s.tabIndex=0,s.classList.add("item"),e.group&&s.classList.add("group-item"),this.handleAriaAttributes(t.elem,s),t.selected&&s.classList.add("selected"),t.elem.disabled?s.dataset.disabled="true":this.addHandlerSelect(this,s),t.elem.classList.forEach((function(e){s.classList.add(e)}));let l=document.createElement("i");l.classList.add("checkmark");let i=document.createElement("span");i.classList.add("text"),i.innerHTML=t.elem.text;let n=document.createElement("a"),a=document.createElement("div");if(a.classList.add("item-wrapper"),a.appendChild(l),a.appendChild(i),n.appendChild(a),t.elem.dataset.desc){let e=document.createElement("div");e.classList.add("subtext"),e.innerHTML=t.elem.dataset.desc,n.appendChild(e)}return s.appendChild(n),s}addHandlerSearch(e,t,s){const l=new RegExp(/.+?(?=\s[+|-])|.+/gm);let i=[...this.value.matchAll(l)],n=[],a=[],r=[],c=[],d=[];for(let e=0;e<i.length;e++){let t=i[e][0].trim().toLowerCase();n.push(t),t.startsWith("--")?""!==t.substr(2)&&r.push(t.substr(2)):t.startsWith("++")?""!==t.substr(2)&&a.push(t.substr(2)):t.startsWith("-")?""!==t.substr(1)&&d.push(t.substr(1)):t.startsWith("+")?""!==t.substr(1)&&c.push(t.substr(1)):c.push(t)}function o(t,s){let l=e.settings.searchFrom,i=!1;return s.forEach((e=>{switch(l){case"both":-1===t.search_value.indexOf(e)&&-1===t.search_label.indexOf(e)&&-1===t.search_desc.indexOf(e)||(i=!0);break;case"values":-1!==t.search_value.indexOf(e)&&(i=!0);break;default:-1===t.search_label.indexOf(e)&&-1===t.search_desc.indexOf(e)||(i=!0)}})),i}function u(e,t){if(!e.group||0===t.length)return null;let s=!1,l=e.label.toLowerCase().trim();return t.forEach((e=>{-1!==l.indexOf(e)&&(s=!0)})),s}e.searchString=n.join(" "),e.items.forEach((e=>{let t=u(e,a),s=u(e,r);e.items.forEach((l=>{if(0===c.length&&0===d.length&&0===a.length&&0===r.length)return l.visible=!0,void(e.match=e.total);let i=o(l,c),n=o(l,d);if(l.visible=!0,0!==a.length||0!==r.length){if(s)return void(l.visible=!1);if(a.length>0&&!t)return void(l.visible=!1);d.length>0&&n&&(l.visible=!1),c.length>0&&i&&(l.visible=!0)}else c.length>0&&!i&&(l.visible=!1),c.length>0&&i&&(l.visible=!0),d.length>0&&n&&(l.visible=!1)}));let l=e.items.filter((e=>!0===e.visible)).length;e.match=l})),e.updateMenu(),e.settings.debug&&e.debugRender()}updateMenu(){let e=this;this.items.forEach((e=>{e.group&&(e.listelem.style.display="list-item",0==e.match&&(e.listelem.style.display="none")),e.items.forEach((e=>{e.listelem.style.display="list-item",e.visible||(e.listelem.style.display="none")}))}));let t=e.items.filter((e=>e.match>0)).length,s=e.menu.querySelector("div.no-results");if(t>0||""==e.searchString)s.innerHTML="",s.innerText="",s.style.display="none";else{let t=e.settings.searchNoResultsText.replace("{0}",e.searchString);s.innerHTML=t,s.innerText=t,s.style.display="block"}}createMenu(){let e=this,t=(this.select,document.createElement("div"));if(t.classList.add("ezmodus-menu"),t.tabIndex=-1,e.settings.searchShow){let s=document.createElement("div");s.classList.add("ezmodus-search");let l=document.createElement("input");l.type="search",l.autocomplete="off",l.placeholder=e.settings.searchInputPlaceHolder,l.addEventListener("keyup",this.addHandlerSearch.bind(l,e,t)),l.addEventListener("change",this.addHandlerSearch.bind(l,e,t)),s.appendChild(l),t.appendChild(s),t.classList.add("with-search")}if(e.settings.multiple&&e.settings.clearButtonShow){let e=this.createClearButton();t.appendChild(e)}let s=document.createElement("ul");s.classList.add("list"),e.items.forEach(((e,t)=>{if(e.group){let t=this.createMenuGroup(e);e.listelem=t,s.appendChild(t)}e.items.forEach(((t,l)=>{let i=this.createMenuItem(e,t);t.listelem=i,s.appendChild(i)}))})),t.appendChild(s);let l=document.createElement("div");return l.classList.add("no-results"),t.appendChild(l),this.menu=t,t}changeDropdownButton(e=null){null===e&&(e=this);let t=Object.values(e.select.options).filter((e=>e.selected));if(!t.length)return e.button.querySelector("span").innerHTML=e.settings.title,void(e.button.querySelector("span").innerText=e.settings.title);if(e.settings.selectedCount>t.length-1){let s=[];t.forEach((function(e){s.push(e.label)}));let l=s.join(", ");return e.button.querySelector("span").innerHTML=l,void(e.button.querySelector("span").innerText=l)}let s=e.settings.selectedText.replace("{0}",t.length);e.button.querySelector("span").innerHTML=s,e.button.querySelector("span").innerText=s}reset(){let e=this;e.items.forEach((e=>{e.items.forEach((e=>{e.selected=!1,e.elem.selected=null,e.listelem.classList.remove("selected"),e.initial&&(e.selected=!0,e.elem.selected=!0,e.listelem.classList.add("selected"))}))})),e.changeDropdownButton(e)}calculateMenuItemStructureWidth(){let e=0,t=this.menu.querySelector("ul"),s=this.menu.querySelector("li");if(null===s)return;let l=s.querySelector("a"),i=s.querySelector("i"),n=s.querySelector("span");return["padding-left","padding-right","margin-left","margin-right","border-left-width","border-right-width"].forEach((function(a){e+=parseInt(window.getComputedStyle(t,null).getPropertyValue(a)),e+=parseInt(window.getComputedStyle(s,null).getPropertyValue(a)),e+=parseInt(window.getComputedStyle(l,null).getPropertyValue(a)),e+=parseInt(window.getComputedStyle(i,null).getPropertyValue(a)),e+=parseInt(window.getComputedStyle(n,null).getPropertyValue(a))})),e+=parseInt(window.getComputedStyle(i,null).getPropertyValue("width")),e}calculateContextWidth(e){let t=window.getComputedStyle(e,null).getPropertyValue("font-size"),s=window.getComputedStyle(e,null).getPropertyValue("font-family"),l=document.createElement("canvas").getContext("2d");return l.font=`${t} ${s}`,l.measureText(e.textContent).width}calculateMenuDimensions(e){let t=this;if(t.settings.size){let t=null;if(t=e.querySelector("li")){let e=this.settings.menuItemHeight??31;t.scrollHeight?e=t.scrollHeight:t.offsetHeight?e=t.offsetHeight:t.clientHeight&&(e=t.clientHeight),this.settings.menuHeight+=this.settings.size*e}e.querySelector(".ezmodus-menu ul").style.maxHeight=this.settings.menuHeight+2+"px"}let s=0;if(t.items.forEach((e=>{if(e.group){let l=t.calculateContextWidth(e.listelem);l>s&&(s=l)}e.items.forEach((e=>{let l=t.calculateContextWidth(e.listelem);l>s&&(s=l)}))})),t.settings.calcMenuWidth=parseInt(s),t.settings.menuDynamic){let e=t.calculateMenuItemStructureWidth(),s=0;t.menu.querySelectorAll("li").forEach((function(e){s<e.scrollWidth&&(s=e.scrollWidth);let l=e.querySelector(".text"),i=t.calculateContextWidth(l),n=e.querySelector(".subtext");if(n){let e=t.calculateContextWidth(n);i<e&&(i=e)}s<i&&(s=i)}));let l=t.settings.menuDynamic/100,i=(s+e)*l;t.menu.style.minWidth=i+"px"}}render(){let e=document.createElement("div");e.classList.add("ezmodus-select"),this.select.parentNode.insertBefore(e,this.select),e.appendChild(this.select);let t=this.createDropdownButton(e,this.select);this.settings.disabled&&t.classList.add("disabled"),this.handleAriaAttributes(this.select,t),this.button=t,e.appendChild(this.button),e.appendChild(this.createMenu()),this.changeDropdownButton(),this.calculateMenuDimensions(e),e.addEventListener("focusout",(function(t){t.currentTarget.contains(t.relatedTarget)||e.classList.remove("open-menu")})),this.dropdown=e}}}}},t={};function s(l){var i=t[l];if(void 0!==i)return i.exports;var n=t[l]={exports:{}};return e[l](n,n.exports,s),n.exports}(()=>{const{ezmodusSelectPicker:e}=s(517);document.addEventListener("DOMContentLoaded",(function(){let t=[];document.querySelectorAll("select.ezmodus-select-picker").forEach((function(s,l){t.push(new e(s,l))})),document.querySelectorAll('*[type="reset"]').forEach((e=>{e.addEventListener("click",(function(){e.closest("form").querySelectorAll("select.ezmodus-select-picker").forEach((e=>{(picker=t[e.dataset.id])&&picker.reset()}))}))}))}))})()})();