diff --git a/autocomplete.min.js b/autocomplete.min.js index fcdbfae..546eb44 100644 --- a/autocomplete.min.js +++ b/autocomplete.min.js @@ -1,4 +1,4 @@ -var E={showAllSuggestions:!1,suggestionsThreshold:1,maximumItems:0,autoselectFirst:!0,ignoreEnter:!1,updateOnSelect:!1,highlightTyped:!1,highlightClass:"",fullWidth:!1,fixed:!1,fuzzy:!1,startsWith:!1,fillIn:!1,preventBrowserAutocomplete:!1,itemClass:"",activeClasses:["bg-primary","text-white"],labelField:"label",valueField:"value",searchFields:["label"],queryParam:"query",items:[],source:null,hiddenInput:!1,hiddenValue:"",clearControl:"",datalist:"",server:"",serverMethod:"GET",serverParams:{},serverDataKey:"data",fetchOptions:{},liveServer:!1,noCache:!0,debounceTime:300,notFoundMessage:"",onRenderItem:(o,t,e)=>t,onSelectItem:(o,t)=>{},onServerResponse:(o,t)=>o.json(),onServerError:(o,t,e)=>{o.name==="AbortError"||t.aborted||console.error(o)},onChange:(o,t)=>{},onBeforeFetch:o=>{},onAfterFetch:o=>{}},x="is-loading",C="is-active",f="show",m="next",v="prev",p=new WeakMap,A=0,b=0;function O(o,t=300){let e;return(...s)=>{clearTimeout(e),e=setTimeout(()=>{o.apply(this,s)},t)}}function I(o){return o.normalize("NFD").replace(/[\u0300-\u036f]/g,"")}function y(o){return o?I(o.toString()).toLowerCase():""}function D(o,t){if(o.indexOf(t)>=0)return!0;let e=0;for(let s=0;st+"‍").join("")}function H(o,t="window"){return o.split(".").reduce((e,s)=>e[s],t)}var S=class{constructor(t,e={}){if(!(t instanceof HTMLElement)){console.error("Invalid element",t);return}p.set(t,this),A++,b++,this.s=t,this.E(e),this.a=!1,this.u=!1,this.h=!1,this.C=O(()=>{this.g(!0)},this.e.debounceTime),this.A(),this.k(),this.e.fixed&&(document.addEventListener("scroll",this,!0),window.addEventListener("resize",this));let s=this.v();s&&s.addEventListener("click",this),["focus","change","blur","input","keydown"].forEach(i=>{this.s.addEventListener(i,this)}),["mousemove","mouseleave"].forEach(i=>{this.i.addEventListener(i,this)}),this.T()}static init(t="input.autocomplete",e={}){document.querySelectorAll(t).forEach(i=>{this.getOrCreateInstance(i,e)})}static getInstance(t){return p.has(t)?p.get(t):null}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,e)}dispose(){b--,["focus","change","blur","input","keydown"].forEach(e=>{this.s.removeEventListener(e,this)}),["mousemove","mouseleave"].forEach(e=>{this.i.removeEventListener(e,this)});let t=this.v();t&&t.removeEventListener("click",this),this.e.fixed&&b<=0&&(document.removeEventListener("scroll",this,!0),window.removeEventListener("resize",this)),this.i.parentElement.removeChild(this.i),p.delete(this.s)}v(){if(this.e.clearControl)return document.querySelector(this.e.clearControl)}handleEvent=t=>{["scroll","resize"].includes(t.type)?(this.b&&window.cancelAnimationFrame(this.b),this.b=window.requestAnimationFrame(()=>{this[`on${t.type}`](t)})):this[`on${t.type}`](t)};E(t={}){this.e=Object.assign({},E);let e={...t,...this.s.dataset},s=i=>["true","false","1","0",!0,!1].includes(i)&&!!JSON.parse(i);for(let[i,r]of Object.entries(E)){if(e[i]===void 0)continue;let n=e[i];switch(typeof r){case"number":this.e[i]=parseInt(n);break;case"boolean":this.e[i]=s(n);break;case"string":this.e[i]=n.toString();break;case"object":if(Array.isArray(r))if(typeof n=="string"){let a=n.includes("|")?"|":",";this.e[i]=n.split(a)}else this.e[i]=n;else this.e[i]=typeof n=="string"?JSON.parse(n):n;break;case"function":this.e[i]=typeof n=="string"?window[n]:n;break;default:this.e[i]=n;break}}}A(){if(this.s.autocomplete="off",this.s.spellcheck=!1,w(this.s,{"aria-autocomplete":"list","aria-haspopup":"menu","aria-expanded":"false",role:"combobox"}),this.s.id&&this.e.preventBrowserAutocomplete){let t=document.querySelector(`[for="${this.s.id}"]`);t&&F(t)}this.n=null,this.e.hiddenInput&&(this.n=document.createElement("input"),this.n.type="hidden",this.n.value=this.e.hiddenValue,this.n.name=this.s.name,this.s.name="_"+this.s.name,k(this.s,this.n))}k(){this.i=document.createElement("ul"),this.i.id="ac-menu-"+A,this.i.classList.add("dropdown-menu","autocomplete-menu","p-0"),this.i.style.maxHeight="280px",this.e.fullWidth||(this.i.style.maxWidth="360px"),this.e.fixed&&(this.i.style.position="fixed"),this.i.style.overflowY="auto",this.i.style.overscrollBehavior="contain",this.i.style.textAlign="unset",k(this.s,this.i),this.s.setAttribute("aria-controls",this.i.id)}onclick(t){t.target.matches(this.e.clearControl)&&this.clear()}oninput(t){this.u||(this.n&&(this.n.value=null),this.showOrSearch())}onchange(t){let e=this.s.value,s=Object.values(this.r).find(i=>i.label===e);this.e.onChange(s,this)}onblur(t){let e=t.relatedTarget;if(this.a&&e&&(e.classList.contains("modal")||e.classList.contains("autocomplete-menu"))){this.s.focus();return}setTimeout(()=>{this.hideSuggestions()},100)}onfocus(t){this.showOrSearch()}onkeydown(t){switch(t.keyCode||t.key){case 13:case"Enter":if(this.isDropdownVisible()){let s=this.getSelection();s&&s.click(),(s||!this.e.ignoreEnter)&&t.preventDefault()}break;case 9:case"Tab":if(this.isDropdownVisible()&&this.s.value){let s=this.getSelection();s&&(s.click(),t.preventDefault())}break;case 38:case"ArrowUp":t.preventDefault(),this.h=!0,this.d(v);break;case 40:case"ArrowDown":t.preventDefault(),this.h=!0,this.isDropdownVisible()?this.d(m):this.showOrSearch(!1);break;case 27:case"Escape":this.isDropdownVisible()&&(this.s.focus(),this.hideSuggestions());break}}onmousemove(t){this.a=!0,this.h=!1}onmouseleave(t){this.a=!1,this.removeSelection()}onscroll(t){this.f()}onresize(t){this.f()}getConfig(t=null){return t!==null?this.e[t]:this.e}setConfig(t,e){this.e[t]=e}setData(t){this.r={},this.l(t)}enable(){this.s.setAttribute("disabled","")}disable(){this.s.removeAttribute("disabled")}isDisabled(){return this.s.hasAttribute("disabled")||this.s.disabled||this.s.hasAttribute("readonly")}isDropdownVisible(){return this.i.classList.contains(f)}clear(){this.s.value="",this.n&&(this.n.value="")}getSelection(){return this.i.querySelector("a."+C)}removeSelection(){let t=this.getSelection();t&&t.classList.remove(...this.c())}c(){return[...this.e.activeClasses,C]}w(t){if(t.style.display==="none")return!1;let e=t.firstElementChild;return e.tagName==="A"&&!e.classList.contains("disabled")}d(t=m,e=null){let s=this.getSelection();if(s){let i=t===m?"nextSibling":"previousSibling";e=s.parentNode;do e=e[i];while(e&&!this.w(e));e?(s.classList.remove(...this.c()),t===v?e.parentNode.scrollTop=e.offsetTop-e.parentNode.offsetTop:e.offsetTop>e.parentNode.offsetHeight-e.offsetHeight&&(e.parentNode.scrollTop+=e.offsetHeight)):s&&(e=s.parentElement)}else{if(t===v)return e;if(!e)for(e=this.i.firstChild;e&&!this.w(e);)e=e.nextSibling}if(e){let i=e.querySelector("a");i.classList.add(...this.c()),this.s.setAttribute("aria-activedescendant",i.id),this.e.updateOnSelect&&(this.s.value=i.dataset.label)}else this.s.setAttribute("aria-activedescendant","");return e}O(){return this.isDisabled()?!1:this.s.value.length>=this.e.suggestionsThreshold}showOrSearch(t=!0){if(t&&!this.O()){this.hideSuggestions();return}this.e.liveServer?this.C():this.e.source?this.e.source(this.s.value,e=>{this.setData(e),this.m()}):this.m()}I(t){let e=this.p(),s=document.createElement("span");return e.append(s),s.classList.add("dropdown-header","text-truncate"),s.innerHTML=t,e}D(t,e){let s=e.label;if(this.e.highlightTyped){let n=y(s).indexOf(t);n!==-1&&(s=s.substring(0,n)+`${s.substring(n,n+t.length)}`+s.substring(n+t.length,s.length))}s=this.e.onRenderItem(e,s,this);let i=this.p(),r=document.createElement("a");if(i.append(r),r.id=this.i.id+"-"+this.i.children.length,r.classList.add("dropdown-item","text-truncate"),this.e.itemClass&&r.classList.add(...this.e.itemClass.split(" ")),r.setAttribute("data-value",e.value),r.setAttribute("data-label",e.label),r.setAttribute("tabindex","-1"),r.setAttribute("role","menuitem"),r.setAttribute("href","#"),r.innerHTML=s,e.data)for(let[n,a]of Object.entries(e.data))r.dataset[n]=a;if(this.e.fillIn){let n=document.createElement("button");n.type="button",n.classList.add("btn","btn-link","border-0"),n.innerHTML=` +var E={showAllSuggestions:!1,suggestionsThreshold:1,maximumItems:0,autoselectFirst:!0,ignoreEnter:!1,tabSelect:!1,updateOnSelect:!1,highlightTyped:!1,highlightClass:"",fullWidth:!1,fixed:!1,fuzzy:!1,startsWith:!1,fillIn:!1,preventBrowserAutocomplete:!1,itemClass:"",activeClasses:["bg-primary","text-white"],labelField:"label",valueField:"value",searchFields:["label"],queryParam:"query",items:[],source:null,hiddenInput:!1,hiddenValue:"",clearControl:"",datalist:"",server:"",serverMethod:"GET",serverParams:{},serverDataKey:"data",fetchOptions:{},liveServer:!1,noCache:!0,debounceTime:300,notFoundMessage:"",onRenderItem:(o,t,e)=>t,onSelectItem:(o,t)=>{},onServerResponse:(o,t)=>o.json(),onServerError:(o,t,e)=>{o.name==="AbortError"||t.aborted||console.error(o)},onChange:(o,t)=>{},onBeforeFetch:o=>{},onAfterFetch:o=>{}},x="is-loading",C="is-active",f="show",m="next",v="prev",p=new WeakMap,A=0,b=0;function O(o,t=300){let e;return(...s)=>{clearTimeout(e),e=setTimeout(()=>{o.apply(this,s)},t)}}function I(o){return o.normalize("NFD").replace(/[\u0300-\u036f]/g,"")}function y(o){return o?I(o.toString()).toLowerCase():""}function D(o,t){if(o.indexOf(t)>=0)return!0;let e=0;for(let s=0;st+"‍").join("")}function H(o,t="window"){return o.split(".").reduce((e,s)=>e[s],t)}var S=class{constructor(t,e={}){if(!(t instanceof HTMLElement)){console.error("Invalid element",t);return}p.set(t,this),A++,b++,this.s=t,this.E(e),this.a=!1,this.u=!1,this.h=!1,this.C=O(()=>{this.g(!0)},this.e.debounceTime),this.A(),this.k(),this.e.fixed&&(document.addEventListener("scroll",this,!0),window.addEventListener("resize",this));let s=this.v();s&&s.addEventListener("click",this),["focus","change","blur","input","keydown"].forEach(i=>{this.s.addEventListener(i,this)}),["mousemove","mouseleave"].forEach(i=>{this.i.addEventListener(i,this)}),this.T()}static init(t="input.autocomplete",e={}){document.querySelectorAll(t).forEach(i=>{this.getOrCreateInstance(i,e)})}static getInstance(t){return p.has(t)?p.get(t):null}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,e)}dispose(){b--,["focus","change","blur","input","keydown"].forEach(e=>{this.s.removeEventListener(e,this)}),["mousemove","mouseleave"].forEach(e=>{this.i.removeEventListener(e,this)});let t=this.v();t&&t.removeEventListener("click",this),this.e.fixed&&b<=0&&(document.removeEventListener("scroll",this,!0),window.removeEventListener("resize",this)),this.i.parentElement.removeChild(this.i),p.delete(this.s)}v(){if(this.e.clearControl)return document.querySelector(this.e.clearControl)}handleEvent=t=>{["scroll","resize"].includes(t.type)?(this.b&&window.cancelAnimationFrame(this.b),this.b=window.requestAnimationFrame(()=>{this[`on${t.type}`](t)})):this[`on${t.type}`](t)};E(t={}){this.e=Object.assign({},E);let e={...t,...this.s.dataset},s=i=>["true","false","1","0",!0,!1].includes(i)&&!!JSON.parse(i);for(let[i,r]of Object.entries(E)){if(e[i]===void 0)continue;let n=e[i];switch(typeof r){case"number":this.e[i]=parseInt(n);break;case"boolean":this.e[i]=s(n);break;case"string":this.e[i]=n.toString();break;case"object":if(Array.isArray(r))if(typeof n=="string"){let a=n.includes("|")?"|":",";this.e[i]=n.split(a)}else this.e[i]=n;else this.e[i]=typeof n=="string"?JSON.parse(n):n;break;case"function":this.e[i]=typeof n=="string"?window[n]:n;break;default:this.e[i]=n;break}}}A(){if(this.s.autocomplete="off",this.s.spellcheck=!1,w(this.s,{"aria-autocomplete":"list","aria-haspopup":"menu","aria-expanded":"false",role:"combobox"}),this.s.id&&this.e.preventBrowserAutocomplete){let t=document.querySelector(`[for="${this.s.id}"]`);t&&F(t)}this.n=null,this.e.hiddenInput&&(this.n=document.createElement("input"),this.n.type="hidden",this.n.value=this.e.hiddenValue,this.n.name=this.s.name,this.s.name="_"+this.s.name,k(this.s,this.n))}k(){this.i=document.createElement("ul"),this.i.id="ac-menu-"+A,this.i.classList.add("dropdown-menu","autocomplete-menu","p-0"),this.i.style.maxHeight="280px",this.e.fullWidth||(this.i.style.maxWidth="360px"),this.e.fixed&&(this.i.style.position="fixed"),this.i.style.overflowY="auto",this.i.style.overscrollBehavior="contain",this.i.style.textAlign="unset",k(this.s,this.i),this.s.setAttribute("aria-controls",this.i.id)}onclick(t){t.target.matches(this.e.clearControl)&&this.clear()}oninput(t){this.u||(this.n&&(this.n.value=null),this.showOrSearch())}onchange(t){let e=this.s.value,s=Object.values(this.r).find(i=>i.label===e);this.e.onChange(s,this)}onblur(t){let e=t.relatedTarget;if(this.a&&e&&(e.classList.contains("modal")||e.classList.contains("autocomplete-menu"))){this.s.focus();return}setTimeout(()=>{this.hideSuggestions()},100)}onfocus(t){this.showOrSearch()}onkeydown(t){switch(t.keyCode||t.key){case 13:case"Enter":if(this.isDropdownVisible()){let s=this.getSelection();s&&s.click(),(s||!this.e.ignoreEnter)&&t.preventDefault()}break;case 9:case"Tab":if(this.isDropdownVisible()&&this.e.tabSelect){let s=this.getSelection();s&&(s.click(),t.preventDefault())}break;case 38:case"ArrowUp":t.preventDefault(),this.h=!0,this.d(v);break;case 40:case"ArrowDown":t.preventDefault(),this.h=!0,this.isDropdownVisible()?this.d(m):this.showOrSearch(!1);break;case 27:case"Escape":this.isDropdownVisible()&&(this.s.focus(),this.hideSuggestions());break}}onmousemove(t){this.a=!0,this.h=!1}onmouseleave(t){this.a=!1,this.removeSelection()}onscroll(t){this.f()}onresize(t){this.f()}getConfig(t=null){return t!==null?this.e[t]:this.e}setConfig(t,e){this.e[t]=e}setData(t){this.r={},this.l(t)}enable(){this.s.setAttribute("disabled","")}disable(){this.s.removeAttribute("disabled")}isDisabled(){return this.s.hasAttribute("disabled")||this.s.disabled||this.s.hasAttribute("readonly")}isDropdownVisible(){return this.i.classList.contains(f)}clear(){this.s.value="",this.n&&(this.n.value="")}getSelection(){return this.i.querySelector("a."+C)}removeSelection(){let t=this.getSelection();t&&t.classList.remove(...this.c())}c(){return[...this.e.activeClasses,C]}w(t){if(t.style.display==="none")return!1;let e=t.firstElementChild;return e.tagName==="A"&&!e.classList.contains("disabled")}d(t=m,e=null){let s=this.getSelection();if(s){let i=t===m?"nextSibling":"previousSibling";e=s.parentNode;do e=e[i];while(e&&!this.w(e));e?(s.classList.remove(...this.c()),t===v?e.parentNode.scrollTop=e.offsetTop-e.parentNode.offsetTop:e.offsetTop>e.parentNode.offsetHeight-e.offsetHeight&&(e.parentNode.scrollTop+=e.offsetHeight)):s&&(e=s.parentElement)}else{if(t===v)return e;if(!e)for(e=this.i.firstChild;e&&!this.w(e);)e=e.nextSibling}if(e){let i=e.querySelector("a");i.classList.add(...this.c()),this.s.setAttribute("aria-activedescendant",i.id),this.e.updateOnSelect&&(this.s.value=i.dataset.label)}else this.s.setAttribute("aria-activedescendant","");return e}O(){return this.isDisabled()?!1:this.s.value.length>=this.e.suggestionsThreshold}showOrSearch(t=!0){if(t&&!this.O()){this.hideSuggestions();return}this.e.liveServer?this.C():this.e.source?this.e.source(this.s.value,e=>{this.setData(e),this.m()}):this.m()}I(t){let e=this.p(),s=document.createElement("span");return e.append(s),s.classList.add("dropdown-header","text-truncate"),s.innerHTML=t,e}D(t,e){let s=e.label;if(this.e.highlightTyped){let n=y(s).indexOf(t);n!==-1&&(s=s.substring(0,n)+`${s.substring(n,n+t.length)}`+s.substring(n+t.length,s.length))}s=this.e.onRenderItem(e,s,this);let i=this.p(),r=document.createElement("a");if(i.append(r),r.id=this.i.id+"-"+this.i.children.length,r.classList.add("dropdown-item","text-truncate"),this.e.itemClass&&r.classList.add(...this.e.itemClass.split(" ")),r.setAttribute("data-value",e.value),r.setAttribute("data-label",e.label),r.setAttribute("tabindex","-1"),r.setAttribute("role","menuitem"),r.setAttribute("href","#"),r.innerHTML=s,e.data)for(let[n,a]of Object.entries(e.data))r.dataset[n]=a;if(this.e.fillIn){let n=document.createElement("button");n.type="button",n.classList.add("btn","btn-link","border-0"),n.innerHTML=` `,i.append(n),i.classList.add("d-flex","justify-content-between"),n.addEventListener("click",a=>{this.s.value=e.label,this.s.focus()})}return r.addEventListener("mouseenter",n=>{this.h||!this.a||(this.removeSelection(),i.querySelector("a").classList.add(...this.c()))}),r.addEventListener("mousedown",n=>{n.preventDefault()}),r.addEventListener("click",n=>{n.preventDefault(),this.u=!0,this.s.value=M(e.label),this.n&&(this.n.value=e.value),this.e.onSelectItem(e,this),this.hideSuggestions(),this.u=!1}),i}m(){if(document.activeElement!=this.s)return;let t=y(this.s.value);this.i.innerHTML="";let e=Object.keys(this.r),s=0,i=null,r=[];for(let n=0;n0&&this.e.searchFields.forEach(u=>{let d=y(h[u]),g=!1;if(this.e.fuzzy)g=D(d,t);else{let L=d.indexOf(t);g=this.e.startsWith?L===0:L>=0}g&&(l=!0)});let T=l||t.length===0;if(c||l){if(s++,h.group&&!r.includes(h.group)){let d=this.I(h.group);this.i.appendChild(d),r.push(h.group)}let u=this.D(t,h);if(!i&&T&&(i=u),this.i.appendChild(u),this.e.maximumItems>0&&s>=this.e.maximumItems)break}}if(i&&this.e.autoselectFirst&&(this.removeSelection(),this.d(m,i)),s===0)if(this.e.notFoundMessage){let n=this.p();n.innerHTML=`${this.e.notFoundMessage}`,this.i.appendChild(n),this.S()}else this.hideSuggestions();else this.S()}p(){let t=document.createElement("li");return t.setAttribute("role","presentation"),t}S(){this.i.classList.add(f),this.i.setAttribute("role","menu"),w(this.s,{"aria-expanded":"true"}),this.f()}toggleSuggestions(t=!0){this.i.classList.contains(f)?this.hideSuggestions():this.showOrSearch(t)}hideSuggestions(){this.i.classList.remove(f),w(this.s,{"aria-expanded":"false"}),this.removeSelection()}getInput(){return this.s}getDropMenu(){return this.i}f(){let t=window.getComputedStyle(this.s),e=this.s.getBoundingClientRect(),s=t.direction==="rtl",i=this.e.fullWidth,r=this.e.fixed,n=null,a=null;r&&(n=e.x,a=e.y+e.height,s&&!i&&(n-=this.i.offsetWidth-e.width)),this.i.style.transform="unset",i&&(this.i.style.width=this.s.offsetWidth+"px"),n!==null&&(this.i.style.left=n+"px"),a!==null&&(this.i.style.top=a+"px");let h=this.i.getBoundingClientRect(),c=window.innerHeight;if(h.y+h.height>c){let l=i?e.height+4:e.height;this.i.style.transform="translateY(calc(-100.1% - "+l+"px))"}}T(){this.r={},this.l(this.e.items);let t=this.e.datalist;if(t){let e=document.querySelector(`#${t}`);if(e){let s=Array.from(e.children).map(i=>{let r=i.getAttribute("value")??i.innerHTML.toLowerCase(),n=i.innerHTML;return{value:r,label:n}});this.l(s)}else console.error(`Datalist not found ${t}`)}this.L(),this.e.server&&!this.e.liveServer&&this.g()}L(){if(this.e.hiddenInput&&!this.e.hiddenValue)for(let[t,e]of Object.entries(this.r))e.label==this.s.value&&(this.n.value=t)}l(t){let e=Object.keys(t);for(let s=0;sh.group=r.group),this.l(r.items);continue}let n=typeof r=="string"?r:r.label,a=typeof r!="object"?{}:r;a.label=r[this.e.labelField]??n,a.value=r[this.e.valueField]??i,a.label&&(this.r[a.value]=a)}}g(t=!1){this.o&&this.o.abort(),this.o=new AbortController;let e=this.s.dataset.serverParams||{};typeof e=="string"&&(e=JSON.parse(e));let s=Object.assign({},this.e.serverParams,e);if(s[this.e.queryParam]=this.s.value,this.e.noCache&&(s.t=Date.now()),s.related){let a=document.getElementById(s.related);if(a){s.related=a.value;let h=a.getAttribute("name");h&&(s[h]=a.value)}}let i=new URLSearchParams(s),r=this.e.server,n=Object.assign(this.e.fetchOptions,{method:this.e.serverMethod||"GET",signal:this.o.signal});n.method==="POST"?n.body=i:r+="?"+i.toString(),this.s.classList.add(x),this.e.onBeforeFetch(this),fetch(r,n).then(a=>this.e.onServerResponse(a,this)).then(a=>{let h=H(this.e.serverDataKey,a)||a;this.setData(h),this.L(),this.o=null,t&&this.m()}).catch(a=>{this.e.onServerError(a,this.o.signal,this)}).finally(a=>{this.s.classList.remove(x),this.e.onAfterFetch(this)})}},j=S;export{j as default}; /** diff --git a/autocomplete.min.js.map b/autocomplete.min.js.map index b3ecd1e..a78d06d 100644 --- a/autocomplete.min.js.map +++ b/autocomplete.min.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["autocomplete.js"], - "sourcesContent": ["/**\n * Bootstrap 5 autocomplete\n * https://github.com/lekoala/bootstrap5-autocomplete\n * @license MIT\n */\n\n// #region config\n\n/**\n * @callback RenderCallback\n * @param {Object} item\n * @param {String} label\n * @param {Autocomplete} inst\n * @returns {string}\n */\n\n/**\n * @callback ItemCallback\n * @param {Object} item\n * @param {Autocomplete} inst\n * @returns {void}\n */\n\n/**\n * @callback ServerCallback\n * @param {Response} response\n * @param {Autocomplete} inst\n * @returns {Promise}\n */\n\n/**\n * @callback ErrorCallback\n * @param {Error} e\n * @param {AbortSignal} signal\n * @param {Autocomplete} inst\n * @returns {void}\n */\n\n/**\n * @callback FetchCallback\n * @param {Autocomplete} inst\n * @returns {void}\n */\n\n/**\n * @typedef Config\n * @property {Boolean} showAllSuggestions Show all suggestions even if they don't match\n * @property {Number} suggestionsThreshold Number of chars required to show suggestions\n * @property {Number} maximumItems Maximum number of items to display\n * @property {Boolean} autoselectFirst Always select the first item\n * @property {Boolean} ignoreEnter Ignore enter if no items are selected (play nicely with autoselectFirst=0)\n * @property {Boolean} updateOnSelect Update input value on selection (doesn't play nice with autoselectFirst)\n * @property {Boolean} highlightTyped Highlight matched part of the label\n * @property {String} highlightClass Class added to the mark label\n * @property {Boolean} fullWidth Match the width on the input field\n * @property {Boolean} fixed Use fixed positioning (solve overflow issues)\n * @property {Boolean} fuzzy Fuzzy search\n * @property {Boolean} startsWith Must start with the string. Defaults to false (it matches any position).\n * @property {Boolean} fillIn Show fill in icon.\n * @property {Boolean} preventBrowserAutocomplete Additional measures to prevent browser autocomplete\n * @property {String} itemClass Applied to the dropdown item. Accepts space separated classes.\n * @property {Array} activeClasses By default: [\"bg-primary\", \"text-white\"]\n * @property {String} labelField Key for the label\n * @property {String} valueField Key for the value\n * @property {Array} searchFields Key for the search\n * @property {String} queryParam Key for the query parameter for server\n * @property {Array|Object} items An array of label/value objects or an object with key/values\n * @property {Function} source A function that provides the list of items\n * @property {Boolean} hiddenInput Create an hidden input which stores the valueField\n * @property {String} hiddenValue Populate the initial hidden value. Mostly useful with liveServer.\n * @property {String} clearControl Selector that will clear the input on click.\n * @property {String} datalist The id of the source datalist\n * @property {String} server Endpoint for data provider\n * @property {String} serverMethod HTTP request method for data provider, default is GET\n * @property {String|Object} serverParams Parameters to pass along to the server. You can specify a \"related\" key with the id of a related field.\n * @property {String} serverDataKey By default: data\n * @property {Object} fetchOptions Any other fetch options (https://developer.mozilla.org/en-US/docs/Web/API/fetch#syntax)\n * @property {Boolean} liveServer Should the endpoint be called each time on input\n * @property {Boolean} noCache Prevent caching by appending a timestamp\n * @property {Number} debounceTime Debounce time for live server\n * @property {String} notFoundMessage Display a no suggestions found message. Leave empty to disable\n * @property {RenderCallback} onRenderItem Callback function that returns the label\n * @property {ItemCallback} onSelectItem Callback function to call on selection\n * @property {ServerCallback} onServerResponse Callback function to process server response. Must return a Promise\n * @property {ErrorCallback} onServerError Callback function to process server errors.\n * @property {ItemCallback} onChange Callback function to call on change-event. Returns currently selected item if any\n * @property {FetchCallback} onBeforeFetch Callback function before fetch\n * @property {FetchCallback} onAfterFetch Callback function after fetch\n */\n\n/**\n * @type {Config}\n */\nconst DEFAULTS = {\n showAllSuggestions: false,\n suggestionsThreshold: 1,\n maximumItems: 0,\n autoselectFirst: true,\n ignoreEnter: false,\n updateOnSelect: false,\n highlightTyped: false,\n highlightClass: \"\",\n fullWidth: false,\n fixed: false,\n fuzzy: false,\n startsWith: false,\n fillIn: false,\n preventBrowserAutocomplete: false,\n itemClass: \"\",\n activeClasses: [\"bg-primary\", \"text-white\"],\n labelField: \"label\",\n valueField: \"value\",\n searchFields: [\"label\"],\n queryParam: \"query\",\n items: [],\n source: null,\n hiddenInput: false,\n hiddenValue: \"\",\n clearControl: \"\",\n datalist: \"\",\n server: \"\",\n serverMethod: \"GET\",\n serverParams: {},\n serverDataKey: \"data\",\n fetchOptions: {},\n liveServer: false,\n noCache: true,\n debounceTime: 300,\n notFoundMessage: \"\",\n onRenderItem: (item, label, inst) => {\n return label;\n },\n onSelectItem: (item, inst) => {},\n onServerResponse: (response, inst) => {\n return response.json();\n },\n onServerError: (e, signal, inst) => {\n // Current version of Firefox rejects the promise with a DOMException\n if (e.name === \"AbortError\" || signal.aborted) {\n return;\n }\n console.error(e);\n },\n onChange: (item, inst) => {},\n onBeforeFetch: (inst) => {},\n onAfterFetch: (inst) => {},\n};\n\n// #endregion\n\n// #region constants\n\nconst LOADING_CLASS = \"is-loading\";\nconst ACTIVE_CLASS = \"is-active\";\nconst SHOW_CLASS = \"show\";\nconst NEXT = \"next\";\nconst PREV = \"prev\";\n\nconst INSTANCE_MAP = new WeakMap();\nlet counter = 0;\nlet activeCounter = 0;\n\n// #endregion\n\n// #region functions\n\n/**\n * @param {Function} func\n * @param {number} timeout\n * @returns {Function}\n */\nfunction debounce(func, timeout = 300) {\n let timer;\n return (...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n //@ts-ignore\n func.apply(this, args);\n }, timeout);\n };\n}\n\n/**\n * @param {String} str\n * @returns {String}\n */\nfunction removeDiacritics(str) {\n return str.normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\");\n}\n\n/**\n * @param {String|Number} str\n * @returns {String}\n */\nfunction normalize(str) {\n if (!str) {\n return \"\";\n }\n return removeDiacritics(str.toString()).toLowerCase();\n}\n\n/**\n * A simple fuzzy match algorithm that checks if chars are matched\n * in order in the target string\n *\n * @param {String} str\n * @param {String} lookup\n * @returns {Boolean}\n */\nfunction fuzzyMatch(str, lookup) {\n if (str.indexOf(lookup) >= 0) {\n return true;\n }\n let pos = 0;\n for (let i = 0; i < lookup.length; i++) {\n const c = lookup[i];\n if (c == \" \") continue;\n pos = str.indexOf(c, pos) + 1;\n if (pos <= 0) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * @param {HTMLElement} el\n * @param {HTMLElement} newEl\n * @returns {HTMLElement}\n */\nfunction insertAfter(el, newEl) {\n return el.parentNode.insertBefore(newEl, el.nextSibling);\n}\n\n/**\n * @param {string} html\n * @returns {string}\n */\nfunction decodeHtml(html) {\n var txt = document.createElement(\"textarea\");\n txt.innerHTML = html;\n return txt.value;\n}\n\n/**\n * @param {HTMLElement} el\n * @param {Object} attrs\n */\nfunction attrs(el, attrs) {\n for (const [k, v] of Object.entries(attrs)) {\n el.setAttribute(k, v);\n }\n}\n\n/**\n * Add a zero width join between chars\n * @param {HTMLElement|Element} el\n */\nfunction zwijit(el) {\n //@ts-ignore\n el.ariaLabel = el.innerText;\n //@ts-ignore\n el.innerHTML = el.innerText\n .split(\"\")\n .map((char) => char + \"‍\")\n .join(\"\");\n}\n\nfunction nested(str, obj = \"window\") {\n return str.split(\".\").reduce((r, p) => r[p], obj);\n}\n\n// #endregion\n\nclass Autocomplete {\n /**\n * @param {HTMLInputElement} el\n * @param {Config|Object} config\n */\n constructor(el, config = {}) {\n if (!(el instanceof HTMLElement)) {\n console.error(\"Invalid element\", el);\n return;\n }\n INSTANCE_MAP.set(el, this);\n counter++;\n activeCounter++;\n this._searchInput = el;\n\n this._configure(config);\n\n // Private vars\n this._isMouse = false;\n this._preventInput = false;\n this._keyboardNavigation = false;\n this._searchFunc = debounce(() => {\n this._loadFromServer(true);\n }, this._config.debounceTime);\n\n // Create html\n this._configureSearchInput();\n this._configureDropElement();\n\n if (this._config.fixed) {\n document.addEventListener(\"scroll\", this, true);\n window.addEventListener(\"resize\", this);\n }\n\n const clearControl = this._getClearControl();\n if (clearControl) {\n clearControl.addEventListener(\"click\", this);\n }\n\n // Add listeners (remove then on dispose()). See handleEvent.\n [\"focus\", \"change\", \"blur\", \"input\", \"keydown\"].forEach((type) => {\n this._searchInput.addEventListener(type, this);\n });\n [\"mousemove\", \"mouseleave\"].forEach((type) => {\n this._dropElement.addEventListener(type, this);\n });\n\n this._fetchData();\n }\n\n // #region Core\n\n /**\n * Attach to all elements matched by the selector\n * @param {string} selector\n * @param {Config|Object} config\n */\n static init(selector = \"input.autocomplete\", config = {}) {\n /**\n * @type {NodeListOf}\n */\n const nodes = document.querySelectorAll(selector);\n nodes.forEach((el) => {\n this.getOrCreateInstance(el, config);\n });\n }\n\n /**\n * @param {HTMLInputElement} el\n */\n static getInstance(el) {\n return INSTANCE_MAP.has(el) ? INSTANCE_MAP.get(el) : null;\n }\n\n /**\n * @param {HTMLInputElement} el\n * @param {Object} config\n */\n static getOrCreateInstance(el, config = {}) {\n return this.getInstance(el) || new this(el, config);\n }\n\n dispose() {\n activeCounter--;\n\n [\"focus\", \"change\", \"blur\", \"input\", \"keydown\"].forEach((type) => {\n this._searchInput.removeEventListener(type, this);\n });\n [\"mousemove\", \"mouseleave\"].forEach((type) => {\n this._dropElement.removeEventListener(type, this);\n });\n\n const clearControl = this._getClearControl();\n if (clearControl) {\n clearControl.removeEventListener(\"click\", this);\n }\n\n // only remove if there are no more active elements\n if (this._config.fixed && activeCounter <= 0) {\n document.removeEventListener(\"scroll\", this, true);\n window.removeEventListener(\"resize\", this);\n }\n\n this._dropElement.parentElement.removeChild(this._dropElement);\n\n INSTANCE_MAP.delete(this._searchInput);\n }\n\n _getClearControl() {\n if (this._config.clearControl) {\n return document.querySelector(this._config.clearControl);\n }\n }\n\n /**\n * @link https://github.com/lifaon74/events-polyfill/issues/10\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\n * @param {Event} event\n */\n handleEvent = (event) => {\n // debounce scroll and resize\n const debounced = [\"scroll\", \"resize\"];\n if (debounced.includes(event.type)) {\n if (this._timer) window.cancelAnimationFrame(this._timer);\n this._timer = window.requestAnimationFrame(() => {\n this[`on${event.type}`](event);\n });\n } else {\n this[`on${event.type}`](event);\n }\n };\n\n /**\n * @param {Config|Object} config\n */\n _configure(config = {}) {\n this._config = Object.assign({}, DEFAULTS);\n\n // Handle options, using arguments first and data attr as override\n const o = { ...config, ...this._searchInput.dataset };\n\n // Allow 1/0, true/false as strings\n const parseBool = (value) => [\"true\", \"false\", \"1\", \"0\", true, false].includes(value) && !!JSON.parse(value);\n\n // Typecast provided options based on defaults types\n for (const [key, defaultValue] of Object.entries(DEFAULTS)) {\n // Check for undefined keys\n if (o[key] === void 0) {\n continue;\n }\n const value = o[key];\n switch (typeof defaultValue) {\n case \"number\":\n this._config[key] = parseInt(value);\n break;\n case \"boolean\":\n this._config[key] = parseBool(value);\n break;\n case \"string\":\n this._config[key] = value.toString();\n break;\n case \"object\":\n // Arrays have a type object in js\n if (Array.isArray(defaultValue)) {\n if (typeof value === \"string\") {\n const separator = value.includes(\"|\") ? \"|\" : \",\";\n this._config[key] = value.split(separator);\n } else {\n this._config[key] = value;\n }\n } else {\n this._config[key] = typeof value === \"string\" ? JSON.parse(value) : value;\n }\n break;\n case \"function\":\n this._config[key] = typeof value === \"string\" ? window[value] : value;\n break;\n default:\n this._config[key] = value;\n break;\n }\n }\n }\n\n // #endregion\n\n // #region Html\n\n _configureSearchInput() {\n this._searchInput.autocomplete = \"off\";\n this._searchInput.spellcheck = false;\n // note: firefox doesn't support the properties so we use attributes\n // @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-autocomplete\n // @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded\n // use the aria-expanded state on the element with role combobox to communicate that the list is displayed.\n attrs(this._searchInput, {\n \"aria-autocomplete\": \"list\",\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": \"false\",\n role: \"combobox\",\n });\n\n // Even with autocomplete \"off\" we can get suggestion from browser due to label\n if (this._searchInput.id && this._config.preventBrowserAutocomplete) {\n const label = document.querySelector(`[for=\"${this._searchInput.id}\"]`);\n if (label) {\n zwijit(label);\n }\n }\n\n // Hidden input?\n this._hiddenInput = null;\n if (this._config.hiddenInput) {\n this._hiddenInput = document.createElement(\"input\");\n this._hiddenInput.type = \"hidden\";\n this._hiddenInput.value = this._config.hiddenValue;\n this._hiddenInput.name = this._searchInput.name;\n this._searchInput.name = \"_\" + this._searchInput.name;\n insertAfter(this._searchInput, this._hiddenInput);\n }\n }\n\n _configureDropElement() {\n this._dropElement = document.createElement(\"ul\");\n this._dropElement.id = \"ac-menu-\" + counter;\n this._dropElement.classList.add(...[\"dropdown-menu\", \"autocomplete-menu\", \"p-0\"]);\n this._dropElement.style.maxHeight = \"280px\";\n if (!this._config.fullWidth) {\n this._dropElement.style.maxWidth = \"360px\";\n }\n if (this._config.fixed) {\n this._dropElement.style.position = \"fixed\";\n }\n this._dropElement.style.overflowY = \"auto\";\n // Prevent scrolling the menu from scrolling the page\n // @link https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior\n this._dropElement.style.overscrollBehavior = \"contain\";\n this._dropElement.style.textAlign = \"unset\"; // otherwise RTL is not good\n\n insertAfter(this._searchInput, this._dropElement);\n // include aria-controls with the value of the id of the suggested list of values.\n this._searchInput.setAttribute(\"aria-controls\", this._dropElement.id);\n }\n\n // #endregion\n\n // #region Events\n\n onclick(e) {\n if (e.target.matches(this._config.clearControl)) {\n this.clear();\n }\n }\n\n oninput(e) {\n if (this._preventInput) {\n return;\n }\n // Input has changed, clear value\n if (this._hiddenInput) {\n this._hiddenInput.value = null;\n }\n this.showOrSearch();\n }\n\n onchange(e) {\n const search = this._searchInput.value;\n const item = Object.values(this._items).find((item) => item.label === search);\n this._config.onChange(item, this);\n }\n\n onblur(e) {\n const related = e.relatedTarget;\n // Clicking on the scroll in a modal blur the element incorrectly\n // In chrome >= 127, the related target is the dropdown menu\n if (this._isMouse && related && (related.classList.contains(\"modal\") || related.classList.contains(\"autocomplete-menu\"))) {\n // Restore focus\n this._searchInput.focus();\n return;\n }\n setTimeout(() => {\n this.hideSuggestions();\n }, 100);\n }\n\n onfocus(e) {\n this.showOrSearch();\n }\n\n /**\n * keypress doesn't send arrow keys, so we use keydown\n * @param {KeyboardEvent} e\n */\n onkeydown(e) {\n const key = e.keyCode || e.key;\n switch (key) {\n case 13:\n case \"Enter\":\n if (this.isDropdownVisible()) {\n const selection = this.getSelection();\n if (selection) {\n selection.click();\n }\n if (selection || !this._config.ignoreEnter) {\n e.preventDefault();\n }\n }\n break;\n case 9:\n case \"Tab\":\n if (this.isDropdownVisible() && this._searchInput.value) {\n const selection = this.getSelection();\n if (selection) {\n selection.click();\n e.preventDefault();\n }\n }\n break;\n case 38:\n case \"ArrowUp\":\n e.preventDefault();\n this._keyboardNavigation = true;\n this._moveSelection(PREV);\n break;\n case 40:\n case \"ArrowDown\":\n e.preventDefault();\n this._keyboardNavigation = true;\n if (this.isDropdownVisible()) {\n this._moveSelection(NEXT);\n } else {\n // show menu regardless of input length\n this.showOrSearch(false);\n }\n break;\n case 27:\n case \"Escape\":\n if (this.isDropdownVisible()) {\n this._searchInput.focus();\n this.hideSuggestions();\n }\n break;\n }\n }\n\n onmousemove(e) {\n this._isMouse = true;\n // Moving the mouse means no longer using keyboard\n this._keyboardNavigation = false;\n }\n\n onmouseleave(e) {\n this._isMouse = false;\n // Remove selection\n this.removeSelection();\n }\n\n onscroll(e) {\n this._positionMenu();\n }\n\n onresize(e) {\n this._positionMenu();\n }\n\n // #endregion\n\n // #region Api\n\n /**\n * @param {String} k\n * @returns {Config}\n */\n getConfig(k = null) {\n if (k !== null) {\n return this._config[k];\n }\n return this._config;\n }\n\n /**\n * @param {String} k\n * @param {*} v\n */\n setConfig(k, v) {\n this._config[k] = v;\n }\n\n setData(src) {\n this._items = {};\n this._addItems(src);\n }\n\n enable() {\n this._searchInput.setAttribute(\"disabled\", \"\");\n }\n\n disable() {\n this._searchInput.removeAttribute(\"disabled\");\n }\n\n /**\n * @returns {boolean}\n */\n isDisabled() {\n return this._searchInput.hasAttribute(\"disabled\") || this._searchInput.disabled || this._searchInput.hasAttribute(\"readonly\");\n }\n\n /**\n * @returns {boolean}\n */\n isDropdownVisible() {\n return this._dropElement.classList.contains(SHOW_CLASS);\n }\n\n clear() {\n this._searchInput.value = \"\";\n if (this._hiddenInput) {\n this._hiddenInput.value = \"\";\n }\n }\n\n // #endregion\n\n // #region Selection management\n\n /**\n * @returns {HTMLElement}\n */\n getSelection() {\n return this._dropElement.querySelector(\"a.\" + ACTIVE_CLASS);\n }\n\n removeSelection() {\n const selection = this.getSelection();\n if (selection) {\n selection.classList.remove(...this._activeClasses());\n }\n }\n\n /**\n * @returns {Array}\n */\n _activeClasses() {\n return [...this._config.activeClasses, ...[ACTIVE_CLASS]];\n }\n\n /**\n * @param {HTMLElement} li\n * @returns {Boolean}\n */\n _isItemEnabled(li) {\n if (li.style.display === \"none\") {\n return false;\n }\n const fc = li.firstElementChild;\n return fc.tagName === \"A\" && !fc.classList.contains(\"disabled\");\n }\n\n /**\n * @param {String} dir\n * @param {*|HTMLElement} sel\n * @returns {HTMLElement}\n */\n _moveSelection(dir = NEXT, sel = null) {\n const active = this.getSelection();\n\n // select first li\n if (!active) {\n // no active selection, cannot go back\n if (dir === PREV) {\n return sel;\n }\n // find first enabled item\n if (!sel) {\n sel = this._dropElement.firstChild;\n while (sel && !this._isItemEnabled(sel)) {\n sel = sel[\"nextSibling\"];\n }\n }\n } else {\n const sibling = dir === NEXT ? \"nextSibling\" : \"previousSibling\";\n\n // Iterate over enabled li\n sel = active.parentNode;\n do {\n sel = sel[sibling];\n } while (sel && !this._isItemEnabled(sel));\n\n // We have a new selection\n if (sel) {\n // Change classes\n active.classList.remove(...this._activeClasses());\n\n // Scroll if necessary\n if (dir === PREV) {\n // Don't use scrollIntoView as it scrolls the whole window\n sel.parentNode.scrollTop = sel.offsetTop - sel.parentNode.offsetTop;\n } else {\n // This is the equivalent of scrollIntoView(false) but only for parent node\n if (sel.offsetTop > sel.parentNode.offsetHeight - sel.offsetHeight) {\n sel.parentNode.scrollTop += sel.offsetHeight;\n }\n }\n } else if (active) {\n sel = active.parentElement;\n }\n }\n\n if (sel) {\n const a = sel.querySelector(\"a\");\n a.classList.add(...this._activeClasses());\n this._searchInput.setAttribute(\"aria-activedescendant\", a.id);\n if (this._config.updateOnSelect) {\n this._searchInput.value = a.dataset.label;\n }\n } else {\n this._searchInput.setAttribute(\"aria-activedescendant\", \"\");\n }\n return sel;\n }\n\n // #endregion\n\n // #region Implementation\n\n /**\n * Do we have enough input to show suggestions ?\n * @returns {Boolean}\n */\n _shouldShow() {\n if (this.isDisabled()) {\n return false;\n }\n return this._searchInput.value.length >= this._config.suggestionsThreshold;\n }\n\n /**\n * Show suggestions or load them\n * @param {Boolean} check\n */\n showOrSearch(check = true) {\n if (check && !this._shouldShow()) {\n this.hideSuggestions();\n return;\n }\n if (this._config.liveServer) {\n this._searchFunc();\n } else if (this._config.source) {\n this._config.source(this._searchInput.value, (items) => {\n this.setData(items);\n this._showSuggestions();\n });\n } else {\n this._showSuggestions();\n }\n }\n\n /**\n * @param {String} name\n * @returns {HTMLElement}\n */\n _createGroup(name) {\n const newChild = this._createLi();\n const newChildSpan = document.createElement(\"span\");\n newChild.append(newChildSpan);\n newChildSpan.classList.add(...[\"dropdown-header\", \"text-truncate\"]);\n newChildSpan.innerHTML = name;\n return newChild;\n }\n\n /**\n * @param {String} lookup\n * @param {Object} item\n * @returns {HTMLElement}\n */\n _createItem(lookup, item) {\n let label = item.label;\n\n if (this._config.highlightTyped) {\n const idx = normalize(label).indexOf(lookup);\n if (idx !== -1) {\n label =\n label.substring(0, idx) +\n `${label.substring(idx, idx + lookup.length)}` +\n label.substring(idx + lookup.length, label.length);\n }\n }\n\n label = this._config.onRenderItem(item, label, this);\n\n const newChild = this._createLi();\n const newChildLink = document.createElement(\"a\");\n newChild.append(newChildLink);\n newChildLink.id = this._dropElement.id + \"-\" + this._dropElement.children.length;\n newChildLink.classList.add(...[\"dropdown-item\", \"text-truncate\"]);\n if (this._config.itemClass) {\n newChildLink.classList.add(...this._config.itemClass.split(\" \"));\n }\n newChildLink.setAttribute(\"data-value\", item.value);\n newChildLink.setAttribute(\"data-label\", item.label);\n // Behave like a datalist (tab doesn't allow item selection)\n // @link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist\n newChildLink.setAttribute(\"tabindex\", \"-1\");\n newChildLink.setAttribute(\"role\", \"menuitem\");\n newChildLink.setAttribute(\"href\", \"#\");\n newChildLink.innerHTML = label;\n if (item.data) {\n for (const [key, value] of Object.entries(item.data)) {\n newChildLink.dataset[key] = value;\n }\n }\n\n if (this._config.fillIn) {\n const fillIn = document.createElement(\"button\");\n fillIn.type = \"button\"; // prevent submit\n fillIn.classList.add(...[\"btn\", \"btn-link\", \"border-0\"]);\n fillIn.innerHTML = `\n \n `;\n newChild.append(fillIn);\n newChild.classList.add(...[\"d-flex\", \"justify-content-between\"]);\n fillIn.addEventListener(\"click\", (event) => {\n this._searchInput.value = item.label;\n this._searchInput.focus(); // focus back to keep editing\n });\n }\n\n // Hover sets active item\n newChildLink.addEventListener(\"mouseenter\", (event) => {\n // Don't trigger enter if using arrows or not currently using the mouse\n if (this._keyboardNavigation || !this._isMouse) {\n return;\n }\n this.removeSelection();\n newChild.querySelector(\"a\").classList.add(...this._activeClasses());\n });\n // Prevent searchInput losing focus and close the menu\n newChildLink.addEventListener(\"mousedown\", (event) => {\n event.preventDefault();\n });\n // Apply value\n newChildLink.addEventListener(\"click\", (event) => {\n event.preventDefault();\n\n // Prevent input otherwise it might trigger autocomplete due to value change\n this._preventInput = true;\n this._searchInput.value = decodeHtml(item.label);\n // Populate value in hidden input\n if (this._hiddenInput) {\n this._hiddenInput.value = item.value;\n }\n this._config.onSelectItem(item, this);\n this.hideSuggestions();\n this._preventInput = false;\n });\n\n return newChild;\n }\n\n /**\n * Show drop menu with suggestions\n */\n _showSuggestions() {\n // It's not focused anymore\n if (document.activeElement != this._searchInput) {\n return;\n }\n const lookup = normalize(this._searchInput.value);\n this._dropElement.innerHTML = \"\";\n\n const keys = Object.keys(this._items);\n let count = 0;\n let firstItem = null;\n\n const groups = [];\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const entry = this._items[key];\n\n // Check search length since we can trigger dropdown with arrow\n const showAllSuggestions = this._config.showAllSuggestions || lookup.length === 0;\n // Do we find a matching string or do we display immediately ?\n let isMatched = lookup.length == 0 && this._config.suggestionsThreshold === 0;\n if (!showAllSuggestions && lookup.length > 0) {\n // match on any field\n this._config.searchFields.forEach((sf) => {\n const text = normalize(entry[sf]);\n let found = false;\n if (this._config.fuzzy) {\n found = fuzzyMatch(text, lookup);\n } else {\n const idx = text.indexOf(lookup);\n found = this._config.startsWith ? idx === 0 : idx >= 0;\n }\n if (found) {\n isMatched = true;\n }\n });\n }\n const selectFirst = isMatched || lookup.length === 0;\n if (showAllSuggestions || isMatched) {\n count++;\n\n // Group\n if (entry.group && !groups.includes(entry.group)) {\n const newItem = this._createGroup(entry.group);\n this._dropElement.appendChild(newItem);\n groups.push(entry.group);\n }\n\n const newItem = this._createItem(lookup, entry);\n // Only select as first item if its matching or no lookup\n if (!firstItem && selectFirst) {\n firstItem = newItem;\n }\n this._dropElement.appendChild(newItem);\n if (this._config.maximumItems > 0 && count >= this._config.maximumItems) {\n break;\n }\n }\n }\n\n if (firstItem && this._config.autoselectFirst) {\n this.removeSelection();\n this._moveSelection(NEXT, firstItem);\n }\n\n if (count === 0) {\n if (this._config.notFoundMessage) {\n const newChild = this._createLi();\n newChild.innerHTML = `${this._config.notFoundMessage}`;\n this._dropElement.appendChild(newChild);\n this._showDropdown();\n } else {\n // Remove dropdown if not found\n this.hideSuggestions();\n }\n } else {\n // Or show it if necessary\n this._showDropdown();\n }\n }\n\n /**\n * @returns {HTMLLIElement}\n */\n _createLi() {\n const newChild = document.createElement(\"li\");\n newChild.setAttribute(\"role\", \"presentation\");\n return newChild;\n }\n\n /**\n * Show and position dropdown\n */\n _showDropdown() {\n this._dropElement.classList.add(SHOW_CLASS);\n // Register role when shown to avoid empty children issues\n this._dropElement.setAttribute(\"role\", \"menu\");\n attrs(this._searchInput, {\n \"aria-expanded\": \"true\",\n });\n this._positionMenu();\n }\n\n /**\n * Show or hide suggestions\n * @param {Boolean} check\n */\n toggleSuggestions(check = true) {\n if (this._dropElement.classList.contains(SHOW_CLASS)) {\n this.hideSuggestions();\n } else {\n this.showOrSearch(check);\n }\n }\n\n /**\n * Hide the dropdown menu\n */\n hideSuggestions() {\n this._dropElement.classList.remove(SHOW_CLASS);\n attrs(this._searchInput, {\n \"aria-expanded\": \"false\",\n });\n this.removeSelection();\n }\n\n /**\n * @returns {HTMLInputElement}\n */\n getInput() {\n return this._searchInput;\n }\n\n /**\n * @returns {HTMLUListElement}\n */\n getDropMenu() {\n return this._dropElement;\n }\n\n /**\n * Position the dropdown menu\n */\n _positionMenu() {\n const styles = window.getComputedStyle(this._searchInput);\n const bounds = this._searchInput.getBoundingClientRect();\n const isRTL = styles.direction === \"rtl\";\n const fullWidth = this._config.fullWidth;\n const fixed = this._config.fixed;\n\n // Don't position left if not fixed since it may not work in all situations\n // due to offsetParent margin or in tables\n let left = null;\n let top = null;\n\n if (fixed) {\n left = bounds.x;\n top = bounds.y + bounds.height;\n\n // Align end\n if (isRTL && !fullWidth) {\n left -= this._dropElement.offsetWidth - bounds.width;\n }\n }\n\n // Reset any height overflow adjustement\n this._dropElement.style.transform = \"unset\";\n\n // Use full holder width\n if (fullWidth) {\n this._dropElement.style.width = this._searchInput.offsetWidth + \"px\";\n }\n\n // Position element\n if (left !== null) {\n this._dropElement.style.left = left + \"px\";\n }\n if (top !== null) {\n this._dropElement.style.top = top + \"px\";\n }\n\n // Overflow height\n const dropBounds = this._dropElement.getBoundingClientRect();\n const h = window.innerHeight;\n\n // We display above input if it overflows\n if (dropBounds.y + dropBounds.height > h) {\n // We need to add the offset twice\n const topOffset = fullWidth ? bounds.height + 4 : bounds.height;\n // In chrome, we need 100.1% to avoid blurry text\n // @link https://stackoverflow.com/questions/32034574/font-looks-blurry-after-translate-in-chrome\n this._dropElement.style.transform = \"translateY(calc(-100.1% - \" + topOffset + \"px))\";\n }\n }\n\n _fetchData() {\n this._items = {};\n\n // From an array of items or an object\n this._addItems(this._config.items);\n\n // From a datalist\n const dl = this._config.datalist;\n if (dl) {\n const datalist = document.querySelector(`#${dl}`);\n if (datalist) {\n const items = Array.from(datalist.children).map((o) => {\n const value = o.getAttribute(\"value\") ?? o.innerHTML.toLowerCase();\n const label = o.innerHTML;\n\n return {\n value,\n label,\n };\n });\n this._addItems(items);\n } else {\n console.error(`Datalist not found ${dl}`);\n }\n }\n this._setHiddenVal();\n\n // From an external source\n if (this._config.server && !this._config.liveServer) {\n this._loadFromServer();\n }\n }\n\n _setHiddenVal() {\n if (this._config.hiddenInput && !this._config.hiddenValue) {\n for (const [value, entry] of Object.entries(this._items)) {\n if (entry.label == this._searchInput.value) {\n this._hiddenInput.value = value;\n }\n }\n }\n }\n\n /**\n * @param {Array|Object} src An array of items or a value:label object\n */\n _addItems(src) {\n const keys = Object.keys(src);\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const entry = src[key];\n\n if (entry.group && entry.items) {\n entry.items.forEach((e) => (e.group = entry.group));\n this._addItems(entry.items);\n continue;\n }\n\n const label = typeof entry === \"string\" ? entry : entry.label;\n const item = typeof entry !== \"object\" ? {} : entry;\n\n // Normalize entry\n item.label = entry[this._config.labelField] ?? label;\n item.value = entry[this._config.valueField] ?? key;\n\n // Make sure we have a label\n if (item.label) {\n this._items[item.value] = item;\n }\n }\n }\n\n /**\n * @param {boolean} show\n */\n _loadFromServer(show = false) {\n if (this._abortController) {\n this._abortController.abort();\n }\n this._abortController = new AbortController();\n\n // Read data params dynamically as well\n let extraParams = this._searchInput.dataset.serverParams || {};\n if (typeof extraParams == \"string\") {\n extraParams = JSON.parse(extraParams);\n }\n const params = Object.assign({}, this._config.serverParams, extraParams);\n // Pass current value\n params[this._config.queryParam] = this._searchInput.value;\n // Prevent caching\n if (this._config.noCache) {\n params.t = Date.now();\n }\n // We have a related field\n if (params.related) {\n /**\n * @type {HTMLInputElement}\n */\n //@ts-ignore\n const input = document.getElementById(params.related);\n if (input) {\n params.related = input.value;\n const inputName = input.getAttribute(\"name\");\n if (inputName) {\n params[inputName] = input.value;\n }\n }\n }\n\n const urlParams = new URLSearchParams(params);\n let url = this._config.server;\n let fetchOptions = Object.assign(this._config.fetchOptions, {\n method: this._config.serverMethod || \"GET\",\n signal: this._abortController.signal,\n });\n\n if (fetchOptions.method === \"POST\") {\n fetchOptions.body = urlParams;\n } else {\n url += \"?\" + urlParams.toString();\n }\n\n this._searchInput.classList.add(LOADING_CLASS);\n this._config.onBeforeFetch(this);\n\n fetch(url, fetchOptions)\n .then((r) => this._config.onServerResponse(r, this))\n .then((suggestions) => {\n const data = nested(this._config.serverDataKey, suggestions) || suggestions;\n this.setData(data);\n this._setHiddenVal();\n this._abortController = null;\n if (show) {\n this._showSuggestions();\n }\n })\n .catch((e) => {\n this._config.onServerError(e, this._abortController.signal, this);\n })\n .finally((e) => {\n this._searchInput.classList.remove(LOADING_CLASS);\n this._config.onAfterFetch(this);\n });\n }\n\n // #endregion\n}\n\nexport default Autocomplete;\n"], - "mappings": "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", + "sourcesContent": ["/**\n * Bootstrap 5 autocomplete\n * https://github.com/lekoala/bootstrap5-autocomplete\n * @license MIT\n */\n\n// #region config\n\n/**\n * @callback RenderCallback\n * @param {Object} item\n * @param {String} label\n * @param {Autocomplete} inst\n * @returns {string}\n */\n\n/**\n * @callback ItemCallback\n * @param {Object} item\n * @param {Autocomplete} inst\n * @returns {void}\n */\n\n/**\n * @callback ServerCallback\n * @param {Response} response\n * @param {Autocomplete} inst\n * @returns {Promise}\n */\n\n/**\n * @callback ErrorCallback\n * @param {Error} e\n * @param {AbortSignal} signal\n * @param {Autocomplete} inst\n * @returns {void}\n */\n\n/**\n * @callback FetchCallback\n * @param {Autocomplete} inst\n * @returns {void}\n */\n\n/**\n * @typedef Config\n * @property {Boolean} showAllSuggestions Show all suggestions even if they don't match\n * @property {Number} suggestionsThreshold Number of chars required to show suggestions\n * @property {Number} maximumItems Maximum number of items to display\n * @property {Boolean} autoselectFirst Always select the first item\n * @property {Boolean} ignoreEnter Ignore enter if no items are selected (play nicely with autoselectFirst=0)\n * @property {Boolean} tabSelect Tab will trigger selection if active\n * @property {Boolean} updateOnSelect Update input value on selection (doesn't play nice with autoselectFirst)\n * @property {Boolean} highlightTyped Highlight matched part of the label\n * @property {String} highlightClass Class added to the mark label\n * @property {Boolean} fullWidth Match the width on the input field\n * @property {Boolean} fixed Use fixed positioning (solve overflow issues)\n * @property {Boolean} fuzzy Fuzzy search\n * @property {Boolean} startsWith Must start with the string. Defaults to false (it matches any position).\n * @property {Boolean} fillIn Show fill in icon.\n * @property {Boolean} preventBrowserAutocomplete Additional measures to prevent browser autocomplete\n * @property {String} itemClass Applied to the dropdown item. Accepts space separated classes.\n * @property {Array} activeClasses By default: [\"bg-primary\", \"text-white\"]\n * @property {String} labelField Key for the label\n * @property {String} valueField Key for the value\n * @property {Array} searchFields Key for the search\n * @property {String} queryParam Key for the query parameter for server\n * @property {Array|Object} items An array of label/value objects or an object with key/values\n * @property {Function} source A function that provides the list of items\n * @property {Boolean} hiddenInput Create an hidden input which stores the valueField\n * @property {String} hiddenValue Populate the initial hidden value. Mostly useful with liveServer.\n * @property {String} clearControl Selector that will clear the input on click.\n * @property {String} datalist The id of the source datalist\n * @property {String} server Endpoint for data provider\n * @property {String} serverMethod HTTP request method for data provider, default is GET\n * @property {String|Object} serverParams Parameters to pass along to the server. You can specify a \"related\" key with the id of a related field.\n * @property {String} serverDataKey By default: data\n * @property {Object} fetchOptions Any other fetch options (https://developer.mozilla.org/en-US/docs/Web/API/fetch#syntax)\n * @property {Boolean} liveServer Should the endpoint be called each time on input\n * @property {Boolean} noCache Prevent caching by appending a timestamp\n * @property {Number} debounceTime Debounce time for live server\n * @property {String} notFoundMessage Display a no suggestions found message. Leave empty to disable\n * @property {RenderCallback} onRenderItem Callback function that returns the label\n * @property {ItemCallback} onSelectItem Callback function to call on selection\n * @property {ServerCallback} onServerResponse Callback function to process server response. Must return a Promise\n * @property {ErrorCallback} onServerError Callback function to process server errors.\n * @property {ItemCallback} onChange Callback function to call on change-event. Returns currently selected item if any\n * @property {FetchCallback} onBeforeFetch Callback function before fetch\n * @property {FetchCallback} onAfterFetch Callback function after fetch\n */\n\n/**\n * @type {Config}\n */\nconst DEFAULTS = {\n showAllSuggestions: false,\n suggestionsThreshold: 1,\n maximumItems: 0,\n autoselectFirst: true,\n ignoreEnter: false,\n tabSelect: false,\n updateOnSelect: false,\n highlightTyped: false,\n highlightClass: \"\",\n fullWidth: false,\n fixed: false,\n fuzzy: false,\n startsWith: false,\n fillIn: false,\n preventBrowserAutocomplete: false,\n itemClass: \"\",\n activeClasses: [\"bg-primary\", \"text-white\"],\n labelField: \"label\",\n valueField: \"value\",\n searchFields: [\"label\"],\n queryParam: \"query\",\n items: [],\n source: null,\n hiddenInput: false,\n hiddenValue: \"\",\n clearControl: \"\",\n datalist: \"\",\n server: \"\",\n serverMethod: \"GET\",\n serverParams: {},\n serverDataKey: \"data\",\n fetchOptions: {},\n liveServer: false,\n noCache: true,\n debounceTime: 300,\n notFoundMessage: \"\",\n onRenderItem: (item, label, inst) => {\n return label;\n },\n onSelectItem: (item, inst) => {},\n onServerResponse: (response, inst) => {\n return response.json();\n },\n onServerError: (e, signal, inst) => {\n // Current version of Firefox rejects the promise with a DOMException\n if (e.name === \"AbortError\" || signal.aborted) {\n return;\n }\n console.error(e);\n },\n onChange: (item, inst) => {},\n onBeforeFetch: (inst) => {},\n onAfterFetch: (inst) => {},\n};\n\n// #endregion\n\n// #region constants\n\nconst LOADING_CLASS = \"is-loading\";\nconst ACTIVE_CLASS = \"is-active\";\nconst SHOW_CLASS = \"show\";\nconst NEXT = \"next\";\nconst PREV = \"prev\";\n\nconst INSTANCE_MAP = new WeakMap();\nlet counter = 0;\nlet activeCounter = 0;\n\n// #endregion\n\n// #region functions\n\n/**\n * @param {Function} func\n * @param {number} timeout\n * @returns {Function}\n */\nfunction debounce(func, timeout = 300) {\n let timer;\n return (...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n //@ts-ignore\n func.apply(this, args);\n }, timeout);\n };\n}\n\n/**\n * @param {String} str\n * @returns {String}\n */\nfunction removeDiacritics(str) {\n return str.normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\");\n}\n\n/**\n * @param {String|Number} str\n * @returns {String}\n */\nfunction normalize(str) {\n if (!str) {\n return \"\";\n }\n return removeDiacritics(str.toString()).toLowerCase();\n}\n\n/**\n * A simple fuzzy match algorithm that checks if chars are matched\n * in order in the target string\n *\n * @param {String} str\n * @param {String} lookup\n * @returns {Boolean}\n */\nfunction fuzzyMatch(str, lookup) {\n if (str.indexOf(lookup) >= 0) {\n return true;\n }\n let pos = 0;\n for (let i = 0; i < lookup.length; i++) {\n const c = lookup[i];\n if (c == \" \") continue;\n pos = str.indexOf(c, pos) + 1;\n if (pos <= 0) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * @param {HTMLElement} el\n * @param {HTMLElement} newEl\n * @returns {HTMLElement}\n */\nfunction insertAfter(el, newEl) {\n return el.parentNode.insertBefore(newEl, el.nextSibling);\n}\n\n/**\n * @param {string} html\n * @returns {string}\n */\nfunction decodeHtml(html) {\n var txt = document.createElement(\"textarea\");\n txt.innerHTML = html;\n return txt.value;\n}\n\n/**\n * @param {HTMLElement} el\n * @param {Object} attrs\n */\nfunction attrs(el, attrs) {\n for (const [k, v] of Object.entries(attrs)) {\n el.setAttribute(k, v);\n }\n}\n\n/**\n * Add a zero width join between chars\n * @param {HTMLElement|Element} el\n */\nfunction zwijit(el) {\n //@ts-ignore\n el.ariaLabel = el.innerText;\n //@ts-ignore\n el.innerHTML = el.innerText\n .split(\"\")\n .map((char) => char + \"‍\")\n .join(\"\");\n}\n\nfunction nested(str, obj = \"window\") {\n return str.split(\".\").reduce((r, p) => r[p], obj);\n}\n\n// #endregion\n\nclass Autocomplete {\n /**\n * @param {HTMLInputElement} el\n * @param {Config|Object} config\n */\n constructor(el, config = {}) {\n if (!(el instanceof HTMLElement)) {\n console.error(\"Invalid element\", el);\n return;\n }\n INSTANCE_MAP.set(el, this);\n counter++;\n activeCounter++;\n this._searchInput = el;\n\n this._configure(config);\n\n // Private vars\n this._isMouse = false;\n this._preventInput = false;\n this._keyboardNavigation = false;\n this._searchFunc = debounce(() => {\n this._loadFromServer(true);\n }, this._config.debounceTime);\n\n // Create html\n this._configureSearchInput();\n this._configureDropElement();\n\n if (this._config.fixed) {\n document.addEventListener(\"scroll\", this, true);\n window.addEventListener(\"resize\", this);\n }\n\n const clearControl = this._getClearControl();\n if (clearControl) {\n clearControl.addEventListener(\"click\", this);\n }\n\n // Add listeners (remove then on dispose()). See handleEvent.\n [\"focus\", \"change\", \"blur\", \"input\", \"keydown\"].forEach((type) => {\n this._searchInput.addEventListener(type, this);\n });\n [\"mousemove\", \"mouseleave\"].forEach((type) => {\n this._dropElement.addEventListener(type, this);\n });\n\n this._fetchData();\n }\n\n // #region Core\n\n /**\n * Attach to all elements matched by the selector\n * @param {string} selector\n * @param {Config|Object} config\n */\n static init(selector = \"input.autocomplete\", config = {}) {\n /**\n * @type {NodeListOf}\n */\n const nodes = document.querySelectorAll(selector);\n nodes.forEach((el) => {\n this.getOrCreateInstance(el, config);\n });\n }\n\n /**\n * @param {HTMLInputElement} el\n */\n static getInstance(el) {\n return INSTANCE_MAP.has(el) ? INSTANCE_MAP.get(el) : null;\n }\n\n /**\n * @param {HTMLInputElement} el\n * @param {Object} config\n */\n static getOrCreateInstance(el, config = {}) {\n return this.getInstance(el) || new this(el, config);\n }\n\n dispose() {\n activeCounter--;\n\n [\"focus\", \"change\", \"blur\", \"input\", \"keydown\"].forEach((type) => {\n this._searchInput.removeEventListener(type, this);\n });\n [\"mousemove\", \"mouseleave\"].forEach((type) => {\n this._dropElement.removeEventListener(type, this);\n });\n\n const clearControl = this._getClearControl();\n if (clearControl) {\n clearControl.removeEventListener(\"click\", this);\n }\n\n // only remove if there are no more active elements\n if (this._config.fixed && activeCounter <= 0) {\n document.removeEventListener(\"scroll\", this, true);\n window.removeEventListener(\"resize\", this);\n }\n\n this._dropElement.parentElement.removeChild(this._dropElement);\n\n INSTANCE_MAP.delete(this._searchInput);\n }\n\n _getClearControl() {\n if (this._config.clearControl) {\n return document.querySelector(this._config.clearControl);\n }\n }\n\n /**\n * @link https://github.com/lifaon74/events-polyfill/issues/10\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\n * @param {Event} event\n */\n handleEvent = (event) => {\n // debounce scroll and resize\n const debounced = [\"scroll\", \"resize\"];\n if (debounced.includes(event.type)) {\n if (this._timer) window.cancelAnimationFrame(this._timer);\n this._timer = window.requestAnimationFrame(() => {\n this[`on${event.type}`](event);\n });\n } else {\n this[`on${event.type}`](event);\n }\n };\n\n /**\n * @param {Config|Object} config\n */\n _configure(config = {}) {\n this._config = Object.assign({}, DEFAULTS);\n\n // Handle options, using arguments first and data attr as override\n const o = { ...config, ...this._searchInput.dataset };\n\n // Allow 1/0, true/false as strings\n const parseBool = (value) => [\"true\", \"false\", \"1\", \"0\", true, false].includes(value) && !!JSON.parse(value);\n\n // Typecast provided options based on defaults types\n for (const [key, defaultValue] of Object.entries(DEFAULTS)) {\n // Check for undefined keys\n if (o[key] === void 0) {\n continue;\n }\n const value = o[key];\n switch (typeof defaultValue) {\n case \"number\":\n this._config[key] = parseInt(value);\n break;\n case \"boolean\":\n this._config[key] = parseBool(value);\n break;\n case \"string\":\n this._config[key] = value.toString();\n break;\n case \"object\":\n // Arrays have a type object in js\n if (Array.isArray(defaultValue)) {\n if (typeof value === \"string\") {\n const separator = value.includes(\"|\") ? \"|\" : \",\";\n this._config[key] = value.split(separator);\n } else {\n this._config[key] = value;\n }\n } else {\n this._config[key] = typeof value === \"string\" ? JSON.parse(value) : value;\n }\n break;\n case \"function\":\n this._config[key] = typeof value === \"string\" ? window[value] : value;\n break;\n default:\n this._config[key] = value;\n break;\n }\n }\n }\n\n // #endregion\n\n // #region Html\n\n _configureSearchInput() {\n this._searchInput.autocomplete = \"off\";\n this._searchInput.spellcheck = false;\n // note: firefox doesn't support the properties so we use attributes\n // @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-autocomplete\n // @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded\n // use the aria-expanded state on the element with role combobox to communicate that the list is displayed.\n attrs(this._searchInput, {\n \"aria-autocomplete\": \"list\",\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": \"false\",\n role: \"combobox\",\n });\n\n // Even with autocomplete \"off\" we can get suggestion from browser due to label\n if (this._searchInput.id && this._config.preventBrowserAutocomplete) {\n const label = document.querySelector(`[for=\"${this._searchInput.id}\"]`);\n if (label) {\n zwijit(label);\n }\n }\n\n // Hidden input?\n this._hiddenInput = null;\n if (this._config.hiddenInput) {\n this._hiddenInput = document.createElement(\"input\");\n this._hiddenInput.type = \"hidden\";\n this._hiddenInput.value = this._config.hiddenValue;\n this._hiddenInput.name = this._searchInput.name;\n this._searchInput.name = \"_\" + this._searchInput.name;\n insertAfter(this._searchInput, this._hiddenInput);\n }\n }\n\n _configureDropElement() {\n this._dropElement = document.createElement(\"ul\");\n this._dropElement.id = \"ac-menu-\" + counter;\n this._dropElement.classList.add(...[\"dropdown-menu\", \"autocomplete-menu\", \"p-0\"]);\n this._dropElement.style.maxHeight = \"280px\";\n if (!this._config.fullWidth) {\n this._dropElement.style.maxWidth = \"360px\";\n }\n if (this._config.fixed) {\n this._dropElement.style.position = \"fixed\";\n }\n this._dropElement.style.overflowY = \"auto\";\n // Prevent scrolling the menu from scrolling the page\n // @link https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior\n this._dropElement.style.overscrollBehavior = \"contain\";\n this._dropElement.style.textAlign = \"unset\"; // otherwise RTL is not good\n\n insertAfter(this._searchInput, this._dropElement);\n // include aria-controls with the value of the id of the suggested list of values.\n this._searchInput.setAttribute(\"aria-controls\", this._dropElement.id);\n }\n\n // #endregion\n\n // #region Events\n\n onclick(e) {\n if (e.target.matches(this._config.clearControl)) {\n this.clear();\n }\n }\n\n oninput(e) {\n if (this._preventInput) {\n return;\n }\n // Input has changed, clear value\n if (this._hiddenInput) {\n this._hiddenInput.value = null;\n }\n this.showOrSearch();\n }\n\n onchange(e) {\n const search = this._searchInput.value;\n const item = Object.values(this._items).find((item) => item.label === search);\n this._config.onChange(item, this);\n }\n\n onblur(e) {\n const related = e.relatedTarget;\n // Clicking on the scroll in a modal blur the element incorrectly\n // In chrome >= 127, the related target is the dropdown menu\n if (this._isMouse && related && (related.classList.contains(\"modal\") || related.classList.contains(\"autocomplete-menu\"))) {\n // Restore focus\n this._searchInput.focus();\n return;\n }\n setTimeout(() => {\n this.hideSuggestions();\n }, 100);\n }\n\n onfocus(e) {\n this.showOrSearch();\n }\n\n /**\n * keypress doesn't send arrow keys, so we use keydown\n * @param {KeyboardEvent} e\n */\n onkeydown(e) {\n const key = e.keyCode || e.key;\n switch (key) {\n case 13:\n case \"Enter\":\n if (this.isDropdownVisible()) {\n const selection = this.getSelection();\n if (selection) {\n selection.click();\n }\n if (selection || !this._config.ignoreEnter) {\n e.preventDefault();\n }\n }\n break;\n case 9:\n case \"Tab\":\n if (this.isDropdownVisible() && this._config.tabSelect) {\n const selection = this.getSelection();\n if (selection) {\n selection.click();\n e.preventDefault();\n }\n }\n break;\n case 38:\n case \"ArrowUp\":\n e.preventDefault();\n this._keyboardNavigation = true;\n this._moveSelection(PREV);\n break;\n case 40:\n case \"ArrowDown\":\n e.preventDefault();\n this._keyboardNavigation = true;\n if (this.isDropdownVisible()) {\n this._moveSelection(NEXT);\n } else {\n // show menu regardless of input length\n this.showOrSearch(false);\n }\n break;\n case 27:\n case \"Escape\":\n if (this.isDropdownVisible()) {\n this._searchInput.focus();\n this.hideSuggestions();\n }\n break;\n }\n }\n\n onmousemove(e) {\n this._isMouse = true;\n // Moving the mouse means no longer using keyboard\n this._keyboardNavigation = false;\n }\n\n onmouseleave(e) {\n this._isMouse = false;\n // Remove selection\n this.removeSelection();\n }\n\n onscroll(e) {\n this._positionMenu();\n }\n\n onresize(e) {\n this._positionMenu();\n }\n\n // #endregion\n\n // #region Api\n\n /**\n * @param {String} k\n * @returns {Config}\n */\n getConfig(k = null) {\n if (k !== null) {\n return this._config[k];\n }\n return this._config;\n }\n\n /**\n * @param {String} k\n * @param {*} v\n */\n setConfig(k, v) {\n this._config[k] = v;\n }\n\n setData(src) {\n this._items = {};\n this._addItems(src);\n }\n\n enable() {\n this._searchInput.setAttribute(\"disabled\", \"\");\n }\n\n disable() {\n this._searchInput.removeAttribute(\"disabled\");\n }\n\n /**\n * @returns {boolean}\n */\n isDisabled() {\n return this._searchInput.hasAttribute(\"disabled\") || this._searchInput.disabled || this._searchInput.hasAttribute(\"readonly\");\n }\n\n /**\n * @returns {boolean}\n */\n isDropdownVisible() {\n return this._dropElement.classList.contains(SHOW_CLASS);\n }\n\n clear() {\n this._searchInput.value = \"\";\n if (this._hiddenInput) {\n this._hiddenInput.value = \"\";\n }\n }\n\n // #endregion\n\n // #region Selection management\n\n /**\n * @returns {HTMLElement}\n */\n getSelection() {\n return this._dropElement.querySelector(\"a.\" + ACTIVE_CLASS);\n }\n\n removeSelection() {\n const selection = this.getSelection();\n if (selection) {\n selection.classList.remove(...this._activeClasses());\n }\n }\n\n /**\n * @returns {Array}\n */\n _activeClasses() {\n return [...this._config.activeClasses, ...[ACTIVE_CLASS]];\n }\n\n /**\n * @param {HTMLElement} li\n * @returns {Boolean}\n */\n _isItemEnabled(li) {\n if (li.style.display === \"none\") {\n return false;\n }\n const fc = li.firstElementChild;\n return fc.tagName === \"A\" && !fc.classList.contains(\"disabled\");\n }\n\n /**\n * @param {String} dir\n * @param {*|HTMLElement} sel\n * @returns {HTMLElement}\n */\n _moveSelection(dir = NEXT, sel = null) {\n const active = this.getSelection();\n\n // select first li\n if (!active) {\n // no active selection, cannot go back\n if (dir === PREV) {\n return sel;\n }\n // find first enabled item\n if (!sel) {\n sel = this._dropElement.firstChild;\n while (sel && !this._isItemEnabled(sel)) {\n sel = sel[\"nextSibling\"];\n }\n }\n } else {\n const sibling = dir === NEXT ? \"nextSibling\" : \"previousSibling\";\n\n // Iterate over enabled li\n sel = active.parentNode;\n do {\n sel = sel[sibling];\n } while (sel && !this._isItemEnabled(sel));\n\n // We have a new selection\n if (sel) {\n // Change classes\n active.classList.remove(...this._activeClasses());\n\n // Scroll if necessary\n if (dir === PREV) {\n // Don't use scrollIntoView as it scrolls the whole window\n sel.parentNode.scrollTop = sel.offsetTop - sel.parentNode.offsetTop;\n } else {\n // This is the equivalent of scrollIntoView(false) but only for parent node\n if (sel.offsetTop > sel.parentNode.offsetHeight - sel.offsetHeight) {\n sel.parentNode.scrollTop += sel.offsetHeight;\n }\n }\n } else if (active) {\n sel = active.parentElement;\n }\n }\n\n if (sel) {\n const a = sel.querySelector(\"a\");\n a.classList.add(...this._activeClasses());\n this._searchInput.setAttribute(\"aria-activedescendant\", a.id);\n if (this._config.updateOnSelect) {\n this._searchInput.value = a.dataset.label;\n }\n } else {\n this._searchInput.setAttribute(\"aria-activedescendant\", \"\");\n }\n return sel;\n }\n\n // #endregion\n\n // #region Implementation\n\n /**\n * Do we have enough input to show suggestions ?\n * @returns {Boolean}\n */\n _shouldShow() {\n if (this.isDisabled()) {\n return false;\n }\n return this._searchInput.value.length >= this._config.suggestionsThreshold;\n }\n\n /**\n * Show suggestions or load them\n * @param {Boolean} check\n */\n showOrSearch(check = true) {\n if (check && !this._shouldShow()) {\n this.hideSuggestions();\n return;\n }\n if (this._config.liveServer) {\n this._searchFunc();\n } else if (this._config.source) {\n this._config.source(this._searchInput.value, (items) => {\n this.setData(items);\n this._showSuggestions();\n });\n } else {\n this._showSuggestions();\n }\n }\n\n /**\n * @param {String} name\n * @returns {HTMLElement}\n */\n _createGroup(name) {\n const newChild = this._createLi();\n const newChildSpan = document.createElement(\"span\");\n newChild.append(newChildSpan);\n newChildSpan.classList.add(...[\"dropdown-header\", \"text-truncate\"]);\n newChildSpan.innerHTML = name;\n return newChild;\n }\n\n /**\n * @param {String} lookup\n * @param {Object} item\n * @returns {HTMLElement}\n */\n _createItem(lookup, item) {\n let label = item.label;\n\n if (this._config.highlightTyped) {\n const idx = normalize(label).indexOf(lookup);\n if (idx !== -1) {\n label =\n label.substring(0, idx) +\n `${label.substring(idx, idx + lookup.length)}` +\n label.substring(idx + lookup.length, label.length);\n }\n }\n\n label = this._config.onRenderItem(item, label, this);\n\n const newChild = this._createLi();\n const newChildLink = document.createElement(\"a\");\n newChild.append(newChildLink);\n newChildLink.id = this._dropElement.id + \"-\" + this._dropElement.children.length;\n newChildLink.classList.add(...[\"dropdown-item\", \"text-truncate\"]);\n if (this._config.itemClass) {\n newChildLink.classList.add(...this._config.itemClass.split(\" \"));\n }\n newChildLink.setAttribute(\"data-value\", item.value);\n newChildLink.setAttribute(\"data-label\", item.label);\n // Behave like a datalist (tab doesn't allow item selection)\n // @link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist\n newChildLink.setAttribute(\"tabindex\", \"-1\");\n newChildLink.setAttribute(\"role\", \"menuitem\");\n newChildLink.setAttribute(\"href\", \"#\");\n newChildLink.innerHTML = label;\n if (item.data) {\n for (const [key, value] of Object.entries(item.data)) {\n newChildLink.dataset[key] = value;\n }\n }\n\n if (this._config.fillIn) {\n const fillIn = document.createElement(\"button\");\n fillIn.type = \"button\"; // prevent submit\n fillIn.classList.add(...[\"btn\", \"btn-link\", \"border-0\"]);\n fillIn.innerHTML = `\n \n `;\n newChild.append(fillIn);\n newChild.classList.add(...[\"d-flex\", \"justify-content-between\"]);\n fillIn.addEventListener(\"click\", (event) => {\n this._searchInput.value = item.label;\n this._searchInput.focus(); // focus back to keep editing\n });\n }\n\n // Hover sets active item\n newChildLink.addEventListener(\"mouseenter\", (event) => {\n // Don't trigger enter if using arrows or not currently using the mouse\n if (this._keyboardNavigation || !this._isMouse) {\n return;\n }\n this.removeSelection();\n newChild.querySelector(\"a\").classList.add(...this._activeClasses());\n });\n // Prevent searchInput losing focus and close the menu\n newChildLink.addEventListener(\"mousedown\", (event) => {\n event.preventDefault();\n });\n // Apply value\n newChildLink.addEventListener(\"click\", (event) => {\n event.preventDefault();\n\n // Prevent input otherwise it might trigger autocomplete due to value change\n this._preventInput = true;\n this._searchInput.value = decodeHtml(item.label);\n // Populate value in hidden input\n if (this._hiddenInput) {\n this._hiddenInput.value = item.value;\n }\n this._config.onSelectItem(item, this);\n this.hideSuggestions();\n this._preventInput = false;\n });\n\n return newChild;\n }\n\n /**\n * Show drop menu with suggestions\n */\n _showSuggestions() {\n // It's not focused anymore\n if (document.activeElement != this._searchInput) {\n return;\n }\n const lookup = normalize(this._searchInput.value);\n this._dropElement.innerHTML = \"\";\n\n const keys = Object.keys(this._items);\n let count = 0;\n let firstItem = null;\n\n const groups = [];\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const entry = this._items[key];\n\n // Check search length since we can trigger dropdown with arrow\n const showAllSuggestions = this._config.showAllSuggestions || lookup.length === 0;\n // Do we find a matching string or do we display immediately ?\n let isMatched = lookup.length == 0 && this._config.suggestionsThreshold === 0;\n if (!showAllSuggestions && lookup.length > 0) {\n // match on any field\n this._config.searchFields.forEach((sf) => {\n const text = normalize(entry[sf]);\n let found = false;\n if (this._config.fuzzy) {\n found = fuzzyMatch(text, lookup);\n } else {\n const idx = text.indexOf(lookup);\n found = this._config.startsWith ? idx === 0 : idx >= 0;\n }\n if (found) {\n isMatched = true;\n }\n });\n }\n const selectFirst = isMatched || lookup.length === 0;\n if (showAllSuggestions || isMatched) {\n count++;\n\n // Group\n if (entry.group && !groups.includes(entry.group)) {\n const newItem = this._createGroup(entry.group);\n this._dropElement.appendChild(newItem);\n groups.push(entry.group);\n }\n\n const newItem = this._createItem(lookup, entry);\n // Only select as first item if its matching or no lookup\n if (!firstItem && selectFirst) {\n firstItem = newItem;\n }\n this._dropElement.appendChild(newItem);\n if (this._config.maximumItems > 0 && count >= this._config.maximumItems) {\n break;\n }\n }\n }\n\n if (firstItem && this._config.autoselectFirst) {\n this.removeSelection();\n this._moveSelection(NEXT, firstItem);\n }\n\n if (count === 0) {\n if (this._config.notFoundMessage) {\n const newChild = this._createLi();\n newChild.innerHTML = `${this._config.notFoundMessage}`;\n this._dropElement.appendChild(newChild);\n this._showDropdown();\n } else {\n // Remove dropdown if not found\n this.hideSuggestions();\n }\n } else {\n // Or show it if necessary\n this._showDropdown();\n }\n }\n\n /**\n * @returns {HTMLLIElement}\n */\n _createLi() {\n const newChild = document.createElement(\"li\");\n newChild.setAttribute(\"role\", \"presentation\");\n return newChild;\n }\n\n /**\n * Show and position dropdown\n */\n _showDropdown() {\n this._dropElement.classList.add(SHOW_CLASS);\n // Register role when shown to avoid empty children issues\n this._dropElement.setAttribute(\"role\", \"menu\");\n attrs(this._searchInput, {\n \"aria-expanded\": \"true\",\n });\n this._positionMenu();\n }\n\n /**\n * Show or hide suggestions\n * @param {Boolean} check\n */\n toggleSuggestions(check = true) {\n if (this._dropElement.classList.contains(SHOW_CLASS)) {\n this.hideSuggestions();\n } else {\n this.showOrSearch(check);\n }\n }\n\n /**\n * Hide the dropdown menu\n */\n hideSuggestions() {\n this._dropElement.classList.remove(SHOW_CLASS);\n attrs(this._searchInput, {\n \"aria-expanded\": \"false\",\n });\n this.removeSelection();\n }\n\n /**\n * @returns {HTMLInputElement}\n */\n getInput() {\n return this._searchInput;\n }\n\n /**\n * @returns {HTMLUListElement}\n */\n getDropMenu() {\n return this._dropElement;\n }\n\n /**\n * Position the dropdown menu\n */\n _positionMenu() {\n const styles = window.getComputedStyle(this._searchInput);\n const bounds = this._searchInput.getBoundingClientRect();\n const isRTL = styles.direction === \"rtl\";\n const fullWidth = this._config.fullWidth;\n const fixed = this._config.fixed;\n\n // Don't position left if not fixed since it may not work in all situations\n // due to offsetParent margin or in tables\n let left = null;\n let top = null;\n\n if (fixed) {\n left = bounds.x;\n top = bounds.y + bounds.height;\n\n // Align end\n if (isRTL && !fullWidth) {\n left -= this._dropElement.offsetWidth - bounds.width;\n }\n }\n\n // Reset any height overflow adjustement\n this._dropElement.style.transform = \"unset\";\n\n // Use full holder width\n if (fullWidth) {\n this._dropElement.style.width = this._searchInput.offsetWidth + \"px\";\n }\n\n // Position element\n if (left !== null) {\n this._dropElement.style.left = left + \"px\";\n }\n if (top !== null) {\n this._dropElement.style.top = top + \"px\";\n }\n\n // Overflow height\n const dropBounds = this._dropElement.getBoundingClientRect();\n const h = window.innerHeight;\n\n // We display above input if it overflows\n if (dropBounds.y + dropBounds.height > h) {\n // We need to add the offset twice\n const topOffset = fullWidth ? bounds.height + 4 : bounds.height;\n // In chrome, we need 100.1% to avoid blurry text\n // @link https://stackoverflow.com/questions/32034574/font-looks-blurry-after-translate-in-chrome\n this._dropElement.style.transform = \"translateY(calc(-100.1% - \" + topOffset + \"px))\";\n }\n }\n\n _fetchData() {\n this._items = {};\n\n // From an array of items or an object\n this._addItems(this._config.items);\n\n // From a datalist\n const dl = this._config.datalist;\n if (dl) {\n const datalist = document.querySelector(`#${dl}`);\n if (datalist) {\n const items = Array.from(datalist.children).map((o) => {\n const value = o.getAttribute(\"value\") ?? o.innerHTML.toLowerCase();\n const label = o.innerHTML;\n\n return {\n value,\n label,\n };\n });\n this._addItems(items);\n } else {\n console.error(`Datalist not found ${dl}`);\n }\n }\n this._setHiddenVal();\n\n // From an external source\n if (this._config.server && !this._config.liveServer) {\n this._loadFromServer();\n }\n }\n\n _setHiddenVal() {\n if (this._config.hiddenInput && !this._config.hiddenValue) {\n for (const [value, entry] of Object.entries(this._items)) {\n if (entry.label == this._searchInput.value) {\n this._hiddenInput.value = value;\n }\n }\n }\n }\n\n /**\n * @param {Array|Object} src An array of items or a value:label object\n */\n _addItems(src) {\n const keys = Object.keys(src);\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const entry = src[key];\n\n if (entry.group && entry.items) {\n entry.items.forEach((e) => (e.group = entry.group));\n this._addItems(entry.items);\n continue;\n }\n\n const label = typeof entry === \"string\" ? entry : entry.label;\n const item = typeof entry !== \"object\" ? {} : entry;\n\n // Normalize entry\n item.label = entry[this._config.labelField] ?? label;\n item.value = entry[this._config.valueField] ?? key;\n\n // Make sure we have a label\n if (item.label) {\n this._items[item.value] = item;\n }\n }\n }\n\n /**\n * @param {boolean} show\n */\n _loadFromServer(show = false) {\n if (this._abortController) {\n this._abortController.abort();\n }\n this._abortController = new AbortController();\n\n // Read data params dynamically as well\n let extraParams = this._searchInput.dataset.serverParams || {};\n if (typeof extraParams == \"string\") {\n extraParams = JSON.parse(extraParams);\n }\n const params = Object.assign({}, this._config.serverParams, extraParams);\n // Pass current value\n params[this._config.queryParam] = this._searchInput.value;\n // Prevent caching\n if (this._config.noCache) {\n params.t = Date.now();\n }\n // We have a related field\n if (params.related) {\n /**\n * @type {HTMLInputElement}\n */\n //@ts-ignore\n const input = document.getElementById(params.related);\n if (input) {\n params.related = input.value;\n const inputName = input.getAttribute(\"name\");\n if (inputName) {\n params[inputName] = input.value;\n }\n }\n }\n\n const urlParams = new URLSearchParams(params);\n let url = this._config.server;\n let fetchOptions = Object.assign(this._config.fetchOptions, {\n method: this._config.serverMethod || \"GET\",\n signal: this._abortController.signal,\n });\n\n if (fetchOptions.method === \"POST\") {\n fetchOptions.body = urlParams;\n } else {\n url += \"?\" + urlParams.toString();\n }\n\n this._searchInput.classList.add(LOADING_CLASS);\n this._config.onBeforeFetch(this);\n\n fetch(url, fetchOptions)\n .then((r) => this._config.onServerResponse(r, this))\n .then((suggestions) => {\n const data = nested(this._config.serverDataKey, suggestions) || suggestions;\n this.setData(data);\n this._setHiddenVal();\n this._abortController = null;\n if (show) {\n this._showSuggestions();\n }\n })\n .catch((e) => {\n this._config.onServerError(e, this._abortController.signal, this);\n })\n .finally((e) => {\n this._searchInput.classList.remove(LOADING_CLASS);\n this._config.onAfterFetch(this);\n });\n }\n\n // #endregion\n}\n\nexport default Autocomplete;\n"], + "mappings": "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", "names": ["DEFAULTS", "item", "label", "inst", "response", "e", "signal", "LOADING_CLASS", "ACTIVE_CLASS", "SHOW_CLASS", "NEXT", "PREV", "INSTANCE_MAP", "counter", "activeCounter", "debounce", "func", "timeout", "timer", "args", "removeDiacritics", "str", "normalize", "fuzzyMatch", "lookup", "pos", "i", "c", "insertAfter", "el", "newEl", "decodeHtml", "html", "txt", "attrs", "k", "v", "zwijit", "char", "nested", "obj", "r", "p", "Autocomplete", "config", "_searchInput", "_configure", "_isMouse", "_preventInput", "_keyboardNavigation", "_searchFunc", "_loadFromServer", "_config", "_configureSearchInput", "_configureDropElement", "clearControl", "_getClearControl", "type", "_dropElement", "_fetchData", "selector", "event", "_timer", "o", "parseBool", "value", "key", "defaultValue", "separator", "_hiddenInput", "search", "_items", "related", "selection", "_moveSelection", "_positionMenu", "src", "_addItems", "_activeClasses", "_isItemEnabled", "li", "fc", "dir", "sel", "active", "sibling", "a", "_shouldShow", "check", "items", "_showSuggestions", "_createGroup", "name", "newChild", "_createLi", "newChildSpan", "_createItem", "idx", "newChildLink", "fillIn", "keys", "count", "firstItem", "groups", "entry", "showAllSuggestions", "isMatched", "sf", "text", "found", "selectFirst", "newItem", "_showDropdown", "styles", "bounds", "isRTL", "fullWidth", "fixed", "left", "top", "dropBounds", "h", "topOffset", "dl", "datalist", "_setHiddenVal", "show", "_abortController", "extraParams", "params", "input", "inputName", "urlParams", "url", "fetchOptions", "suggestions", "data", "autocomplete_default"] }