From 12b61b475f943987788fa794c4531ac35de6ef0e Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 15 Jun 2023 19:18:21 +0200 Subject: [PATCH] build min file --- package.json | 2 +- tags.min.js | 2 +- tags.min.js.map | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 46071c4..79de2c0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bootstrap5-tags", "type": "module", - "version": "1.5.24", + "version": "1.6.0", "description": "Replace select[multiple] with nices badges for Bootstrap 5", "main": "tags", "scripts": { diff --git a/tags.min.js b/tags.min.js index 077a568..0d3e927 100644 --- a/tags.min.js +++ b/tags.min.js @@ -1,2 +1,2 @@ -var F={allowNew:!1,showAllSuggestions:!1,badgeStyle:"primary",allowClear:!1,clearEnd:!1,selected:[],regex:"",separator:[],max:0,clearLabel:"Clear",searchLabel:"Type a value",keepOpen:!1,allowSame:!1,baseClass:"",placeholder:"",addOnBlur:!1,showDisabled:!1,hideNativeValidation:!1,suggestionsThreshold:1,maximumItems:0,autoselectFirst:!0,updateOnSelect:!1,highlightTyped:!1,fullWidth:!1,fixed:!1,fuzzy:!1,activeClasses:["bg-primary","text-white"],labelField:"label",valueField:"value",searchFields:["label"],queryParam:"query",server:"",serverMethod:"GET",serverParams:{},serverDataKey:"data",fetchOptions:{},liveServer:!1,noCache:!0,debounceTime:300,notFoundMessage:"",onRenderItem:(o,t,e)=>t,onSelectItem:(o,t)=>{},onClearItem:(o,t)=>{},onCreateItem:(o,t)=>{},onBlur:(o,t)=>{},onFocus:(o,t)=>{},onCanAdd:(o,t,e)=>{},onServerResponse:(o,t)=>o.json()},w="tags-",k="is-loading",M="is-active",p="is-invalid",L="show",v="data-value",A="next",E="prev",D="form-control-focus",H="form-placeholder-shown",V="form-control-disabled",x=new WeakMap,N=0;function q(o,t=300){let e;return(...i)=>{clearTimeout(e),e=setTimeout(()=>{o.apply(this,i)},t)}}function z(o,t=null){let e=c("span");document.body.appendChild(e),e.style.fontSize=t||"inherit",e.style.height="auto",e.style.width="auto",e.style.position="absolute",e.style.whiteSpace="no-wrap",e.innerHTML=o;let i=Math.ceil(e.clientWidth);return document.body.removeChild(e),i}function B(o){return o.normalize("NFD").replace(/[\u0300-\u036f]/g,"")}function I(o){return o?B(o.toString()).toLowerCase():""}function W(o,t){if(o.indexOf(t)>=0)return!0;let e=0;for(let i=0;i{this.g(!0)},this.e.debounceTime),this.d=!0,this.F(),this.n=c("div"),this.r=c("div"),this.n.appendChild(this.r),this.i.parentElement.insertBefore(this.n,this.i),this.k(),this.M(),this.D(),this.H(),this.V(),this.resetState(),this.e.fixed&&(document.addEventListener("scroll",this,!0),window.addEventListener("resize",this)),this.s.addEventListener("focus",this),this.s.addEventListener("blur",this),this.s.addEventListener("input",this),this.s.addEventListener("keydown",this),this.l.addEventListener("mousemove",this),this.loadData()}static init(t="select[multiple]",e={}){let i=document.querySelectorAll(t);for(let s=0;s{this[`on${t.type}`](t)})):this[`on${t.type}`](t)}T(t={}){this.e=Object.assign({},F);let e={...t,...this.i.dataset},i=s=>["true","false","1","0",!0,!1].includes(s)&&!!JSON.parse(s);for(let[s,a]of Object.entries(F)){if(e[s]===void 0)continue;let l=e[s];switch(typeof a){case"number":this.e[s]=parseInt(l);break;case"boolean":this.e[s]=i(l);break;case"string":this.e[s]=l.toString();break;case"object":if(Array.isArray(a)){let n=l.includes("|")?"|":",";this.e[s]=typeof l=="string"?l.split(n):l}else this.e[s]=typeof l=="string"?JSON.parse(l):l;break;case"function":this.e[s]=typeof l=="string"?l.split(".").reduce((n,r)=>n[r],window):l,this.e[s]||console.error("Invalid function",l);break;default:this.e[s]=l;break}}this.e.placeholder||(this.e.placeholder=this.N())}config(t=null){return t?this.e[t]:this.e}F(){for(this.overflowParent=null,this.parentForm=this.i.parentElement;this.parentForm&&(this.parentForm.style.overflow==="hidden"&&(this.overflowParent=this.parentForm),this.parentForm=this.parentForm.parentElement,!(this.parentForm&&this.parentForm.nodeName=="FORM")););this.parentForm&&this.parentForm.addEventListener("reset",this)}N(){if(this.i.hasAttribute("placeholder"))return this.i.getAttribute("placeholder");if(this.i.dataset.placeholder)return this.i.dataset.placeholder;let t=this.i.querySelector("option");return!t||!this.e.autoselectFirst?"":(S(t,"selected"),t.value?"":t.textContent)}D(){this.e.hideNativeValidation?(this.i.style.position="absolute",this.i.style.left="-9999px"):this.i.style.cssText="height:1px;width:1px;opacity:0;padding:0;margin:0;border:0;float:left;flex-basis:100%;",this.i.tabIndex=-1,this.i.addEventListener("focus",t=>{this.onclick(t)}),this.i.addEventListener("invalid",t=>{this.n.classList.add(p)})}V(){this.l=c("ul"),this.l.classList.add("dropdown-menu",w+"menu","p-0"),this.l.id=w+"menu-"+N,this.l.setAttribute("role","menu");let t=this.l.style;t.maxHeight="280px",this.e.fullWidth||(t.maxWidth="360px"),this.e.fixed&&(t.position="fixed"),t.overflowY="auto",t.overscrollBehavior="contain",t.textAlign="unset",this.l.addEventListener("mouseenter",e=>{this.h=!1}),this.n.appendChild(this.l),this.s.setAttribute("aria-controls",this.l.id)}k(){this.n.classList.add("form-control","dropdown"),this.i.classList.contains("form-select-lg")&&this.n.classList.add("form-control-lg"),this.i.classList.contains("form-select-sm")&&this.n.classList.add("form-control-sm"),this.overflowParent&&(this.n.style.position="inherit"),this.w()===4&&(this.n.style.height="auto"),this.n.addEventListener("click",this)}M(){this.r.addEventListener("click",i=>{this.isDisabled()||this.s.style.visibility!="hidden"&&this.s.focus()});let t=this.r.style;t.display="flex",t.alignItems="center",t.flexWrap="wrap";let e=this.i.selectedOptions||[];for(let i=0;i{this.o&&this.o.abort();let e=!0;if(this.e.addOnBlur&&this.s.value&&(e=this.A()),this.n.classList.remove(D),this.hideSuggestions(e),this.d){let i=this.getSelection(),s={selection:i?i.dataset.value:null,input:this.s.value};this.e.onBlur(t,this),this.i.dispatchEvent(new CustomEvent("tags.blur",{bubbles:!0,detail:s}))}},100)}oninput(t){let e=this.s.value;if(e){let i=e.slice(-1);if(this.e.separator.length&&this.e.separator.includes(i)){this.s.value=this.s.value.slice(0,-1);let s=this.s.value,a=s,l={};if(this.e.allowNew)l.new=1;else{let n=this.getSelection();if(!n)return;s=n.getAttribute(v),a=n.dataset.label}this.u(a,s,l);return}}setTimeout(()=>{this.a()}),this.showOrSearch()}onkeydown(t){let e=t.keyCode||t.key,i=t.target;switch(t.keyCode==229&&(e=i.value.charAt(i.selectionStart-1).charCodeAt(0)),e){case 13:case"Enter":t.preventDefault(),this.A();break;case 38:case"ArrowUp":t.preventDefault(),this.h=!0,this.m(E);break;case 40:case"ArrowDown":t.preventDefault(),this.h=!0,this.isDropdownVisible()?this.m(A):this.showOrSearch(!1);break;case 8:case"Backspace":this.s.value.length==0&&(this.removeLastItem(),this.a(),this.showOrSearch());break;case 27:case"Escape":this.s.focus(),this.hideSuggestions();break}}onmousemove(t){this.h=!1}onscroll(t){this.b()}onresize(t){this.b()}onclick(t=null){t&&t.preventDefault(),!(this.isSingle()||this.isMaxReached())&&this.s.focus()}onreset(t){this.reset()}loadData(){this.e.server?this.e.liveServer||this.g():this.resetSuggestions()}resetState(){this.isDisabled()?(this.n.setAttribute("readonly",""),this.s.setAttribute("disabled",""),this.n.classList.add(V)):(S(this.n,"readonly"),S(this.s,"disabled"),this.n.classList.remove(V))}resetSuggestions(){let t=Array.from(this.i.children).filter(e=>e instanceof HTMLOptGroupElement||!e.disabled||this.e.showDisabled).map(e=>e instanceof HTMLOptGroupElement?{group:e.getAttribute("label"),items:e.children}:{value:e.getAttribute("value"),label:e.textContent,disabled:e.disabled,data:Object.assign(e.dataset)});this.C(t)}A(){let t=this.getSelection();if(t)return t.click(),!0;if(this.e.allowNew&&this.s.value){let e=this.s.value;return!!this.u(e,e,{new:1})}return!1}g(t=!1){this.o&&this.o.abort(),this.o=new AbortController;let e=Object.assign({},this.e.serverParams);if(e[this.e.queryParam]=this.s.value,this.e.noCache&&(e.t=Date.now()),e.related){let l=document.getElementById(e.related);if(l){e.related=l.value;let n=l.getAttribute("name");n&&(e[n]=l.value)}}let i=new URLSearchParams(e),s=this.e.server,a=Object.assign(this.e.fetchOptions,{method:this.e.serverMethod||"GET",signal:this.o.signal});a.method==="POST"?a.body=i:s+="?"+i.toString(),this.n.classList.add(k),fetch(s,a).then(l=>this.e.onServerResponse(l,this)).then(l=>{let n=l[this.e.serverDataKey]||l;this.C(n),this.o=null,t&&this.v()}).catch(l=>{l.name!=="AbortError"&&console.error(l)}).finally(l=>{this.n.classList.remove(k)})}u(t,e=null,i={}){if(!this.canAdd(t,i))return null;let s=this.addItem(t,e,i);return this.e.keepOpen?this.v():this.resetSearchInput(),s}f(t){if(t.style.display==="none")return!1;let e=t.firstElementChild;return e.tagName==="A"&&!e.classList.contains("disabled")}m(t=A,e=null){let i=this.getSelection();if(i){let s=t===A?"nextSibling":"previousSibling";e=i.parentNode;do e=e[s];while(e&&!this.f(e));e?i.classList.remove(...this.c()):i&&(e=i.parentElement)}else{if(t===E)return e;if(!e)for(e=this.l.firstChild;e&&!this.f(e);)e=e.nextSibling}if(e){let s=e.offsetHeight,a=e.offsetTop,l=e.parentNode,n=l.offsetHeight,r=l.scrollHeight,h=l.offsetTop;if(s===0&&setTimeout(()=>{l.scrollTop=0}),t===E){let u=a-h>10?a-h:0;l.scrollTop=u}else a+s-(n+l.scrollTop)>0&&s>0&&(l.scrollTop=a+s-n+1,l.scrollTop+n>=r-10&&(l.scrollTop=a-h));let d=e.querySelector("a");d.classList.add(...this.c()),this.s.setAttribute("aria-activedescendant",d.id),this.e.updateOnSelect&&(this.s.value=d.dataset.label,this.a())}else this.s.setAttribute("aria-activedescendant","");return e}a(){this.n.classList.remove(H),this.s.value?this.s.size=this.s.value.length:this.getSelectedValues().length?(this.s.placeholder="",this.s.size=1):(this.s.size=this.e.placeholder.length>0?this.e.placeholder.length:1,this.s.placeholder=this.e.placeholder,this.n.classList.add(H));let t=this.s.value||this.s.placeholder,e=window.getComputedStyle(this.n).fontSize,i=z(t,e)+16;this.s.style.width=i+"px"}C(t){for(;this.l.lastChild;)this.l.removeChild(this.l.lastChild);let e=0,i=1;for(let s=0;s',this.l.appendChild(s)}}E(t,e){if(!t[this.e.valueField])return;let i=t[this.e.valueField],s=t[this.e.labelField];if(this.e.server&&!this.e.liveServer&&(t.selected||this.e.selected.includes(i))){let r=this.u(s,i,t.data);r&&(r.dataset.init="true")}let a=this.e.onRenderItem(t,s,this),l=c("li");l.setAttribute("role","presentation"),t.group_id&&l.setAttribute("data-group-id",""+t.group_id);let n=c("a");l.append(n),n.id=this.l.id+"-"+e,n.classList.add("dropdown-item","text-truncate"),t.disabled&&n.classList.add("disabled"),n.setAttribute(v,i),n.dataset.label=s,this.e.searchFields.forEach(r=>{l.dataset[r]=t[r]}),n.setAttribute("href","#"),n.innerHTML=a,this.l.appendChild(l),n.addEventListener("mouseenter",r=>{this.h||(this.removeSelection(),l.querySelector("a").classList.add(...this.c()))}),n.addEventListener("mousedown",r=>{r.preventDefault()}),n.addEventListener("click",r=>{r.preventDefault(),this.u(s,i,t.data),this.e.onSelectItem(t,this)})}initialOptions(){return this.i.querySelectorAll("option[data-init]")}reset(){this.removeAll(),this.d=!1;let t=this.initialOptions();for(let e=0;ee.value)}getAvailableValues(){let t=this.i.querySelectorAll("option");return Array.from(t).map(e=>e.value)}showOrSearch(t=!0){if(t&&!this.R()){this.hideSuggestions(!1);return}this.e.liveServer?this.O():this.v()}hideSuggestions(t=!0){this.l.classList.remove(L),y(this.s,{"aria-expanded":"false"}),this.removeSelection(),t&&this.n.classList.remove(p)}toggleSuggestions(t=!0,e=!0){this.l.classList.contains(L)?this.hideSuggestions(e):this.showOrSearch(t)}R(){return this.isDisabled()||this.e.maximumItems>0&&this.getSelectedValues().length>=this.e.maximumItems?!1:this.s.value.length>=this.e.suggestionsThreshold}v(){if(document.activeElement!=this.s||this.s.style.visibility=="hidden")return;let t=I(this.s.value),e=this.getSelectedValues(),i=this.l.querySelectorAll("li"),s=0,a=null,l=!1,n={};for(let r=0;r0&&this.e.searchFields.forEach(m=>{let b=I(d.dataset[m]);(this.e.fuzzy?W(b,t):b.indexOf(t)>=0)&&(f=!0)});let T=f||t.length===0;if(u||f?(s++,R(h),h.dataset.groupId&&(n[h.dataset.groupId]=!0),!a&&this.f(h)&&T&&(a=h),this.e.maximumItems>0&&s>this.e.maximumItems&&C(h)):C(h),this.e.highlightTyped){let m=d.textContent,b=I(m).indexOf(t),O=m.substring(0,b)+`${m.substring(b,b+t.length)}`+m.substring(b+t.length,m.length);d.innerHTML=O}this.f(h)&&(l=!0)}if(!this.e.allowNew&&!(t.length===0&&!l)&&this.n.classList.add(p),this.e.allowNew&&this.e.regex&&this.isInvalid()&&this.n.classList.remove(p),Array.from(i).filter(r=>r.dataset.id).forEach(r=>{n[r.dataset.id]===!0&&R(r)}),l&&(this.n.classList.remove(p),a&&this.e.autoselectFirst&&(this.removeSelection(),this.m(A,a))),s===0)if(this.e.notFoundMessage){let r=this.l.querySelector("."+w+"not-found");r.style.display="block";let h=this.e.notFoundMessage.replace("{{tag}}",this.s.value);r.innerHTML=`${h}`,this.I()}else this.hideSuggestions(!1);else this.I()}I(){this.l.classList.add(L),y(this.s,{"aria-expanded":"true"}),this.b()}b(){let t=window.getComputedStyle(this.s),e=this.s.getBoundingClientRect(),i=t.direction==="rtl",s=null,a=null;if(this.e.fixed?(this.e.fullWidth?s=this.n.getBoundingClientRect().x:s=e.x,a=e.y+e.height):this.e.fullWidth?s=0:s=this.s.offsetLeft,i&&!this.e.fullWidth&&(s-=this.l.offsetWidth-e.width),!this.e.fullWidth){let r=Math.min(window.innerWidth,document.body.offsetWidth),h=i?e.x+e.width-this.l.offsetWidth-1:r-1-(e.x+this.l.offsetWidth);h<0&&(s=i?s-h:s+h)}this.l.style.transform="unset",this.e.fullWidth&&(this.l.style.width=this.n.offsetWidth+"px"),s!==null&&(this.l.style.left=s+"px"),a!==null&&(this.l.style.top=a+"px");let l=this.l.getBoundingClientRect(),n=window.innerHeight;l.y+l.height>n&&(this.l.style.transform="translateY(calc(-100% - "+this.s.offsetHeight+"px))")}w(){let t=5;return window.jQuery&&$.fn.tooltip!=null&&$.fn.tooltip.Constructor!=null&&(t=parseInt($.fn.tooltip.Constructor.VERSION.charAt(0))),t}q(t){let e=Array.from(this.i.querySelectorAll("option")).find(i=>i.textContent==t);return!!(e&&e.getAttribute("selected"))}z(t){return new RegExp(this.e.regex.trim()).test(t)}getSelection(){return this.l.querySelector("a."+M)}removeSelection(){let t=this.getSelection();t&&t.classList.remove(...this.c())}c(){return[...this.e.activeClasses,M]}getActiveSelection(){return this.getSelection()}removeActiveSelection(){return this.removeSelection()}removeAll(){this.getSelectedValues().forEach(e=>{this.removeItem(e,!0)}),this.a()}removeLastItem(t=!1){let e=this.r.querySelectorAll("span:not(.disabled)");if(!e.length)return;let i=e[e.length-1];this.removeItem(i.getAttribute(v),t)}enable(){this.i.setAttribute("disabled",""),this.resetState()}disable(){S(this.i,"disabled"),this.resetState()}isDisabled(){return this.i.hasAttribute("disabled")||this.i.disabled||this.i.hasAttribute("readonly")}isDropdownVisible(){return this.l.classList.contains(L)}isInvalid(){return this.n.classList.contains(p)}isSingle(){return!this.i.hasAttribute("multiple")}isMaxReached(){return this.e.max&&this.getSelectedValues().length>=this.e.max}canAdd(t,e={}){return!t||this.isDisabled()||!this.isSingle()&&!this.e.allowSame&&this.q(t)||this.isMaxReached()?!1:this.e.regex&&e.new&&!this.z(t)?(this.n.classList.add(p),!1):this.e.onCanAdd&&this.e.onCanAdd(t,e,this)===!1?(this.n.classList.add(p),!1):!0}addItem(t,e=null,i={}){e||(e=t),this.isSingle()&&this.getSelectedValues().length&&this.removeLastItem(!0);let s=CSS.escape(e),a=this.i.querySelectorAll('option[value="'+s+'"]'),l=null;if(this.e.allowSame?a.forEach(r=>{r.textContent===t&&!r.selected&&(l=r)}):l=a[0]||null,!l){l=c("option"),l.value=e,l.textContent=t;for(let[r,h]of Object.entries(i))l.dataset[r]=h;this.i.appendChild(l),this.e.onCreateItem(l,this)}l&&(i=Object.assign({title:l.getAttribute("title")},i,l.dataset)),l.setAttribute("selected","selected"),l.selected=!0;let n=this.i.innerHTML;return this.i.innerHTML="",this.i.innerHTML=n,this.L(t,e,i),this.d&&this.i.dispatchEvent(new Event("change",{bubbles:!0})),l}L(t,e=null,i={}){let s=this.w(),a=this.e.allowClear&&!i.disabled,l=t,n=c("span"),r=["badge"],h=this.e.badgeStyle;if(i.badgeStyle&&(h=i.badgeStyle),i.badgeClass&&r.push(...i.badgeClass.split(" ")),this.e.baseClass?r.push(...this.e.baseClass.split(" ")):s===5?r=[...r,"bg-"+h,"mw-100","overflow-x-hidden"]:r=[...r,"badge-"+h],i.disabled&&r.push("disabled","opacity-50"),n.style.margin="2px 6px 2px 0px",n.style.marginBlock="2px",n.style.marginInline="0px 6px",n.classList.add(...r),n.setAttribute(v,e),i.title&&n.setAttribute("title",i.title),a){let d=r.includes("text-dark")?"btn-close":"btn-close-white",u,f;this.e.clearEnd?(u=s===5?"ms-2":"ml-2",f=s===5?"float-end":"float:right;"):(u=s===5?"me-2":"mr-2",f=s===5?"float-start":"float:left;"),l=(s===5?'':'')+l}n.innerHTML=l,this.r.insertBefore(n,this.s),window.bootstrap&&window.bootstrap.Tooltip&&window.bootstrap.Tooltip.getOrCreateInstance(n),a&&n.querySelector("button").addEventListener("click",d=>{d.preventDefault(),d.stopPropagation(),this.isDisabled()||(this.removeItem(e),document.activeElement.blur(),this.a())})}removeItem(t,e=!1){let i=CSS.escape(t),s=this.r.querySelector("span["+v+'="'+i+'"]');if(!s)return;s.remove();let a=this.i.querySelector('option[value="'+i+'"][selected]');a&&(S(a,"selected"),a.selected=!1,this.d&&!e&&this.i.dispatchEvent(new Event("change",{bubbles:!0}))),this.s.style.visibility=="hidden"&&!this.isMaxReached()&&(this.s.style.visibility="visible"),e||this.e.onClearItem(t,this)}},P=g;export{P as default}; +var k={items:[],allowNew:!1,showAllSuggestions:!1,badgeStyle:"primary",allowClear:!1,clearEnd:!1,selected:[],regex:"",separator:[],max:0,clearLabel:"Clear",searchLabel:"Type a value",keepOpen:!1,allowSame:!1,baseClass:"",placeholder:"",addOnBlur:!1,showDisabled:!1,hideNativeValidation:!1,suggestionsThreshold:-1,maximumItems:0,autoselectFirst:!0,updateOnSelect:!1,highlightTyped:!1,fullWidth:!1,fixed:!1,fuzzy:!1,singleBadge:!1,activeClasses:["bg-primary","text-white"],labelField:"label",valueField:"value",searchFields:["label"],queryParam:"query",server:"",serverMethod:"GET",serverParams:{},serverDataKey:"data",fetchOptions:{},liveServer:!1,noCache:!0,debounceTime:300,notFoundMessage:"",onRenderItem:(o,t,e)=>t,onSelectItem:(o,t)=>{},onClearItem:(o,t)=>{},onCreateItem:(o,t)=>{},onBlur:(o,t)=>{},onFocus:(o,t)=>{},onCanAdd:(o,t,e)=>{},onServerResponse:(o,t)=>o.json()},v="tags-",D="is-loading",M="is-active",m="is-invalid",A="show",b="data-value",x="next",I="prev",H="form-control-focus",N="form-placeholder-shown",V="form-control-disabled",C=new WeakMap,q=0,T=0;function R(o,t=300){let e;return(...s)=>{clearTimeout(e),e=setTimeout(()=>{o.apply(this,s)},t)}}function z(o,t=null){let e=f("span");document.body.appendChild(e),e.style.fontSize=t||"inherit",e.style.height="auto",e.style.width="auto",e.style.position="absolute",e.style.whiteSpace="no-wrap",e.innerHTML=o;let s=Math.ceil(e.clientWidth);return document.body.removeChild(e),s}function W(o){return o.normalize("NFD").replace(/[\u0300-\u036f]/g,"")}function O(o){return o?W(o.toString()).toLowerCase():""}function j(o,t){if(o.indexOf(t)>=0)return!0;let e=0;for(let s=0;s{this.S(!0)},this.e.debounceTime),this.d=!0,this.F(),this.n=f("div"),this.r=f("div"),this.n.appendChild(this.r),this.i.parentElement.insertBefore(this.n,this.i),this.k(),this.D(),this.M(),this.H(),this.N(),this.resetState(),this.e.fixed&&(document.addEventListener("scroll",this,!0),window.addEventListener("resize",this)),this.s.addEventListener("focus",this),this.s.addEventListener("blur",this),this.s.addEventListener("input",this),this.s.addEventListener("keydown",this),this.l.addEventListener("mousemove",this),this.loadData(!0)}static init(t="select[multiple]",e={}){let s=document.querySelectorAll(t);for(let i=0;i{this[`on${t.type}`](t)})):this[`on${t.type}`](t)}T(t={}){this.e=Object.assign({},k);let e=this.i.dataset.config?JSON.parse(this.i.dataset.config):{},s={...t,...e,...this.i.dataset};for(let[i,r]of Object.entries(k)){if(i=="config"||s[i]===void 0)continue;let n=s[i];switch(typeof r){case"number":this.e[i]=parseInt(n);break;case"boolean":this.e[i]=P(n);break;case"string":this.e[i]=n.toString();break;case"object":this.e[i]=n,typeof n=="string"&&(["{","["].includes(n[0])?this.e[i]=JSON.parse(n):this.e[i]=n.split(n.includes("|")?"|":","));break;case"function":this.e[i]=typeof n=="string"?n.split(".").reduce((l,a)=>l[a],window):n,this.e[i]||console.error("Invalid function",n);break;default:this.e[i]=n;break}}this.e.placeholder||(this.e.placeholder=this.V()),this.e.suggestionsThreshold==-1&&(this.e.suggestionsThreshold=this.e.liveServer?1:0)}config(t=null){return t?this.e[t]:this.e}setConfig(t,e){this.e[t]=e}F(){for(this.overflowParent=null,this.parentForm=this.i.parentElement;this.parentForm&&(this.parentForm.style.overflow==="hidden"&&(this.overflowParent=this.parentForm),this.parentForm=this.parentForm.parentElement,!(this.parentForm&&this.parentForm.nodeName=="FORM")););this.parentForm&&this.parentForm.addEventListener("reset",this)}V(){if(this.i.hasAttribute("placeholder"))return this.i.getAttribute("placeholder");if(this.i.dataset.placeholder)return this.i.dataset.placeholder;let t=this.i.querySelector("option");return!t||!this.e.autoselectFirst?"":(S(t,"selected"),t.selected=!1,t.value?"":t.textContent)}M(){this.e.hideNativeValidation?(this.i.style.position="absolute",this.i.style.left="-9999px"):this.i.style.cssText="height:1px;width:1px;opacity:0;padding:0;margin:0;border:0;float:left;flex-basis:100%;",this.i.tabIndex=-1,this.i.addEventListener("focus",t=>{this.onclick(t)}),this.i.addEventListener("invalid",t=>{this.n.classList.add(m)})}N(){this.l=f("ul"),this.l.classList.add("dropdown-menu",v+"menu"),this.l.id=v+"menu-"+q,this.l.setAttribute("role","menu");let t=this.l.style;t.padding="0",t.maxHeight="280px",this.e.fullWidth||(t.maxWidth="360px"),this.e.fixed&&(t.position="fixed"),t.overflowY="auto",t.overscrollBehavior="contain",t.textAlign="unset",this.l.addEventListener("mouseenter",e=>{this.h=!1}),this.n.appendChild(this.l),this.s.setAttribute("aria-controls",this.l.id)}k(){this.n.classList.add("form-control","dropdown"),this.i.classList.contains("form-select-lg")&&this.n.classList.add("form-control-lg"),this.i.classList.contains("form-select-sm")&&this.n.classList.add("form-control-sm"),this.overflowParent&&(this.n.style.position="inherit"),this.L()===4&&(this.n.style.height="auto"),this.e.suggestionsThreshold==0&&this.n.classList.add("form-select"),this.n.addEventListener("click",this)}D(){this.r.addEventListener("click",e=>{this.isDisabled()||this.s.style.visibility!="hidden"&&this.s.focus()});let t=this.r.style;t.display="flex",t.alignItems="center",t.flexWrap="wrap"}H(){this.s=f("input"),this.s.type="text",this.s.autocomplete="field-"+Date.now(),this.s.spellcheck=!1,L(this.s,{"aria-auto-complete":"list","aria-has-popup":"menu","aria-expanded":"false","aria-label":this.e.searchLabel,role:"combobox"}),this.s.style.cssText="background-color:transparent;color:currentColor;border:0;padding:0;outline:0;max-width:100%",this.resetSearchInput(!0),this.r.appendChild(this.s),this.q=window.getComputedStyle(this.s).direction==="rtl"}onfocus(t){this.n.classList.add(H),this.showOrSearch(),this.e.onFocus(t,this)}onblur(t){this.o&&this.o.abort();let e=!0;if(this.e.addOnBlur&&this.s.value&&(e=this.A()),this.n.classList.remove(H),this.hideSuggestions(e),this.d){let s=this.getSelection(),i={selection:s?s.dataset.value:null,input:this.s.value};this.e.onBlur(t,this),this.i.dispatchEvent(new CustomEvent("tags.blur",{bubbles:!0,detail:i}))}}oninput(t){let e=this.s.value;if(e){let s=e.slice(-1);if(this.e.separator.length&&this.e.separator.includes(s)){this.s.value=this.s.value.slice(0,-1);let i=this.s.value,r=i,n={};if(this.e.allowNew)n.new=1;else{let l=this.getSelection();if(!l)return;i=l.getAttribute(b),r=l.dataset.label}this.f(r,i,n);return}}setTimeout(()=>{this.a()}),this.showOrSearch()}onkeydown(t){let e=t.keyCode||t.key,s=t.target;switch(t.keyCode==229&&(e=s.value.charAt(s.selectionStart-1).charCodeAt(0)),e){case 13:case"Enter":t.preventDefault(),this.A();break;case 38:case"ArrowUp":t.preventDefault(),this.h=!0,this.p(I);break;case 40:case"ArrowDown":t.preventDefault(),this.h=!0,this.isDropdownVisible()?this.p(x):this.showOrSearch(!1);break;case 8:case"Backspace":this.s.value.length==0&&(this.removeLastItem(),this.a(),this.showOrSearch());break;case 27:case"Escape":this.s.focus(),this.hideSuggestions();break}}onmousemove(t){this.h=!1}onscroll(t){this.m()}onresize(t){this.m()}onclick(t=null){t&&t.preventDefault(),!(!this.isSingle()&&this.isMaxReached())&&this.s.focus()}onreset(t){this.reset()}loadData(t=!1){Object.keys(this.e.items).length>0?this.setData(this.e.items,!0):this.resetSuggestions(!0),this.e.server&&(this.e.liveServer||this.S(!t))}B(){let t=this.i.selectedOptions||[];for(let e=0;es instanceof HTMLOptGroupElement||!s.disabled||this.e.showDisabled).map(s=>s instanceof HTMLOptGroupElement?{group:s.getAttribute("label"),items:s.children}:{value:s.getAttribute("value"),label:s.textContent,disabled:s.disabled,selected:s.selected,data:Object.assign({},s.dataset)});this.setData(e,t)}A(){let t=this.getSelection();if(t)return t.click(),!0;if(this.e.allowNew&&this.s.value){let e=this.s.value;return!!this.f(e,e,{new:1})}return!1}S(t=!1){this.o&&this.o.abort(),this.o=new AbortController;let e=Object.assign({},this.e.serverParams);if(e[this.e.queryParam]=this.s.value,this.e.noCache&&(e.t=Date.now()),e.related){let n=document.getElementById(e.related);if(n){e.related=n.value;let l=n.getAttribute("name");l&&(e[l]=n.value)}}let s=new URLSearchParams(e),i=this.e.server,r=Object.assign(this.e.fetchOptions,{method:this.e.serverMethod||"GET",signal:this.o.signal});r.method==="POST"?r.body=s:i+="?"+s.toString(),this.n.classList.add(D),fetch(i,r).then(n=>this.e.onServerResponse(n,this)).then(n=>{let l=n[this.e.serverDataKey]||n;this.setData(l,!t),this.o=null,t&&this.g()}).catch(n=>{n.name!=="AbortError"&&console.error(n)}).finally(n=>{this.n.classList.remove(D)})}f(t,e=null,s={}){if(!this.canAdd(t,s))return null;let i=this.addItem(t,e,s);return this.b(),this.e.keepOpen?this.g():this.resetSearchInput(),i}u(t){if(t.style.display==="none")return!1;let e=t.firstElementChild;return e.tagName==="A"&&!e.classList.contains("disabled")}p(t=x,e=null){let s=this.getSelection();if(s){let i=t===x?"nextSibling":"previousSibling";e=s.parentNode;do e=e[i];while(e&&!this.u(e));e?s.classList.remove(...this.c()):s&&(e=s.parentElement)}else{if(t===I)return e;if(!e)for(e=this.l.firstChild;e&&!this.u(e);)e=e.nextSibling}if(e){let i=e.offsetHeight,r=e.offsetTop,n=e.parentNode,l=n.offsetHeight,a=n.scrollHeight,h=n.offsetTop;if(i===0&&setTimeout(()=>{n.scrollTop=0}),t===I){let c=r-h>10?r-h:0;n.scrollTop=c}else r+i-(l+n.scrollTop)>0&&i>0&&(n.scrollTop=r+i-l+1,n.scrollTop+l>=a-10&&(n.scrollTop=r-h));let d=e.querySelector("a");d.classList.add(...this.c()),this.s.setAttribute("aria-activedescendant",d.id),this.e.updateOnSelect&&(this.s.value=d.dataset.label,this.a())}else this.s.setAttribute("aria-activedescendant","");return e}a(){this.n.classList.remove(N),this.s.value?this.s.size=this.s.value.length:this.getSelectedValues().length?(this.s.placeholder="",this.s.size=1):(this.s.size=this.e.placeholder.length>0?this.e.placeholder.length:1,this.s.placeholder=this.e.placeholder,this.n.classList.add(N));let t=this.s.value||this.s.placeholder,e=window.getComputedStyle(this.n).fontSize,s=z(t,e)+16;this.s.style.width=s+"px"}R(t){for(;this.l.lastChild;)this.l.removeChild(this.l.lastChild);let e=0,s=1;for(let i=0;i',this.l.appendChild(i)}}C(t,e){if(!t[this.e.valueField])return;let s=t[this.e.valueField],i=t[this.e.labelField],r=this.e.onRenderItem(t,i,this),n=f("li");n.setAttribute("role","presentation"),t.group_id&&n.setAttribute("data-group-id",""+t.group_id);let l=f("a");n.append(l),l.id=this.l.id+"-"+e,l.classList.add("dropdown-item","text-truncate"),t.disabled&&l.classList.add("disabled"),l.setAttribute(b,s),l.dataset.label=i,this.e.searchFields.forEach(a=>{n.dataset[a]=t[a]}),l.setAttribute("href","#"),l.innerHTML=r,this.l.appendChild(n),l.addEventListener("mouseenter",a=>{this.h||(this.removeSelection(),n.querySelector("a").classList.add(...this.c()))}),l.addEventListener("mousedown",a=>{a.preventDefault()}),l.addEventListener("click",a=>{a.preventDefault(),a.stopPropagation(),this.f(i,s,t.data),this.e.onSelectItem(t,this)})}initialOptions(){return this.i.querySelectorAll("option[data-init]")}E(){this.i.querySelectorAll("option").forEach(t=>{S(t,"selected")})}reset(){this.removeAll(),this.d=!1;let t=this.initialOptions();this.E();for(let e=0;ee.value)}getAvailableValues(){let t=this.i.querySelectorAll("option");return Array.from(t).map(e=>e.value)}showOrSearch(t=!0){if(t&&!this.z()){this.hideSuggestions(!1);return}this.e.liveServer?this.O():this.g()}hideSuggestions(t=!0){this.l.classList.remove(A),L(this.s,{"aria-expanded":"false"}),this.removeSelection(),t&&this.n.classList.remove(m)}toggleSuggestions(t=!0,e=!0){this.l.classList.contains(A)?this.hideSuggestions(e):this.showOrSearch(t)}z(){return this.isDisabled()||this.e.maximumItems>0&&this.getSelectedValues().length>=this.e.maximumItems?!1:this.s.value.length>=this.e.suggestionsThreshold}g(){if(document.activeElement!=this.s||this.s.style.visibility=="hidden")return;let t=O(this.s.value),e={},s=this.l.querySelectorAll("li"),i=0,r=null,n=!1,l={};for(let a=0;a0&&this.e.searchFields.forEach(u=>{let p=O(d.dataset[u]);(this.e.fuzzy?j(p,t):p.indexOf(t)>=0)&&(g=!0)});let w=g||t.length===0;if(c||g?(i++,B(h),h.dataset.groupId&&(l[h.dataset.groupId]=!0),!r&&this.u(h)&&w&&(r=h),this.e.maximumItems>0&&i>this.e.maximumItems&&E(h)):E(h),this.e.highlightTyped){let u=d.textContent,p=O(u).indexOf(t),F=u.substring(0,p)+`${u.substring(p,p+t.length)}`+u.substring(p+t.length,u.length);d.innerHTML=F}this.u(h)&&(n=!0)}if(!this.e.allowNew&&!(t.length===0&&!n)&&this.n.classList.add(m),this.e.allowNew&&this.e.regex&&this.isInvalid()&&this.n.classList.remove(m),Array.from(s).filter(a=>a.dataset.id).forEach(a=>{l[a.dataset.id]===!0&&B(a)}),n&&(this.n.classList.remove(m),r&&this.e.autoselectFirst&&(this.removeSelection(),this.p(x,r))),i===0)if(this.e.notFoundMessage){let a=this.l.querySelector("."+v+"not-found");a.style.display="block";let h=this.e.notFoundMessage.replace("{{tag}}",this.s.value);a.innerHTML=`${h}`,this.I()}else this.hideSuggestions(!1);else this.I()}I(){this.l.classList.add(A),L(this.s,{"aria-expanded":"true"}),this.m()}m(){let t=this.q,e=this.s.getBoundingClientRect(),s=null,i=null;if(this.e.fixed?(this.e.fullWidth?s=this.n.getBoundingClientRect().x:s=e.x,i=e.y+e.height):this.e.fullWidth?s=0:s=this.s.offsetLeft,t&&!this.e.fullWidth&&(s-=this.l.offsetWidth-e.width),!this.e.fullWidth){let l=Math.min(window.innerWidth,document.body.offsetWidth),a=t?e.x+e.width-this.l.offsetWidth-1:l-1-(e.x+this.l.offsetWidth);a<0&&(s=t?s-a:s+a)}this.l.style.transform="unset",this.e.fullWidth&&(this.l.style.width=this.n.offsetWidth+"px"),s!==null&&(this.l.style.left=s+"px"),i!==null&&(this.l.style.top=i+"px");let r=this.l.getBoundingClientRect(),n=window.innerHeight;r.y+r.height>n&&(this.l.style.transform="translateY(calc(-100% - "+this.s.offsetHeight+"px))")}L(){let t=5;return window.jQuery&&$.fn.tooltip!=null&&$.fn.tooltip.Constructor!=null&&(t=parseInt($.fn.tooltip.Constructor.VERSION.charAt(0))),t}W(t){return!!Array.from(this.i.querySelectorAll("option")).find(s=>s.textContent==t&&s.getAttribute("selected"))}j(t){return!!Array.from(this.i.querySelectorAll("option")).find(s=>s.textContent==t&&!s.getAttribute("selected"))}P(t){return new RegExp(this.e.regex.trim()).test(t)}getSelection(){return this.l.querySelector("a."+M)}removeSelection(){let t=this.getSelection();t&&t.classList.remove(...this.c())}c(){return[...this.e.activeClasses,M]}getActiveSelection(){return this.getSelection()}removeActiveSelection(){return this.removeSelection()}removeAll(){this.getSelectedValues().forEach(e=>{this.removeItem(e,!0)}),this.a()}removeLastItem(t=!1){let e=this.r.querySelectorAll("span."+v+"badge");if(!e.length)return;let s=e[e.length-1];this.removeItem(s.getAttribute(b),t)}enable(){this.i.setAttribute("disabled",""),this.resetState()}disable(){S(this.i,"disabled"),this.resetState()}isDisabled(){return this.i.hasAttribute("disabled")||this.i.disabled||this.i.hasAttribute("readonly")}isDropdownVisible(){return this.l.classList.contains(A)}isInvalid(){return this.n.classList.contains(m)}isSingle(){return!this.i.hasAttribute("multiple")}isMaxReached(){return this.e.max&&this.getSelectedValues().length>=this.e.max}canAdd(t,e={}){return!t||e.new&&!this.e.allowNew||this.isDisabled()||!this.isSingle()&&!this.e.allowSame&&(e.new&&this.W(t)||!e.new&&!this.j(t))||this.isMaxReached()?!1:this.e.regex&&e.new&&!this.P(t)?(this.n.classList.add(m),!1):this.e.onCanAdd&&this.e.onCanAdd(t,e,this)===!1?(this.n.classList.add(m),!1):!0}setData(t,e=!1){Array.isArray(t)||(t=Object.entries(t).map(([s,i])=>({value:s,label:i}))),e&&(this.E(),t.forEach(s=>{let i=s[this.e.valueField],r=s[this.e.labelField];if(i&&(s.selected||this.e.selected.includes(i))){let n=this.addItem(r,i,s.data);n&&n.setAttribute("data-init","true")}})),this.R(t),this.b()}v(t,e="",s=0){let r='option[value="'+CSS.escape(t)+'"]'+e;return this.i.querySelectorAll(r)[s]||null}addItem(t,e=null,s={}){e||(e=t),this.isSingle()&&this.getSelectedValues().length&&this.removeLastItem(!0);let i=this.v(e,":not([selected])");if(!i){i=f("option"),i.value=e,i.textContent=t;for(let[r,n]of Object.entries(s))i.dataset[r]=n;this.i.appendChild(i),this.e.onCreateItem(i,this)}return i&&(s=Object.assign({title:i.getAttribute("title")},s,i.dataset)),i.setAttribute("selected","selected"),i.selected=!0,this._(t,e,s),this.d&&this.i.dispatchEvent(new Event("change",{bubbles:!0})),i}b(){let t=this.i.innerHTML;this.i.innerHTML="",this.i.innerHTML=t,this.a()}_(t,e=null,s={}){let i=this.L()===5,r=this.e.allowClear&&!s.disabled,n=t,l=f("span"),a=[v+"badge"],h=this.isSingle()&&!this.e.singleBadge;if(!h){a.push("badge");let c=this.e.badgeStyle;s.badgeStyle&&(c=s.badgeStyle),s.badgeClass&&a.push(...s.badgeClass.split(" ")),this.e.baseClass?a.push(...this.e.baseClass.split(" ")):i?a=[...a,"bg-"+c,"text-truncate"]:a=[...a,"badge-"+c],l.style.maxWidth="100%"}s.disabled&&a.push("disabled","opacity-50");let d=h?0:2;if(l.style.margin=d+"px 6px "+d+"px 0px",l.style.marginBlock=d+"px",l.style.marginInline="0px 6px",l.classList.add(...a),l.setAttribute(b,e),s.title&&l.setAttribute("title",s.title),r){l.style.display="inline-flex",l.style.alignItems="center";let c=a.includes("text-dark")||h?"btn-close":"btn-close btn-close-white",g="margin-inline: 0px 6px;",w="";this.e.clearEnd&&(g="margin-inline: 6px 0px;",w="order:2;"),n=(i?'':'')+n}l.innerHTML=n,this.r.insertBefore(l,this.s),window.bootstrap&&window.bootstrap.Tooltip&&i&&window.bootstrap.Tooltip.getOrCreateInstance(l),r&&l.querySelector("button").addEventListener("click",c=>{c.preventDefault(),c.stopPropagation(),this.isDisabled()||(this.removeItem(e),document.activeElement.blur(),this.a())})}removeItem(t,e=!1){let s=CSS.escape(t),i=this.r.querySelectorAll("span["+b+'="'+s+'"]');if(!i.length)return;let r=i.length-1;i[r].remove();let n=this.v(t,"[selected]",r);n&&(S(n,"selected"),n.selected=!1,this.d&&!e&&this.i.dispatchEvent(new Event("change",{bubbles:!0}))),this.s.style.visibility=="hidden"&&!this.isMaxReached()&&(this.s.style.visibility="visible"),e||this.e.onClearItem(t,this)}},_=y;export{_ as default}; //# sourceMappingURL=tags.min.js.map diff --git a/tags.min.js.map b/tags.min.js.map index 1d505b3..82db377 100644 --- a/tags.min.js.map +++ b/tags.min.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["tags.js"], - "sourcesContent": ["/**\r\n * Bootstrap 5 (and 4!) tags\r\n *\r\n * Turns your select[multiple] into nice tags lists\r\n *\r\n * Required Bootstrap 5 styles:\r\n * - badge\r\n * - background-color utility\r\n * - margin-end utility\r\n * - float-start utility\r\n * - forms\r\n * - dropdown\r\n */\r\n\r\n// #region config\r\n\r\n/**\r\n * @callback EventCallback\r\n * @param {Event} event\r\n * @param {Tags} inst\r\n * @returns {void}\r\n */\r\n\r\n/**\r\n * @callback ServerCallback\r\n * @param {Response} response\r\n * @param {Tags} inst\r\n * @returns {Promise}\r\n */\r\n\r\n/**\r\n * @callback RenderCallback\r\n * @param {Suggestion} item\r\n * @param {String} label\r\n * @param {Tags} inst\r\n * @returns {String}\r\n */\r\n\r\n/**\r\n * @callback ItemCallback\r\n * @param {Suggestion} item\r\n * @param {Tags} inst\r\n * @returns {void}\r\n */\r\n\r\n/**\r\n * @callback ValueCallback\r\n * @param {String} value\r\n * @param {Tags} inst\r\n * @returns {void}\r\n */\r\n\r\n/**\r\n * @callback AddCallback\r\n * @param {String} value\r\n * @param {Object} data\r\n * @param {Tags} inst\r\n * @returns {void|Boolean}\r\n */\r\n\r\n/**\r\n * @callback CreateCallback\r\n * @param {HTMLOptionElement} option\r\n * @param {Tags} inst\r\n * @returns {void}\r\n */\r\n\r\n/**\r\n * @typedef Config\r\n * @property {Boolean} allowNew Allows creation of new tags\r\n * @property {Boolean} showAllSuggestions Show all suggestions even if they don't match. Disables validation.\r\n * @property {String} badgeStyle Color of the badge (color can be configured per option as well)\r\n * @property {Boolean} allowClear Show a clear icon\r\n * @property {Boolean} clearEnd Place clear icon at the end\r\n * @property {Array|String} selected A comma separated list of selected values\r\n * @property {String} regex Regex for new tags\r\n * @property {Array|String} separator A list (pipe separated) of characters that should act as separator (default is using enter key)\r\n * @property {Number} max Limit to a maximum of tags (0 = no limit)\r\n * @property {String} placeholder Provides a placeholder if none are provided as the first empty option\r\n * @property {String} clearLabel Text as clear tooltip\r\n * @property {String} searchLabel Default placeholder\r\n * @property {Boolean} keepOpen Keep suggestions open after selection, clear on focus out\r\n * @property {Boolean} allowSame Allow same tags used multiple times\r\n * @property {String} baseClass Customize the class applied to badges\r\n * @property {Boolean} addOnBlur Add new tags on blur (only if allowNew is enabled)\r\n * @property {Boolean} showDisabled Show disabled tags\r\n * @property {Boolean} hideNativeValidation Hide native validation tooltips\r\n * @property {Number} suggestionsThreshold Number of chars required to show suggestions\r\n * @property {Number} maximumItems Maximum number of items to display\r\n * @property {Boolean} autoselectFirst Always select the first item\r\n * @property {Boolean} updateOnSelect Update input value on selection (doesn't play nice with autoselectFirst)\r\n * @property {Boolean} highlightTyped Highlight matched part of the suggestion\r\n * @property {Boolean} fullWidth Match the width on the input field\r\n * @property {Boolean} fixed Use fixed positioning (solve overflow issues)\r\n * @property {Boolean} fuzzy Fuzzy search\r\n * @property {Array} activeClasses By default: [\"bg-primary\", \"text-white\"]\r\n * @property {String} labelField Key for the label\r\n * @property {String} valueField Key for the value\r\n * @property {Array} searchFields Key for the search\r\n * @property {String} queryParam Name of the param passed to endpoint (query by default)\r\n * @property {String} server Endpoint for data provider\r\n * @property {String} serverMethod HTTP request method for data provider, default is GET\r\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.\r\n * @property {String} serverDataKey By default: data\r\n * @property {Object} fetchOptions Any other fetch options (https://developer.mozilla.org/en-US/docs/Web/API/fetch#syntax)\r\n * @property {Boolean} liveServer Should the endpoint be called each time on input\r\n * @property {Boolean} noCache Prevent caching by appending a timestamp\r\n * @property {Number} debounceTime Debounce time for live server\r\n * @property {String} notFoundMessage Display a no suggestions found message. Leave empty to disable\r\n * @property {RenderCallback} onRenderItem Callback function that returns the suggestion\r\n * @property {ItemCallback} onSelectItem Callback function to call on selection\r\n * @property {ValueCallback} onClearItem Callback function to call on clear\r\n * @property {CreateCallback} onCreateItem Callback function when an item is created\r\n * @property {EventCallback} onBlur Callback function on blur\r\n * @property {EventCallback} onFocus Callback function on focus\r\n * @property {AddCallback} onCanAdd Callback function to validate item. Return false to show validation message.\r\n * @property {ServerCallback} onServerResponse Callback function to process server response. Must return a Promise\r\n */\r\n\r\n/**\r\n * @typedef Suggestion\r\n * @property {String} value Can be overriden by config valueField\r\n * @property {String} label Can be overriden by config labelField\r\n * @property {Boolean} disabled\r\n * @property {Object} data\r\n * @property {Boolean} [selected]\r\n * @property {Number} [group_id]\r\n */\r\n\r\n/**\r\n * @typedef SuggestionGroup\r\n * @property {String} group\r\n * @property {Array} items\r\n */\r\n\r\n/**\r\n * @type {Config}\r\n */\r\nconst DEFAULTS = {\r\n allowNew: false,\r\n showAllSuggestions: false,\r\n badgeStyle: \"primary\",\r\n allowClear: false,\r\n clearEnd: false,\r\n selected: [],\r\n regex: \"\",\r\n separator: [],\r\n max: 0,\r\n clearLabel: \"Clear\",\r\n searchLabel: \"Type a value\",\r\n keepOpen: false,\r\n allowSame: false,\r\n baseClass: \"\",\r\n placeholder: \"\",\r\n addOnBlur: false,\r\n showDisabled: false,\r\n hideNativeValidation: false,\r\n suggestionsThreshold: 1,\r\n maximumItems: 0,\r\n autoselectFirst: true,\r\n updateOnSelect: false,\r\n highlightTyped: false,\r\n fullWidth: false,\r\n fixed: false,\r\n fuzzy: false,\r\n activeClasses: [\"bg-primary\", \"text-white\"],\r\n labelField: \"label\",\r\n valueField: \"value\",\r\n searchFields: [\"label\"],\r\n queryParam: \"query\",\r\n server: \"\",\r\n serverMethod: \"GET\",\r\n serverParams: {},\r\n serverDataKey: \"data\",\r\n fetchOptions: {},\r\n liveServer: false,\r\n noCache: true,\r\n debounceTime: 300,\r\n notFoundMessage: \"\",\r\n onRenderItem: (item, label, inst) => {\r\n return label;\r\n },\r\n onSelectItem: (item, inst) => {},\r\n onClearItem: (value, inst) => {},\r\n onCreateItem: (option, inst) => {},\r\n onBlur: (event, inst) => {},\r\n onFocus: (event, inst) => {},\r\n onCanAdd: (text, data, inst) => {},\r\n onServerResponse: (response, inst) => {\r\n return response.json();\r\n },\r\n};\r\n\r\n// #endregion\r\n\r\n// #region constants\r\n\r\nconst CLASS_PREFIX = \"tags-\";\r\nconst LOADING_CLASS = \"is-loading\";\r\nconst ACTIVE_CLASS = \"is-active\";\r\nconst INVALID_CLASS = \"is-invalid\";\r\nconst SHOW_CLASS = \"show\";\r\nconst VALUE_ATTRIBUTE = \"data-value\";\r\nconst NEXT = \"next\";\r\nconst PREV = \"prev\";\r\nconst FOCUS_CLASS = \"form-control-focus\"; // should match form-control:focus\r\nconst PLACEHOLDER_CLASS = \"form-placeholder-shown\"; // should match :placeholder-shown\r\nconst DISABLED_CLASS = \"form-control-disabled\"; // should match form-control:disabled\r\nconst INSTANCE_MAP = new WeakMap();\r\nlet counter = 0;\r\n\r\n// #endregion\r\n\r\n// #region functions\r\n\r\n/**\r\n * @param {Function} func\r\n * @param {number} timeout\r\n * @returns {Function}\r\n */\r\nfunction debounce(func, timeout = 300) {\r\n let timer;\r\n return (...args) => {\r\n clearTimeout(timer);\r\n timer = setTimeout(() => {\r\n //@ts-ignore\r\n func.apply(this, args);\r\n }, timeout);\r\n };\r\n}\r\n\r\n/**\r\n * @param {string} text\r\n * @param {string} size\r\n * @returns {Number}\r\n */\r\nfunction calcTextWidth(text, size = null) {\r\n const span = ce(\"span\");\r\n document.body.appendChild(span);\r\n span.style.fontSize = size || \"inherit\";\r\n span.style.height = \"auto\";\r\n span.style.width = \"auto\";\r\n span.style.position = \"absolute\";\r\n span.style.whiteSpace = \"no-wrap\";\r\n span.innerHTML = text;\r\n const width = Math.ceil(span.clientWidth);\r\n document.body.removeChild(span);\r\n return width;\r\n}\r\n\r\n/**\r\n * @param {String} str\r\n * @returns {String}\r\n */\r\nfunction removeDiacritics(str) {\r\n return str.normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\");\r\n}\r\n\r\n/**\r\n * @param {String|Number} str\r\n * @returns {String}\r\n */\r\nfunction normalize(str) {\r\n if (!str) {\r\n return \"\";\r\n }\r\n return removeDiacritics(str.toString()).toLowerCase();\r\n}\r\n\r\n/**\r\n * A simple fuzzy match algorithm that checks if chars are matched\r\n * in order in the target string\r\n *\r\n * @param {String} str\r\n * @param {String} lookup\r\n * @returns {Boolean}\r\n */\r\nfunction fuzzyMatch(str, lookup) {\r\n if (str.indexOf(lookup) >= 0) {\r\n return true;\r\n }\r\n let pos = 0;\r\n for (let i = 0; i < lookup.length; i++) {\r\n const c = lookup[i];\r\n if (c == \" \") continue;\r\n pos = str.indexOf(c, pos) + 1;\r\n if (pos <= 0) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} item\r\n */\r\nfunction hideItem(item) {\r\n item.style.display = \"none\";\r\n attrs(item, {\r\n \"aria-hidden\": \"true\",\r\n });\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} item\r\n */\r\nfunction showItem(item) {\r\n item.style.display = \"list-item\";\r\n attrs(item, {\r\n \"aria-hidden\": \"false\",\r\n });\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n * @param {Object} attrs\r\n */\r\nfunction attrs(el, attrs) {\r\n for (const [k, v] of Object.entries(attrs)) {\r\n el.setAttribute(k, v);\r\n }\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n * @param {string} attr\r\n */\r\nfunction rmAttr(el, attr) {\r\n if (el.hasAttribute(attr)) {\r\n el.removeAttribute(attr);\r\n }\r\n}\r\n\r\n/**\r\n * @template {keyof HTMLElementTagNameMap} K\r\n * @param {K|String} tagName Name of the element\r\n * @returns {HTMLElementTagNameMap[K]}\r\n */\r\nfunction ce(tagName) {\r\n //@ts-ignore\r\n return document.createElement(tagName);\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n * @param {HTMLElement} newEl\r\n * @returns {HTMLElement}\r\n */\r\n// function insertAfter(el, newEl) {\r\n// return el.parentNode.insertBefore(newEl, el.nextSibling);\r\n// }\r\n\r\n// #endregion\r\n\r\nclass Tags {\r\n /**\r\n * @param {HTMLSelectElement} el\r\n * @param {Object|Config} config\r\n */\r\n constructor(el, config = {}) {\r\n if (!(el instanceof HTMLElement)) {\r\n console.error(\"Invalid element\", el);\r\n return;\r\n }\r\n INSTANCE_MAP.set(el, this);\r\n counter++;\r\n this._selectElement = el;\r\n this._willBlur = null;\r\n\r\n this._configure(config);\r\n\r\n // private vars\r\n this._keyboardNavigation = false;\r\n this._searchFunc = debounce(() => {\r\n this._loadFromServer(true);\r\n }, this._config.debounceTime);\r\n this._fireEvents = true;\r\n\r\n this._configureParent();\r\n\r\n // Create elements\r\n this._holderElement = ce(\"div\"); // this is the one holding the fake input and the dropmenu\r\n this._containerElement = ce(\"div\"); // this is the one for the fake input (labels + input)\r\n this._holderElement.appendChild(this._containerElement);\r\n\r\n // insert before select, this helps having native validation tooltips positioned properly\r\n this._selectElement.parentElement.insertBefore(this._holderElement, this._selectElement);\r\n // insertAfter(this._selectElement, this._holderElement);\r\n\r\n // Configure them\r\n this._configureHolderElement();\r\n this._configureContainerElement();\r\n this._configureSelectElement();\r\n this._configureSearchInput();\r\n this._configureDropElement();\r\n this.resetState();\r\n\r\n if (this._config.fixed) {\r\n document.addEventListener(\"scroll\", this, true); // capture input for all scrollables elements\r\n window.addEventListener(\"resize\", this);\r\n }\r\n\r\n // Add listeners (remove then on dispose()). See handleEvent.\r\n this._searchInput.addEventListener(\"focus\", this); // focusin bubbles, focus does not.\r\n this._searchInput.addEventListener(\"blur\", this); // focusout bubbles, blur does not.\r\n this._searchInput.addEventListener(\"input\", this);\r\n this._searchInput.addEventListener(\"keydown\", this);\r\n this._dropElement.addEventListener(\"mousemove\", this);\r\n\r\n this.loadData();\r\n }\r\n\r\n // #region Core\r\n\r\n /**\r\n * Attach to all elements matched by the selector\r\n * @param {string} selector\r\n * @param {Object} opts\r\n */\r\n static init(selector = \"select[multiple]\", opts = {}) {\r\n /**\r\n * @type {NodeListOf}\r\n */\r\n let list = document.querySelectorAll(selector);\r\n for (let i = 0; i < list.length; i++) {\r\n if (Tags.getInstance(list[i])) {\r\n continue;\r\n }\r\n new Tags(list[i], opts);\r\n }\r\n }\r\n\r\n /**\r\n * @param {HTMLSelectElement} el\r\n */\r\n static getInstance(el) {\r\n if (INSTANCE_MAP.has(el)) {\r\n return INSTANCE_MAP.get(el);\r\n }\r\n }\r\n\r\n dispose() {\r\n this._searchInput.removeEventListener(\"focus\", this);\r\n this._searchInput.removeEventListener(\"blur\", this);\r\n this._searchInput.removeEventListener(\"input\", this);\r\n this._searchInput.removeEventListener(\"keydown\", this);\r\n this._dropElement.removeEventListener(\"mousemove\", this);\r\n\r\n if (this._config.fixed) {\r\n document.removeEventListener(\"scroll\", this, true);\r\n window.removeEventListener(\"resize\", this);\r\n }\r\n\r\n // restore select, remove our custom stuff and unbind parent\r\n this._selectElement.style.display = \"block\";\r\n this._holderElement.parentElement.removeChild(this._holderElement);\r\n if (this.parentForm) {\r\n this.parentForm.removeEventListener(\"reset\", this);\r\n }\r\n\r\n INSTANCE_MAP.delete(this._selectElement);\r\n }\r\n\r\n /**\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\r\n * @param {Event} event\r\n */\r\n handleEvent(event) {\r\n // debounce scroll and resize\r\n const debounced = [\"scroll\", \"resize\"];\r\n if (debounced.includes(event.type)) {\r\n if (this._timer) window.cancelAnimationFrame(this._timer);\r\n this._timer = window.requestAnimationFrame(() => {\r\n this[`on${event.type}`](event);\r\n });\r\n } else {\r\n this[`on${event.type}`](event);\r\n }\r\n }\r\n\r\n /**\r\n * @param {Config|Object} config\r\n */\r\n _configure(config = {}) {\r\n this._config = Object.assign({}, DEFAULTS);\r\n\r\n // Handle options, using arguments first and data attr as override\r\n const o = { ...config, ...this._selectElement.dataset };\r\n\r\n // Allow 1/0, true/false as strings\r\n const parseBool = (value) => [\"true\", \"false\", \"1\", \"0\", true, false].includes(value) && !!JSON.parse(value);\r\n\r\n // Typecast provided options based on defaults types\r\n for (const [key, defaultValue] of Object.entries(DEFAULTS)) {\r\n // Check for undefined keys\r\n if (o[key] === void 0) {\r\n continue;\r\n }\r\n const value = o[key];\r\n switch (typeof defaultValue) {\r\n case \"number\":\r\n this._config[key] = parseInt(value);\r\n break;\r\n case \"boolean\":\r\n this._config[key] = parseBool(value);\r\n break;\r\n case \"string\":\r\n this._config[key] = value.toString();\r\n break;\r\n case \"object\":\r\n // Arrays have a type object in js\r\n if (Array.isArray(defaultValue)) {\r\n // string separator can be | or ,\r\n const separator = value.includes(\"|\") ? \"|\" : \",\";\r\n this._config[key] = typeof value === \"string\" ? value.split(separator) : value;\r\n } else {\r\n this._config[key] = typeof value === \"string\" ? JSON.parse(value) : value;\r\n }\r\n break;\r\n case \"function\":\r\n this._config[key] = typeof value === \"string\" ? value.split(\".\").reduce((r, p) => r[p], window) : value;\r\n if (!this._config[key]) {\r\n console.error(\"Invalid function\", value);\r\n }\r\n break;\r\n default:\r\n this._config[key] = value;\r\n break;\r\n }\r\n }\r\n\r\n // Dynamic default values\r\n if (!this._config.placeholder) {\r\n this._config.placeholder = this._getPlaceholder();\r\n }\r\n }\r\n\r\n /**\r\n * @param {String} k\r\n * @returns {*}\r\n */\r\n config(k = null) {\r\n return k ? this._config[k] : this._config;\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Html\r\n\r\n /**\r\n * Find overflow parent for positioning\r\n * and bind reset event of the parent form\r\n */\r\n _configureParent() {\r\n this.overflowParent = null;\r\n this.parentForm = this._selectElement.parentElement;\r\n while (this.parentForm) {\r\n if (this.parentForm.style.overflow === \"hidden\") {\r\n this.overflowParent = this.parentForm;\r\n }\r\n this.parentForm = this.parentForm.parentElement;\r\n if (this.parentForm && this.parentForm.nodeName == \"FORM\") {\r\n break;\r\n }\r\n }\r\n if (this.parentForm) {\r\n this.parentForm.addEventListener(\"reset\", this);\r\n }\r\n }\r\n\r\n /**\r\n * @returns {string}\r\n */\r\n _getPlaceholder() {\r\n // Use placeholder and data-placeholder in priority\r\n if (this._selectElement.hasAttribute(\"placeholder\")) {\r\n return this._selectElement.getAttribute(\"placeholder\");\r\n }\r\n if (this._selectElement.dataset.placeholder) {\r\n return this._selectElement.dataset.placeholder;\r\n }\r\n // Fallback to first option if no value\r\n let firstOption = this._selectElement.querySelector(\"option\");\r\n if (!firstOption || !this._config.autoselectFirst) {\r\n return \"\";\r\n }\r\n rmAttr(firstOption, \"selected\");\r\n return !firstOption.value ? firstOption.textContent : \"\";\r\n }\r\n\r\n _configureSelectElement() {\r\n // Hiding the select should keep it focusable, otherwise we get this\r\n // An invalid form control with name='...' is not focusable.\r\n // If it's not focusable, we need to remove the native validation attributes\r\n\r\n // If we use display none, we don't get the focus event\r\n // this._selectElement.style.display = \"none\";\r\n\r\n // If we position it like this, the html5 validation message will not display properly\r\n if (this._config.hideNativeValidation) {\r\n // This position dont break render within input-group and is focusable\r\n this._selectElement.style.position = \"absolute\";\r\n this._selectElement.style.left = \"-9999px\";\r\n } else {\r\n // Hide but keep it focusable. If 0 height, no native validation message will show\r\n // It is placed below so that native tooltip is displayed properly\r\n // Flex basis is required for input-group otherwise it breaks the layout\r\n this._selectElement.style.cssText = `height:1px;width:1px;opacity:0;padding:0;margin:0;border:0;float:left;flex-basis:100%;`;\r\n }\r\n\r\n // Make sure it's not usable using tab\r\n this._selectElement.tabIndex = -1;\r\n\r\n // No need for custom label click event if select is focusable\r\n // const label = document.querySelector('label[for=\"' + this._selectElement.getAttribute(\"id\") + '\"]');\r\n // if (label) {\r\n // label.addEventListener(\"click\", this);\r\n // }\r\n\r\n // It can be focused by clicking on the label\r\n this._selectElement.addEventListener(\"focus\", (event) => {\r\n this.onclick(event);\r\n });\r\n\r\n // When using regular html5 validation, make sure our fake element get the proper class\r\n this._selectElement.addEventListener(\"invalid\", (event) => {\r\n this._holderElement.classList.add(INVALID_CLASS);\r\n });\r\n }\r\n\r\n /**\r\n * Configure drop element\r\n * Needs to be called after searchInput is created\r\n */\r\n _configureDropElement() {\r\n this._dropElement = ce(\"ul\");\r\n this._dropElement.classList.add(...[\"dropdown-menu\", CLASS_PREFIX + \"menu\", \"p-0\"]);\r\n this._dropElement.id = CLASS_PREFIX + \"menu-\" + counter;\r\n this._dropElement.setAttribute(\"role\", \"menu\");\r\n\r\n const dropStyles = this._dropElement.style;\r\n dropStyles.maxHeight = \"280px\";\r\n if (!this._config.fullWidth) {\r\n dropStyles.maxWidth = \"360px\";\r\n }\r\n if (this._config.fixed) {\r\n dropStyles.position = \"fixed\";\r\n }\r\n dropStyles.overflowY = \"auto\";\r\n // Prevent scrolling the menu from scrolling the page\r\n // @link https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior\r\n dropStyles.overscrollBehavior = \"contain\";\r\n dropStyles.textAlign = \"unset\"; // otherwise RTL is not good\r\n\r\n // If the mouse was outside, entering remove keyboard nav mode\r\n this._dropElement.addEventListener(\"mouseenter\", (event) => {\r\n this._keyboardNavigation = false;\r\n });\r\n this._holderElement.appendChild(this._dropElement);\r\n\r\n // include aria-controls with the value of the id of the suggested list of values.\r\n this._searchInput.setAttribute(\"aria-controls\", this._dropElement.id);\r\n }\r\n\r\n _configureHolderElement() {\r\n this._holderElement.classList.add(...[\"form-control\", \"dropdown\"]);\r\n // Reflect size\r\n if (this._selectElement.classList.contains(\"form-select-lg\")) {\r\n this._holderElement.classList.add(\"form-control-lg\");\r\n }\r\n if (this._selectElement.classList.contains(\"form-select-sm\")) {\r\n this._holderElement.classList.add(\"form-control-sm\");\r\n }\r\n // If we have an overflow parent, we can simply inherit styles\r\n if (this.overflowParent) {\r\n this._holderElement.style.position = \"inherit\";\r\n }\r\n if (this._getBootstrapVersion() === 4) {\r\n // Prevent fixed height due to form-control\r\n this._holderElement.style.height = \"auto\";\r\n }\r\n\r\n // Without this, clicking on a floating label won't always focus properly\r\n this._holderElement.addEventListener(\"click\", this);\r\n }\r\n\r\n _configureContainerElement() {\r\n this._containerElement.addEventListener(\"click\", (event) => {\r\n if (this.isDisabled()) {\r\n return;\r\n }\r\n if (this._searchInput.style.visibility != \"hidden\") {\r\n this._searchInput.focus();\r\n }\r\n });\r\n\r\n // Add some extra css to help positioning\r\n const containerStyles = this._containerElement.style;\r\n containerStyles.display = \"flex\";\r\n containerStyles.alignItems = \"center\";\r\n containerStyles.flexWrap = \"wrap\";\r\n\r\n // add initial values\r\n // we use selectedOptions because single select can have a selected option\r\n // without a selected attribute if it's the first value\r\n const initialValues = this._selectElement.selectedOptions || [];\r\n for (let j = 0; j < initialValues.length; j++) {\r\n /**\r\n * @type {HTMLOptionElement}\r\n */\r\n let initialValue = initialValues[j];\r\n if (!initialValue.value) {\r\n continue;\r\n }\r\n\r\n // Enforce selected attr for consistency\r\n initialValue.setAttribute(\"selected\", \"selected\");\r\n\r\n // track initial values for reset\r\n initialValue.dataset.init = \"true\";\r\n if (initialValue.hasAttribute(\"disabled\")) {\r\n initialValue.dataset.disabled = \"true\";\r\n }\r\n\r\n // tooltips\r\n if (initialValue.hasAttribute(\"title\")) {\r\n initialValue.dataset.title = initialValue.getAttribute(\"title\");\r\n }\r\n\r\n this._createBadge(initialValue.textContent, initialValue.value, initialValue.dataset);\r\n }\r\n }\r\n\r\n _configureSearchInput() {\r\n this._searchInput = ce(\"input\");\r\n this._searchInput.type = \"text\";\r\n this._searchInput.autocomplete = \"field-\" + Date.now(); // off is ignored\r\n this._searchInput.spellcheck = false;\r\n // note: firefox doesn't support the properties so we use attributes\r\n // @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-autocomplete\r\n // @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded\r\n // use the aria-expanded state on the element with role combobox to communicate that the list is displayed.\r\n // https://developer.mozilla.org/en-US/docs/Web/API/Element/ariaLabel\r\n attrs(this._searchInput, {\r\n \"aria-auto-complete\": \"list\",\r\n \"aria-has-popup\": \"menu\",\r\n \"aria-expanded\": \"false\",\r\n \"aria-label\": this._config.searchLabel,\r\n role: \"combobox\",\r\n });\r\n this._searchInput.style.cssText = `background-color:transparent;color:currentColor;border:0;padding:0;outline:0;max-width:100%`;\r\n this.resetSearchInput(true);\r\n\r\n this._containerElement.appendChild(this._searchInput);\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Events\r\n\r\n onfocus(event) {\r\n if (this._willBlur) {\r\n clearTimeout(this._willBlur);\r\n }\r\n this._holderElement.classList.add(FOCUS_CLASS);\r\n this.showOrSearch();\r\n this._config.onFocus(event, this);\r\n }\r\n\r\n onblur(event) {\r\n // Prevent focus being triggered when clicking again\r\n this._willBlur = setTimeout(() => {\r\n // Cancel any pending request\r\n if (this._abortController) {\r\n this._abortController.abort();\r\n }\r\n let clearValidation = true;\r\n if (this._config.addOnBlur && this._searchInput.value) {\r\n clearValidation = this._enterValue();\r\n }\r\n this._holderElement.classList.remove(FOCUS_CLASS);\r\n this.hideSuggestions(clearValidation);\r\n if (this._fireEvents) {\r\n const sel = this.getSelection();\r\n const data = {\r\n selection: sel ? sel.dataset.value : null,\r\n input: this._searchInput.value,\r\n };\r\n this._config.onBlur(event, this);\r\n this._selectElement.dispatchEvent(new CustomEvent(\"tags.blur\", { bubbles: true, detail: data }));\r\n }\r\n }, 100);\r\n }\r\n\r\n oninput(ev) {\r\n const data = this._searchInput.value;\r\n\r\n // Add item if a separator is used\r\n // On mobile or copy paste, it can pass multiple chars (eg: when pressing space and it formats the string)\r\n if (data) {\r\n const lastChar = data.slice(-1);\r\n if (this._config.separator.length && this._config.separator.includes(lastChar)) {\r\n // Remove separator even if adding is prevented\r\n this._searchInput.value = this._searchInput.value.slice(0, -1);\r\n let value = this._searchInput.value;\r\n let label = value;\r\n let addData = {};\r\n // There is no good reason to use the separator feature without allowNew, but who knows!\r\n if (!this._config.allowNew) {\r\n const sel = this.getSelection();\r\n if (!sel) {\r\n return;\r\n }\r\n value = sel.getAttribute(VALUE_ATTRIBUTE);\r\n label = sel.dataset.label;\r\n } else {\r\n addData.new = 1;\r\n }\r\n this._add(label, value, addData);\r\n return;\r\n }\r\n }\r\n\r\n // Adjust input width to current content\r\n setTimeout(() => {\r\n this._adjustWidth();\r\n });\r\n\r\n // Check if we should display suggestions\r\n this.showOrSearch();\r\n }\r\n\r\n /**\r\n * keypress doesn't send arrow keys, so we use keydown\r\n * @param {KeyboardEvent} event\r\n */\r\n onkeydown(event) {\r\n // Keycode reference : https://css-tricks.com/snippets/javascript/javascript-keycodes/\r\n let key = event.keyCode || event.key;\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n // @ts-ignore\r\n const target = event.target;\r\n\r\n // Android virtual keyboard might always return 229\r\n if (event.keyCode == 229) {\r\n key = target.value.charAt(target.selectionStart - 1).charCodeAt(0);\r\n }\r\n\r\n // Keyboard keys\r\n switch (key) {\r\n case 13:\r\n case \"Enter\":\r\n event.preventDefault();\r\n this._enterValue();\r\n break;\r\n case 38:\r\n case \"ArrowUp\":\r\n event.preventDefault();\r\n this._keyboardNavigation = true;\r\n this._moveSelection(PREV);\r\n break;\r\n case 40:\r\n case \"ArrowDown\":\r\n event.preventDefault();\r\n this._keyboardNavigation = true;\r\n if (this.isDropdownVisible()) {\r\n this._moveSelection(NEXT);\r\n } else {\r\n // show menu regardless of input length\r\n this.showOrSearch(false);\r\n }\r\n break;\r\n case 8:\r\n case \"Backspace\":\r\n // If the current item is empty, remove the last one\r\n if (this._searchInput.value.length == 0) {\r\n this.removeLastItem();\r\n this._adjustWidth();\r\n this.showOrSearch();\r\n }\r\n break;\r\n case 27:\r\n case \"Escape\":\r\n this._searchInput.focus();\r\n this.hideSuggestions();\r\n break;\r\n }\r\n }\r\n\r\n onmousemove(e) {\r\n // Moving the mouse means no longer using keyboard\r\n this._keyboardNavigation = false;\r\n }\r\n\r\n onscroll(e) {\r\n this._positionMenu();\r\n }\r\n\r\n onresize(e) {\r\n this._positionMenu();\r\n }\r\n\r\n onclick(e = null) {\r\n if (e) {\r\n e.preventDefault();\r\n }\r\n if (this.isSingle() || this.isMaxReached()) {\r\n return;\r\n }\r\n // Focus on input when clicking on element or focusing select\r\n this._searchInput.focus();\r\n }\r\n\r\n onreset(e) {\r\n this.reset();\r\n }\r\n\r\n // #endregion\r\n\r\n loadData() {\r\n if (this._config.server) {\r\n if (this._config.liveServer) {\r\n // No need to load anything since it will happen when typing\r\n } else {\r\n this._loadFromServer();\r\n }\r\n } else {\r\n this.resetSuggestions();\r\n }\r\n }\r\n\r\n resetState() {\r\n if (this.isDisabled()) {\r\n this._holderElement.setAttribute(\"readonly\", \"\");\r\n this._searchInput.setAttribute(\"disabled\", \"\");\r\n this._holderElement.classList.add(DISABLED_CLASS);\r\n } else {\r\n rmAttr(this._holderElement, \"readonly\");\r\n rmAttr(this._searchInput, \"disabled\");\r\n this._holderElement.classList.remove(DISABLED_CLASS);\r\n }\r\n }\r\n\r\n resetSuggestions() {\r\n let suggestions = Array.from(this._selectElement.children)\r\n .filter(\r\n /**\r\n * @param {HTMLOptionElement|HTMLOptGroupElement} option\r\n */\r\n (option) => {\r\n return option instanceof HTMLOptGroupElement || !option.disabled || this._config.showDisabled;\r\n }\r\n )\r\n .map(\r\n /**\r\n * @param {HTMLOptionElement|HTMLOptGroupElement} option\r\n */\r\n (option) => {\r\n if (option instanceof HTMLOptGroupElement) {\r\n return {\r\n group: option.getAttribute(\"label\"),\r\n items: option.children,\r\n };\r\n }\r\n return {\r\n value: option.getAttribute(\"value\"),\r\n label: option.textContent,\r\n disabled: option.disabled,\r\n data: Object.assign(option.dataset),\r\n };\r\n }\r\n );\r\n this._buildSuggestions(suggestions);\r\n }\r\n\r\n /**\r\n * Try to add the current value\r\n * @returns {Boolean}\r\n */\r\n _enterValue() {\r\n let selection = this.getSelection();\r\n if (selection) {\r\n selection.click();\r\n return true;\r\n } else {\r\n // We use what is typed if not selected and not empty\r\n if (this._config.allowNew && this._searchInput.value) {\r\n let text = this._searchInput.value;\r\n const el = this._add(text, text, { new: 1 });\r\n return el ? true : false;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * @param {Boolean} show\r\n */\r\n _loadFromServer(show = false) {\r\n if (this._abortController) {\r\n this._abortController.abort();\r\n }\r\n this._abortController = new AbortController();\r\n\r\n const params = Object.assign({}, this._config.serverParams);\r\n // Pass current value\r\n params[this._config.queryParam] = this._searchInput.value;\r\n // Prevent caching\r\n if (this._config.noCache) {\r\n params.t = Date.now();\r\n }\r\n // We have a related field\r\n if (params.related) {\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n //@ts-ignore\r\n const input = document.getElementById(params.related);\r\n if (input) {\r\n params.related = input.value;\r\n const inputName = input.getAttribute(\"name\");\r\n if (inputName) {\r\n params[inputName] = input.value;\r\n }\r\n }\r\n }\r\n\r\n const urlParams = new URLSearchParams(params);\r\n let url = this._config.server;\r\n let fetchOptions = Object.assign(this._config.fetchOptions, {\r\n method: this._config.serverMethod || \"GET\",\r\n signal: this._abortController.signal,\r\n });\r\n\r\n if (fetchOptions.method === \"POST\") {\r\n fetchOptions.body = urlParams;\r\n } else {\r\n url += \"?\" + urlParams.toString();\r\n }\r\n\r\n this._holderElement.classList.add(LOADING_CLASS);\r\n fetch(url, fetchOptions)\r\n .then((r) => this._config.onServerResponse(r, this))\r\n .then((suggestions) => {\r\n const data = suggestions[this._config.serverDataKey] || suggestions;\r\n\r\n // initial suggestions\r\n this._buildSuggestions(data);\r\n this._abortController = null;\r\n if (show) {\r\n this._showSuggestions();\r\n }\r\n })\r\n .catch((e) => {\r\n if (e.name === \"AbortError\") {\r\n return;\r\n }\r\n console.error(e);\r\n })\r\n .finally((e) => {\r\n this._holderElement.classList.remove(LOADING_CLASS);\r\n });\r\n }\r\n\r\n /**\r\n * Wrapper for the public addItem method that check if the item\r\n * can be added\r\n *\r\n * @param {string} text\r\n * @param {string} value\r\n * @param {object} data\r\n * @return {HTMLOptionElement|null}\r\n */\r\n _add(text, value = null, data = {}) {\r\n if (!this.canAdd(text, data)) {\r\n return null;\r\n }\r\n const el = this.addItem(text, value, data);\r\n if (this._config.keepOpen) {\r\n this._showSuggestions();\r\n } else {\r\n this.resetSearchInput();\r\n }\r\n return el;\r\n }\r\n\r\n /**\r\n * @param {HTMLElement} li\r\n * @returns {Boolean}\r\n */\r\n _isItemEnabled(li) {\r\n if (li.style.display === \"none\") {\r\n return false;\r\n }\r\n const fc = li.firstElementChild;\r\n return fc.tagName === \"A\" && !fc.classList.contains(\"disabled\");\r\n }\r\n\r\n /**\r\n * @param {String} dir\r\n * @param {*|HTMLElement} sel\r\n * @returns {HTMLElement}\r\n */\r\n _moveSelection(dir = NEXT, sel = null) {\r\n const active = this.getSelection();\r\n\r\n // select first li if visible\r\n if (!active) {\r\n // no active selection, cannot go back\r\n if (dir === PREV) {\r\n return sel;\r\n }\r\n // find first enabled item\r\n if (!sel) {\r\n sel = this._dropElement.firstChild;\r\n while (sel && !this._isItemEnabled(sel)) {\r\n sel = sel[\"nextSibling\"];\r\n }\r\n }\r\n } else {\r\n const sibling = dir === NEXT ? \"nextSibling\" : \"previousSibling\";\r\n\r\n // Iterate over visible li\r\n sel = active.parentNode;\r\n do {\r\n sel = sel[sibling];\r\n } while (sel && !this._isItemEnabled(sel));\r\n\r\n // We have a new selection\r\n if (sel) {\r\n // Remove classes from current active\r\n active.classList.remove(...this._activeClasses());\r\n } else if (active) {\r\n // Use active element as selection\r\n sel = active.parentElement;\r\n }\r\n }\r\n\r\n if (sel) {\r\n // Scroll if necessary\r\n const selHeight = sel.offsetHeight;\r\n const selTop = sel.offsetTop;\r\n const parent = sel.parentNode;\r\n const parentHeight = parent.offsetHeight;\r\n const parentScrollHeight = parent.scrollHeight;\r\n const parentTop = parent.offsetTop;\r\n\r\n // Reset scroll, this can happen if menu was scrolled then hidden\r\n if (selHeight === 0) {\r\n setTimeout(() => {\r\n parent.scrollTop = 0;\r\n });\r\n }\r\n\r\n if (dir === PREV) {\r\n // Don't use scrollIntoView as it scrolls the whole window\r\n // Avoid minor top scroll due to headers\r\n const scrollTop = selTop - parentTop > 10 ? selTop - parentTop : 0;\r\n parent.scrollTop = scrollTop;\r\n } else {\r\n // This is the equivalent of scrollIntoView(false) but only for parent node\r\n // Only scroll if the element is not visible\r\n const scrollNeeded = selTop + selHeight - (parentHeight + parent.scrollTop);\r\n if (scrollNeeded > 0 && selHeight > 0) {\r\n parent.scrollTop = selTop + selHeight - parentHeight + 1;\r\n // On last element, make sure we scroll the the bottom\r\n if (parent.scrollTop + parentHeight >= parentScrollHeight - 10) {\r\n parent.scrollTop = selTop - parentTop;\r\n }\r\n }\r\n }\r\n\r\n // Adjust link\r\n const a = sel.querySelector(\"a\");\r\n a.classList.add(...this._activeClasses());\r\n this._searchInput.setAttribute(\"aria-activedescendant\", a.id);\r\n if (this._config.updateOnSelect) {\r\n this._searchInput.value = a.dataset.label;\r\n this._adjustWidth();\r\n }\r\n } else {\r\n this._searchInput.setAttribute(\"aria-activedescendant\", \"\");\r\n }\r\n return sel;\r\n }\r\n\r\n /**\r\n * Adjust the field to fit its content and show/hide placeholder if needed\r\n */\r\n _adjustWidth() {\r\n this._holderElement.classList.remove(PLACEHOLDER_CLASS);\r\n if (this._searchInput.value) {\r\n this._searchInput.size = this._searchInput.value.length;\r\n } else {\r\n // Show the placeholder only if empty\r\n if (this.getSelectedValues().length) {\r\n this._searchInput.placeholder = \"\";\r\n this._searchInput.size = 1;\r\n } else {\r\n this._searchInput.size = this._config.placeholder.length > 0 ? this._config.placeholder.length : 1;\r\n this._searchInput.placeholder = this._config.placeholder;\r\n this._holderElement.classList.add(PLACEHOLDER_CLASS);\r\n }\r\n }\r\n\r\n // If the string contains ascii chars or strange font, input size may be wrong\r\n // We cannot only rely on the size attribute\r\n const v = this._searchInput.value || this._searchInput.placeholder;\r\n const computedFontSize = window.getComputedStyle(this._holderElement).fontSize;\r\n const w = calcTextWidth(v, computedFontSize) + 16;\r\n this._searchInput.style.width = w + \"px\"; // Don't use minWidth as it would prevent using maxWidth\r\n }\r\n\r\n /**\r\n * Add suggestions to the drop element\r\n * @param {Array} suggestions\r\n */\r\n _buildSuggestions(suggestions) {\r\n while (this._dropElement.lastChild) {\r\n this._dropElement.removeChild(this._dropElement.lastChild);\r\n }\r\n let idx = 0;\r\n let groupId = 1; // start at one, because data-id = \"\" + 0 doesn't do anything\r\n for (let i = 0; i < suggestions.length; i++) {\r\n const suggestion = suggestions[i];\r\n\r\n // Handle optgroups\r\n if (suggestion[\"group\"]) {\r\n const newChild = ce(\"li\");\r\n newChild.setAttribute(\"role\", \"presentation\");\r\n newChild.dataset.id = \"\" + groupId;\r\n const newChildSpan = ce(\"span\");\r\n newChild.append(newChildSpan);\r\n newChildSpan.classList.add(...[\"dropdown-header\", \"text-truncate\"]);\r\n newChildSpan.innerHTML = suggestion[\"group\"];\r\n this._dropElement.appendChild(newChild);\r\n\r\n if (suggestion[\"items\"]) {\r\n for (let j = 0; j < suggestion[\"items\"].length; j++) {\r\n const groupSuggestion = suggestion[\"items\"][j];\r\n groupSuggestion.group_id = groupId;\r\n this._buildSuggestionsItem(suggestion[\"items\"][j], idx);\r\n idx++;\r\n }\r\n }\r\n\r\n groupId++;\r\n }\r\n\r\n this._buildSuggestionsItem(suggestion, idx);\r\n idx++;\r\n }\r\n\r\n // Create the not found message\r\n if (this._config.notFoundMessage) {\r\n const notFound = ce(\"li\");\r\n notFound.setAttribute(\"role\", \"presentation\");\r\n notFound.classList.add(CLASS_PREFIX + \"not-found\");\r\n // Actual message is refreshed on typing, but we need item for consistency\r\n notFound.innerHTML = ``;\r\n this._dropElement.appendChild(notFound);\r\n }\r\n }\r\n\r\n /**\r\n * @param {Suggestion} suggestion\r\n * @param {Number} i\r\n */\r\n _buildSuggestionsItem(suggestion, i) {\r\n if (!suggestion[this._config.valueField]) {\r\n return;\r\n }\r\n\r\n const value = suggestion[this._config.valueField];\r\n const label = suggestion[this._config.labelField];\r\n\r\n // initial selection from remote data (only works if live server is disabled)\r\n if (this._config.server && !this._config.liveServer) {\r\n if (suggestion.selected || this._config.selected.includes(value)) {\r\n // We need _add to create an actual option so we can track it for reset later\r\n const added = this._add(label, value, suggestion.data);\r\n // track for reset\r\n if (added) {\r\n added.dataset.init = \"true\";\r\n }\r\n }\r\n }\r\n\r\n let textContent = this._config.onRenderItem(suggestion, label, this);\r\n\r\n const newChild = ce(\"li\");\r\n newChild.setAttribute(\"role\", \"presentation\");\r\n if (suggestion.group_id) {\r\n newChild.setAttribute(\"data-group-id\", \"\" + suggestion.group_id);\r\n }\r\n const newChildLink = ce(\"a\");\r\n newChild.append(newChildLink);\r\n newChildLink.id = this._dropElement.id + \"-\" + i;\r\n newChildLink.classList.add(...[\"dropdown-item\", \"text-truncate\"]);\r\n if (suggestion.disabled) {\r\n newChildLink.classList.add(...[\"disabled\"]);\r\n }\r\n newChildLink.setAttribute(VALUE_ATTRIBUTE, value);\r\n newChildLink.dataset.label = label;\r\n this._config.searchFields.forEach((sf) => {\r\n newChild.dataset[sf] = suggestion[sf];\r\n });\r\n newChildLink.setAttribute(\"href\", \"#\");\r\n newChildLink.innerHTML = textContent;\r\n this._dropElement.appendChild(newChild);\r\n\r\n // Hover sets active item\r\n newChildLink.addEventListener(\"mouseenter\", (event) => {\r\n // Don't trigger enter if using arrows\r\n if (this._keyboardNavigation) {\r\n return;\r\n }\r\n this.removeSelection();\r\n newChild.querySelector(\"a\").classList.add(...this._activeClasses());\r\n });\r\n newChildLink.addEventListener(\"mousedown\", (event) => {\r\n // Otherwise searchInput would lose focus and close the menu\r\n event.preventDefault();\r\n });\r\n newChildLink.addEventListener(\"click\", (event) => {\r\n event.preventDefault();\r\n this._add(label, value, suggestion.data);\r\n this._config.onSelectItem(suggestion, this);\r\n });\r\n }\r\n\r\n /**\r\n * @returns {NodeListOf}\r\n */\r\n initialOptions() {\r\n return this._selectElement.querySelectorAll(\"option[data-init]\");\r\n }\r\n\r\n reset() {\r\n this.removeAll();\r\n\r\n // Reset doesn't fire change event\r\n this._fireEvents = false;\r\n const opts = this.initialOptions();\r\n for (let j = 0; j < opts.length; j++) {\r\n const iv = opts[j];\r\n this.addItem(iv.textContent, iv.value, iv.dataset);\r\n }\r\n this._adjustWidth();\r\n this._fireEvents = true;\r\n }\r\n\r\n /**\r\n * @param {Boolean} init Pass true during init\r\n */\r\n resetSearchInput(init = false) {\r\n this._searchInput.value = \"\";\r\n this._adjustWidth();\r\n\r\n if (!init) {\r\n this.hideSuggestions();\r\n // Trigger input even to show suggestions if needed when focused\r\n if (this._searchInput === document.activeElement) {\r\n this._searchInput.dispatchEvent(new Event(\"input\"));\r\n }\r\n }\r\n\r\n // We use visibility instead of display to keep layout intact\r\n if (this.isMaxReached()) {\r\n this._searchInput.style.visibility = \"hidden\";\r\n } else if (this._searchInput.style.visibility == \"hidden\") {\r\n this._searchInput.style.visibility = \"visible\";\r\n }\r\n\r\n if (this.isSingle() && !init) {\r\n //@ts-ignore\r\n document.activeElement.blur();\r\n }\r\n }\r\n\r\n /**\r\n * @returns {Array}\r\n */\r\n getSelectedValues() {\r\n // option[selected] is used rather that selectedOptions as it works more consistently\r\n /**\r\n * @type {NodeListOf}\r\n */\r\n const selected = this._selectElement.querySelectorAll(\"option[selected]\");\r\n return Array.from(selected).map((el) => el.value);\r\n }\r\n\r\n /**\r\n * @returns {Array}\r\n */\r\n getAvailableValues() {\r\n /**\r\n * @type {NodeListOf}\r\n */\r\n const selected = this._selectElement.querySelectorAll(\"option\");\r\n return Array.from(selected).map((el) => el.value);\r\n }\r\n\r\n /**\r\n * Show suggestions or search them depending on live server\r\n * @param {Boolean} check\r\n */\r\n showOrSearch(check = true) {\r\n if (check && !this._shouldShow()) {\r\n // focusing should not clear validation\r\n this.hideSuggestions(false);\r\n return;\r\n }\r\n if (this._config.liveServer) {\r\n this._searchFunc();\r\n } else {\r\n this._showSuggestions();\r\n }\r\n }\r\n\r\n /**\r\n * The element create with buildSuggestions\r\n * @param {Boolean} clearValidation\r\n */\r\n hideSuggestions(clearValidation = true) {\r\n this._dropElement.classList.remove(SHOW_CLASS);\r\n attrs(this._searchInput, {\r\n \"aria-expanded\": \"false\",\r\n });\r\n this.removeSelection();\r\n if (clearValidation) {\r\n this._holderElement.classList.remove(INVALID_CLASS);\r\n }\r\n }\r\n\r\n /**\r\n * Show or hide suggestions\r\n * @param {Boolean} check\r\n * @param {Boolean} clearValidation\r\n */\r\n toggleSuggestions(check = true, clearValidation = true) {\r\n if (this._dropElement.classList.contains(SHOW_CLASS)) {\r\n this.hideSuggestions(clearValidation);\r\n } else {\r\n this.showOrSearch(check);\r\n }\r\n }\r\n\r\n /**\r\n * Do we have enough input to show suggestions ?\r\n * @returns {Boolean}\r\n */\r\n _shouldShow() {\r\n if (this.isDisabled()) {\r\n return false;\r\n }\r\n if (this._config.maximumItems > 0 && this.getSelectedValues().length >= this._config.maximumItems) {\r\n return false;\r\n }\r\n return this._searchInput.value.length >= this._config.suggestionsThreshold;\r\n }\r\n\r\n /**\r\n * The element create with buildSuggestions\r\n */\r\n _showSuggestions() {\r\n // It's not focused anymore\r\n if (document.activeElement != this._searchInput) {\r\n return;\r\n }\r\n // Never show suggestions if you cannot add new values\r\n if (this._searchInput.style.visibility == \"hidden\") {\r\n return;\r\n }\r\n\r\n const lookup = normalize(this._searchInput.value);\r\n\r\n // Get current values\r\n const values = this.getSelectedValues();\r\n\r\n // Filter the list according to search string\r\n const list = this._dropElement.querySelectorAll(\"li\");\r\n let count = 0;\r\n let firstItem = null;\r\n let hasPossibleValues = false;\r\n let visibleGroups = {};\r\n for (let i = 0; i < list.length; i++) {\r\n /**\r\n * @type {HTMLLIElement}\r\n */\r\n let item = list[i];\r\n /**\r\n * @type {HTMLAnchorElement|HTMLSpanElement}\r\n */\r\n //@ts-ignore\r\n let link = item.firstElementChild;\r\n\r\n // This is the empty result message or a header\r\n if (link instanceof HTMLSpanElement) {\r\n // We will show it later\r\n if (item.dataset.id) {\r\n visibleGroups[item.dataset.id] = false;\r\n }\r\n hideItem(item);\r\n continue;\r\n }\r\n\r\n // Remove previous selection\r\n link.classList.remove(...this._activeClasses());\r\n\r\n // Hide selected values\r\n if (!this._config.allowSame && values.indexOf(link.getAttribute(VALUE_ATTRIBUTE)) != -1) {\r\n hideItem(item);\r\n continue;\r\n }\r\n\r\n // Check search length since we can trigger dropdown with arrow\r\n const showAllSuggestions = this._config.showAllSuggestions || lookup.length === 0;\r\n // Do we find a matching string or do we display immediately ?\r\n let isMatched = lookup.length == 0 && this._config.suggestionsThreshold === 0;\r\n if (!showAllSuggestions && lookup.length > 0) {\r\n // match on any field\r\n this._config.searchFields.forEach((sf) => {\r\n const text = normalize(link.dataset[sf]);\r\n const found = this._config.fuzzy ? fuzzyMatch(text, lookup) : text.indexOf(lookup) >= 0;\r\n if (found) {\r\n isMatched = true;\r\n }\r\n });\r\n }\r\n\r\n const selectFirst = isMatched || lookup.length === 0;\r\n if (showAllSuggestions || isMatched) {\r\n count++;\r\n showItem(item);\r\n if (item.dataset.groupId) {\r\n visibleGroups[item.dataset.groupId] = true;\r\n }\r\n // Only select as first item if its matching or no lookup\r\n if (!firstItem && this._isItemEnabled(item) && selectFirst) {\r\n firstItem = item;\r\n }\r\n if (this._config.maximumItems > 0 && count > this._config.maximumItems) {\r\n hideItem(item);\r\n }\r\n } else {\r\n hideItem(item);\r\n }\r\n\r\n if (this._config.highlightTyped) {\r\n // using .textContent removes any html that can be present (eg: mark added through highlightTyped)\r\n const textContent = link.textContent;\r\n const idx = normalize(textContent).indexOf(lookup);\r\n const highlighted =\r\n textContent.substring(0, idx) +\r\n `${textContent.substring(idx, idx + lookup.length)}` +\r\n textContent.substring(idx + lookup.length, textContent.length);\r\n link.innerHTML = highlighted;\r\n }\r\n\r\n if (this._isItemEnabled(item)) {\r\n hasPossibleValues = true;\r\n }\r\n }\r\n\r\n // No item and we don't allow new items => error\r\n if (!this._config.allowNew && !(lookup.length === 0 && !hasPossibleValues)) {\r\n this._holderElement.classList.add(INVALID_CLASS);\r\n }\r\n\r\n // If we allow new elements, regex validation should happen on canAdd instead\r\n if (this._config.allowNew && this._config.regex && this.isInvalid()) {\r\n this._holderElement.classList.remove(INVALID_CLASS);\r\n }\r\n\r\n // Show all groups with visible values\r\n Array.from(list)\r\n .filter((li) => {\r\n return li.dataset.id;\r\n })\r\n .forEach((li) => {\r\n if (visibleGroups[li.dataset.id] === true) {\r\n showItem(li);\r\n }\r\n });\r\n\r\n if (hasPossibleValues) {\r\n // Remove validation message if we show selectable values\r\n this._holderElement.classList.remove(INVALID_CLASS);\r\n\r\n // Autoselect first\r\n if (firstItem && this._config.autoselectFirst) {\r\n this.removeSelection();\r\n this._moveSelection(NEXT, firstItem);\r\n }\r\n }\r\n\r\n // Remove dropdown if list is empty\r\n if (count === 0) {\r\n if (this._config.notFoundMessage) {\r\n /**\r\n * @type {HTMLElement}\r\n */\r\n const notFound = this._dropElement.querySelector(\".\" + CLASS_PREFIX + \"not-found\");\r\n notFound.style.display = \"block\";\r\n const notFoundMessage = this._config.notFoundMessage.replace(\"{{tag}}\", this._searchInput.value);\r\n notFound.innerHTML = `${notFoundMessage}`;\r\n this._showDropdown();\r\n } else {\r\n // Remove dropdown if not found (do not clear validation)\r\n this.hideSuggestions(false);\r\n }\r\n } else {\r\n // Or show it if necessary\r\n this._showDropdown();\r\n }\r\n }\r\n\r\n _showDropdown() {\r\n this._dropElement.classList.add(SHOW_CLASS);\r\n attrs(this._searchInput, {\r\n \"aria-expanded\": \"true\",\r\n });\r\n this._positionMenu();\r\n }\r\n\r\n _positionMenu() {\r\n const styles = window.getComputedStyle(this._searchInput);\r\n const bounds = this._searchInput.getBoundingClientRect();\r\n const isRTL = styles.direction === \"rtl\";\r\n\r\n let left = null;\r\n let top = null;\r\n\r\n if (this._config.fixed) {\r\n // In full width, use holder as left reference, otherwise use input\r\n if (this._config.fullWidth) {\r\n const holderBounds = this._holderElement.getBoundingClientRect();\r\n left = holderBounds.x;\r\n } else {\r\n left = bounds.x;\r\n }\r\n top = bounds.y + bounds.height;\r\n } else {\r\n // When positioning is not fixed, we leave it up to the browser\r\n // it may not work in complex situations with scrollable overflows, etc\r\n if (this._config.fullWidth) {\r\n // Stick it at the start\r\n left = 0;\r\n } else {\r\n // Position next to input (offsetLeft != bounds.x)\r\n left = this._searchInput.offsetLeft;\r\n }\r\n }\r\n\r\n // Align end\r\n if (isRTL && !this._config.fullWidth) {\r\n left -= this._dropElement.offsetWidth - bounds.width;\r\n }\r\n\r\n // Horizontal overflow\r\n if (!this._config.fullWidth) {\r\n const w = Math.min(window.innerWidth, document.body.offsetWidth);\r\n const hdiff = isRTL\r\n ? bounds.x + bounds.width - this._dropElement.offsetWidth - 1\r\n : w - 1 - (bounds.x + this._dropElement.offsetWidth);\r\n if (hdiff < 0) {\r\n left = isRTL ? left - hdiff : left + hdiff;\r\n }\r\n }\r\n\r\n // Reset any height overflow adjustement\r\n this._dropElement.style.transform = \"unset\";\r\n\r\n // Use full holder width\r\n if (this._config.fullWidth) {\r\n this._dropElement.style.width = this._holderElement.offsetWidth + \"px\";\r\n }\r\n\r\n // Position element\r\n if (left !== null) {\r\n this._dropElement.style.left = left + \"px\";\r\n }\r\n if (top !== null) {\r\n this._dropElement.style.top = top + \"px\";\r\n }\r\n\r\n // Overflow height\r\n const dropBounds = this._dropElement.getBoundingClientRect();\r\n const h = window.innerHeight;\r\n\r\n // We display above input if it overflows\r\n if (dropBounds.y + dropBounds.height > h) {\r\n this._dropElement.style.transform = \"translateY(calc(-100% - \" + this._searchInput.offsetHeight + \"px))\";\r\n }\r\n }\r\n\r\n /**\r\n * @returns {Number}\r\n */\r\n _getBootstrapVersion() {\r\n let ver = 5;\r\n // If we have jQuery and the tooltip plugin for BS4\r\n //@ts-ignore\r\n if (window.jQuery && $.fn.tooltip != undefined && $.fn.tooltip.Constructor != undefined) {\r\n //@ts-ignore\r\n ver = parseInt($.fn.tooltip.Constructor.VERSION.charAt(0));\r\n }\r\n return ver;\r\n }\r\n\r\n /**\r\n * Find if label is already selected (based on attribute)\r\n * @param {string} text\r\n * @returns {Boolean}\r\n */\r\n _isSelected(text) {\r\n const opt = Array.from(this._selectElement.querySelectorAll(\"option\")).find((el) => el.textContent == text);\r\n if (opt && opt.getAttribute(\"selected\")) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks if value matches a configured regex\r\n * @param {string} value\r\n * @returns {Boolean}\r\n */\r\n _validateRegex(value) {\r\n const regex = new RegExp(this._config.regex.trim());\r\n return regex.test(value);\r\n }\r\n\r\n /**\r\n * @returns {HTMLElement}\r\n */\r\n getSelection() {\r\n return this._dropElement.querySelector(\"a.\" + ACTIVE_CLASS);\r\n }\r\n\r\n removeSelection() {\r\n const selection = this.getSelection();\r\n if (selection) {\r\n selection.classList.remove(...this._activeClasses());\r\n }\r\n }\r\n\r\n /**\r\n * @returns {Array}\r\n */\r\n _activeClasses() {\r\n return [...this._config.activeClasses, ...[ACTIVE_CLASS]];\r\n }\r\n\r\n /**\r\n * @deprecated since 1.5\r\n * @returns {HTMLElement}\r\n */\r\n getActiveSelection() {\r\n return this.getSelection();\r\n }\r\n\r\n /**\r\n * @deprecated since 1.5\r\n */\r\n removeActiveSelection() {\r\n return this.removeSelection();\r\n }\r\n\r\n removeAll() {\r\n let items = this.getSelectedValues();\r\n items.forEach((item) => {\r\n this.removeItem(item, true);\r\n });\r\n this._adjustWidth();\r\n }\r\n\r\n /**\r\n * @param {Boolean} noEvents\r\n */\r\n removeLastItem(noEvents = false) {\r\n let items = this._containerElement.querySelectorAll(\"span:not(.disabled)\");\r\n if (!items.length) {\r\n return;\r\n }\r\n let lastItem = items[items.length - 1];\r\n this.removeItem(lastItem.getAttribute(VALUE_ATTRIBUTE), noEvents);\r\n }\r\n\r\n enable() {\r\n this._selectElement.setAttribute(\"disabled\", \"\");\r\n this.resetState();\r\n }\r\n\r\n disable() {\r\n rmAttr(this._selectElement, \"disabled\");\r\n this.resetState();\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isDisabled() {\r\n return this._selectElement.hasAttribute(\"disabled\") || this._selectElement.disabled || this._selectElement.hasAttribute(\"readonly\");\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isDropdownVisible() {\r\n return this._dropElement.classList.contains(SHOW_CLASS);\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isInvalid() {\r\n return this._holderElement.classList.contains(INVALID_CLASS);\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isSingle() {\r\n return !this._selectElement.hasAttribute(\"multiple\");\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isMaxReached() {\r\n return this._config.max && this.getSelectedValues().length >= this._config.max;\r\n }\r\n\r\n /**\r\n * @param {string} text\r\n * @param {Object} data\r\n * @returns {Boolean}\r\n */\r\n canAdd(text, data = {}) {\r\n // Check invalid input\r\n if (!text) {\r\n return false;\r\n }\r\n // Check disabled\r\n if (this.isDisabled()) {\r\n return false;\r\n }\r\n // Check already selected input (single will replace)\r\n if (!this.isSingle() && !this._config.allowSame && this._isSelected(text)) {\r\n return false;\r\n }\r\n // Check for max\r\n if (this.isMaxReached()) {\r\n return false;\r\n }\r\n // Check for regex on new input\r\n if (this._config.regex && data.new && !this._validateRegex(text)) {\r\n this._holderElement.classList.add(INVALID_CLASS);\r\n return false;\r\n }\r\n // Check for custom validation\r\n if (this._config.onCanAdd && this._config.onCanAdd(text, data, this) === false) {\r\n this._holderElement.classList.add(INVALID_CLASS);\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * You might want to use canAdd before to ensure the item is valid\r\n * @param {string} text\r\n * @param {string} value\r\n * @param {object} data\r\n * @return {HTMLOptionElement} The created or selected option\r\n */\r\n addItem(text, value = null, data = {}) {\r\n if (!value) {\r\n value = text;\r\n }\r\n\r\n // Single items remove first\r\n if (this.isSingle() && this.getSelectedValues().length) {\r\n this.removeLastItem(true);\r\n }\r\n\r\n // Keep in mind that we can have the same value for multiple options\r\n // escape invalid characters for HTML attributes: \\' \" = < > ` &.'\r\n const escapedValue = CSS.escape(value);\r\n let opts = this._selectElement.querySelectorAll('option[value=\"' + escapedValue + '\"]');\r\n /**\r\n * @type {HTMLOptionElement}\r\n */\r\n let opt = null;\r\n if (this._config.allowSame) {\r\n // Match same items by content\r\n opts.forEach(\r\n /**\r\n * @param {HTMLOptionElement} o\r\n */\r\n (o) => {\r\n if (o.textContent === text && !o.selected) {\r\n opt = o;\r\n }\r\n }\r\n );\r\n } else {\r\n //@ts-ignore\r\n opt = opts[0] || null;\r\n }\r\n\r\n // we need to create a new option\r\n if (!opt) {\r\n opt = ce(\"option\");\r\n opt.value = value;\r\n opt.textContent = text; // innerText is not well supported by jsdom\r\n // Pass along data provided\r\n for (const [key, value] of Object.entries(data)) {\r\n opt.dataset[key] = value;\r\n }\r\n this._selectElement.appendChild(opt);\r\n this._config.onCreateItem(opt, this);\r\n }\r\n\r\n if (opt) {\r\n data = Object.assign(\r\n {\r\n title: opt.getAttribute(\"title\"),\r\n },\r\n data,\r\n opt.dataset\r\n );\r\n }\r\n // update select, we need to set attribute for option[selected]\r\n opt.setAttribute(\"selected\", \"selected\");\r\n opt.selected = true;\r\n\r\n // mobile safari is doing it's own crazy thing...\r\n // without this, it wil not pick up the proper state of the select element and validation will fail\r\n const html = this._selectElement.innerHTML;\r\n this._selectElement.innerHTML = \"\";\r\n this._selectElement.innerHTML = html;\r\n\r\n this._createBadge(text, value, data);\r\n\r\n // Fire change event\r\n if (this._fireEvents) {\r\n this._selectElement.dispatchEvent(new Event(\"change\", { bubbles: true }));\r\n }\r\n\r\n return opt;\r\n }\r\n\r\n /**\r\n * @param {string} text\r\n * @param {string} value\r\n * @param {object} data\r\n */\r\n _createBadge(text, value = null, data = {}) {\r\n const bver = this._getBootstrapVersion();\r\n const allowClear = this._config.allowClear && !data.disabled;\r\n\r\n // create span\r\n let html = text;\r\n let span = ce(\"span\");\r\n let classes = [\"badge\"];\r\n let badgeStyle = this._config.badgeStyle;\r\n if (data.badgeStyle) {\r\n badgeStyle = data.badgeStyle;\r\n }\r\n if (data.badgeClass) {\r\n classes.push(...data.badgeClass.split(\" \"));\r\n }\r\n if (this._config.baseClass) {\r\n // custom style\r\n classes.push(...this._config.baseClass.split(\" \"));\r\n } else if (bver === 5) {\r\n // https://getbootstrap.com/docs/5.3/components/badge/\r\n // add extra classes to avoid any layout issues due to very large labels\r\n classes = [...classes, ...[\"bg-\" + badgeStyle, \"mw-100\", \"overflow-x-hidden\"]];\r\n } else {\r\n // https://getbootstrap.com/docs/4.6/components/badge/\r\n classes = [...classes, ...[\"badge-\" + badgeStyle]];\r\n }\r\n\r\n if (data.disabled) {\r\n classes.push(...[\"disabled\", \"opacity-50\"]);\r\n }\r\n\r\n // We cannot really rely on classes to get a proper sizing\r\n span.style.margin = \"2px 6px 2px 0px\";\r\n // Use logical styles for RTL support\r\n span.style.marginBlock = \"2px\";\r\n span.style.marginInline = \"0px 6px\";\r\n span.classList.add(...classes);\r\n span.setAttribute(VALUE_ATTRIBUTE, value);\r\n // Tooltips\r\n if (data.title) {\r\n span.setAttribute(\"title\", data.title);\r\n }\r\n\r\n if (allowClear) {\r\n const closeClass = classes.includes(\"text-dark\") ? \"btn-close\" : \"btn-close-white\";\r\n let btnMargin;\r\n let btnFloat;\r\n if (this._config.clearEnd) {\r\n btnMargin = bver === 5 ? \"ms-2\" : \"ml-2\";\r\n btnFloat = bver === 5 ? \"float-end\" : \"float:right;\";\r\n } else {\r\n btnMargin = bver === 5 ? \"me-2\" : \"mr-2\";\r\n btnFloat = bver === 5 ? \"float-start\" : \"float:left;\";\r\n }\r\n const btn =\r\n bver === 5\r\n ? ''\r\n : '';\r\n html = btn + html;\r\n }\r\n\r\n span.innerHTML = html;\r\n this._containerElement.insertBefore(span, this._searchInput);\r\n if (window.bootstrap && window.bootstrap.Tooltip) {\r\n window.bootstrap.Tooltip.getOrCreateInstance(span);\r\n }\r\n\r\n if (allowClear) {\r\n span.querySelector(\"button\").addEventListener(\"click\", (event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (!this.isDisabled()) {\r\n this.removeItem(value);\r\n //@ts-ignore\r\n document.activeElement.blur();\r\n this._adjustWidth();\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * @param {string} value\r\n * @param {Boolean} value\r\n */\r\n removeItem(value, noEvents = false) {\r\n // Remove badge if any\r\n // escape invalid characters for HTML attributes: \\' \" = < > ` &.'\r\n const escapedValue = CSS.escape(value);\r\n let item = this._containerElement.querySelector(\"span[\" + VALUE_ATTRIBUTE + '=\"' + escapedValue + '\"]');\r\n if (!item) {\r\n return;\r\n }\r\n item.remove();\r\n\r\n // update select\r\n /**\r\n * @type {HTMLOptionElement}\r\n */\r\n let opt = this._selectElement.querySelector('option[value=\"' + escapedValue + '\"][selected]');\r\n\r\n if (opt) {\r\n rmAttr(opt, \"selected\");\r\n opt.selected = false;\r\n\r\n // Fire change event\r\n if (this._fireEvents && !noEvents) {\r\n this._selectElement.dispatchEvent(new Event(\"change\", { bubbles: true }));\r\n }\r\n }\r\n\r\n // Make input visible\r\n if (this._searchInput.style.visibility == \"hidden\" && !this.isMaxReached()) {\r\n this._searchInput.style.visibility = \"visible\";\r\n }\r\n\r\n if (!noEvents) {\r\n this._config.onClearItem(value, this);\r\n }\r\n }\r\n}\r\n\r\nexport default Tags;\r\n"], - "mappings": "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", - "names": ["DEFAULTS", "item", "label", "inst", "value", "option", "event", "text", "data", "response", "CLASS_PREFIX", "LOADING_CLASS", "ACTIVE_CLASS", "INVALID_CLASS", "SHOW_CLASS", "VALUE_ATTRIBUTE", "NEXT", "PREV", "FOCUS_CLASS", "PLACEHOLDER_CLASS", "DISABLED_CLASS", "INSTANCE_MAP", "counter", "debounce", "func", "timeout", "timer", "args", "calcTextWidth", "size", "span", "ce", "width", "removeDiacritics", "str", "normalize", "fuzzyMatch", "lookup", "pos", "c", "hideItem", "attrs", "showItem", "el", "k", "v", "rmAttr", "attr", "tagName", "Tags", "config", "_selectElement", "_willBlur", "_configure", "_keyboardNavigation", "_searchFunc", "_loadFromServer", "_config", "_fireEvents", "_configureParent", "_holderElement", "_containerElement", "_configureHolderElement", "_configureContainerElement", "_configureSelectElement", "_configureSearchInput", "_configureDropElement", "_searchInput", "_dropElement", "selector", "opts", "list", "i", "_timer", "o", "parseBool", "key", "defaultValue", "separator", "r", "p", "_getPlaceholder", "firstOption", "dropStyles", "_getBootstrapVersion", "containerStyles", "initialValues", "j", "initialValue", "_createBadge", "_abortController", "clearValidation", "_enterValue", "sel", "ev", "lastChar", "addData", "_add", "_adjustWidth", "target", "_moveSelection", "e", "_positionMenu", "suggestions", "_buildSuggestions", "selection", "show", "params", "input", "inputName", "urlParams", "url", "fetchOptions", "_showSuggestions", "_isItemEnabled", "li", "fc", "dir", "active", "sibling", "_activeClasses", "selHeight", "selTop", "parent", "parentHeight", "parentScrollHeight", "parentTop", "scrollTop", "a", "computedFontSize", "w", "idx", "groupId", "suggestion", "newChild", "newChildSpan", "groupSuggestion", "_buildSuggestionsItem", "notFound", "added", "textContent", "newChildLink", "sf", "iv", "init", "selected", "check", "_shouldShow", "values", "count", "firstItem", "hasPossibleValues", "visibleGroups", "link", "showAllSuggestions", "isMatched", "selectFirst", "highlighted", "notFoundMessage", "_showDropdown", "styles", "bounds", "isRTL", "left", "top", "hdiff", "dropBounds", "h", "ver", "_isSelected", "opt", "_validateRegex", "noEvents", "items", "lastItem", "escapedValue", "html", "bver", "allowClear", "classes", "badgeStyle", "closeClass", "btnMargin", "btnFloat", "tags_default"] + "sourcesContent": ["/**\r\n * Bootstrap 5 (and 4!) tags\r\n *\r\n * Turns your select[multiple] into nice tags lists\r\n *\r\n * Required Bootstrap 5 styles:\r\n * - badge\r\n * - background-color utility\r\n * - text-truncate utility\r\n * - forms\r\n * - dropdown\r\n */\r\n\r\n// #region config\r\n\r\n/**\r\n * @callback EventCallback\r\n * @param {Event} event\r\n * @param {Tags} inst\r\n * @returns {void}\r\n */\r\n\r\n/**\r\n * @callback ServerCallback\r\n * @param {Response} response\r\n * @param {Tags} inst\r\n * @returns {Promise}\r\n */\r\n\r\n/**\r\n * @callback RenderCallback\r\n * @param {Suggestion} item\r\n * @param {String} label\r\n * @param {Tags} inst\r\n * @returns {String}\r\n */\r\n\r\n/**\r\n * @callback ItemCallback\r\n * @param {Suggestion} item\r\n * @param {Tags} inst\r\n * @returns {void}\r\n */\r\n\r\n/**\r\n * @callback ValueCallback\r\n * @param {String} value\r\n * @param {Tags} inst\r\n * @returns {void}\r\n */\r\n\r\n/**\r\n * @callback AddCallback\r\n * @param {String} value\r\n * @param {Object} data\r\n * @param {Tags} inst\r\n * @returns {void|Boolean}\r\n */\r\n\r\n/**\r\n * @callback CreateCallback\r\n * @param {HTMLOptionElement} option\r\n * @param {Tags} inst\r\n * @returns {void}\r\n */\r\n\r\n/**\r\n * @typedef Config\r\n * @property {Array} items Source items\r\n * @property {Boolean} allowNew Allows creation of new tags\r\n * @property {Boolean} showAllSuggestions Show all suggestions even if they don't match. Disables validation.\r\n * @property {String} badgeStyle Color of the badge (color can be configured per option as well)\r\n * @property {Boolean} allowClear Show a clear icon\r\n * @property {Boolean} clearEnd Place clear icon at the end\r\n * @property {Array} selected A list of initially selected values\r\n * @property {String} regex Regex for new tags\r\n * @property {Array|String} separator A list (pipe separated) of characters that should act as separator (default is using enter key)\r\n * @property {Number} max Limit to a maximum of tags (0 = no limit)\r\n * @property {String} placeholder Provides a placeholder if none are provided as the first empty option\r\n * @property {String} clearLabel Text as clear tooltip\r\n * @property {String} searchLabel Default placeholder\r\n * @property {Boolean} keepOpen Keep suggestions open after selection, clear on focus out\r\n * @property {Boolean} allowSame Allow same tags used multiple times\r\n * @property {String} baseClass Customize the class applied to badges\r\n * @property {Boolean} addOnBlur Add new tags on blur (only if allowNew is enabled)\r\n * @property {Boolean} showDisabled Show disabled tags\r\n * @property {Boolean} hideNativeValidation Hide native validation tooltips\r\n * @property {Number} suggestionsThreshold Number of chars required to show suggestions\r\n * @property {Number} maximumItems Maximum number of items to display\r\n * @property {Boolean} autoselectFirst Always select the first item\r\n * @property {Boolean} updateOnSelect Update input value on selection (doesn't play nice with autoselectFirst)\r\n * @property {Boolean} highlightTyped Highlight matched part of the suggestion\r\n * @property {Boolean} fullWidth Match the width on the input field\r\n * @property {Boolean} fixed Use fixed positioning (solve overflow issues)\r\n * @property {Boolean} fuzzy Fuzzy search\r\n * @property {Boolean} singleBadge Show badge for single elements\r\n * @property {Array} activeClasses By default: [\"bg-primary\", \"text-white\"]\r\n * @property {String} labelField Key for the label\r\n * @property {String} valueField Key for the value\r\n * @property {Array} searchFields Key for the search\r\n * @property {String} queryParam Name of the param passed to endpoint (query by default)\r\n * @property {String} server Endpoint for data provider\r\n * @property {String} serverMethod HTTP request method for data provider, default is GET\r\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.\r\n * @property {String} serverDataKey By default: data\r\n * @property {Object} fetchOptions Any other fetch options (https://developer.mozilla.org/en-US/docs/Web/API/fetch#syntax)\r\n * @property {Boolean} liveServer Should the endpoint be called each time on input\r\n * @property {Boolean} noCache Prevent caching by appending a timestamp\r\n * @property {Number} debounceTime Debounce time for live server\r\n * @property {String} notFoundMessage Display a no suggestions found message. Leave empty to disable\r\n * @property {RenderCallback} onRenderItem Callback function that returns the suggestion\r\n * @property {ItemCallback} onSelectItem Callback function to call on selection\r\n * @property {ValueCallback} onClearItem Callback function to call on clear\r\n * @property {CreateCallback} onCreateItem Callback function when an item is created\r\n * @property {EventCallback} onBlur Callback function on blur\r\n * @property {EventCallback} onFocus Callback function on focus\r\n * @property {AddCallback} onCanAdd Callback function to validate item. Return false to show validation message.\r\n * @property {ServerCallback} onServerResponse Callback function to process server response. Must return a Promise\r\n */\r\n\r\n/**\r\n * @typedef Suggestion\r\n * @property {String} value Can be overriden by config valueField\r\n * @property {String} label Can be overriden by config labelField\r\n * @property {Boolean} disabled\r\n * @property {Object} data\r\n * @property {Boolean} [selected]\r\n * @property {Number} [group_id]\r\n */\r\n\r\n/**\r\n * @typedef SuggestionGroup\r\n * @property {String} group\r\n * @property {Array} items\r\n */\r\n\r\n/**\r\n * @type {Config}\r\n */\r\nconst DEFAULTS = {\r\n items: [],\r\n allowNew: false,\r\n showAllSuggestions: false,\r\n badgeStyle: \"primary\",\r\n allowClear: false,\r\n clearEnd: false,\r\n selected: [],\r\n regex: \"\",\r\n separator: [],\r\n max: 0,\r\n clearLabel: \"Clear\",\r\n searchLabel: \"Type a value\",\r\n keepOpen: false,\r\n allowSame: false,\r\n baseClass: \"\",\r\n placeholder: \"\",\r\n addOnBlur: false,\r\n showDisabled: false,\r\n hideNativeValidation: false,\r\n suggestionsThreshold: -1,\r\n maximumItems: 0,\r\n autoselectFirst: true,\r\n updateOnSelect: false,\r\n highlightTyped: false,\r\n fullWidth: false,\r\n fixed: false,\r\n fuzzy: false,\r\n singleBadge: false,\r\n activeClasses: [\"bg-primary\", \"text-white\"],\r\n labelField: \"label\",\r\n valueField: \"value\",\r\n searchFields: [\"label\"],\r\n queryParam: \"query\",\r\n server: \"\",\r\n serverMethod: \"GET\",\r\n serverParams: {},\r\n serverDataKey: \"data\",\r\n fetchOptions: {},\r\n liveServer: false,\r\n noCache: true,\r\n debounceTime: 300,\r\n notFoundMessage: \"\",\r\n onRenderItem: (item, label, inst) => {\r\n return label;\r\n },\r\n onSelectItem: (item, inst) => {},\r\n onClearItem: (value, inst) => {},\r\n onCreateItem: (option, inst) => {},\r\n onBlur: (event, inst) => {},\r\n onFocus: (event, inst) => {},\r\n onCanAdd: (text, data, inst) => {},\r\n onServerResponse: (response, inst) => {\r\n return response.json();\r\n },\r\n};\r\n\r\n// #endregion\r\n\r\n// #region constants\r\n\r\nconst CLASS_PREFIX = \"tags-\";\r\nconst LOADING_CLASS = \"is-loading\";\r\nconst ACTIVE_CLASS = \"is-active\";\r\nconst INVALID_CLASS = \"is-invalid\";\r\nconst SHOW_CLASS = \"show\";\r\nconst VALUE_ATTRIBUTE = \"data-value\";\r\nconst NEXT = \"next\";\r\nconst PREV = \"prev\";\r\nconst FOCUS_CLASS = \"form-control-focus\"; // should match form-control:focus\r\nconst PLACEHOLDER_CLASS = \"form-placeholder-shown\"; // should match :placeholder-shown\r\nconst DISABLED_CLASS = \"form-control-disabled\"; // should match form-control:disabled\r\nconst INSTANCE_MAP = new WeakMap();\r\nlet counter = 0;\r\nlet activeCounter = 0;\r\n\r\n// #endregion\r\n\r\n// #region functions\r\n\r\n/**\r\n * @param {Function} func\r\n * @param {number} timeout\r\n * @returns {Function}\r\n */\r\nfunction debounce(func, timeout = 300) {\r\n let timer;\r\n return (...args) => {\r\n clearTimeout(timer);\r\n timer = setTimeout(() => {\r\n //@ts-ignore\r\n func.apply(this, args);\r\n }, timeout);\r\n };\r\n}\r\n\r\n/**\r\n * @param {string} text\r\n * @param {string} size\r\n * @returns {Number}\r\n */\r\nfunction calcTextWidth(text, size = null) {\r\n const span = ce(\"span\");\r\n document.body.appendChild(span);\r\n span.style.fontSize = size || \"inherit\";\r\n span.style.height = \"auto\";\r\n span.style.width = \"auto\";\r\n span.style.position = \"absolute\";\r\n span.style.whiteSpace = \"no-wrap\";\r\n span.innerHTML = text;\r\n const width = Math.ceil(span.clientWidth);\r\n document.body.removeChild(span);\r\n return width;\r\n}\r\n\r\n/**\r\n * @param {String} str\r\n * @returns {String}\r\n */\r\nfunction removeDiacritics(str) {\r\n return str.normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\");\r\n}\r\n\r\n/**\r\n * @param {String|Number} str\r\n * @returns {String}\r\n */\r\nfunction normalize(str) {\r\n if (!str) {\r\n return \"\";\r\n }\r\n return removeDiacritics(str.toString()).toLowerCase();\r\n}\r\n\r\n/**\r\n * A simple fuzzy match algorithm that checks if chars are matched\r\n * in order in the target string\r\n *\r\n * @param {String} str\r\n * @param {String} lookup\r\n * @returns {Boolean}\r\n */\r\nfunction fuzzyMatch(str, lookup) {\r\n if (str.indexOf(lookup) >= 0) {\r\n return true;\r\n }\r\n let pos = 0;\r\n for (let i = 0; i < lookup.length; i++) {\r\n const c = lookup[i];\r\n if (c == \" \") continue;\r\n pos = str.indexOf(c, pos) + 1;\r\n if (pos <= 0) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} item\r\n */\r\nfunction hideItem(item) {\r\n item.style.display = \"none\";\r\n attrs(item, {\r\n \"aria-hidden\": \"true\",\r\n });\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} item\r\n */\r\nfunction showItem(item) {\r\n item.style.display = \"list-item\";\r\n attrs(item, {\r\n \"aria-hidden\": \"false\",\r\n });\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n * @param {Object} attrs\r\n */\r\nfunction attrs(el, attrs) {\r\n for (const [k, v] of Object.entries(attrs)) {\r\n el.setAttribute(k, v);\r\n }\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n * @param {string} attr\r\n */\r\nfunction rmAttr(el, attr) {\r\n if (el.hasAttribute(attr)) {\r\n el.removeAttribute(attr);\r\n }\r\n}\r\n\r\n/**\r\n * Allow 1/0, true/false as strings\r\n * @param {any} value\r\n * @returns {Boolean}\r\n */\r\nfunction parseBool(value) {\r\n return [\"true\", \"false\", \"1\", \"0\", true, false].includes(value) && !!JSON.parse(value);\r\n}\r\n\r\n/**\r\n * @template {keyof HTMLElementTagNameMap} K\r\n * @param {K|String} tagName Name of the element\r\n * @returns {*}\r\n */\r\nfunction ce(tagName) {\r\n return document.createElement(tagName);\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n * @param {HTMLElement} newEl\r\n * @returns {HTMLElement}\r\n */\r\n// function insertAfter(el, newEl) {\r\n// return el.parentNode.insertBefore(newEl, el.nextSibling);\r\n// }\r\n\r\n// #endregion\r\n\r\nclass Tags {\r\n /**\r\n * @param {HTMLSelectElement} el\r\n * @param {Object|Config} config\r\n */\r\n constructor(el, config = {}) {\r\n if (!(el instanceof HTMLElement)) {\r\n console.error(\"Invalid element\", el);\r\n return;\r\n }\r\n INSTANCE_MAP.set(el, this);\r\n counter++;\r\n activeCounter++;\r\n this._selectElement = el;\r\n\r\n this._configure(config);\r\n\r\n // private vars\r\n this._keyboardNavigation = false;\r\n this._searchFunc = debounce(() => {\r\n this._loadFromServer(true);\r\n }, this._config.debounceTime);\r\n this._fireEvents = true;\r\n\r\n this._configureParent();\r\n\r\n // Create elements\r\n this._holderElement = ce(\"div\"); // this is the one holding the fake input and the dropmenu\r\n this._containerElement = ce(\"div\"); // this is the one for the fake input (labels + input)\r\n this._holderElement.appendChild(this._containerElement);\r\n\r\n // insert before select, this helps having native validation tooltips positioned properly\r\n this._selectElement.parentElement.insertBefore(this._holderElement, this._selectElement);\r\n // insertAfter(this._selectElement, this._holderElement);\r\n\r\n // Configure them\r\n this._configureHolderElement();\r\n this._configureContainerElement();\r\n this._configureSelectElement();\r\n this._configureSearchInput();\r\n this._configureDropElement();\r\n this.resetState();\r\n\r\n if (this._config.fixed) {\r\n document.addEventListener(\"scroll\", this, true); // capture input for all scrollables elements\r\n window.addEventListener(\"resize\", this);\r\n }\r\n\r\n // Add listeners (remove then on dispose()). See handleEvent.\r\n this._searchInput.addEventListener(\"focus\", this); // focusin bubbles, focus does not.\r\n this._searchInput.addEventListener(\"blur\", this); // focusout bubbles, blur does not.\r\n this._searchInput.addEventListener(\"input\", this);\r\n this._searchInput.addEventListener(\"keydown\", this);\r\n this._dropElement.addEventListener(\"mousemove\", this);\r\n\r\n this.loadData(true);\r\n }\r\n\r\n // #region Core\r\n\r\n /**\r\n * Attach to all elements matched by the selector\r\n * @param {string} selector\r\n * @param {Object} opts\r\n */\r\n static init(selector = \"select[multiple]\", opts = {}) {\r\n /**\r\n * @type {NodeListOf}\r\n */\r\n let list = document.querySelectorAll(selector);\r\n for (let i = 0; i < list.length; i++) {\r\n if (Tags.getInstance(list[i])) {\r\n continue;\r\n }\r\n new Tags(list[i], opts);\r\n }\r\n }\r\n\r\n /**\r\n * @param {HTMLSelectElement} el\r\n */\r\n static getInstance(el) {\r\n if (INSTANCE_MAP.has(el)) {\r\n return INSTANCE_MAP.get(el);\r\n }\r\n }\r\n\r\n dispose() {\r\n activeCounter--;\r\n\r\n this._searchInput.removeEventListener(\"focus\", this);\r\n this._searchInput.removeEventListener(\"blur\", this);\r\n this._searchInput.removeEventListener(\"input\", this);\r\n this._searchInput.removeEventListener(\"keydown\", this);\r\n this._dropElement.removeEventListener(\"mousemove\", this);\r\n\r\n if (this._config.fixed && activeCounter <= 0) {\r\n document.removeEventListener(\"scroll\", this, true);\r\n window.removeEventListener(\"resize\", this);\r\n }\r\n\r\n // restore select, remove our custom stuff and unbind parent\r\n this._selectElement.style.display = \"block\";\r\n this._holderElement.parentElement.removeChild(this._holderElement);\r\n if (this.parentForm) {\r\n this.parentForm.removeEventListener(\"reset\", this);\r\n }\r\n\r\n INSTANCE_MAP.delete(this._selectElement);\r\n }\r\n\r\n /**\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\r\n * @param {Event} event\r\n */\r\n handleEvent(event) {\r\n // debounce scroll and resize\r\n const debounced = [\"scroll\", \"resize\"];\r\n if (debounced.includes(event.type)) {\r\n if (this._timer) window.cancelAnimationFrame(this._timer);\r\n this._timer = window.requestAnimationFrame(() => {\r\n this[`on${event.type}`](event);\r\n });\r\n } else {\r\n this[`on${event.type}`](event);\r\n }\r\n }\r\n\r\n /**\r\n * @param {Config|Object} config\r\n */\r\n _configure(config = {}) {\r\n this._config = Object.assign({}, DEFAULTS);\r\n\r\n const json = this._selectElement.dataset.config ? JSON.parse(this._selectElement.dataset.config) : {};\r\n // Handle options, using arguments first, then json config and then data attr as override\r\n const o = { ...config, ...json, ...this._selectElement.dataset };\r\n\r\n // Typecast provided options based on defaults types\r\n for (const [key, defaultValue] of Object.entries(DEFAULTS)) {\r\n // Check for undefined keys\r\n if (key == \"config\" || o[key] === void 0) {\r\n continue;\r\n }\r\n const value = o[key];\r\n switch (typeof defaultValue) {\r\n case \"number\":\r\n this._config[key] = parseInt(value);\r\n break;\r\n case \"boolean\":\r\n this._config[key] = parseBool(value);\r\n break;\r\n case \"string\":\r\n this._config[key] = value.toString();\r\n break;\r\n case \"object\":\r\n this._config[key] = value;\r\n if (typeof value === \"string\") {\r\n if ([\"{\", \"[\"].includes(value[0])) {\r\n // JSON like string\r\n this._config[key] = JSON.parse(value);\r\n } else {\r\n // CSV or pipe separated string\r\n this._config[key] = value.split(value.includes(\"|\") ? \"|\" : \",\");\r\n }\r\n }\r\n break;\r\n case \"function\":\r\n // Find a global function with this name\r\n this._config[key] = typeof value === \"string\" ? value.split(\".\").reduce((r, p) => r[p], window) : value;\r\n if (!this._config[key]) {\r\n console.error(\"Invalid function\", value);\r\n }\r\n break;\r\n default:\r\n this._config[key] = value;\r\n break;\r\n }\r\n }\r\n\r\n // Dynamic default values\r\n if (!this._config.placeholder) {\r\n this._config.placeholder = this._getPlaceholder();\r\n }\r\n if (this._config.suggestionsThreshold == -1) {\r\n // if we don't have ajax auto completion, behave like a select by default\r\n this._config.suggestionsThreshold = this._config.liveServer ? 1 : 0;\r\n }\r\n }\r\n\r\n /**\r\n * @param {String} k\r\n * @returns {*}\r\n */\r\n config(k = null) {\r\n return k ? this._config[k] : this._config;\r\n }\r\n\r\n /**\r\n * @param {String} k\r\n * @param {*} v\r\n */\r\n setConfig(k, v) {\r\n this._config[k] = v;\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Html\r\n\r\n /**\r\n * Find overflow parent for positioning\r\n * and bind reset event of the parent form\r\n */\r\n _configureParent() {\r\n this.overflowParent = null;\r\n this.parentForm = this._selectElement.parentElement;\r\n while (this.parentForm) {\r\n if (this.parentForm.style.overflow === \"hidden\") {\r\n this.overflowParent = this.parentForm;\r\n }\r\n this.parentForm = this.parentForm.parentElement;\r\n if (this.parentForm && this.parentForm.nodeName == \"FORM\") {\r\n break;\r\n }\r\n }\r\n if (this.parentForm) {\r\n this.parentForm.addEventListener(\"reset\", this);\r\n }\r\n }\r\n\r\n /**\r\n * @returns {string}\r\n */\r\n _getPlaceholder() {\r\n // Use placeholder and data-placeholder in priority\r\n if (this._selectElement.hasAttribute(\"placeholder\")) {\r\n return this._selectElement.getAttribute(\"placeholder\");\r\n }\r\n if (this._selectElement.dataset.placeholder) {\r\n return this._selectElement.dataset.placeholder;\r\n }\r\n // Fallback to first option if no value\r\n let firstOption = this._selectElement.querySelector(\"option\");\r\n if (!firstOption || !this._config.autoselectFirst) {\r\n return \"\";\r\n }\r\n rmAttr(firstOption, \"selected\");\r\n firstOption.selected = false;\r\n return !firstOption.value ? firstOption.textContent : \"\";\r\n }\r\n\r\n _configureSelectElement() {\r\n // Hiding the select should keep it focusable, otherwise we get this\r\n // An invalid form control with name='...' is not focusable.\r\n // If it's not focusable, we need to remove the native validation attributes\r\n\r\n // If we use display none, we don't get the focus event\r\n // this._selectElement.style.display = \"none\";\r\n\r\n // If we position it like this, the html5 validation message will not display properly\r\n if (this._config.hideNativeValidation) {\r\n // This position dont break render within input-group and is focusable\r\n this._selectElement.style.position = \"absolute\";\r\n this._selectElement.style.left = \"-9999px\";\r\n } else {\r\n // Hide but keep it focusable. If 0 height, no native validation message will show\r\n // It is placed below so that native tooltip is displayed properly\r\n // Flex basis is required for input-group otherwise it breaks the layout\r\n this._selectElement.style.cssText = `height:1px;width:1px;opacity:0;padding:0;margin:0;border:0;float:left;flex-basis:100%;`;\r\n }\r\n\r\n // Make sure it's not usable using tab\r\n this._selectElement.tabIndex = -1;\r\n\r\n // No need for custom label click event if select is focusable\r\n // const label = document.querySelector('label[for=\"' + this._selectElement.getAttribute(\"id\") + '\"]');\r\n // if (label) {\r\n // label.addEventListener(\"click\", this);\r\n // }\r\n\r\n // It can be focused by clicking on the label\r\n this._selectElement.addEventListener(\"focus\", (event) => {\r\n this.onclick(event);\r\n });\r\n\r\n // When using regular html5 validation, make sure our fake element get the proper class\r\n this._selectElement.addEventListener(\"invalid\", (event) => {\r\n this._holderElement.classList.add(INVALID_CLASS);\r\n });\r\n }\r\n\r\n /**\r\n * Configure drop element\r\n * Needs to be called after searchInput is created\r\n */\r\n _configureDropElement() {\r\n this._dropElement = ce(\"ul\");\r\n this._dropElement.classList.add(...[\"dropdown-menu\", CLASS_PREFIX + \"menu\"]);\r\n this._dropElement.id = CLASS_PREFIX + \"menu-\" + counter;\r\n this._dropElement.setAttribute(\"role\", \"menu\");\r\n\r\n const dropStyles = this._dropElement.style;\r\n dropStyles.padding = \"0\"; // avoid ugly space before option\r\n dropStyles.maxHeight = \"280px\";\r\n if (!this._config.fullWidth) {\r\n dropStyles.maxWidth = \"360px\";\r\n }\r\n if (this._config.fixed) {\r\n dropStyles.position = \"fixed\";\r\n }\r\n dropStyles.overflowY = \"auto\";\r\n // Prevent scrolling the menu from scrolling the page\r\n // @link https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior\r\n dropStyles.overscrollBehavior = \"contain\";\r\n dropStyles.textAlign = \"unset\"; // otherwise RTL is not good\r\n\r\n // If the mouse was outside, entering remove keyboard nav mode\r\n this._dropElement.addEventListener(\"mouseenter\", (event) => {\r\n this._keyboardNavigation = false;\r\n });\r\n this._holderElement.appendChild(this._dropElement);\r\n\r\n // include aria-controls with the value of the id of the suggested list of values.\r\n this._searchInput.setAttribute(\"aria-controls\", this._dropElement.id);\r\n }\r\n\r\n _configureHolderElement() {\r\n this._holderElement.classList.add(...[\"form-control\", \"dropdown\"]);\r\n // Reflect size\r\n if (this._selectElement.classList.contains(\"form-select-lg\")) {\r\n this._holderElement.classList.add(\"form-control-lg\");\r\n }\r\n if (this._selectElement.classList.contains(\"form-select-sm\")) {\r\n this._holderElement.classList.add(\"form-control-sm\");\r\n }\r\n // If we have an overflow parent, we can simply inherit styles\r\n if (this.overflowParent) {\r\n this._holderElement.style.position = \"inherit\";\r\n }\r\n if (this._getBootstrapVersion() === 4) {\r\n // Prevent fixed height due to form-control\r\n this._holderElement.style.height = \"auto\";\r\n }\r\n\r\n // It is really more like a dropdown\r\n if (this._config.suggestionsThreshold == 0) {\r\n this._holderElement.classList.add(\"form-select\");\r\n }\r\n\r\n // Without this, clicking on a floating label won't always focus properly\r\n this._holderElement.addEventListener(\"click\", this);\r\n }\r\n\r\n _configureContainerElement() {\r\n this._containerElement.addEventListener(\"click\", (event) => {\r\n if (this.isDisabled()) {\r\n return;\r\n }\r\n if (this._searchInput.style.visibility != \"hidden\") {\r\n this._searchInput.focus();\r\n }\r\n });\r\n\r\n // Add some extra css to help positioning\r\n const containerStyles = this._containerElement.style;\r\n containerStyles.display = \"flex\";\r\n containerStyles.alignItems = \"center\";\r\n containerStyles.flexWrap = \"wrap\";\r\n }\r\n\r\n _configureSearchInput() {\r\n this._searchInput = ce(\"input\");\r\n this._searchInput.type = \"text\";\r\n this._searchInput.autocomplete = \"field-\" + Date.now(); // off is ignored\r\n this._searchInput.spellcheck = false;\r\n // note: firefox doesn't support the properties so we use attributes\r\n // @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-autocomplete\r\n // @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded\r\n // use the aria-expanded state on the element with role combobox to communicate that the list is displayed.\r\n // https://developer.mozilla.org/en-US/docs/Web/API/Element/ariaLabel\r\n attrs(this._searchInput, {\r\n \"aria-auto-complete\": \"list\",\r\n \"aria-has-popup\": \"menu\",\r\n \"aria-expanded\": \"false\",\r\n \"aria-label\": this._config.searchLabel,\r\n role: \"combobox\",\r\n });\r\n this._searchInput.style.cssText = `background-color:transparent;color:currentColor;border:0;padding:0;outline:0;max-width:100%`;\r\n this.resetSearchInput(true);\r\n\r\n this._containerElement.appendChild(this._searchInput);\r\n\r\n this._rtl = window.getComputedStyle(this._searchInput).direction === \"rtl\";\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Events\r\n\r\n onfocus(event) {\r\n this._holderElement.classList.add(FOCUS_CLASS);\r\n this.showOrSearch();\r\n this._config.onFocus(event, this);\r\n }\r\n\r\n onblur(event) {\r\n // Cancel any pending request\r\n if (this._abortController) {\r\n this._abortController.abort();\r\n }\r\n let clearValidation = true;\r\n if (this._config.addOnBlur && this._searchInput.value) {\r\n clearValidation = this._enterValue();\r\n }\r\n this._holderElement.classList.remove(FOCUS_CLASS);\r\n this.hideSuggestions(clearValidation);\r\n if (this._fireEvents) {\r\n const sel = this.getSelection();\r\n const data = {\r\n selection: sel ? sel.dataset.value : null,\r\n input: this._searchInput.value,\r\n };\r\n this._config.onBlur(event, this);\r\n this._selectElement.dispatchEvent(new CustomEvent(\"tags.blur\", { bubbles: true, detail: data }));\r\n }\r\n }\r\n\r\n oninput(ev) {\r\n const data = this._searchInput.value;\r\n\r\n // Add item if a separator is used\r\n // On mobile or copy paste, it can pass multiple chars (eg: when pressing space and it formats the string)\r\n if (data) {\r\n const lastChar = data.slice(-1);\r\n if (this._config.separator.length && this._config.separator.includes(lastChar)) {\r\n // Remove separator even if adding is prevented\r\n this._searchInput.value = this._searchInput.value.slice(0, -1);\r\n let value = this._searchInput.value;\r\n let label = value;\r\n let addData = {};\r\n // There is no good reason to use the separator feature without allowNew, but who knows!\r\n if (!this._config.allowNew) {\r\n const sel = this.getSelection();\r\n if (!sel) {\r\n return;\r\n }\r\n value = sel.getAttribute(VALUE_ATTRIBUTE);\r\n label = sel.dataset.label;\r\n } else {\r\n addData.new = 1;\r\n }\r\n this._add(label, value, addData);\r\n return;\r\n }\r\n }\r\n\r\n // Adjust input width to current content\r\n setTimeout(() => {\r\n this._adjustWidth();\r\n });\r\n\r\n // Check if we should display suggestions\r\n this.showOrSearch();\r\n }\r\n\r\n /**\r\n * keypress doesn't send arrow keys, so we use keydown\r\n * @param {KeyboardEvent} event\r\n */\r\n onkeydown(event) {\r\n // Keycode reference : https://css-tricks.com/snippets/javascript/javascript-keycodes/\r\n let key = event.keyCode || event.key;\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n // @ts-ignore\r\n const target = event.target;\r\n\r\n // Android virtual keyboard might always return 229\r\n if (event.keyCode == 229) {\r\n key = target.value.charAt(target.selectionStart - 1).charCodeAt(0);\r\n }\r\n\r\n // Keyboard keys\r\n switch (key) {\r\n case 13:\r\n case \"Enter\":\r\n event.preventDefault();\r\n this._enterValue();\r\n break;\r\n case 38:\r\n case \"ArrowUp\":\r\n event.preventDefault();\r\n this._keyboardNavigation = true;\r\n this._moveSelection(PREV);\r\n break;\r\n case 40:\r\n case \"ArrowDown\":\r\n event.preventDefault();\r\n this._keyboardNavigation = true;\r\n if (this.isDropdownVisible()) {\r\n this._moveSelection(NEXT);\r\n } else {\r\n // show menu regardless of input length\r\n this.showOrSearch(false);\r\n }\r\n break;\r\n case 8:\r\n case \"Backspace\":\r\n // If the current item is empty, remove the last one\r\n if (this._searchInput.value.length == 0) {\r\n this.removeLastItem();\r\n this._adjustWidth();\r\n this.showOrSearch();\r\n }\r\n break;\r\n case 27:\r\n case \"Escape\":\r\n this._searchInput.focus();\r\n this.hideSuggestions();\r\n break;\r\n }\r\n }\r\n\r\n onmousemove(e) {\r\n // Moving the mouse means no longer using keyboard\r\n this._keyboardNavigation = false;\r\n }\r\n\r\n onscroll(e) {\r\n this._positionMenu();\r\n }\r\n\r\n onresize(e) {\r\n this._positionMenu();\r\n }\r\n\r\n onclick(e = null) {\r\n if (e) {\r\n e.preventDefault();\r\n }\r\n if (!this.isSingle() && this.isMaxReached()) {\r\n return;\r\n }\r\n // Focus on input when clicking on element or focusing select\r\n this._searchInput.focus();\r\n }\r\n\r\n onreset(e) {\r\n this.reset();\r\n }\r\n\r\n // #endregion\r\n\r\n /**\r\n * @param {Boolean} init called during init\r\n */\r\n loadData(init = false) {\r\n if (Object.keys(this._config.items).length > 0) {\r\n this.setData(this._config.items, true);\r\n } else {\r\n this.resetSuggestions(true);\r\n }\r\n\r\n if (this._config.server) {\r\n if (this._config.liveServer) {\r\n // No need to load anything since it will happen when typing\r\n // Initial values are loaded from config items or from provided options\r\n } else {\r\n this._loadFromServer(!init);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Make sure we have valid selected attributes\r\n */\r\n _setSelectedAttributes() {\r\n // we use selectedOptions because single select can have a selected option without a selected attribute if it's the first value\r\n const selectedOptions = this._selectElement.selectedOptions || [];\r\n for (let j = 0; j < selectedOptions.length; j++) {\r\n // Enforce selected attr for consistency\r\n if (selectedOptions[j].value && !selectedOptions[j].hasAttribute(\"selected\")) {\r\n selectedOptions[j].setAttribute(\"selected\", \"selected\");\r\n }\r\n }\r\n }\r\n\r\n resetState() {\r\n if (this.isDisabled()) {\r\n this._holderElement.setAttribute(\"readonly\", \"\");\r\n this._searchInput.setAttribute(\"disabled\", \"\");\r\n this._holderElement.classList.add(DISABLED_CLASS);\r\n } else {\r\n rmAttr(this._holderElement, \"readonly\");\r\n rmAttr(this._searchInput, \"disabled\");\r\n this._holderElement.classList.remove(DISABLED_CLASS);\r\n }\r\n }\r\n\r\n /**\r\n * Reset suggestions from select element\r\n * Iterates over option children then calls setData\r\n * @param {Boolean} init called during init\r\n */\r\n resetSuggestions(init = false) {\r\n this._setSelectedAttributes();\r\n let suggestions = Array.from(this._selectElement.children)\r\n .filter(\r\n /**\r\n * @param {HTMLOptionElement|HTMLOptGroupElement} option\r\n */\r\n (option) => {\r\n return option instanceof HTMLOptGroupElement || !option.disabled || this._config.showDisabled;\r\n }\r\n )\r\n .map(\r\n /**\r\n * @param {HTMLOptionElement|HTMLOptGroupElement} option\r\n */\r\n (option) => {\r\n if (option instanceof HTMLOptGroupElement) {\r\n return {\r\n group: option.getAttribute(\"label\"),\r\n items: option.children,\r\n };\r\n }\r\n return {\r\n value: option.getAttribute(\"value\"),\r\n label: option.textContent,\r\n disabled: option.disabled,\r\n selected: option.selected,\r\n data: Object.assign({}, option.dataset),\r\n };\r\n }\r\n );\r\n\r\n this.setData(suggestions, init);\r\n }\r\n\r\n /**\r\n * Try to add the current value\r\n * @returns {Boolean}\r\n */\r\n _enterValue() {\r\n let selection = this.getSelection();\r\n if (selection) {\r\n selection.click();\r\n return true;\r\n } else {\r\n // We use what is typed if not selected and not empty\r\n if (this._config.allowNew && this._searchInput.value) {\r\n let text = this._searchInput.value;\r\n const el = this._add(text, text, { new: 1 });\r\n return el ? true : false;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * @param {Boolean} show Show menu after load. False during init\r\n */\r\n _loadFromServer(show = false) {\r\n if (this._abortController) {\r\n this._abortController.abort();\r\n }\r\n this._abortController = new AbortController();\r\n\r\n const params = Object.assign({}, this._config.serverParams);\r\n // Pass current value\r\n params[this._config.queryParam] = this._searchInput.value;\r\n // Prevent caching\r\n if (this._config.noCache) {\r\n params.t = Date.now();\r\n }\r\n // We have a related field\r\n if (params.related) {\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n //@ts-ignore\r\n const input = document.getElementById(params.related);\r\n if (input) {\r\n params.related = input.value;\r\n const inputName = input.getAttribute(\"name\");\r\n if (inputName) {\r\n params[inputName] = input.value;\r\n }\r\n }\r\n }\r\n\r\n const urlParams = new URLSearchParams(params);\r\n let url = this._config.server;\r\n let fetchOptions = Object.assign(this._config.fetchOptions, {\r\n method: this._config.serverMethod || \"GET\",\r\n signal: this._abortController.signal,\r\n });\r\n\r\n if (fetchOptions.method === \"POST\") {\r\n fetchOptions.body = urlParams;\r\n } else {\r\n url += \"?\" + urlParams.toString();\r\n }\r\n\r\n this._holderElement.classList.add(LOADING_CLASS);\r\n fetch(url, fetchOptions)\r\n .then((r) => this._config.onServerResponse(r, this))\r\n .then((suggestions) => {\r\n const data = suggestions[this._config.serverDataKey] || suggestions;\r\n this.setData(data, !show);\r\n this._abortController = null;\r\n if (show) {\r\n this._showSuggestions();\r\n }\r\n })\r\n .catch((e) => {\r\n if (e.name === \"AbortError\") {\r\n return;\r\n }\r\n console.error(e);\r\n })\r\n .finally((e) => {\r\n this._holderElement.classList.remove(LOADING_CLASS);\r\n });\r\n }\r\n\r\n /**\r\n * Wrapper for the public addItem method that check if the item\r\n * can be added\r\n *\r\n * @param {string} text\r\n * @param {string} value\r\n * @param {object} data\r\n * @returns {HTMLOptionElement|null}\r\n */\r\n _add(text, value = null, data = {}) {\r\n if (!this.canAdd(text, data)) {\r\n return null;\r\n }\r\n const el = this.addItem(text, value, data);\r\n this._resetHtmlState();\r\n if (this._config.keepOpen) {\r\n this._showSuggestions();\r\n } else {\r\n this.resetSearchInput();\r\n }\r\n return el;\r\n }\r\n\r\n /**\r\n * @param {HTMLElement} li\r\n * @returns {Boolean}\r\n */\r\n _isItemEnabled(li) {\r\n if (li.style.display === \"none\") {\r\n return false;\r\n }\r\n const fc = li.firstElementChild;\r\n return fc.tagName === \"A\" && !fc.classList.contains(\"disabled\");\r\n }\r\n\r\n /**\r\n * @param {String} dir\r\n * @param {*|HTMLElement} sel\r\n * @returns {HTMLElement}\r\n */\r\n _moveSelection(dir = NEXT, sel = null) {\r\n const active = this.getSelection();\r\n\r\n // select first li if visible\r\n if (!active) {\r\n // no active selection, cannot go back\r\n if (dir === PREV) {\r\n return sel;\r\n }\r\n // find first enabled item\r\n if (!sel) {\r\n sel = this._dropElement.firstChild;\r\n while (sel && !this._isItemEnabled(sel)) {\r\n sel = sel[\"nextSibling\"];\r\n }\r\n }\r\n } else {\r\n const sibling = dir === NEXT ? \"nextSibling\" : \"previousSibling\";\r\n\r\n // Iterate over visible li\r\n sel = active.parentNode;\r\n do {\r\n sel = sel[sibling];\r\n } while (sel && !this._isItemEnabled(sel));\r\n\r\n // We have a new selection\r\n if (sel) {\r\n // Remove classes from current active\r\n active.classList.remove(...this._activeClasses());\r\n } else if (active) {\r\n // Use active element as selection\r\n sel = active.parentElement;\r\n }\r\n }\r\n\r\n if (sel) {\r\n // Scroll if necessary\r\n const selHeight = sel.offsetHeight;\r\n const selTop = sel.offsetTop;\r\n const parent = sel.parentNode;\r\n const parentHeight = parent.offsetHeight;\r\n const parentScrollHeight = parent.scrollHeight;\r\n const parentTop = parent.offsetTop;\r\n\r\n // Reset scroll, this can happen if menu was scrolled then hidden\r\n if (selHeight === 0) {\r\n setTimeout(() => {\r\n parent.scrollTop = 0;\r\n });\r\n }\r\n\r\n if (dir === PREV) {\r\n // Don't use scrollIntoView as it scrolls the whole window\r\n // Avoid minor top scroll due to headers\r\n const scrollTop = selTop - parentTop > 10 ? selTop - parentTop : 0;\r\n parent.scrollTop = scrollTop;\r\n } else {\r\n // This is the equivalent of scrollIntoView(false) but only for parent node\r\n // Only scroll if the element is not visible\r\n const scrollNeeded = selTop + selHeight - (parentHeight + parent.scrollTop);\r\n if (scrollNeeded > 0 && selHeight > 0) {\r\n parent.scrollTop = selTop + selHeight - parentHeight + 1;\r\n // On last element, make sure we scroll the the bottom\r\n if (parent.scrollTop + parentHeight >= parentScrollHeight - 10) {\r\n parent.scrollTop = selTop - parentTop;\r\n }\r\n }\r\n }\r\n\r\n // Adjust link\r\n const a = sel.querySelector(\"a\");\r\n a.classList.add(...this._activeClasses());\r\n this._searchInput.setAttribute(\"aria-activedescendant\", a.id);\r\n if (this._config.updateOnSelect) {\r\n this._searchInput.value = a.dataset.label;\r\n this._adjustWidth();\r\n }\r\n } else {\r\n this._searchInput.setAttribute(\"aria-activedescendant\", \"\");\r\n }\r\n return sel;\r\n }\r\n\r\n /**\r\n * Adjust the field to fit its content and show/hide placeholder if needed\r\n */\r\n _adjustWidth() {\r\n this._holderElement.classList.remove(PLACEHOLDER_CLASS);\r\n if (this._searchInput.value) {\r\n this._searchInput.size = this._searchInput.value.length;\r\n } else {\r\n // Show the placeholder only if empty\r\n if (this.getSelectedValues().length) {\r\n this._searchInput.placeholder = \"\";\r\n this._searchInput.size = 1;\r\n } else {\r\n this._searchInput.size = this._config.placeholder.length > 0 ? this._config.placeholder.length : 1;\r\n this._searchInput.placeholder = this._config.placeholder;\r\n this._holderElement.classList.add(PLACEHOLDER_CLASS);\r\n }\r\n }\r\n\r\n // If the string contains ascii chars or strange font, input size may be wrong\r\n // We cannot only rely on the size attribute\r\n const v = this._searchInput.value || this._searchInput.placeholder;\r\n const computedFontSize = window.getComputedStyle(this._holderElement).fontSize;\r\n const w = calcTextWidth(v, computedFontSize) + 16;\r\n this._searchInput.style.width = w + \"px\"; // Don't use minWidth as it would prevent using maxWidth\r\n }\r\n\r\n /**\r\n * Add suggestions to the drop element\r\n * @param {Array} suggestions\r\n */\r\n _buildSuggestions(suggestions) {\r\n while (this._dropElement.lastChild) {\r\n this._dropElement.removeChild(this._dropElement.lastChild);\r\n }\r\n let idx = 0;\r\n let groupId = 1; // start at one, because data-id = \"\" + 0 doesn't do anything\r\n for (let i = 0; i < suggestions.length; i++) {\r\n const suggestion = suggestions[i];\r\n\r\n if (!suggestion) {\r\n continue;\r\n }\r\n\r\n // Handle optgroups\r\n if (suggestion[\"group\"] && suggestion[\"items\"]) {\r\n const newChild = ce(\"li\");\r\n newChild.setAttribute(\"role\", \"presentation\");\r\n newChild.dataset.id = \"\" + groupId;\r\n const newChildSpan = ce(\"span\");\r\n newChild.append(newChildSpan);\r\n newChildSpan.classList.add(...[\"dropdown-header\", \"text-truncate\"]);\r\n newChildSpan.innerHTML = suggestion[\"group\"];\r\n this._dropElement.appendChild(newChild);\r\n\r\n if (suggestion[\"items\"]) {\r\n for (let j = 0; j < suggestion[\"items\"].length; j++) {\r\n const groupSuggestion = suggestion[\"items\"][j];\r\n groupSuggestion.group_id = groupId;\r\n this._buildSuggestionsItem(suggestion[\"items\"][j], idx);\r\n idx++;\r\n }\r\n }\r\n\r\n groupId++;\r\n }\r\n\r\n //@ts-ignore\r\n this._buildSuggestionsItem(suggestion, idx);\r\n idx++;\r\n }\r\n\r\n // Create the not found message\r\n if (this._config.notFoundMessage) {\r\n const notFound = ce(\"li\");\r\n notFound.setAttribute(\"role\", \"presentation\");\r\n notFound.classList.add(CLASS_PREFIX + \"not-found\");\r\n // Actual message is refreshed on typing, but we need item for consistency\r\n notFound.innerHTML = ``;\r\n this._dropElement.appendChild(notFound);\r\n }\r\n }\r\n\r\n /**\r\n * @param {Suggestion} suggestion\r\n * @param {Number} i The global counter\r\n */\r\n _buildSuggestionsItem(suggestion, i) {\r\n if (!suggestion[this._config.valueField]) {\r\n return;\r\n }\r\n\r\n const value = suggestion[this._config.valueField];\r\n const label = suggestion[this._config.labelField];\r\n\r\n let textContent = this._config.onRenderItem(suggestion, label, this);\r\n\r\n const newChild = ce(\"li\");\r\n newChild.setAttribute(\"role\", \"presentation\");\r\n if (suggestion.group_id) {\r\n newChild.setAttribute(\"data-group-id\", \"\" + suggestion.group_id);\r\n }\r\n const newChildLink = ce(\"a\");\r\n newChild.append(newChildLink);\r\n newChildLink.id = this._dropElement.id + \"-\" + i;\r\n newChildLink.classList.add(...[\"dropdown-item\", \"text-truncate\"]);\r\n if (suggestion.disabled) {\r\n newChildLink.classList.add(...[\"disabled\"]);\r\n }\r\n newChildLink.setAttribute(VALUE_ATTRIBUTE, value);\r\n newChildLink.dataset.label = label;\r\n this._config.searchFields.forEach((sf) => {\r\n newChild.dataset[sf] = suggestion[sf];\r\n });\r\n newChildLink.setAttribute(\"href\", \"#\");\r\n newChildLink.innerHTML = textContent;\r\n this._dropElement.appendChild(newChild);\r\n\r\n // Hover sets active item\r\n newChildLink.addEventListener(\"mouseenter\", (event) => {\r\n // Don't trigger enter if using arrows\r\n if (this._keyboardNavigation) {\r\n return;\r\n }\r\n this.removeSelection();\r\n newChild.querySelector(\"a\").classList.add(...this._activeClasses());\r\n });\r\n newChildLink.addEventListener(\"mousedown\", (event) => {\r\n // Otherwise searchInput would lose focus and close the menu\r\n event.preventDefault();\r\n });\r\n newChildLink.addEventListener(\"click\", (event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this._add(label, value, suggestion.data);\r\n this._config.onSelectItem(suggestion, this);\r\n });\r\n }\r\n\r\n /**\r\n * @returns {NodeListOf}\r\n */\r\n initialOptions() {\r\n return this._selectElement.querySelectorAll(\"option[data-init]\");\r\n }\r\n\r\n /**\r\n * Call this before looping in a list that calls addItem\r\n * This will make sure addItem will not add incorrectly options to the select\r\n */\r\n _removeSelectedAttrs() {\r\n this._selectElement.querySelectorAll(\"option\").forEach((opt) => {\r\n rmAttr(opt, \"selected\");\r\n });\r\n }\r\n\r\n reset() {\r\n this.removeAll();\r\n\r\n // Reset doesn't fire change event\r\n this._fireEvents = false;\r\n const opts = this.initialOptions();\r\n this._removeSelectedAttrs();\r\n for (let j = 0; j < opts.length; j++) {\r\n const iv = opts[j];\r\n this.addItem(iv.textContent, iv.value, iv.dataset);\r\n }\r\n this._resetHtmlState();\r\n this._fireEvents = true;\r\n }\r\n\r\n /**\r\n * @param {Boolean} init Pass true during init\r\n */\r\n resetSearchInput(init = false) {\r\n this._searchInput.value = \"\";\r\n this._adjustWidth();\r\n\r\n if (!init) {\r\n this.hideSuggestions();\r\n // Trigger input even to show suggestions if needed when focused\r\n if (this._searchInput === document.activeElement) {\r\n this._searchInput.dispatchEvent(new Event(\"input\"));\r\n }\r\n }\r\n\r\n // We use visibility instead of display to keep layout intact\r\n if (this.isMaxReached()) {\r\n this._searchInput.style.visibility = \"hidden\";\r\n } else if (this._searchInput.style.visibility == \"hidden\") {\r\n this._searchInput.style.visibility = \"visible\";\r\n }\r\n\r\n if (this.isSingle() && !init) {\r\n //@ts-ignore\r\n document.activeElement.blur();\r\n }\r\n }\r\n\r\n /**\r\n * @returns {Array}\r\n */\r\n getSelectedValues() {\r\n // option[selected] is used rather that selectedOptions as it works more consistently\r\n /**\r\n * @type {NodeListOf}\r\n */\r\n const selected = this._selectElement.querySelectorAll(\"option[selected]\");\r\n return Array.from(selected).map((el) => el.value);\r\n }\r\n\r\n /**\r\n * @returns {Array}\r\n */\r\n getAvailableValues() {\r\n /**\r\n * @type {NodeListOf}\r\n */\r\n const selected = this._selectElement.querySelectorAll(\"option\");\r\n return Array.from(selected).map((el) => el.value);\r\n }\r\n\r\n /**\r\n * Show suggestions or search them depending on live server\r\n * @param {Boolean} check\r\n */\r\n showOrSearch(check = true) {\r\n if (check && !this._shouldShow()) {\r\n // focusing should not clear validation\r\n this.hideSuggestions(false);\r\n return;\r\n }\r\n if (this._config.liveServer) {\r\n this._searchFunc();\r\n } else {\r\n this._showSuggestions();\r\n }\r\n }\r\n\r\n /**\r\n * The element create with buildSuggestions\r\n * @param {Boolean} clearValidation\r\n */\r\n hideSuggestions(clearValidation = true) {\r\n this._dropElement.classList.remove(SHOW_CLASS);\r\n attrs(this._searchInput, {\r\n \"aria-expanded\": \"false\",\r\n });\r\n this.removeSelection();\r\n if (clearValidation) {\r\n this._holderElement.classList.remove(INVALID_CLASS);\r\n }\r\n }\r\n\r\n /**\r\n * Show or hide suggestions\r\n * @param {Boolean} check\r\n * @param {Boolean} clearValidation\r\n */\r\n toggleSuggestions(check = true, clearValidation = true) {\r\n if (this._dropElement.classList.contains(SHOW_CLASS)) {\r\n this.hideSuggestions(clearValidation);\r\n } else {\r\n this.showOrSearch(check);\r\n }\r\n }\r\n\r\n /**\r\n * Do we have enough input to show suggestions ?\r\n * @returns {Boolean}\r\n */\r\n _shouldShow() {\r\n if (this.isDisabled()) {\r\n return false;\r\n }\r\n if (this._config.maximumItems > 0 && this.getSelectedValues().length >= this._config.maximumItems) {\r\n return false;\r\n }\r\n return this._searchInput.value.length >= this._config.suggestionsThreshold;\r\n }\r\n\r\n /**\r\n * The element create with buildSuggestions\r\n */\r\n _showSuggestions() {\r\n // It's not focused anymore\r\n if (document.activeElement != this._searchInput) {\r\n return;\r\n }\r\n // Never show suggestions if you cannot add new values\r\n if (this._searchInput.style.visibility == \"hidden\") {\r\n return;\r\n }\r\n\r\n const lookup = normalize(this._searchInput.value);\r\n\r\n const valueCounter = {};\r\n\r\n // Filter the list according to search string\r\n const list = this._dropElement.querySelectorAll(\"li\");\r\n let count = 0;\r\n let firstItem = null;\r\n let hasPossibleValues = false;\r\n let visibleGroups = {};\r\n for (let i = 0; i < list.length; i++) {\r\n /**\r\n * @type {HTMLLIElement}\r\n */\r\n let item = list[i];\r\n /**\r\n * @type {HTMLAnchorElement|HTMLSpanElement}\r\n */\r\n //@ts-ignore\r\n let link = item.firstElementChild;\r\n\r\n // This is the empty result message or a header\r\n if (link instanceof HTMLSpanElement) {\r\n // We will show it later\r\n if (item.dataset.id) {\r\n visibleGroups[item.dataset.id] = false;\r\n }\r\n hideItem(item);\r\n continue;\r\n }\r\n\r\n // Remove previous selection\r\n link.classList.remove(...this._activeClasses());\r\n\r\n // Hide selected values\r\n if (!this._config.allowSame) {\r\n const v = link.getAttribute(VALUE_ATTRIBUTE);\r\n // Find if the matching option is already selected by index to deal with same values\r\n valueCounter[v] = valueCounter[v] || 0;\r\n const opt = this._findOption(link.getAttribute(VALUE_ATTRIBUTE), \"[selected]\", valueCounter[v]++);\r\n if (opt) {\r\n hideItem(item);\r\n continue;\r\n }\r\n }\r\n\r\n // Check search length since we can trigger dropdown with arrow\r\n const showAllSuggestions = this._config.showAllSuggestions || lookup.length === 0;\r\n // Do we find a matching string or do we display immediately ?\r\n let isMatched = lookup.length == 0 && this._config.suggestionsThreshold === 0;\r\n if (!showAllSuggestions && lookup.length > 0) {\r\n // match on any field\r\n this._config.searchFields.forEach((sf) => {\r\n const text = normalize(link.dataset[sf]);\r\n const found = this._config.fuzzy ? fuzzyMatch(text, lookup) : text.indexOf(lookup) >= 0;\r\n if (found) {\r\n isMatched = true;\r\n }\r\n });\r\n }\r\n\r\n const selectFirst = isMatched || lookup.length === 0;\r\n if (showAllSuggestions || isMatched) {\r\n count++;\r\n showItem(item);\r\n if (item.dataset.groupId) {\r\n visibleGroups[item.dataset.groupId] = true;\r\n }\r\n // Only select as first item if its matching or no lookup\r\n if (!firstItem && this._isItemEnabled(item) && selectFirst) {\r\n firstItem = item;\r\n }\r\n if (this._config.maximumItems > 0 && count > this._config.maximumItems) {\r\n hideItem(item);\r\n }\r\n } else {\r\n hideItem(item);\r\n }\r\n\r\n if (this._config.highlightTyped) {\r\n // using .textContent removes any html that can be present (eg: mark added through highlightTyped)\r\n const textContent = link.textContent;\r\n const idx = normalize(textContent).indexOf(lookup);\r\n const highlighted =\r\n textContent.substring(0, idx) +\r\n `${textContent.substring(idx, idx + lookup.length)}` +\r\n textContent.substring(idx + lookup.length, textContent.length);\r\n link.innerHTML = highlighted;\r\n }\r\n\r\n if (this._isItemEnabled(item)) {\r\n hasPossibleValues = true;\r\n }\r\n }\r\n\r\n // No item and we don't allow new items => error\r\n if (!this._config.allowNew && !(lookup.length === 0 && !hasPossibleValues)) {\r\n this._holderElement.classList.add(INVALID_CLASS);\r\n }\r\n\r\n // If we allow new elements, regex validation should happen on canAdd instead\r\n if (this._config.allowNew && this._config.regex && this.isInvalid()) {\r\n this._holderElement.classList.remove(INVALID_CLASS);\r\n }\r\n\r\n // Show all groups with visible values\r\n Array.from(list)\r\n .filter((li) => {\r\n return li.dataset.id;\r\n })\r\n .forEach((li) => {\r\n if (visibleGroups[li.dataset.id] === true) {\r\n showItem(li);\r\n }\r\n });\r\n\r\n if (hasPossibleValues) {\r\n // Remove validation message if we show selectable values\r\n this._holderElement.classList.remove(INVALID_CLASS);\r\n\r\n // Autoselect first\r\n if (firstItem && this._config.autoselectFirst) {\r\n this.removeSelection();\r\n this._moveSelection(NEXT, firstItem);\r\n }\r\n }\r\n\r\n // Remove dropdown if list is empty\r\n if (count === 0) {\r\n if (this._config.notFoundMessage) {\r\n /**\r\n * @type {HTMLElement}\r\n */\r\n const notFound = this._dropElement.querySelector(\".\" + CLASS_PREFIX + \"not-found\");\r\n notFound.style.display = \"block\";\r\n const notFoundMessage = this._config.notFoundMessage.replace(\"{{tag}}\", this._searchInput.value);\r\n notFound.innerHTML = `${notFoundMessage}`;\r\n this._showDropdown();\r\n } else {\r\n // Remove dropdown if not found (do not clear validation)\r\n this.hideSuggestions(false);\r\n }\r\n } else {\r\n // Or show it if necessary\r\n this._showDropdown();\r\n }\r\n }\r\n\r\n _showDropdown() {\r\n this._dropElement.classList.add(SHOW_CLASS);\r\n attrs(this._searchInput, {\r\n \"aria-expanded\": \"true\",\r\n });\r\n this._positionMenu();\r\n }\r\n\r\n _positionMenu() {\r\n const isRTL = this._rtl;\r\n const bounds = this._searchInput.getBoundingClientRect();\r\n\r\n let left = null;\r\n let top = null;\r\n\r\n if (this._config.fixed) {\r\n // In full width, use holder as left reference, otherwise use input\r\n if (this._config.fullWidth) {\r\n const holderBounds = this._holderElement.getBoundingClientRect();\r\n left = holderBounds.x;\r\n } else {\r\n left = bounds.x;\r\n }\r\n top = bounds.y + bounds.height;\r\n } else {\r\n // When positioning is not fixed, we leave it up to the browser\r\n // it may not work in complex situations with scrollable overflows, etc\r\n if (this._config.fullWidth) {\r\n // Stick it at the start\r\n left = 0;\r\n } else {\r\n // Position next to input (offsetLeft != bounds.x)\r\n left = this._searchInput.offsetLeft;\r\n }\r\n }\r\n\r\n // Align end\r\n if (isRTL && !this._config.fullWidth) {\r\n left -= this._dropElement.offsetWidth - bounds.width;\r\n }\r\n\r\n // Horizontal overflow\r\n if (!this._config.fullWidth) {\r\n const w = Math.min(window.innerWidth, document.body.offsetWidth);\r\n const hdiff = isRTL\r\n ? bounds.x + bounds.width - this._dropElement.offsetWidth - 1\r\n : w - 1 - (bounds.x + this._dropElement.offsetWidth);\r\n if (hdiff < 0) {\r\n left = isRTL ? left - hdiff : left + hdiff;\r\n }\r\n }\r\n\r\n // Reset any height overflow adjustement\r\n this._dropElement.style.transform = \"unset\";\r\n\r\n // Use full holder width\r\n if (this._config.fullWidth) {\r\n this._dropElement.style.width = this._holderElement.offsetWidth + \"px\";\r\n }\r\n\r\n // Position element\r\n if (left !== null) {\r\n this._dropElement.style.left = left + \"px\";\r\n }\r\n if (top !== null) {\r\n this._dropElement.style.top = top + \"px\";\r\n }\r\n\r\n // Overflow height\r\n const dropBounds = this._dropElement.getBoundingClientRect();\r\n const h = window.innerHeight;\r\n\r\n // We display above input if it overflows\r\n if (dropBounds.y + dropBounds.height > h) {\r\n this._dropElement.style.transform = \"translateY(calc(-100% - \" + this._searchInput.offsetHeight + \"px))\";\r\n }\r\n }\r\n\r\n /**\r\n * @returns {Number}\r\n */\r\n _getBootstrapVersion() {\r\n let ver = 5;\r\n // If we have jQuery and the tooltip plugin for BS4\r\n //@ts-ignore\r\n if (window.jQuery && $.fn.tooltip != undefined && $.fn.tooltip.Constructor != undefined) {\r\n //@ts-ignore\r\n ver = parseInt($.fn.tooltip.Constructor.VERSION.charAt(0));\r\n }\r\n return ver;\r\n }\r\n\r\n /**\r\n * Find if label is already selected (based on attribute)\r\n * @param {string} text\r\n * @returns {Boolean}\r\n */\r\n _isSelected(text) {\r\n const opt = Array.from(this._selectElement.querySelectorAll(\"option\")).find(\r\n (el) => el.textContent == text && el.getAttribute(\"selected\")\r\n );\r\n return opt ? true : false;\r\n }\r\n\r\n /**\r\n * Find if label is selectable (based on attribute)\r\n * @param {string} text\r\n * @returns {Boolean}\r\n */\r\n _isSelectable(text) {\r\n const opt = Array.from(this._selectElement.querySelectorAll(\"option\")).find(\r\n (el) => el.textContent == text && !el.getAttribute(\"selected\")\r\n );\r\n return opt ? true : false;\r\n }\r\n\r\n /**\r\n * Checks if value matches a configured regex\r\n * @param {string} value\r\n * @returns {Boolean}\r\n */\r\n _validateRegex(value) {\r\n const regex = new RegExp(this._config.regex.trim());\r\n return regex.test(value);\r\n }\r\n\r\n /**\r\n * @returns {HTMLElement}\r\n */\r\n getSelection() {\r\n return this._dropElement.querySelector(\"a.\" + ACTIVE_CLASS);\r\n }\r\n\r\n removeSelection() {\r\n const selection = this.getSelection();\r\n if (selection) {\r\n selection.classList.remove(...this._activeClasses());\r\n }\r\n }\r\n\r\n /**\r\n * @returns {Array}\r\n */\r\n _activeClasses() {\r\n return [...this._config.activeClasses, ...[ACTIVE_CLASS]];\r\n }\r\n\r\n /**\r\n * @deprecated since 1.5\r\n * @returns {HTMLElement}\r\n */\r\n getActiveSelection() {\r\n return this.getSelection();\r\n }\r\n\r\n /**\r\n * @deprecated since 1.5\r\n */\r\n removeActiveSelection() {\r\n return this.removeSelection();\r\n }\r\n\r\n /**\r\n * Remove all items\r\n */\r\n removeAll() {\r\n let items = this.getSelectedValues();\r\n items.forEach((item) => {\r\n this.removeItem(item, true);\r\n });\r\n this._adjustWidth();\r\n }\r\n\r\n /**\r\n * @param {Boolean} noEvents\r\n */\r\n removeLastItem(noEvents = false) {\r\n let items = this._containerElement.querySelectorAll(\"span.\" + CLASS_PREFIX + \"badge\");\r\n if (!items.length) {\r\n return;\r\n }\r\n let lastItem = items[items.length - 1];\r\n this.removeItem(lastItem.getAttribute(VALUE_ATTRIBUTE), noEvents);\r\n }\r\n\r\n enable() {\r\n this._selectElement.setAttribute(\"disabled\", \"\");\r\n this.resetState();\r\n }\r\n\r\n disable() {\r\n rmAttr(this._selectElement, \"disabled\");\r\n this.resetState();\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isDisabled() {\r\n return this._selectElement.hasAttribute(\"disabled\") || this._selectElement.disabled || this._selectElement.hasAttribute(\"readonly\");\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isDropdownVisible() {\r\n return this._dropElement.classList.contains(SHOW_CLASS);\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isInvalid() {\r\n return this._holderElement.classList.contains(INVALID_CLASS);\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isSingle() {\r\n return !this._selectElement.hasAttribute(\"multiple\");\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isMaxReached() {\r\n return this._config.max && this.getSelectedValues().length >= this._config.max;\r\n }\r\n\r\n /**\r\n * @param {string} text\r\n * @param {Object} data\r\n * @returns {Boolean}\r\n */\r\n canAdd(text, data = {}) {\r\n // Check invalid input\r\n if (!text) {\r\n return false;\r\n }\r\n // Doesn't allow new\r\n if (data.new && !this._config.allowNew) {\r\n return false;\r\n }\r\n // Check disabled\r\n if (this.isDisabled()) {\r\n return false;\r\n }\r\n // Check already selected input (single will replace, so never return false if selected)\r\n if (!this.isSingle() && !this._config.allowSame) {\r\n // For new tags, check if selected\r\n if (data.new && this._isSelected(text)) {\r\n return false;\r\n }\r\n // For existing tags, check if selectable\r\n if (!data.new && !this._isSelectable(text)) {\r\n return false;\r\n }\r\n }\r\n // Check for max\r\n if (this.isMaxReached()) {\r\n return false;\r\n }\r\n // Check for regex on new input\r\n if (this._config.regex && data.new && !this._validateRegex(text)) {\r\n this._holderElement.classList.add(INVALID_CLASS);\r\n return false;\r\n }\r\n // Check for custom validation\r\n if (this._config.onCanAdd && this._config.onCanAdd(text, data, this) === false) {\r\n this._holderElement.classList.add(INVALID_CLASS);\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Set data\r\n * @param {Array|Object} src An array of items or a value:label object\r\n * @param {Boolean} init called during init\r\n */\r\n setData(src, init = false) {\r\n // Convert value:label to array\r\n if (!Array.isArray(src)) {\r\n src = Object.entries(src).map(([value, label]) => ({ value, label }));\r\n }\r\n\r\n // Track initial selection in case of reset\r\n if (init) {\r\n // addItem will add attribute back\r\n this._removeSelectedAttrs();\r\n src.forEach((suggestion) => {\r\n const value = suggestion[this._config.valueField];\r\n const label = suggestion[this._config.labelField];\r\n\r\n if (!value) {\r\n return;\r\n }\r\n\r\n if (suggestion.selected || this._config.selected.includes(value)) {\r\n const added = this.addItem(label, value, suggestion.data);\r\n // Add attribute to actual option to allow for same options being selected\r\n if (added) {\r\n added.setAttribute(\"data-init\", \"true\");\r\n }\r\n }\r\n });\r\n }\r\n\r\n this._buildSuggestions(src);\r\n this._resetHtmlState();\r\n }\r\n\r\n /**\r\n * Keep in mind that we can have the same value for multiple options\r\n * @param {*} value\r\n * @param {string} mode\r\n * @param {number} counter\r\n * @returns {HTMLOptionElement|null}\r\n */\r\n _findOption(value, mode = \"\", counter = 0) {\r\n // escape invalid characters for HTML attributes: \\' \" = < > ` &.'\r\n const escapedValue = CSS.escape(value);\r\n const sel = 'option[value=\"' + escapedValue + '\"]' + mode;\r\n const opts = this._selectElement.querySelectorAll(sel);\r\n //@ts-ignore\r\n return opts[counter] || null;\r\n }\r\n\r\n /**\r\n * You might want to use canAdd before to ensure the item is valid\r\n * @param {string} text\r\n * @param {string} value\r\n * @param {object} data\r\n * @return {HTMLOptionElement} The created or selected option\r\n */\r\n addItem(text, value = null, data = {}) {\r\n if (!value) {\r\n value = text;\r\n }\r\n\r\n // Single items remove first\r\n if (this.isSingle() && this.getSelectedValues().length) {\r\n this.removeLastItem(true);\r\n }\r\n\r\n let opt = this._findOption(value, \":not([selected])\");\r\n\r\n // we need to create a new option\r\n if (!opt) {\r\n opt = ce(\"option\");\r\n opt.value = value;\r\n opt.textContent = text; // innerText is not well supported by jsdom\r\n // Pass along data provided\r\n for (const [key, value] of Object.entries(data)) {\r\n opt.dataset[key] = value;\r\n }\r\n this._selectElement.appendChild(opt);\r\n this._config.onCreateItem(opt, this);\r\n }\r\n\r\n if (opt) {\r\n data = Object.assign(\r\n {\r\n title: opt.getAttribute(\"title\"),\r\n },\r\n data,\r\n opt.dataset\r\n );\r\n }\r\n // update select, we need to set attribute for option[selected]\r\n opt.setAttribute(\"selected\", \"selected\");\r\n opt.selected = true;\r\n\r\n this._createBadge(text, value, data);\r\n\r\n // Fire change event\r\n if (this._fireEvents) {\r\n this._selectElement.dispatchEvent(new Event(\"change\", { bubbles: true }));\r\n }\r\n\r\n return opt;\r\n }\r\n\r\n /**\r\n * mobile safari is doing it's own crazy thing...\r\n * without this, it wil not pick up the proper state of the select element and validation will fail\r\n */\r\n _resetHtmlState() {\r\n const html = this._selectElement.innerHTML;\r\n this._selectElement.innerHTML = \"\";\r\n this._selectElement.innerHTML = html;\r\n\r\n this._adjustWidth();\r\n }\r\n\r\n /**\r\n * @param {string} text\r\n * @param {string} value\r\n * @param {object} data\r\n */\r\n _createBadge(text, value = null, data = {}) {\r\n const v5 = this._getBootstrapVersion() === 5;\r\n const allowClear = this._config.allowClear && !data.disabled;\r\n\r\n // create span\r\n let html = text;\r\n\r\n /**\r\n * @type {HTMLSpanElement}\r\n */\r\n let span = ce(\"span\");\r\n let classes = [CLASS_PREFIX + \"badge\"];\r\n\r\n const isSingle = this.isSingle() && !this._config.singleBadge;\r\n\r\n if (!isSingle) {\r\n classes.push(\"badge\");\r\n let badgeStyle = this._config.badgeStyle;\r\n if (data.badgeStyle) {\r\n badgeStyle = data.badgeStyle;\r\n }\r\n if (data.badgeClass) {\r\n classes.push(...data.badgeClass.split(\" \"));\r\n }\r\n if (this._config.baseClass) {\r\n // custom style\r\n classes.push(...this._config.baseClass.split(\" \"));\r\n } else if (v5) {\r\n // https://getbootstrap.com/docs/5.3/components/badge/\r\n classes = [...classes, ...[\"bg-\" + badgeStyle], \"text-truncate\"];\r\n } else {\r\n // https://getbootstrap.com/docs/4.6/components/badge/\r\n classes = [...classes, ...[\"badge-\" + badgeStyle]];\r\n }\r\n\r\n // add extra styles to avoid any layout issues due to very large labels\r\n span.style.maxWidth = \"100%\";\r\n }\r\n\r\n if (data.disabled) {\r\n classes.push(...[\"disabled\", \"opacity-50\"]);\r\n }\r\n\r\n const vertMargin = isSingle ? 0 : 2;\r\n\r\n // We cannot really rely on classes to get a proper sizing\r\n span.style.margin = vertMargin + \"px 6px \" + vertMargin + \"px 0px\";\r\n // Use logical styles for RTL support\r\n span.style.marginBlock = vertMargin + \"px\";\r\n span.style.marginInline = \"0px 6px\";\r\n span.classList.add(...classes);\r\n span.setAttribute(VALUE_ATTRIBUTE, value);\r\n // Tooltips\r\n if (data.title) {\r\n span.setAttribute(\"title\", data.title);\r\n }\r\n\r\n if (allowClear) {\r\n span.style.display = \"inline-flex\";\r\n span.style.alignItems = \"center\";\r\n\r\n // TODO: btn-close white is deprecated\r\n // @link https://getbootstrap.com/docs/5.2/components/close-button/\r\n const closeClass = classes.includes(\"text-dark\") || isSingle ? \"btn-close\" : \"btn-close btn-close-white\";\r\n let btnMargin = \"margin-inline: 0px 6px;\";\r\n let btnOrder = \"\";\r\n if (this._config.clearEnd) {\r\n btnMargin = \"margin-inline: 6px 0px;\";\r\n btnOrder = \"order:2;\"; // use flex order to move to the end\r\n }\r\n const btn = v5\r\n ? ''\r\n : '';\r\n html = btn + html;\r\n }\r\n\r\n span.innerHTML = html;\r\n this._containerElement.insertBefore(span, this._searchInput);\r\n if (window.bootstrap && window.bootstrap.Tooltip && v5) {\r\n window.bootstrap.Tooltip.getOrCreateInstance(span);\r\n }\r\n\r\n if (allowClear) {\r\n span.querySelector(\"button\").addEventListener(\"click\", (event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (!this.isDisabled()) {\r\n this.removeItem(value);\r\n //@ts-ignore\r\n document.activeElement.blur();\r\n this._adjustWidth();\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * @param {string} value\r\n * @param {Boolean} value\r\n */\r\n removeItem(value, noEvents = false) {\r\n // Remove badge if any\r\n // escape invalid characters for HTML attributes: \\' \" = < > ` &.'\r\n const escapedValue = CSS.escape(value);\r\n let items = this._containerElement.querySelectorAll(\"span[\" + VALUE_ATTRIBUTE + '=\"' + escapedValue + '\"]');\r\n if (!items.length) {\r\n return;\r\n }\r\n const idx = items.length - 1;\r\n items[idx].remove();\r\n\r\n // update select\r\n let opt = this._findOption(value, \"[selected]\", idx);\r\n if (opt) {\r\n rmAttr(opt, \"selected\");\r\n opt.selected = false;\r\n\r\n // Fire change event\r\n if (this._fireEvents && !noEvents) {\r\n this._selectElement.dispatchEvent(new Event(\"change\", { bubbles: true }));\r\n }\r\n }\r\n\r\n // Make input visible\r\n if (this._searchInput.style.visibility == \"hidden\" && !this.isMaxReached()) {\r\n this._searchInput.style.visibility = \"visible\";\r\n }\r\n\r\n if (!noEvents) {\r\n this._config.onClearItem(value, this);\r\n }\r\n }\r\n}\r\n\r\nexport default Tags;\r\n"], + "mappings": "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", + "names": ["DEFAULTS", "item", "label", "inst", "value", "option", "event", "text", "data", "response", "CLASS_PREFIX", "LOADING_CLASS", "ACTIVE_CLASS", "INVALID_CLASS", "SHOW_CLASS", "VALUE_ATTRIBUTE", "NEXT", "PREV", "FOCUS_CLASS", "PLACEHOLDER_CLASS", "DISABLED_CLASS", "INSTANCE_MAP", "counter", "activeCounter", "debounce", "func", "timeout", "timer", "args", "calcTextWidth", "size", "span", "ce", "width", "removeDiacritics", "str", "normalize", "fuzzyMatch", "lookup", "pos", "i", "c", "hideItem", "attrs", "showItem", "el", "k", "v", "rmAttr", "attr", "parseBool", "tagName", "Tags", "config", "_selectElement", "_configure", "_keyboardNavigation", "_searchFunc", "_loadFromServer", "_config", "_fireEvents", "_configureParent", "_holderElement", "_containerElement", "_configureHolderElement", "_configureContainerElement", "_configureSelectElement", "_configureSearchInput", "_configureDropElement", "_searchInput", "_dropElement", "selector", "opts", "list", "_timer", "json", "o", "key", "defaultValue", "r", "p", "_getPlaceholder", "firstOption", "dropStyles", "_getBootstrapVersion", "containerStyles", "_rtl", "_abortController", "clearValidation", "_enterValue", "sel", "ev", "lastChar", "addData", "_add", "_adjustWidth", "target", "_moveSelection", "e", "_positionMenu", "init", "_setSelectedAttributes", "selectedOptions", "j", "suggestions", "selection", "show", "params", "input", "inputName", "urlParams", "url", "fetchOptions", "_showSuggestions", "_resetHtmlState", "_isItemEnabled", "li", "fc", "dir", "active", "sibling", "_activeClasses", "selHeight", "selTop", "parent", "parentHeight", "parentScrollHeight", "parentTop", "scrollTop", "a", "computedFontSize", "w", "_buildSuggestions", "idx", "groupId", "suggestion", "newChild", "newChildSpan", "groupSuggestion", "_buildSuggestionsItem", "notFound", "textContent", "newChildLink", "sf", "_removeSelectedAttrs", "opt", "iv", "selected", "check", "_shouldShow", "valueCounter", "count", "firstItem", "hasPossibleValues", "visibleGroups", "link", "_findOption", "showAllSuggestions", "isMatched", "selectFirst", "highlighted", "notFoundMessage", "_showDropdown", "isRTL", "bounds", "left", "top", "hdiff", "dropBounds", "h", "ver", "_isSelected", "_isSelectable", "_validateRegex", "noEvents", "items", "lastItem", "src", "added", "mode", "_createBadge", "html", "v5", "allowClear", "classes", "isSingle", "badgeStyle", "vertMargin", "closeClass", "btnMargin", "btnOrder", "escapedValue", "tags_default"] }