From 4ff5ec18f988c655c14b5a907f4230664392fe58 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 8 Jun 2023 15:04:53 +0200 Subject: [PATCH] build min file --- tags.min.js | 2 +- tags.min.js.map | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tags.min.js b/tags.min.js index 5a78e7b..db9b884 100644 --- a/tags.min.js +++ b/tags.min.js @@ -1,2 +1,2 @@ -var E={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,activeClasses:["bg-primary","text-white"],labelField:"label",valueField:"value",queryParam:"query",server:"",serverMethod:"GET",serverParams:{},fetchOptions:{},liveServer:!1,noCache:!0,debounceTime:300,notFoundMessage:"",onRenderItem:(h,t,e)=>t,onSelectItem:(h,t)=>{},onClearItem:(h,t)=>{},onCreateItem:(h,t)=>{},onBlur:(h,t)=>{},onFocus:(h,t)=>{},onCanAdd:(h,t,e)=>{},onServerResponse:(h,t)=>h.json()},g="tags-",C="is-loading",x="is-active",f="is-invalid",S="show",p="data-value",y="next",A="prev",I="form-control-focus",T="form-placeholder-shown",k="form-control-disabled",w=new WeakMap,O=0;function N(h,t=300){let e;return(...s)=>{clearTimeout(e),e=setTimeout(()=>{h.apply(this,s)},t)}}function R(h,t=null){let e=document.createElement("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=h;let s=Math.ceil(e.clientWidth);return document.body.removeChild(e),s}function F(h){return h.normalize("NFD").replace(/[\u0300-\u036f]/g,"")}function L(h){h.style.display="none",h.ariaHidden="true"}function M(h){h.style.display="list-item",h.ariaHidden="false"}var m=class{constructor(t,e={}){if(!(t instanceof HTMLElement)){console.error("Invalid element",t);return}w.set(t,this),O++,this.i=t,this.p=null,this.I(e),this.h=!1,this.T=N(()=>{this.g(!0)},this.e.debounceTime),this.d=!0,this.k(),this.n=document.createElement("div"),this.r=document.createElement("div"),this.n.appendChild(this.r),this.i.parentElement.insertBefore(this.n,this.i),this.O(),this.F(),this.M(),this.D(),this.H(),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 s=document.querySelectorAll(t);for(let l=0;l["true","false","1","0",!0,!1].includes(l)&&!!JSON.parse(l);for(let[l,a]of Object.entries(E)){if(e[l]===void 0)continue;let i=e[l];switch(typeof a){case"number":this.e[l]=parseInt(i);break;case"boolean":this.e[l]=s(i);break;case"string":this.e[l]=i.toString();break;case"object":if(Array.isArray(a)){let n=i.includes("|")?"|":",";this.e[l]=typeof i=="string"?i.split(n):i}else this.e[l]=typeof i=="string"?JSON.parse(i):i;break;case"function":this.e[l]=typeof i=="string"?i.split(".").reduce((n,r)=>n[r],window):i,this.e[l]||console.error("Invalid function",i);break;default:this.e[l]=i;break}}this.e.placeholder||(this.e.placeholder=this.V())}config(t=null){return t?this.e[t]:this.e}k(){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?"":(t.hasAttribute("selected")&&t.removeAttribute("selected"),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(f)})}H(){this.l=document.createElement("ul"),this.l.classList.add("dropdown-menu",g+"menu","p-0"),this.l.setAttribute("id",g+"menu-"+O),this.l.setAttribute("role","menu"),this.l.style.maxHeight="280px",this.e.fullWidth||(this.l.style.maxWidth="360px"),this.e.fixed&&(this.l.style.position="fixed"),this.l.style.overflowY="auto",this.l.style.overscrollBehavior="contain",this.l.style.textAlign="unset",this.l.addEventListener("mouseenter",t=>{this.h=!1}),this.n.appendChild(this.l),this.s.setAttribute("aria-controls",this.l.getAttribute("id"))}O(){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.S()===4&&(this.n.style.height="auto"),this.n.addEventListener("click",this)}F(){this.r.addEventListener("click",e=>{this.isDisabled()||this.s.style.visibility!="hidden"&&this.s.focus()}),this.r.style.display="flex",this.r.style.alignItems="center",this.r.style.flexWrap="wrap";let t=this.i.selectedOptions||[];for(let e=0;e{this.o&&this.o.abort();let e=!0;if(this.e.addOnBlur&&this.s.value&&(e=this.L()),this.n.classList.remove(I),this.hideSuggestions(e),this.d){let s=this.getSelection(),l={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:l}))}},100)}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 l=this.s.value,a=l,i={};if(this.e.allowNew)i.new=1;else{let n=this.getSelection();if(!n)return;l=n.getAttribute(p),a=n.dataset.label}this.u(a,l,i);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.L();break;case 38:case"ArrowUp":t.preventDefault(),this.h=!0,this.m(A);break;case 40:case"ArrowDown":t.preventDefault(),this.h=!0,this.isDropdownVisible()?this.m(y):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(k)):(this.n.hasAttribute("readonly")&&this.n.removeAttribute("readonly"),this.s.hasAttribute("disabled")&&this.s.removeAttribute("disabled"),this.n.classList.remove(k))}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.A(t)}L(){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 i=document.getElementById(e.related);i&&(e.related=i.value)}let s=new URLSearchParams(e),l=this.e.server,a=Object.assign(this.e.fetchOptions,{method:this.e.serverMethod||"GET",signal:this.o.signal});a.method==="POST"?a.body=s:l+="?"+s.toString(),this.n.classList.add(C),fetch(l,a).then(i=>this.e.onServerResponse(i,this)).then(i=>{let n=i.data||i;this.A(n),this.o=null,t&&this.v()}).catch(i=>{i.name!=="AbortError"&&console.error(i)}).finally(i=>{this.n.classList.remove(C)})}u(t,e=null,s={}){if(!this.canAdd(t,s))return null;let l=this.addItem(t,e,s);return this.e.keepOpen?this.v():this.resetSearchInput(),l}f(t){if(t.style.display==="none")return!1;let e=t.firstElementChild;return e.tagName==="A"&&!e.classList.contains("disabled")}m(t=y,e=null){let s=this.getSelection();if(s){let l=t===y?"nextSibling":"previousSibling";e=s.parentNode;do e=e[l];while(e&&!this.f(e));e?s.classList.remove(...this.c()):s&&(e=s.parentElement)}else{if(t===A)return e;if(!e)for(e=this.l.firstChild;e&&!this.f(e);)e=e.nextSibling}if(e){let l=e.offsetHeight,a=e.offsetTop,i=e.parentNode,n=i.offsetHeight,r=i.scrollHeight,o=i.offsetTop;if(l===0&&setTimeout(()=>{i.scrollTop=0}),t===A){let u=a-o>10?a-o:0;i.scrollTop=u}else a+l-(n+i.scrollTop)>0&&l>0&&(i.scrollTop=a+l-n+1,i.scrollTop+n>=r-10&&(i.scrollTop=a-o));let d=e.querySelector("a");d.classList.add(...this.c()),this.s.setAttribute("aria-activedescendant",d.getAttribute("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(T),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(T));let t=this.s.value||this.s.placeholder,e=window.getComputedStyle(this.n).fontSize,s=R(t,e)+16;this.s.style.width=s+"px"}A(t){for(;this.l.lastChild;)this.l.removeChild(this.l.lastChild);let e=0,s=1;for(let l=0;l',this.l.appendChild(l)}}E(t,e){if(!t[this.e.valueField])return;let s=t[this.e.valueField],l=t[this.e.labelField];if(this.e.server&&!this.e.liveServer&&(t.selected||this.e.selected.includes(s))){let r=this.u(l,s,t.data);r&&(r.dataset.init="true")}let a=this.e.onRenderItem(t,l,this),i=document.createElement("li");i.setAttribute("role","presentation"),t.group_id&&i.setAttribute("data-group-id",""+t.group_id);let n=document.createElement("a");i.append(n),n.setAttribute("id",this.l.getAttribute("id")+"-"+e),n.classList.add("dropdown-item","text-truncate"),t.disabled&&n.classList.add("disabled"),n.setAttribute(p,s),n.setAttribute("data-label",l),n.setAttribute("href","#"),n.innerHTML=a,this.l.appendChild(i),n.addEventListener("mouseenter",r=>{this.h||(this.removeSelection(),i.querySelector("a").classList.add(...this.c()))}),n.addEventListener("mousedown",r=>{r.preventDefault()}),n.addEventListener("click",r=>{r.preventDefault(),this.u(l,s,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.N()){this.hideSuggestions(!1);return}this.e.liveServer?this.T():this.v()}hideSuggestions(t=!0){this.l.classList.remove(S),this.s.ariaExpanded="false",this.removeSelection(),t&&this.n.classList.remove(f)}toggleSuggestions(t=!0,e=!0){this.l.classList.contains(S)?this.hideSuggestions(e):this.showOrSearch(t)}N(){return this.isDisabled()||this.e.maximumItems>0&&this.getSelectedValues().length>=this.e.maximumItems?!1:this.s.value.length>=this.e.suggestionsThreshold}v(){if(this.s.style.visibility=="hidden")return;let t=F(this.s.value).toLowerCase(),e=this.getSelectedValues(),s=this.l.querySelectorAll("li"),l=0,a=null,i=!1,n={};for(let r=0;r0?u.indexOf(t):-1,b=c>=0||t.length===0&&this.e.suggestionsThreshold===0,D=this.e.showAllSuggestions||t.length===0,H=b||t.length===0;if(D||b?(l++,M(o),o.dataset.groupId&&(n[o.dataset.groupId]=!0),!a&&this.f(o)&&H&&(a=o),this.e.maximumItems>0&&l>this.e.maximumItems&&L(o)):L(o),this.e.highlightTyped&&b){let v=d.textContent,V=v.substring(0,c)+`${v.substring(c,c+t.length)}`+v.substring(c+t.length,v.length);d.innerHTML=V}this.f(o)&&(i=!0)}if(!this.e.allowNew&&!(t.length===0&&!i)&&this.n.classList.add(f),this.e.allowNew&&this.e.regex&&this.isInvalid()&&this.n.classList.remove(f),Array.from(s).filter(r=>r.dataset.id).forEach(r=>{n[r.dataset.id]===!0&&M(r)}),i&&(this.n.classList.remove(f),a&&this.e.autoselectFirst&&(this.removeSelection(),this.m(y,a))),l===0)if(this.e.notFoundMessage){let r=this.l.querySelector("."+g+"not-found");r.style.display="block";let o=this.e.notFoundMessage.replace("{{tag}}",this.s.value);r.innerHTML=`${o}`,this.C()}else this.hideSuggestions(!1);else this.C()}C(){this.l.classList.add(S),this.s.ariaExpanded="true",this.b()}b(){let t=window.getComputedStyle(this.s),e=this.s.getBoundingClientRect(),s=t.direction==="rtl",l=null,a=null;if(this.e.fixed?(this.e.fullWidth?l=this.n.getBoundingClientRect().x:l=e.x,a=e.y+e.height):this.e.fullWidth?l=0:l=this.s.offsetLeft,s&&!this.e.fullWidth&&(l-=this.l.offsetWidth-e.width),!this.e.fullWidth){let o=Math.min(window.innerWidth,document.body.offsetWidth),d=s?e.x+e.width-this.l.offsetWidth-1:o-1-(e.x+this.l.offsetWidth);d<0&&(l=s?l-d:l+d)}this.l.style.transform="unset",this.e.fullWidth&&(this.l.style.width=this.n.offsetWidth+"px"),l!==null&&(this.l.style.left=l+"px"),a!==null&&(this.l.style.top=a+"px");let i=this.l.getBoundingClientRect(),n=Math.min(window.innerHeight,document.body.offsetHeight);n-1-(i.y+i.height)<0&&e.y>n/2&&(this.l.style.transform="translateY(calc(-100% - "+this.s.offsetHeight+"px))")}S(){let t=5;return window.jQuery&&$.fn.tooltip!=null&&$.fn.tooltip.Constructor!=null&&(t=parseInt($.fn.tooltip.Constructor.VERSION.charAt(0))),t}R(t){let e=Array.from(this.i.querySelectorAll("option")).find(s=>s.textContent==t);return!!(e&&e.getAttribute("selected"))}q(t){return new RegExp(this.e.regex.trim()).test(t)}getSelection(){return this.l.querySelector("a."+x)}removeSelection(){let t=this.getSelection();t&&t.classList.remove(...this.c())}c(){return[...this.e.activeClasses,x]}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 s=e[e.length-1];this.removeItem(s.getAttribute(p),t)}enable(){this.i.setAttribute("disabled",""),this.resetState()}disable(){this.i.removeAttribute("disabled"),this.resetState()}isDisabled(){return this.i.hasAttribute("disabled")||this.i.disabled||this.i.hasAttribute("readonly")}isDropdownVisible(){return this.l.classList.contains(S)}isInvalid(){return this.n.classList.contains(f)}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.R(t)||this.isMaxReached()?!1:this.e.regex&&e.new&&!this.q(t)?(this.n.classList.add(f),!1):this.e.onCanAdd&&this.e.onCanAdd(t,e,this)===!1?(this.n.classList.add(f),!1):!0}addItem(t,e=null,s={}){e||(e=t),this.isSingle()&&this.getSelectedValues().length&&this.removeLastItem(!0);let l=CSS.escape(e),a=this.i.querySelectorAll('option[value="'+l+'"]'),i=null;if(this.e.allowSame?a.forEach(r=>{r.textContent===t&&!r.selected&&(i=r)}):i=a[0]||null,!i){i=document.createElement("option"),i.value=e,i.textContent=t;for(let[r,o]of Object.entries(s))i.dataset[r]=o;this.i.appendChild(i),this.e.onCreateItem(i,this)}i&&(s=Object.assign({title:i.getAttribute("title")},s,i.dataset)),i.setAttribute("selected","selected"),i.selected=!0;let n=this.i.innerHTML;return this.i.innerHTML="",this.i.innerHTML=n,this.w(t,e,s),this.d&&this.i.dispatchEvent(new Event("change",{bubbles:!0})),i}w(t,e=null,s={}){let l=this.S(),a=this.e.allowClear&&!s.disabled,i=t,n=document.createElement("span"),r=["badge"],o=this.e.badgeStyle;if(s.badgeStyle&&(o=s.badgeStyle),s.badgeClass&&r.push(...s.badgeClass.split(" ")),this.e.baseClass?r.push(...this.e.baseClass.split(" ")):l===5?r=[...r,"bg-"+o,"mw-100","overflow-x-hidden"]:r=[...r,"badge-"+o],s.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(p,e),s.title&&n.setAttribute("title",s.title),a){let d=r.includes("text-dark")?"btn-close":"btn-close-white",u,c;this.e.clearEnd?(u=l===5?"ms-2":"ml-2",c=l===5?"float-end":"float:right;"):(u=l===5?"me-2":"mr-2",c=l===5?"float-start":"float:left;"),i=(l===5?'':'')+i}n.innerHTML=i,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 s=CSS.escape(t),l=this.r.querySelector("span["+p+'="'+s+'"]');if(!l)return;l.remove();let a=this.i.querySelector('option[value="'+s+'"][selected]');a&&(a.removeAttribute("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)}},q=m;export{q as default}; +var I={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:(h,t,e)=>t,onSelectItem:(h,t)=>{},onClearItem:(h,t)=>{},onCreateItem:(h,t)=>{},onBlur:(h,t)=>{},onFocus:(h,t)=>{},onCanAdd:(h,t,e)=>{},onServerResponse:(h,t)=>h.json()},g="tags-",T="is-loading",O="is-active",f="is-invalid",y="show",b="data-value",S="next",A="prev",k="form-control-focus",F="form-placeholder-shown",M="form-control-disabled",w=new WeakMap,D=0;function V(h,t=300){let e;return(...s)=>{clearTimeout(e),e=setTimeout(()=>{h.apply(this,s)},t)}}function N(h,t=null){let e=document.createElement("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=h;let s=Math.ceil(e.clientWidth);return document.body.removeChild(e),s}function R(h){return h.normalize("NFD").replace(/[\u0300-\u036f]/g,"")}function E(h){return h?R(h.toString()).toLowerCase():""}function q(h,t){if(h.indexOf(t)>=0)return!0;let e=0;for(let s=0;s{this.g(!0)},this.e.debounceTime),this.d=!0,this.O(),this.n=document.createElement("div"),this.r=document.createElement("div"),this.n.appendChild(this.r),this.i.parentElement.insertBefore(this.n,this.i),this.k(),this.F(),this.M(),this.D(),this.H(),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 s=document.querySelectorAll(t);for(let l=0;l["true","false","1","0",!0,!1].includes(l)&&!!JSON.parse(l);for(let[l,a]of Object.entries(I)){if(e[l]===void 0)continue;let i=e[l];switch(typeof a){case"number":this.e[l]=parseInt(i);break;case"boolean":this.e[l]=s(i);break;case"string":this.e[l]=i.toString();break;case"object":if(Array.isArray(a)){let n=i.includes("|")?"|":",";this.e[l]=typeof i=="string"?i.split(n):i}else this.e[l]=typeof i=="string"?JSON.parse(i):i;break;case"function":this.e[l]=typeof i=="string"?i.split(".").reduce((n,r)=>n[r],window):i,this.e[l]||console.error("Invalid function",i);break;default:this.e[l]=i;break}}this.e.placeholder||(this.e.placeholder=this.V())}config(t=null){return t?this.e[t]:this.e}O(){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?"":(t.hasAttribute("selected")&&t.removeAttribute("selected"),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(f)})}H(){this.l=document.createElement("ul"),this.l.classList.add("dropdown-menu",g+"menu","p-0"),this.l.id=g+"menu-"+D,this.l.setAttribute("role","menu"),this.l.style.maxHeight="280px",this.e.fullWidth||(this.l.style.maxWidth="360px"),this.e.fixed&&(this.l.style.position="fixed"),this.l.style.overflowY="auto",this.l.style.overscrollBehavior="contain",this.l.style.textAlign="unset",this.l.addEventListener("mouseenter",t=>{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.S()===4&&(this.n.style.height="auto"),this.n.addEventListener("click",this)}F(){this.r.addEventListener("click",e=>{this.isDisabled()||this.s.style.visibility!="hidden"&&this.s.focus()}),this.r.style.display="flex",this.r.style.alignItems="center",this.r.style.flexWrap="wrap";let t=this.i.selectedOptions||[];for(let e=0;e{this.o&&this.o.abort();let e=!0;if(this.e.addOnBlur&&this.s.value&&(e=this.L()),this.n.classList.remove(k),this.hideSuggestions(e),this.d){let s=this.getSelection(),l={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:l}))}},100)}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 l=this.s.value,a=l,i={};if(this.e.allowNew)i.new=1;else{let n=this.getSelection();if(!n)return;l=n.getAttribute(b),a=n.dataset.label}this.u(a,l,i);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.L();break;case 38:case"ArrowUp":t.preventDefault(),this.h=!0,this.m(A);break;case 40:case"ArrowDown":t.preventDefault(),this.h=!0,this.isDropdownVisible()?this.m(S):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(M)):(this.n.hasAttribute("readonly")&&this.n.removeAttribute("readonly"),this.s.hasAttribute("disabled")&&this.s.removeAttribute("disabled"),this.n.classList.remove(M))}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.A(t)}L(){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 i=document.getElementById(e.related);if(i){e.related=i.value;let n=i.getAttribute("name");n&&(e[n]=i.value)}}let s=new URLSearchParams(e),l=this.e.server,a=Object.assign(this.e.fetchOptions,{method:this.e.serverMethod||"GET",signal:this.o.signal});a.method==="POST"?a.body=s:l+="?"+s.toString(),this.n.classList.add(T),fetch(l,a).then(i=>this.e.onServerResponse(i,this)).then(i=>{let n=i[this.e.serverDataKey]||i;this.A(n),this.o=null,t&&this.v()}).catch(i=>{i.name!=="AbortError"&&console.error(i)}).finally(i=>{this.n.classList.remove(T)})}u(t,e=null,s={}){if(!this.canAdd(t,s))return null;let l=this.addItem(t,e,s);return this.e.keepOpen?this.v():this.resetSearchInput(),l}f(t){if(t.style.display==="none")return!1;let e=t.firstElementChild;return e.tagName==="A"&&!e.classList.contains("disabled")}m(t=S,e=null){let s=this.getSelection();if(s){let l=t===S?"nextSibling":"previousSibling";e=s.parentNode;do e=e[l];while(e&&!this.f(e));e?s.classList.remove(...this.c()):s&&(e=s.parentElement)}else{if(t===A)return e;if(!e)for(e=this.l.firstChild;e&&!this.f(e);)e=e.nextSibling}if(e){let l=e.offsetHeight,a=e.offsetTop,i=e.parentNode,n=i.offsetHeight,r=i.scrollHeight,o=i.offsetTop;if(l===0&&setTimeout(()=>{i.scrollTop=0}),t===A){let c=a-o>10?a-o:0;i.scrollTop=c}else a+l-(n+i.scrollTop)>0&&l>0&&(i.scrollTop=a+l-n+1,i.scrollTop+n>=r-10&&(i.scrollTop=a-o));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(F),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(F));let t=this.s.value||this.s.placeholder,e=window.getComputedStyle(this.n).fontSize,s=N(t,e)+16;this.s.style.width=s+"px"}A(t){for(;this.l.lastChild;)this.l.removeChild(this.l.lastChild);let e=0,s=1;for(let l=0;l',this.l.appendChild(l)}}E(t,e){if(!t[this.e.valueField])return;let s=t[this.e.valueField],l=t[this.e.labelField];if(this.e.server&&!this.e.liveServer&&(t.selected||this.e.selected.includes(s))){let r=this.u(l,s,t.data);r&&(r.dataset.init="true")}let a=this.e.onRenderItem(t,l,this),i=document.createElement("li");i.setAttribute("role","presentation"),t.group_id&&i.setAttribute("data-group-id",""+t.group_id);let n=document.createElement("a");i.append(n),n.id=this.l.id+"-"+e,n.classList.add("dropdown-item","text-truncate"),t.disabled&&n.classList.add("disabled"),n.setAttribute(b,s),n.dataset.label=l,this.e.searchFields.forEach(r=>{i.dataset[r]=t[r]}),n.setAttribute("href","#"),n.innerHTML=a,this.l.appendChild(i),n.addEventListener("mouseenter",r=>{this.h||(this.removeSelection(),i.querySelector("a").classList.add(...this.c()))}),n.addEventListener("mousedown",r=>{r.preventDefault()}),n.addEventListener("click",r=>{r.preventDefault(),this.u(l,s,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.N()){this.hideSuggestions(!1);return}this.e.liveServer?this.T():this.v()}hideSuggestions(t=!0){this.l.classList.remove(y),this.s.ariaExpanded="false",this.removeSelection(),t&&this.n.classList.remove(f)}toggleSuggestions(t=!0,e=!0){this.l.classList.contains(y)?this.hideSuggestions(e):this.showOrSearch(t)}N(){return this.isDisabled()||this.e.maximumItems>0&&this.getSelectedValues().length>=this.e.maximumItems?!1:this.s.value.length>=this.e.suggestionsThreshold}v(){if(this.s.style.visibility=="hidden")return;let t=E(this.s.value),e=this.getSelectedValues(),s=this.l.querySelectorAll("li"),l=0,a=null,i=!1,n={};for(let r=0;r0&&this.e.searchFields.forEach(p=>{let m=E(d.dataset[p]);(this.e.fuzzy?q(m,t):m.indexOf(t)>=0)&&(u=!0)});let x=u||t.length===0;if(c||u?(l++,H(o),o.dataset.groupId&&(n[o.dataset.groupId]=!0),!a&&this.f(o)&&x&&(a=o),this.e.maximumItems>0&&l>this.e.maximumItems&&L(o)):L(o),this.e.highlightTyped){let p=d.textContent,m=E(p).indexOf(t),C=p.substring(0,m)+`${p.substring(m,m+t.length)}`+p.substring(m+t.length,p.length);d.innerHTML=C}this.f(o)&&(i=!0)}if(!this.e.allowNew&&!(t.length===0&&!i)&&this.n.classList.add(f),this.e.allowNew&&this.e.regex&&this.isInvalid()&&this.n.classList.remove(f),Array.from(s).filter(r=>r.dataset.id).forEach(r=>{n[r.dataset.id]===!0&&H(r)}),i&&(this.n.classList.remove(f),a&&this.e.autoselectFirst&&(this.removeSelection(),this.m(S,a))),l===0)if(this.e.notFoundMessage){let r=this.l.querySelector("."+g+"not-found");r.style.display="block";let o=this.e.notFoundMessage.replace("{{tag}}",this.s.value);r.innerHTML=`${o}`,this.C()}else this.hideSuggestions(!1);else this.C()}C(){this.l.classList.add(y),this.s.ariaExpanded="true",this.b()}b(){let t=window.getComputedStyle(this.s),e=this.s.getBoundingClientRect(),s=t.direction==="rtl",l=null,a=null;if(this.e.fixed?(this.e.fullWidth?l=this.n.getBoundingClientRect().x:l=e.x,a=e.y+e.height):this.e.fullWidth?l=0:l=this.s.offsetLeft,s&&!this.e.fullWidth&&(l-=this.l.offsetWidth-e.width),!this.e.fullWidth){let o=Math.min(window.innerWidth,document.body.offsetWidth),d=s?e.x+e.width-this.l.offsetWidth-1:o-1-(e.x+this.l.offsetWidth);d<0&&(l=s?l-d:l+d)}this.l.style.transform="unset",this.e.fullWidth&&(this.l.style.width=this.n.offsetWidth+"px"),l!==null&&(this.l.style.left=l+"px"),a!==null&&(this.l.style.top=a+"px");let i=this.l.getBoundingClientRect(),n=Math.min(window.innerHeight,document.body.offsetHeight);n-1-(i.y+i.height)<0&&e.y>n/2&&(this.l.style.transform="translateY(calc(-100% - "+this.s.offsetHeight+"px))")}S(){let t=5;return window.jQuery&&$.fn.tooltip!=null&&$.fn.tooltip.Constructor!=null&&(t=parseInt($.fn.tooltip.Constructor.VERSION.charAt(0))),t}R(t){let e=Array.from(this.i.querySelectorAll("option")).find(s=>s.textContent==t);return!!(e&&e.getAttribute("selected"))}q(t){return new RegExp(this.e.regex.trim()).test(t)}getSelection(){return this.l.querySelector("a."+O)}removeSelection(){let t=this.getSelection();t&&t.classList.remove(...this.c())}c(){return[...this.e.activeClasses,O]}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 s=e[e.length-1];this.removeItem(s.getAttribute(b),t)}enable(){this.i.setAttribute("disabled",""),this.resetState()}disable(){this.i.removeAttribute("disabled"),this.resetState()}isDisabled(){return this.i.hasAttribute("disabled")||this.i.disabled||this.i.hasAttribute("readonly")}isDropdownVisible(){return this.l.classList.contains(y)}isInvalid(){return this.n.classList.contains(f)}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.R(t)||this.isMaxReached()?!1:this.e.regex&&e.new&&!this.q(t)?(this.n.classList.add(f),!1):this.e.onCanAdd&&this.e.onCanAdd(t,e,this)===!1?(this.n.classList.add(f),!1):!0}addItem(t,e=null,s={}){e||(e=t),this.isSingle()&&this.getSelectedValues().length&&this.removeLastItem(!0);let l=CSS.escape(e),a=this.i.querySelectorAll('option[value="'+l+'"]'),i=null;if(this.e.allowSame?a.forEach(r=>{r.textContent===t&&!r.selected&&(i=r)}):i=a[0]||null,!i){i=document.createElement("option"),i.value=e,i.textContent=t;for(let[r,o]of Object.entries(s))i.dataset[r]=o;this.i.appendChild(i),this.e.onCreateItem(i,this)}i&&(s=Object.assign({title:i.getAttribute("title")},s,i.dataset)),i.setAttribute("selected","selected"),i.selected=!0;let n=this.i.innerHTML;return this.i.innerHTML="",this.i.innerHTML=n,this.w(t,e,s),this.d&&this.i.dispatchEvent(new Event("change",{bubbles:!0})),i}w(t,e=null,s={}){let l=this.S(),a=this.e.allowClear&&!s.disabled,i=t,n=document.createElement("span"),r=["badge"],o=this.e.badgeStyle;if(s.badgeStyle&&(o=s.badgeStyle),s.badgeClass&&r.push(...s.badgeClass.split(" ")),this.e.baseClass?r.push(...this.e.baseClass.split(" ")):l===5?r=[...r,"bg-"+o,"mw-100","overflow-x-hidden"]:r=[...r,"badge-"+o],s.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(b,e),s.title&&n.setAttribute("title",s.title),a){let d=r.includes("text-dark")?"btn-close":"btn-close-white",c,u;this.e.clearEnd?(c=l===5?"ms-2":"ml-2",u=l===5?"float-end":"float:right;"):(c=l===5?"me-2":"mr-2",u=l===5?"float-start":"float:left;"),i=(l===5?'':'')+i}n.innerHTML=i,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 s=CSS.escape(t),l=this.r.querySelector("span["+b+'="'+s+'"]');if(!l)return;l.remove();let a=this.i.querySelector('option[value="'+s+'"][selected]');a&&(a.removeAttribute("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)}},z=v;export{z as default}; //# sourceMappingURL=tags.min.js.map diff --git a/tags.min.js.map b/tags.min.js.map index c5659d1..a3fea72 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 {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 {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\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 activeClasses: [\"bg-primary\", \"text-white\"],\r\n labelField: \"label\",\r\n valueField: \"value\",\r\n queryParam: \"query\",\r\n server: \"\",\r\n serverMethod: \"GET\",\r\n serverParams: {},\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 = document.createElement(\"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 {HTMLElement} item\r\n */\r\nfunction hideItem(item) {\r\n item.style.display = \"none\";\r\n item.ariaHidden = \"true\";\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 item.ariaHidden = \"false\";\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 = document.createElement(\"div\"); // this is the one holding the fake input and the dropmenu\r\n this._containerElement = document.createElement(\"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 this[`on${event.type}`](event);\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 if (firstOption.hasAttribute(\"selected\")) {\r\n firstOption.removeAttribute(\"selected\");\r\n }\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 = document.createElement(\"ul\");\r\n this._dropElement.classList.add(...[\"dropdown-menu\", CLASS_PREFIX + \"menu\", \"p-0\"]);\r\n this._dropElement.setAttribute(\"id\", CLASS_PREFIX + \"menu-\" + counter);\r\n this._dropElement.setAttribute(\"role\", \"menu\");\r\n this._dropElement.style.maxHeight = \"280px\";\r\n if (!this._config.fullWidth) {\r\n this._dropElement.style.maxWidth = \"360px\";\r\n }\r\n if (this._config.fixed) {\r\n this._dropElement.style.position = \"fixed\";\r\n }\r\n this._dropElement.style.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 this._dropElement.style.overscrollBehavior = \"contain\";\r\n this._dropElement.style.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.getAttribute(\"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 this._containerElement.style.display = \"flex\";\r\n this._containerElement.style.alignItems = \"center\";\r\n this._containerElement.style.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 = document.createElement(\"input\");\r\n this._searchInput.type = \"text\";\r\n this._searchInput.autocomplete = \"off\";\r\n this._searchInput.spellcheck = false;\r\n // @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-autocomplete\r\n this._searchInput.ariaAutoComplete = \"list\";\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 this._searchInput.ariaExpanded = \"false\";\r\n this._searchInput.ariaHasPopup = \"menu\";\r\n this._searchInput.setAttribute(\"role\", \"combobox\");\r\n this._searchInput.ariaLabel = this._config.searchLabel;\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 if (this._holderElement.hasAttribute(\"readonly\")) {\r\n this._holderElement.removeAttribute(\"readonly\");\r\n }\r\n if (this._searchInput.hasAttribute(\"disabled\")) {\r\n this._searchInput.removeAttribute(\"disabled\");\r\n }\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 }\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 let data = suggestions.data || 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.getAttribute(\"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 = document.createElement(\"li\");\r\n newChild.setAttribute(\"role\", \"presentation\");\r\n newChild.dataset.id = \"\" + groupId;\r\n const newChildSpan = document.createElement(\"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 = document.createElement(\"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 = document.createElement(\"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 = document.createElement(\"a\");\r\n newChild.append(newChildLink);\r\n newChildLink.setAttribute(\"id\", this._dropElement.getAttribute(\"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.setAttribute(\"data-label\", label);\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 this._searchInput.ariaExpanded = \"false\";\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 // 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 = removeDiacritics(this._searchInput.value).toLowerCase();\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 // using .textContent removes any html that can be present (eg: mark added through highlightTyped)\r\n const text = removeDiacritics(link.textContent).toLowerCase();\r\n const idx = lookup.length > 0 ? text.indexOf(lookup) : -1;\r\n // Do we find a matching string or do we display immediately ?\r\n const isMatched = idx >= 0 || (lookup.length === 0 && this._config.suggestionsThreshold === 0);\r\n const showAll = this._config.showAllSuggestions || lookup.length === 0;\r\n const selectFirst = isMatched || lookup.length === 0;\r\n if (showAll || 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 && isMatched) {\r\n const textContent = link.textContent;\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 this._searchInput.ariaExpanded = \"true\";\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 = Math.min(window.innerHeight, document.body.offsetHeight);\r\n const vdiff = h - 1 - (dropBounds.y + dropBounds.height);\r\n\r\n // We display above input if we have more space there\r\n if (vdiff < 0 && bounds.y > h / 2) {\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 this._selectElement.removeAttribute(\"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 = document.createElement(\"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 = document.createElement(\"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 opt.removeAttribute(\"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", "width", "removeDiacritics", "str", "hideItem", "showItem", "Tags", "el", "config", "_selectElement", "_willBlur", "_configure", "_keyboardNavigation", "_searchFunc", "_loadFromServer", "_config", "_fireEvents", "_configureParent", "_holderElement", "_containerElement", "_configureHolderElement", "_configureContainerElement", "_configureSelectElement", "_configureSearchInput", "_configureDropElement", "_searchInput", "_dropElement", "selector", "opts", "list", "i", "o", "parseBool", "key", "defaultValue", "separator", "r", "p", "_getPlaceholder", "k", "firstOption", "_getBootstrapVersion", "initialValues", "j", "initialValue", "_createBadge", "_abortController", "clearValidation", "_enterValue", "sel", "ev", "lastChar", "addData", "_add", "_adjustWidth", "target", "_moveSelection", "e", "_positionMenu", "suggestions", "_buildSuggestions", "selection", "show", "params", "input", "urlParams", "url", "fetchOptions", "_showSuggestions", "_isItemEnabled", "li", "fc", "dir", "active", "sibling", "_activeClasses", "selHeight", "selTop", "parent", "parentHeight", "parentScrollHeight", "parentTop", "scrollTop", "a", "v", "computedFontSize", "w", "idx", "groupId", "suggestion", "newChild", "newChildSpan", "groupSuggestion", "_buildSuggestionsItem", "notFound", "added", "textContent", "newChildLink", "iv", "init", "selected", "check", "_shouldShow", "lookup", "values", "count", "firstItem", "hasPossibleValues", "visibleGroups", "link", "isMatched", "showAll", "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 * - 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 = document.createElement(\"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 item.ariaHidden = \"true\";\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 item.ariaHidden = \"false\";\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 = document.createElement(\"div\"); // this is the one holding the fake input and the dropmenu\r\n this._containerElement = document.createElement(\"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 this[`on${event.type}`](event);\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 if (firstOption.hasAttribute(\"selected\")) {\r\n firstOption.removeAttribute(\"selected\");\r\n }\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 = document.createElement(\"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 this._dropElement.style.maxHeight = \"280px\";\r\n if (!this._config.fullWidth) {\r\n this._dropElement.style.maxWidth = \"360px\";\r\n }\r\n if (this._config.fixed) {\r\n this._dropElement.style.position = \"fixed\";\r\n }\r\n this._dropElement.style.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 this._dropElement.style.overscrollBehavior = \"contain\";\r\n this._dropElement.style.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 this._containerElement.style.display = \"flex\";\r\n this._containerElement.style.alignItems = \"center\";\r\n this._containerElement.style.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 = document.createElement(\"input\");\r\n this._searchInput.type = \"text\";\r\n this._searchInput.autocomplete = \"off\";\r\n this._searchInput.spellcheck = false;\r\n // @link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-autocomplete\r\n this._searchInput.ariaAutoComplete = \"list\";\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 this._searchInput.ariaExpanded = \"false\";\r\n this._searchInput.ariaHasPopup = \"menu\";\r\n this._searchInput.setAttribute(\"role\", \"combobox\");\r\n this._searchInput.ariaLabel = this._config.searchLabel;\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 if (this._holderElement.hasAttribute(\"readonly\")) {\r\n this._holderElement.removeAttribute(\"readonly\");\r\n }\r\n if (this._searchInput.hasAttribute(\"disabled\")) {\r\n this._searchInput.removeAttribute(\"disabled\");\r\n }\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 = document.createElement(\"li\");\r\n newChild.setAttribute(\"role\", \"presentation\");\r\n newChild.dataset.id = \"\" + groupId;\r\n const newChildSpan = document.createElement(\"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 = document.createElement(\"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 = document.createElement(\"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 = document.createElement(\"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 this._searchInput.ariaExpanded = \"false\";\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 // 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 this._searchInput.ariaExpanded = \"true\";\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 = Math.min(window.innerHeight, document.body.offsetHeight);\r\n const vdiff = h - 1 - (dropBounds.y + dropBounds.height);\r\n\r\n // We display above input if we have more space there\r\n if (vdiff < 0 && bounds.y > h / 2) {\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 this._selectElement.removeAttribute(\"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 = document.createElement(\"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 = document.createElement(\"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 opt.removeAttribute(\"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", "width", "removeDiacritics", "str", "normalize", "fuzzyMatch", "lookup", "pos", "i", "c", "hideItem", "showItem", "Tags", "el", "config", "_selectElement", "_willBlur", "_configure", "_keyboardNavigation", "_searchFunc", "_loadFromServer", "_config", "_fireEvents", "_configureParent", "_holderElement", "_containerElement", "_configureHolderElement", "_configureContainerElement", "_configureSelectElement", "_configureSearchInput", "_configureDropElement", "_searchInput", "_dropElement", "selector", "opts", "list", "o", "parseBool", "key", "defaultValue", "separator", "r", "p", "_getPlaceholder", "k", "firstOption", "_getBootstrapVersion", "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", "v", "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"] }