From fe5c6c07b93e6ccba2ae4b47ff4c85765456d7ec Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 5 Jul 2022 08:47:00 +0200 Subject: [PATCH] build min file --- package.json | 2 +- tags.min.js | 2 +- tags.min.js.map | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 8fe61f4..6e28102 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bootstrap5-tags", "type": "module", - "version": "1.4.38", + "version": "1.4.37", "description": "Replace select[multiple] with nices badges for Bootstrap 5", "main": "tags", "scripts": { diff --git a/tags.min.js b/tags.min.js index b6c720d..ba08dcb 100644 --- a/tags.min.js +++ b/tags.min.js @@ -1,2 +1,2 @@ -var b="is-active",c=["is-active","bg-primary","text-white"],f="data-value",m=new WeakMap,p=class{constructor(e,t={}){e.style.display="none",m.set(e,this),this.t=e;let s=l=>["true","false","1","0",!0,!1].includes(l)&&!!JSON.parse(l),i={...t,...e.dataset};for(this.allowNew=i.allowNew?s(i.allowNew):!1,this.showAllSuggestions=i.showAllSuggestions?s(i.showAllSuggestions):!1,this.badgeStyle=i.badgeStyle||"primary",this.allowClear=i.allowClear?s(i.allowClear):!1,this.clearPosition=i.clearPosition||"left",this.server=i.server||!1,this.liveServer=i.liveServer?s(i.liveServer):!1,this.serverParams=i.serverParams||{},typeof this.serverParams=="string"&&(this.serverParams=JSON.parse(this.serverParams)),this.selected=i.selected?i.selected.split(","):[],this.suggestionsThreshold=typeof i.suggestionsThreshold<"u"?parseInt(i.suggestionsThreshold):1,this.validationRegex=i.regex||"",this.separator=i.separator?i.separator.split("|"):[],this.max=i.max?parseInt(i.max):null,this.clearLabel=i.clearLabel||"Clear",this.searchLabel=i.searchLabel||"Type a value",this.valueField=i.valueField||"value",this.labelField=i.labelField||"label",this.keepOpen=i.keepOpen?s(i.keepOpen):!1,this.fullWidth=i.fullWidth?s(i.fullWidth):!1,this.debounceTime=i.debounceTime?parseInt(i.debounceTime):300,this.baseClass=i.baseClass||"",this.placeholder=i.placeholder||this.v(),this.h=!1,this.o=!0,this.b=p.debounce(()=>{this.f(!0)},this.debounceTime),this.overflowParent=null,this.parentForm=e.parentElement;this.parentForm&&(this.parentForm.style.overflow==="hidden"&&(this.overflowParent=this.parentForm),this.parentForm=this.parentForm.parentElement,!(this.parentForm&&this.parentForm.nodeName=="FORM")););this.reset=this.reset.bind(this),this.parentForm&&this.parentForm.addEventListener("reset",this.reset),this.i=document.createElement("div"),this.l=document.createElement("div"),this.s=document.createElement("ul"),this.e=document.createElement("input"),this.i.appendChild(this.l),this.l.appendChild(this.e),this.i.appendChild(this.s),this.t.parentNode.insertBefore(this.i,this.t.nextSibling),this.g(),this.S(),this.w(),this.A(),this.resetState(),this.server&&!this.liveServer?this.f():this.resetSuggestions()}static init(e="select[multiple]",t={}){let s=document.querySelectorAll(e);for(let i=0;i{clearTimeout(s),s=setTimeout(()=>{e.apply(this,i)},t)}}dispose(){m.delete(this.t),this.t.style.display="block",this.i.parentNode.removeChild(this.i),this.parentForm&&this.parentForm.removeEventListener("reset",this.reset)}resetState(){this.isDisabled()?(this.i.setAttribute("readonly",""),this.e.setAttribute("disabled","")):(this.i.hasAttribute("readonly")&&this.i.removeAttribute("readonly"),this.e.hasAttribute("disabled")&&this.e.removeAttribute("disabled"))}resetSuggestions(){let e=Array.from(this.t.querySelectorAll("option")).filter(t=>!t.disabled).map(t=>({value:t.getAttribute("value"),label:t.textContent}));this.p(e)}f(e=!1){this.d&&this.d.abort(),this.d=new AbortController,this.serverParams.query=this.e.value;let t=new URLSearchParams(this.serverParams).toString();fetch(this.server+"?"+t,{signal:this.d.signal}).then(s=>s.json()).then(s=>{let i=s.data||s;this.p(i),this.d=null,e&&this.n()}).catch(s=>{s.name!=="AbortError"&&console.error(s)})}v(){if(this.t.hasAttribute("placeholder"))return this.t.getAttribute("placeholder");if(this.t.dataset.placeholder)return this.t.dataset.placeholder;let e=this.t.querySelector("option");return e?(e.hasAttribute("selected")&&e.removeAttribute("selected"),e.value?"":e.textContent):""}S(){this.s.classList.add("dropdown-menu","p-0"),this.s.style.maxHeight="280px",this.fullWidth||(this.s.style.maxWidth="360px"),this.s.style.overflowY="auto",this.s.addEventListener("mouseenter",e=>{this.h=!1})}g(){this.i.classList.add("form-control","dropdown"),this.t.classList.contains("form-select-lg")&&this.i.classList.add("form-control-lg"),this.t.classList.contains("form-select-sm")&&this.i.classList.add("form-control-sm"),this.overflowParent&&(this.i.style.position="inherit"),this.m()===4&&(this.i.style.height="auto")}w(){this.l.addEventListener("click",t=>{this.isDisabled()||this.e.style.visibility!="hidden"&&this.e.focus()});let e=this.t.selectedOptions;for(let t=0;t{if(e.data){let t=e.data.slice(-1);if(this.separator.length&&this.e.value&&this.separator.includes(t)){this.e.value=this.e.value.slice(0,-1);let s=this.e.value;this.c(s,null);return}}this.a(),this.e.value.length>=this.suggestionsThreshold?this.liveServer?this.b():this.n():this.r()}),this.e.addEventListener("focus",e=>{this.e.value.length>=this.suggestionsThreshold&&this.n()}),this.e.addEventListener("focusout",e=>{this.r(),this.keepOpen&&this.u()}),this.e.addEventListener("keydown",e=>{switch(e.keyCode||e.key){case 13:case"Enter":e.preventDefault();let s=this.getActiveSelection();if(s)s.click();else if(this.allowNew&&this.e.value){let l=this.e.value;this.c(l,null)}break;case 38:case"ArrowUp":e.preventDefault(),this.h=!0;let i=this.L();this.e.value.length==0&&this.s.classList.contains("show")&&!i&&this.r();break;case 40:case"ArrowDown":e.preventDefault(),this.h=!0,this.C(),this.e.value.length==0&&!this.s.classList.contains("show")&&this.n();break;case 8:case"Backspace":this.e.value.length==0&&(this.removeLastItem(),this.a(),this.r());break;case 27:case"Escape":this.r();break}})}c(e,t=null,s={}){!this.canAdd(e,t)||(this.addItem(e,t,s),this.keepOpen?this.n():this.u())}L(){let e=this.getActiveSelection();if(e){let t=e.parentNode;do t=t.previousSibling;while(t&&t.style.display=="none");return t?(e.classList.remove(...c),t.querySelector("a").classList.add(...c),t.parentNode.scrollTop=t.offsetTop-t.parentNode.offsetTop,t):null}return null}C(){let e=this.getActiveSelection(),t=null;if(e){t=e.parentNode;do t=t.nextSibling;while(t&&t.style.display=="none");return t?(e.classList.remove(...c),t.querySelector("a").classList.add(...c),t.offsetTop>t.parentNode.offsetHeight-t.offsetHeight&&(t.parentNode.scrollTop+=t.offsetHeight),t):null}return t}x(e,t=null){var s=document.createElement("span");document.body.appendChild(s),s.style.fontSize=t||"inherit",s.style.height="auto",s.style.width="auto",s.style.position="absolute",s.style.whiteSpace="no-wrap",s.innerHTML=e;let i=Math.ceil(s.clientWidth)+8;return document.body.removeChild(s),i}a(){this.e.value?this.e.size=this.e.value.length:this.getSelectedValues().length?(this.e.placeholder="",this.e.size=1):(this.e.size=this.placeholder.length>0?this.placeholder.length:1,this.e.placeholder=this.placeholder);let e=this.e.value||this.e.placeholder,t=window.getComputedStyle(this.i).fontSize,s=this.x(e,t);this.e.style.minWidth=s+"px"}p(e){for(;this.s.lastChild;)this.s.removeChild(this.s.lastChild);for(let t=0;t{this.h||(this.removeActiveSelection(),i.querySelector("a").classList.add(...c))}),l.addEventListener("mousemove",h=>{this.h=!1}),l.addEventListener("mousedown",h=>{h.preventDefault()}),l.addEventListener("click",h=>{h.preventDefault(),this.c(l.textContent,l.getAttribute(f),l.dataset)})}}reset(){this.removeAll(),this.o=!1;let e=this.t.querySelectorAll("option[data-init]");for(let t=0;t=this.max?this.e.style.visibility="hidden":this.e.style.visibility=="hidden"&&(this.e.style.visibility="visible"),this.isSingle()&&!e&&document.activeElement.blur()}getSelectedValues(){let e=this.t.querySelectorAll("option[selected]");return Array.from(e).map(t=>t.value)}n(){if(this.e.style.visibility=="hidden")return;let e=this.e.value.toLocaleLowerCase(),t=this.getSelectedValues(),s=this.s.querySelectorAll("li"),i=!1,l=null,h=!1;for(let r=0;rs.textContent==e);return!!(t&&t.getAttribute("selected"))}k(e){return new RegExp(this.validationRegex.trim()).test(e)}getActiveSelection(){return this.s.querySelector("a."+b)}removeActiveSelection(){let e=this.getActiveSelection();e&&e.classList.remove(...c)}removeAll(){this.getSelectedValues().forEach(t=>{this.removeItem(t,!0)}),this.a()}removeLastItem(e){let t=this.l.querySelectorAll("span");if(!t.length)return;let s=t[t.length-1];this.removeItem(s.getAttribute(f),e)}isDisabled(){return this.t.hasAttribute("disabled")||this.t.disabled||this.t.hasAttribute("readonly")}isInvalid(){return this.i.classList.contains("is-invalid")}isSingle(){return!this.t.hasAttribute("multiple")}canAdd(e,t=null){return t||(t=e),!e||this.isDisabled()||!this.isSingle()&&this.E(e)||this.max&&this.getSelectedValues().length>=this.max?!1:this.validationRegex&&!this.k(e)?(this.i.classList.add("is-invalid"),!1):!0}addItem(e,t=null,s={}){t||(t=e),this.isSingle()&&this.getSelectedValues().length&&this.removeLastItem(!0);let i=this.m(),l=this.t.querySelector('option[value="'+t+'"]');l&&(s=l.dataset);let h=e,r=document.createElement("span"),a=["badge"],d=this.badgeStyle;if(s.badgeStyle&&(d=s.badgeStyle),s.badgeClass&&a.push(...s.badgeClass.split(" ")),this.baseClass?(i===5?a.push("me-2"):a.push("mr-2"),a.push(...this.baseClass.split(" "))):i===5?a=[...a,"me-2","bg-"+d,"mw-100"]:a=[...a,"mr-2","badge-"+d],r.classList.add(...a),r.setAttribute(f,t),this.allowClear){let n=a.includes("text-dark")?"btn-close":"btn-close-white",o,u;this.clearPosition==="right"?(o=i===5?"ms-2":"ml-2",u=i===5?"float-end":"float:right;"):(o=i===5?"me-2":"mr-2",u=i===5?"float-start":"float:left;"),h=(i===5?'':'')+h}if(r.innerHTML=h,this.l.insertBefore(r,this.e),this.allowClear&&r.querySelector("button").addEventListener("click",n=>{n.preventDefault(),n.stopPropagation(),this.isDisabled()||(this.removeItem(t),document.activeElement.blur(),this.a())}),!l){l=document.createElement("option"),l.value=t,l.textContent=e;for(let[n,o]of Object.entries(s))l.dataset[n]=o;this.t.appendChild(l)}l.setAttribute("selected","selected"),l.selected=!0,this.o&&this.t.dispatchEvent(new Event("change",{bubbles:!0}))}removeItem(e,t=!1){let s=this.l.querySelector("span["+f+'="'+e+'"]');if(!s)return;s.remove();let i=this.t.querySelector('option[value="'+e+'"]');i&&(i.removeAttribute("selected"),i.selected=!1,this.o&&!t&&this.t.dispatchEvent(new Event("change",{bubbles:!0}))),this.e.style.visibility=="hidden"&&this.max&&this.getSelectedValues().length["true","false","1","0",!0,!1].includes(l)&&!!JSON.parse(l),i={...t,...e.dataset};for(this.allowNew=i.allowNew?s(i.allowNew):!1,this.showAllSuggestions=i.showAllSuggestions?s(i.showAllSuggestions):!1,this.badgeStyle=i.badgeStyle||"primary",this.allowClear=i.allowClear?s(i.allowClear):!1,this.clearEnd=i.clearEnd?s(i.clearEnd):!1,this.server=i.server||!1,this.liveServer=i.liveServer?s(i.liveServer):!1,this.serverParams=i.serverParams||{},typeof this.serverParams=="string"&&(this.serverParams=JSON.parse(this.serverParams)),this.selected=i.selected?i.selected.split(","):[],this.suggestionsThreshold=typeof i.suggestionsThreshold<"u"?parseInt(i.suggestionsThreshold):1,this.validationRegex=i.regex||"",this.separator=i.separator?i.separator.split("|"):[],this.max=i.max?parseInt(i.max):null,this.clearLabel=i.clearLabel||"Clear",this.searchLabel=i.searchLabel||"Type a value",this.valueField=i.valueField||"value",this.labelField=i.labelField||"label",this.keepOpen=i.keepOpen?s(i.keepOpen):!1,this.fullWidth=i.fullWidth?s(i.fullWidth):!1,this.debounceTime=i.debounceTime?parseInt(i.debounceTime):300,this.baseClass=i.baseClass||"",this.placeholder=i.placeholder||this.v(),this.n=!1,this.o=!0,this.b=p.debounce(()=>{this.f(!0)},this.debounceTime),this.overflowParent=null,this.parentForm=e.parentElement;this.parentForm&&(this.parentForm.style.overflow==="hidden"&&(this.overflowParent=this.parentForm),this.parentForm=this.parentForm.parentElement,!(this.parentForm&&this.parentForm.nodeName=="FORM")););this.reset=this.reset.bind(this),this.parentForm&&this.parentForm.addEventListener("reset",this.reset),this.i=document.createElement("div"),this.l=document.createElement("div"),this.s=document.createElement("ul"),this.e=document.createElement("input"),this.i.appendChild(this.l),this.l.appendChild(this.e),this.i.appendChild(this.s),this.t.parentNode.insertBefore(this.i,this.t.nextSibling),this.g(),this.S(),this.w(),this.A(),this.resetState(),this.server&&!this.liveServer?this.f():this.resetSuggestions()}static init(e="select[multiple]",t={}){let s=document.querySelectorAll(e);for(let i=0;i{clearTimeout(s),s=setTimeout(()=>{e.apply(this,i)},t)}}dispose(){m.delete(this.t),this.t.style.display="block",this.i.parentNode.removeChild(this.i),this.parentForm&&this.parentForm.removeEventListener("reset",this.reset)}resetState(){this.isDisabled()?(this.i.setAttribute("readonly",""),this.e.setAttribute("disabled","")):(this.i.hasAttribute("readonly")&&this.i.removeAttribute("readonly"),this.e.hasAttribute("disabled")&&this.e.removeAttribute("disabled"))}resetSuggestions(){let e=Array.from(this.t.querySelectorAll("option")).filter(t=>!t.disabled).map(t=>({value:t.getAttribute("value"),label:t.textContent}));this.p(e)}f(e=!1){this.d&&this.d.abort(),this.d=new AbortController,this.serverParams.query=this.e.value;let t=new URLSearchParams(this.serverParams).toString();fetch(this.server+"?"+t,{signal:this.d.signal}).then(s=>s.json()).then(s=>{let i=s.data||s;this.p(i),this.d=null,e&&this.h()}).catch(s=>{s.name!=="AbortError"&&console.error(s)})}v(){if(this.t.hasAttribute("placeholder"))return this.t.getAttribute("placeholder");if(this.t.dataset.placeholder)return this.t.dataset.placeholder;let e=this.t.querySelector("option");return e?(e.hasAttribute("selected")&&e.removeAttribute("selected"),e.value?"":e.textContent):""}S(){this.s.classList.add("dropdown-menu","p-0"),this.s.style.maxHeight="280px",this.fullWidth||(this.s.style.maxWidth="360px"),this.s.style.overflowY="auto",this.s.addEventListener("mouseenter",e=>{this.n=!1})}g(){this.i.classList.add("form-control","dropdown"),this.t.classList.contains("form-select-lg")&&this.i.classList.add("form-control-lg"),this.t.classList.contains("form-select-sm")&&this.i.classList.add("form-control-sm"),this.overflowParent&&(this.i.style.position="inherit"),this.m()===4&&(this.i.style.height="auto")}w(){this.l.addEventListener("click",t=>{this.isDisabled()||this.e.style.visibility!="hidden"&&this.e.focus()});let e=this.t.selectedOptions;for(let t=0;t{if(e.data){let t=e.data.slice(-1);if(this.separator.length&&this.e.value&&this.separator.includes(t)){this.e.value=this.e.value.slice(0,-1);let s=this.e.value;this.c(s,null);return}}this.a(),this.e.value.length>=this.suggestionsThreshold?this.liveServer?this.b():this.h():this.r()}),this.e.addEventListener("focus",e=>{this.e.value.length>=this.suggestionsThreshold&&this.h()}),this.e.addEventListener("focusout",e=>{this.r(),this.keepOpen&&this.u()}),this.e.addEventListener("keydown",e=>{switch(e.keyCode||e.key){case 13:case"Enter":e.preventDefault();let s=this.getActiveSelection();if(s)s.click();else if(this.allowNew&&this.e.value){let l=this.e.value;this.c(l,null)}break;case 38:case"ArrowUp":e.preventDefault(),this.n=!0;let i=this.L();this.e.value.length==0&&this.s.classList.contains("show")&&!i&&this.r();break;case 40:case"ArrowDown":e.preventDefault(),this.n=!0,this.C(),this.e.value.length==0&&!this.s.classList.contains("show")&&this.h();break;case 8:case"Backspace":this.e.value.length==0&&(this.removeLastItem(),this.a(),this.r());break;case 27:case"Escape":this.r();break}})}c(e,t=null,s={}){!this.canAdd(e,t)||(this.addItem(e,t,s),this.keepOpen?this.h():this.u())}L(){let e=this.getActiveSelection();if(e){let t=e.parentNode;do t=t.previousSibling;while(t&&t.style.display=="none");return t?(e.classList.remove(...c),t.querySelector("a").classList.add(...c),t.parentNode.scrollTop=t.offsetTop-t.parentNode.offsetTop,t):null}return null}C(){let e=this.getActiveSelection(),t=null;if(e){t=e.parentNode;do t=t.nextSibling;while(t&&t.style.display=="none");return t?(e.classList.remove(...c),t.querySelector("a").classList.add(...c),t.offsetTop>t.parentNode.offsetHeight-t.offsetHeight&&(t.parentNode.scrollTop+=t.offsetHeight),t):null}return t}E(e,t=null){var s=document.createElement("span");document.body.appendChild(s),s.style.fontSize=t||"inherit",s.style.height="auto",s.style.width="auto",s.style.position="absolute",s.style.whiteSpace="no-wrap",s.innerHTML=e;let i=Math.ceil(s.clientWidth)+8;return document.body.removeChild(s),i}a(){this.e.value?this.e.size=this.e.value.length:this.getSelectedValues().length?(this.e.placeholder="",this.e.size=1):(this.e.size=this.placeholder.length>0?this.placeholder.length:1,this.e.placeholder=this.placeholder);let e=this.e.value||this.e.placeholder,t=window.getComputedStyle(this.i).fontSize,s=this.E(e,t);this.e.style.minWidth=s+"px"}p(e){for(;this.s.lastChild;)this.s.removeChild(this.s.lastChild);for(let t=0;t{this.n||(this.removeActiveSelection(),i.querySelector("a").classList.add(...c))}),l.addEventListener("mousemove",n=>{this.n=!1}),l.addEventListener("mousedown",n=>{n.preventDefault()}),l.addEventListener("click",n=>{n.preventDefault(),this.c(l.textContent,l.getAttribute(f),l.dataset)})}}reset(){this.removeAll(),this.o=!1;let e=this.t.querySelectorAll("option[data-init]");for(let t=0;t=this.max?this.e.style.visibility="hidden":this.e.style.visibility=="hidden"&&(this.e.style.visibility="visible"),this.isSingle()&&!e&&document.activeElement.blur()}getSelectedValues(){let e=this.t.querySelectorAll("option[selected]");return Array.from(e).map(t=>t.value)}h(){if(this.e.style.visibility=="hidden")return;let e=this.e.value.toLocaleLowerCase(),t=this.getSelectedValues(),s=this.s.querySelectorAll("li"),i=!1,l=null,n=!1;for(let r=0;rs.textContent==e);return!!(t&&t.getAttribute("selected"))}k(e){return new RegExp(this.validationRegex.trim()).test(e)}getActiveSelection(){return this.s.querySelector("a."+b)}removeActiveSelection(){let e=this.getActiveSelection();e&&e.classList.remove(...c)}removeAll(){this.getSelectedValues().forEach(t=>{this.removeItem(t,!0)}),this.a()}removeLastItem(e){let t=this.l.querySelectorAll("span");if(!t.length)return;let s=t[t.length-1];this.removeItem(s.getAttribute(f),e)}isDisabled(){return this.t.hasAttribute("disabled")||this.t.disabled||this.t.hasAttribute("readonly")}isInvalid(){return this.i.classList.contains("is-invalid")}isSingle(){return!this.t.hasAttribute("multiple")}canAdd(e,t=null){return t||(t=e),!e||this.isDisabled()||!this.isSingle()&&this.x(e)||this.max&&this.getSelectedValues().length>=this.max?!1:this.validationRegex&&!this.k(e)?(this.i.classList.add("is-invalid"),!1):!0}addItem(e,t=null,s={}){t||(t=e),this.isSingle()&&this.getSelectedValues().length&&this.removeLastItem(!0);let i=this.m(),l=this.t.querySelector('option[value="'+t+'"]');l&&(s=l.dataset);let n=e,r=document.createElement("span"),a=["badge"],d=this.badgeStyle;if(s.badgeStyle&&(d=s.badgeStyle),s.badgeClass&&a.push(...s.badgeClass.split(" ")),this.baseClass?(i===5?a.push("me-2"):a.push("mr-2"),a.push(...this.baseClass.split(" "))):i===5?a=[...a,"me-2","bg-"+d,"mw-100"]:a=[...a,"mr-2","badge-"+d],r.classList.add(...a),r.setAttribute(f,t),this.allowClear){let h=a.includes("text-dark")?"btn-close":"btn-close-white",o,u;this.clearEnd?(o=i===5?"ms-2":"ml-2",u=i===5?"float-end":"float:right;"):(o=i===5?"me-2":"mr-2",u=i===5?"float-start":"float:left;"),n=(i===5?'':'')+n}if(r.innerHTML=n,this.l.insertBefore(r,this.e),this.allowClear&&r.querySelector("button").addEventListener("click",h=>{h.preventDefault(),h.stopPropagation(),this.isDisabled()||(this.removeItem(t),document.activeElement.blur(),this.a())}),!l){l=document.createElement("option"),l.value=t,l.textContent=e;for(let[h,o]of Object.entries(s))l.dataset[h]=o;this.t.appendChild(l)}l.setAttribute("selected","selected"),l.selected=!0,this.o&&this.t.dispatchEvent(new Event("change",{bubbles:!0}))}removeItem(e,t=!1){let s=this.l.querySelector("span["+f+'="'+e+'"]');if(!s)return;s.remove();let i=this.t.querySelector('option[value="'+e+'"]');i&&(i.removeAttribute("selected"),i.selected=!1,this.o&&!t&&this.t.dispatchEvent(new Event("change",{bubbles:!0}))),this.e.style.visibility=="hidden"&&this.max&&this.getSelectedValues().length [\"true\", \"false\", \"1\", \"0\", true, false].includes(value) && !!JSON.parse(value);\r\n\r\n // Handle options, using global settings first and data attr override\r\n const opts = { ...globalOpts, ...el.dataset };\r\n this.allowNew = opts.allowNew ? parseBool(opts.allowNew) : false;\r\n this.showAllSuggestions = opts.showAllSuggestions ? parseBool(opts.showAllSuggestions) : false;\r\n this.badgeStyle = opts.badgeStyle || \"primary\";\r\n this.allowClear = opts.allowClear ? parseBool(opts.allowClear) : false;\r\n this.clearPosition = opts.clearPosition || \"left\";\r\n this.server = opts.server || false;\r\n this.liveServer = opts.liveServer ? parseBool(opts.liveServer) : false;\r\n this.serverParams = opts.serverParams || {};\r\n if (typeof this.serverParams == \"string\") {\r\n this.serverParams = JSON.parse(this.serverParams);\r\n }\r\n this.selected = opts.selected ? opts.selected.split(\",\") : [];\r\n this.suggestionsThreshold = typeof opts.suggestionsThreshold != \"undefined\" ? parseInt(opts.suggestionsThreshold) : 1;\r\n this.validationRegex = opts.regex || \"\";\r\n this.separator = opts.separator ? opts.separator.split(\"|\") : [];\r\n this.max = opts.max ? parseInt(opts.max) : null;\r\n this.clearLabel = opts.clearLabel || \"Clear\";\r\n this.searchLabel = opts.searchLabel || \"Type a value\";\r\n this.valueField = opts.valueField || \"value\";\r\n this.labelField = opts.labelField || \"label\";\r\n this.keepOpen = opts.keepOpen ? parseBool(opts.keepOpen) : false;\r\n this.fullWidth = opts.fullWidth ? parseBool(opts.fullWidth) : false;\r\n this.debounceTime = opts.debounceTime ? parseInt(opts.debounceTime) : 300;\r\n this.baseClass = opts.baseClass || \"\";\r\n\r\n this.placeholder = opts.placeholder || this._getPlaceholder();\r\n this._keyboardNavigation = false;\r\n this._fireEvents = true;\r\n this._searchFunc = Tags.debounce(() => {\r\n this._loadFromServer(true);\r\n }, this.debounceTime);\r\n\r\n this.overflowParent = null;\r\n this.parentForm = el.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 this.reset = this.reset.bind(this);\r\n if (this.parentForm) {\r\n this.parentForm.addEventListener(\"reset\", this.reset);\r\n }\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._dropElement = document.createElement(\"ul\");\r\n this._searchInput = document.createElement(\"input\");\r\n\r\n this._holderElement.appendChild(this._containerElement);\r\n this._containerElement.appendChild(this._searchInput);\r\n this._holderElement.appendChild(this._dropElement);\r\n // insert after select\r\n this._selectElement.parentNode.insertBefore(this._holderElement, this._selectElement.nextSibling);\r\n\r\n // Configure them\r\n this._configureHolderElement();\r\n this._configureDropElement();\r\n this._configureContainerElement();\r\n this._configureSearchInput();\r\n this.resetState();\r\n\r\n if (this.server && !this.liveServer) {\r\n this._loadFromServer();\r\n } else {\r\n this.resetSuggestions();\r\n }\r\n }\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 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 /**\r\n * @param {Function} func\r\n * @param {number} timeout\r\n * @returns {Function}\r\n */\r\n static debounce(func, timeout = 300) {\r\n let timer;\r\n return (...args) => {\r\n clearTimeout(timer);\r\n timer = setTimeout(() => {\r\n func.apply(this, args);\r\n }, timeout);\r\n };\r\n }\r\n\r\n dispose() {\r\n INSTANCE_MAP.delete(this._selectElement);\r\n this._selectElement.style.display = \"block\";\r\n this._holderElement.parentNode.removeChild(this._holderElement);\r\n if (this.parentForm) {\r\n this.parentForm.removeEventListener(\"reset\", this.reset);\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 } 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 }\r\n }\r\n\r\n resetSuggestions() {\r\n let suggestions = Array.from(this._selectElement.querySelectorAll(\"option\"))\r\n .filter((option) => {\r\n return !option.disabled;\r\n })\r\n .map((option) => {\r\n return {\r\n value: option.getAttribute(\"value\"),\r\n label: option.textContent,\r\n };\r\n });\r\n this._buildSuggestions(suggestions);\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 this.serverParams.query = this._searchInput.value;\r\n const params = new URLSearchParams(this.serverParams).toString();\r\n\r\n fetch(this.server + \"?\" + params, { signal: this._abortController.signal })\r\n .then((r) => r.json())\r\n .then((suggestions) => {\r\n let data = suggestions.data || 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 }\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) {\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 _configureDropElement() {\r\n this._dropElement.classList.add(...[\"dropdown-menu\", \"p-0\"]);\r\n this._dropElement.style.maxHeight = \"280px\";\r\n if (!this.fullWidth) {\r\n this._dropElement.style.maxWidth = \"360px\";\r\n }\r\n this._dropElement.style.overflowY = \"auto\";\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 }\r\n\r\n _configureHolderElement() {\r\n this._holderElement.classList.add(...[\"form-control\", \"dropdown\"]);\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 don't have an overflow parent, we can simply inherit styles\r\n // If we have an overflow parent, it needs a relatively positioned element\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\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 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 let initialValues = this._selectElement.selectedOptions;\r\n for (let j = 0; j < initialValues.length; j++) {\r\n let initialValue = initialValues[j];\r\n if (!initialValue.value) {\r\n continue;\r\n }\r\n // track initial values for reset\r\n initialValue.dataset.init = 1;\r\n this.addItem(initialValue.textContent, initialValue.value);\r\n }\r\n }\r\n\r\n _configureSearchInput() {\r\n this._searchInput.type = \"text\";\r\n this._searchInput.autocomplete = \"off\";\r\n this._searchInput.spellcheck = false;\r\n this._searchInput.style.backgroundColor = \"transparent\";\r\n this._searchInput.style.border = 0;\r\n this._searchInput.style.outline = 0;\r\n this._searchInput.style.maxWidth = \"100%\";\r\n this._searchInput.ariaLabel = this.searchLabel;\r\n this._resetSearchInput(true);\r\n\r\n this._searchInput.addEventListener(\"input\", (event) => {\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 (event.data) {\r\n const lastChar = event.data.slice(-1);\r\n if (this.separator.length && this._searchInput.value && this.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 text = this._searchInput.value;\r\n this._add(text, null);\r\n return;\r\n }\r\n }\r\n\r\n // Adjust input width to current content\r\n this._adjustWidth();\r\n\r\n // Check if we should display suggestions\r\n if (this._searchInput.value.length >= this.suggestionsThreshold) {\r\n if (this.liveServer) {\r\n this._searchFunc();\r\n } else {\r\n this._showSuggestions();\r\n }\r\n } else {\r\n this._hideSuggestions();\r\n }\r\n });\r\n this._searchInput.addEventListener(\"focus\", (event) => {\r\n if (this._searchInput.value.length >= this.suggestionsThreshold) {\r\n this._showSuggestions();\r\n }\r\n });\r\n this._searchInput.addEventListener(\"focusout\", (event) => {\r\n this._hideSuggestions();\r\n if (this.keepOpen) {\r\n this._resetSearchInput();\r\n }\r\n });\r\n // keypress doesn't send arrow keys, so we use keydown\r\n this._searchInput.addEventListener(\"keydown\", (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 // Keyboard keys\r\n switch (key) {\r\n case 13:\r\n case \"Enter\":\r\n event.preventDefault();\r\n let selection = this.getActiveSelection();\r\n if (selection) {\r\n selection.click();\r\n } else {\r\n // We use what is typed if not selected and not empty\r\n if (this.allowNew && this._searchInput.value) {\r\n let text = this._searchInput.value;\r\n this._add(text, null);\r\n }\r\n }\r\n break;\r\n case 38:\r\n case \"ArrowUp\":\r\n event.preventDefault();\r\n this._keyboardNavigation = true;\r\n let newSelection = this._moveSelectionUp();\r\n // If we use arrow up without input and there is no new selection, hide suggestions\r\n if (this._searchInput.value.length == 0 && this._dropElement.classList.contains(\"show\") && !newSelection) {\r\n this._hideSuggestions();\r\n }\r\n break;\r\n case 40:\r\n case \"ArrowDown\":\r\n event.preventDefault();\r\n this._keyboardNavigation = true;\r\n this._moveSelectionDown();\r\n // If we use arrow down without input, show suggestions\r\n if (this._searchInput.value.length == 0 && !this._dropElement.classList.contains(\"show\")) {\r\n this._showSuggestions();\r\n }\r\n break;\r\n case 8:\r\n case \"Backspace\":\r\n if (this._searchInput.value.length == 0) {\r\n this.removeLastItem();\r\n this._adjustWidth();\r\n this._hideSuggestions();\r\n }\r\n break;\r\n case 27:\r\n case \"Escape\":\r\n // We may wish to not use the suggestions\r\n this._hideSuggestions();\r\n break;\r\n }\r\n });\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 _add(text, value = null, data = {}) {\r\n if (!this.canAdd(text, value)) {\r\n return;\r\n }\r\n this.addItem(text, value, data);\r\n if (this.keepOpen) {\r\n this._showSuggestions();\r\n } else {\r\n this._resetSearchInput();\r\n }\r\n }\r\n\r\n /**\r\n * @returns {HTMLElement}\r\n */\r\n _moveSelectionUp() {\r\n let active = this.getActiveSelection();\r\n if (active) {\r\n let prev = active.parentNode;\r\n do {\r\n prev = prev.previousSibling;\r\n } while (prev && prev.style.display == \"none\");\r\n if (!prev) {\r\n return null;\r\n }\r\n active.classList.remove(...ACTIVE_CLASSES);\r\n prev.querySelector(\"a\").classList.add(...ACTIVE_CLASSES);\r\n // Don't use scrollIntoView as it scrolls the whole window\r\n prev.parentNode.scrollTop = prev.offsetTop - prev.parentNode.offsetTop;\r\n return prev;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * @returns {HTMLElement}\r\n */\r\n _moveSelectionDown() {\r\n let active = this.getActiveSelection();\r\n let next = null;\r\n if (active) {\r\n next = active.parentNode;\r\n do {\r\n next = next.nextSibling;\r\n } while (next && next.style.display == \"none\");\r\n if (!next) {\r\n return null;\r\n }\r\n active.classList.remove(...ACTIVE_CLASSES);\r\n next.querySelector(\"a\").classList.add(...ACTIVE_CLASSES);\r\n // This is the equivalent of scrollIntoView(false) but only for parent node\r\n if (next.offsetTop > next.parentNode.offsetHeight - next.offsetHeight) {\r\n next.parentNode.scrollTop += next.offsetHeight;\r\n }\r\n return next;\r\n }\r\n return next;\r\n }\r\n\r\n /**\r\n * @param {string} text\r\n * @param {string} size\r\n * @returns {Number}\r\n */\r\n _calcTextWidth(text, size = null) {\r\n var 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) + 8;\r\n document.body.removeChild(span);\r\n return width;\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 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.placeholder.length > 0 ? this.placeholder.length : 1;\r\n this._searchInput.placeholder = this.placeholder;\r\n }\r\n }\r\n\r\n // If the string contains ascii chars or strange font, input size may be wrong\r\n const v = this._searchInput.value || this._searchInput.placeholder;\r\n const computedFontSize = window.getComputedStyle(this._holderElement).fontSize;\r\n const w = this._calcTextWidth(v, computedFontSize);\r\n this._searchInput.style.minWidth = w + \"px\";\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 for (let i = 0; i < suggestions.length; i++) {\r\n let suggestion = suggestions[i];\r\n if (!suggestion[this.valueField]) {\r\n continue;\r\n }\r\n\r\n // initial selection\r\n if (suggestion.selected || this.selected.includes(suggestion[this.valueField])) {\r\n this._add(suggestion[this.labelField], suggestion[this.valueField], suggestion.data);\r\n continue; // no need to add as suggestion\r\n }\r\n\r\n let newChild = document.createElement(\"li\");\r\n let newChildLink = document.createElement(\"a\");\r\n newChild.append(newChildLink);\r\n newChildLink.classList.add(...[\"dropdown-item\", \"text-truncate\"]);\r\n newChildLink.setAttribute(VALUE_ATTRIBUTE, suggestion[this.valueField]);\r\n newChildLink.setAttribute(\"href\", \"#\");\r\n newChildLink.textContent = suggestion[this.labelField];\r\n if (suggestion.data) {\r\n for (const [key, value] of Object.entries(suggestion.data)) {\r\n newChildLink.dataset[key] = value;\r\n }\r\n }\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.removeActiveSelection();\r\n newChild.querySelector(\"a\").classList.add(...ACTIVE_CLASSES);\r\n });\r\n // Moving the mouse means no longer using keyboard\r\n newChildLink.addEventListener(\"mousemove\", (event) => {\r\n this._keyboardNavigation = false;\r\n });\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(newChildLink.textContent, newChildLink.getAttribute(VALUE_ATTRIBUTE), newChildLink.dataset);\r\n });\r\n }\r\n }\r\n\r\n reset() {\r\n this.removeAll();\r\n\r\n // Reset doesn't fire change event\r\n this._fireEvents = false;\r\n let initialValues = this._selectElement.querySelectorAll(\"option[data-init]\");\r\n for (let j = 0; j < initialValues.length; j++) {\r\n let initialValue = initialValues[j];\r\n this.addItem(initialValue.textContent, initialValue.value);\r\n }\r\n this._adjustWidth();\r\n this._fireEvents = true;\r\n }\r\n\r\n /**\r\n * @param {bool} 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\r\n this._searchInput.dispatchEvent(new Event(\"input\"));\r\n }\r\n\r\n // We use visibility instead of display to keep layout intact\r\n if (this.max && this.getSelectedValues().length >= this.max) {\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 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 let selected = this._selectElement.querySelectorAll(\"option[selected]\");\r\n return Array.from(selected).map((el) => el.value);\r\n }\r\n\r\n /**\r\n * The element create with buildSuggestions\r\n */\r\n _showSuggestions() {\r\n if (this._searchInput.style.visibility == \"hidden\") {\r\n return;\r\n }\r\n\r\n // Get search value\r\n let search = this._searchInput.value.toLocaleLowerCase();\r\n\r\n // Get current values\r\n let values = this.getSelectedValues();\r\n\r\n // Filter the list according to search string\r\n let list = this._dropElement.querySelectorAll(\"li\");\r\n let found = false;\r\n let firstItem = null;\r\n let hasPossibleValues = false;\r\n for (let i = 0; i < list.length; i++) {\r\n let item = list[i];\r\n let text = item.textContent.toLocaleLowerCase();\r\n let link = item.querySelector(\"a\");\r\n\r\n // Remove previous selection\r\n link.classList.remove(...ACTIVE_CLASSES);\r\n\r\n // Hide selected values\r\n if (values.indexOf(link.getAttribute(VALUE_ATTRIBUTE)) != -1) {\r\n item.style.display = \"none\";\r\n continue;\r\n }\r\n\r\n hasPossibleValues = true;\r\n\r\n // Check search length since we can trigger dropdown with arrow\r\n let isMatched = search.length === 0 || text.indexOf(search) !== -1;\r\n if (this.showAllSuggestions || this.suggestionsThreshold === 0 || isMatched) {\r\n item.style.display = \"list-item\";\r\n found = true;\r\n if (!firstItem && isMatched) {\r\n firstItem = item;\r\n }\r\n } else {\r\n item.style.display = \"none\";\r\n }\r\n }\r\n\r\n if (firstItem || this.showAllSuggestions) {\r\n this._holderElement.classList.remove(\"is-invalid\");\r\n // Always select first item\r\n if (firstItem) {\r\n firstItem.querySelector(\"a\").classList.add(...ACTIVE_CLASSES);\r\n firstItem.parentNode.scrollTop = firstItem.offsetTop;\r\n }\r\n } else {\r\n // No item and we don't allow new items => error\r\n if (!this.allowNew && !(search.length === 0 && !hasPossibleValues)) {\r\n this._holderElement.classList.add(\"is-invalid\");\r\n } else if (this.validationRegex && this.isInvalid()) {\r\n this._holderElement.classList.remove(\"is-invalid\");\r\n }\r\n }\r\n\r\n // Remove dropdown if not found or to show validation message\r\n if (!found || this.isInvalid()) {\r\n this._dropElement.classList.remove(\"show\");\r\n } else {\r\n // Or show it if necessary\r\n this._dropElement.classList.add(\"show\");\r\n\r\n if (this.fullWidth) {\r\n // Use full input width\r\n this._dropElement.style.left = -1 + \"px\";\r\n this._dropElement.style.width = this._holderElement.offsetWidth + \"px\";\r\n } else {\r\n // Position next to search input\r\n let left = this._searchInput.offsetLeft;\r\n\r\n // Overflow right\r\n const w = document.body.offsetWidth - 1; // avoid rounding issues\r\n const scrollbarOffset = 30; // scrollbars are not taken into account\r\n const wdiff = w - (left + this._dropElement.offsetWidth) - scrollbarOffset;\r\n\r\n // If the dropdowns goes out of the viewport, remove the diff from the left position\r\n if (wdiff < 0) {\r\n left = left + wdiff;\r\n }\r\n this._dropElement.style.left = left + \"px\";\r\n\r\n // Overflow bottom\r\n const h = document.body.offsetHeight;\r\n let bottom = this._searchInput.getBoundingClientRect().y + window.pageYOffset + this._dropElement.offsetHeight;\r\n const hdiff = h - bottom;\r\n if (hdiff < 0) {\r\n // We display above input\r\n this._dropElement.style.transform = \"translateY(calc(-100% - \" + scrollbarOffset + \"px))\";\r\n } else {\r\n this._dropElement.style.transform = \"none\";\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * The element create with buildSuggestions\r\n */\r\n _hideSuggestions() {\r\n this._dropElement.classList.remove(\"show\");\r\n this._holderElement.classList.remove(\"is-invalid\");\r\n this.removeActiveSelection();\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 if (window.jQuery && $.fn.tooltip != undefined && $.fn.tooltip.Constructor != undefined) {\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.validationRegex.trim());\r\n return regex.test(value);\r\n }\r\n\r\n /**\r\n * @returns {HTMLElement}\r\n */\r\n getActiveSelection() {\r\n return this._dropElement.querySelector(\"a.\" + ACTIVE_CLASS);\r\n }\r\n\r\n removeActiveSelection() {\r\n let selection = this.getActiveSelection();\r\n if (selection) {\r\n selection.classList.remove(...ACTIVE_CLASSES);\r\n }\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) {\r\n let items = this._containerElement.querySelectorAll(\"span\");\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 /**\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 isInvalid() {\r\n return this._holderElement.classList.contains(\"is-invalid\");\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 * @param {string} text\r\n * @param {string} value\r\n * @returns {boolean}\r\n */\r\n canAdd(text, value = null) {\r\n if (!value) {\r\n value = text;\r\n }\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._isSelected(text)) {\r\n return false;\r\n }\r\n // Check for max\r\n if (this.max && this.getSelectedValues().length >= this.max) {\r\n return false;\r\n }\r\n // Check for regex\r\n if (this.validationRegex && !this._validateRegex(text)) {\r\n this._holderElement.classList.add(\"is-invalid\");\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 */\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 const bver = this._getBootstrapVersion();\r\n let opt = this._selectElement.querySelector('option[value=\"' + value + '\"]');\r\n if (opt) {\r\n data = opt.dataset;\r\n }\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.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.baseClass) {\r\n // custom style\r\n bver === 5 ? classes.push(\"me-2\") : classes.push(\"mr-2\");\r\n classes.push(...this.baseClass.split(\" \"));\r\n } else if (bver === 5) {\r\n //https://getbootstrap.com/docs/5.1/components/badge/\r\n classes = [...classes, ...[\"me-2\", \"bg-\" + badgeStyle, \"mw-100\"]];\r\n } else {\r\n // https://getbootstrap.com/docs/4.6/components/badge/\r\n classes = [...classes, ...[\"mr-2\", \"badge-\" + badgeStyle]];\r\n }\r\n span.classList.add(...classes);\r\n span.setAttribute(VALUE_ATTRIBUTE, value);\r\n\r\n if (this.allowClear) {\r\n const closeClass = classes.includes(\"text-dark\") ? \"btn-close\" : \"btn-close-white\";\r\n let margin;\r\n let float;\r\n if (this.clearPosition === \"right\") {\r\n margin = bver === 5 ? \"ms-2\" : \"ml-2\";\r\n float = bver === 5 ? \"float-end\" : \"float:right;\";\r\n } else {\r\n margin = bver === 5 ? \"me-2\" : \"mr-2\";\r\n float = 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\r\n if (this.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 document.activeElement.blur();\r\n this._adjustWidth();\r\n }\r\n });\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 }\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 // Fire change event\r\n if (this._fireEvents) {\r\n this._selectElement.dispatchEvent(new Event(\"change\", { bubbles: true }));\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 let item = this._containerElement.querySelector(\"span[\" + VALUE_ATTRIBUTE + '=\"' + value + '\"]');\r\n if (!item) {\r\n return;\r\n }\r\n item.remove();\r\n\r\n // update select\r\n let opt = this._selectElement.querySelector('option[value=\"' + value + '\"]');\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.max && this.getSelectedValues().length < this.max) {\r\n this._searchInput.style.visibility = \"visible\";\r\n }\r\n }\r\n}\r\n\r\nexport default Tags;\r\n"], - "mappings": "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", + "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\nconst ACTIVE_CLASS = \"is-active\";\r\nconst ACTIVE_CLASSES = [\"is-active\", \"bg-primary\", \"text-white\"];\r\nconst VALUE_ATTRIBUTE = \"data-value\";\r\n\r\n// Static map will minify very badly as class prop, so we use an external constant\r\nconst INSTANCE_MAP = new WeakMap();\r\n\r\nclass Tags {\r\n /**\r\n * @param {HTMLSelectElement} el\r\n * @param {Object} globalOpts\r\n */\r\n constructor(el, globalOpts = {}) {\r\n // Hide the select element and register a tags attr\r\n el.style.display = \"none\";\r\n INSTANCE_MAP.set(el, this);\r\n this._selectElement = el;\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 // Handle options, using global settings first and data attr override\r\n const opts = { ...globalOpts, ...el.dataset };\r\n this.allowNew = opts.allowNew ? parseBool(opts.allowNew) : false;\r\n this.showAllSuggestions = opts.showAllSuggestions ? parseBool(opts.showAllSuggestions) : false;\r\n this.badgeStyle = opts.badgeStyle || \"primary\";\r\n this.allowClear = opts.allowClear ? parseBool(opts.allowClear) : false;\r\n this.clearEnd = opts.clearEnd ? parseBool(opts.clearEnd) : false;\r\n this.server = opts.server || false;\r\n this.liveServer = opts.liveServer ? parseBool(opts.liveServer) : false;\r\n this.serverParams = opts.serverParams || {};\r\n if (typeof this.serverParams == \"string\") {\r\n this.serverParams = JSON.parse(this.serverParams);\r\n }\r\n this.selected = opts.selected ? opts.selected.split(\",\") : [];\r\n this.suggestionsThreshold = typeof opts.suggestionsThreshold != \"undefined\" ? parseInt(opts.suggestionsThreshold) : 1;\r\n this.validationRegex = opts.regex || \"\";\r\n this.separator = opts.separator ? opts.separator.split(\"|\") : [];\r\n this.max = opts.max ? parseInt(opts.max) : null;\r\n this.clearLabel = opts.clearLabel || \"Clear\";\r\n this.searchLabel = opts.searchLabel || \"Type a value\";\r\n this.valueField = opts.valueField || \"value\";\r\n this.labelField = opts.labelField || \"label\";\r\n this.keepOpen = opts.keepOpen ? parseBool(opts.keepOpen) : false;\r\n this.fullWidth = opts.fullWidth ? parseBool(opts.fullWidth) : false;\r\n this.debounceTime = opts.debounceTime ? parseInt(opts.debounceTime) : 300;\r\n this.baseClass = opts.baseClass || \"\";\r\n\r\n this.placeholder = opts.placeholder || this._getPlaceholder();\r\n this._keyboardNavigation = false;\r\n this._fireEvents = true;\r\n this._searchFunc = Tags.debounce(() => {\r\n this._loadFromServer(true);\r\n }, this.debounceTime);\r\n\r\n this.overflowParent = null;\r\n this.parentForm = el.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 this.reset = this.reset.bind(this);\r\n if (this.parentForm) {\r\n this.parentForm.addEventListener(\"reset\", this.reset);\r\n }\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._dropElement = document.createElement(\"ul\");\r\n this._searchInput = document.createElement(\"input\");\r\n\r\n this._holderElement.appendChild(this._containerElement);\r\n this._containerElement.appendChild(this._searchInput);\r\n this._holderElement.appendChild(this._dropElement);\r\n // insert after select\r\n this._selectElement.parentNode.insertBefore(this._holderElement, this._selectElement.nextSibling);\r\n\r\n // Configure them\r\n this._configureHolderElement();\r\n this._configureDropElement();\r\n this._configureContainerElement();\r\n this._configureSearchInput();\r\n this.resetState();\r\n\r\n if (this.server && !this.liveServer) {\r\n this._loadFromServer();\r\n } else {\r\n this.resetSuggestions();\r\n }\r\n }\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 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 /**\r\n * @param {Function} func\r\n * @param {number} timeout\r\n * @returns {Function}\r\n */\r\n static debounce(func, timeout = 300) {\r\n let timer;\r\n return (...args) => {\r\n clearTimeout(timer);\r\n timer = setTimeout(() => {\r\n func.apply(this, args);\r\n }, timeout);\r\n };\r\n }\r\n\r\n dispose() {\r\n INSTANCE_MAP.delete(this._selectElement);\r\n this._selectElement.style.display = \"block\";\r\n this._holderElement.parentNode.removeChild(this._holderElement);\r\n if (this.parentForm) {\r\n this.parentForm.removeEventListener(\"reset\", this.reset);\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 } 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 }\r\n }\r\n\r\n resetSuggestions() {\r\n let suggestions = Array.from(this._selectElement.querySelectorAll(\"option\"))\r\n .filter((option) => {\r\n return !option.disabled;\r\n })\r\n .map((option) => {\r\n return {\r\n value: option.getAttribute(\"value\"),\r\n label: option.textContent,\r\n };\r\n });\r\n this._buildSuggestions(suggestions);\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 this.serverParams.query = this._searchInput.value;\r\n const params = new URLSearchParams(this.serverParams).toString();\r\n\r\n fetch(this.server + \"?\" + params, { signal: this._abortController.signal })\r\n .then((r) => r.json())\r\n .then((suggestions) => {\r\n let data = suggestions.data || 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 }\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) {\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 _configureDropElement() {\r\n this._dropElement.classList.add(...[\"dropdown-menu\", \"p-0\"]);\r\n this._dropElement.style.maxHeight = \"280px\";\r\n if (!this.fullWidth) {\r\n this._dropElement.style.maxWidth = \"360px\";\r\n }\r\n this._dropElement.style.overflowY = \"auto\";\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 }\r\n\r\n _configureHolderElement() {\r\n this._holderElement.classList.add(...[\"form-control\", \"dropdown\"]);\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 don't have an overflow parent, we can simply inherit styles\r\n // If we have an overflow parent, it needs a relatively positioned element\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\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 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 let initialValues = this._selectElement.selectedOptions;\r\n for (let j = 0; j < initialValues.length; j++) {\r\n let initialValue = initialValues[j];\r\n if (!initialValue.value) {\r\n continue;\r\n }\r\n // track initial values for reset\r\n initialValue.dataset.init = 1;\r\n this.addItem(initialValue.textContent, initialValue.value);\r\n }\r\n }\r\n\r\n _configureSearchInput() {\r\n this._searchInput.type = \"text\";\r\n this._searchInput.autocomplete = \"off\";\r\n this._searchInput.spellcheck = false;\r\n this._searchInput.style.backgroundColor = \"transparent\";\r\n this._searchInput.style.border = 0;\r\n this._searchInput.style.outline = 0;\r\n this._searchInput.style.maxWidth = \"100%\";\r\n this._searchInput.ariaLabel = this.searchLabel;\r\n this._resetSearchInput(true);\r\n\r\n this._searchInput.addEventListener(\"input\", (event) => {\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 (event.data) {\r\n const lastChar = event.data.slice(-1);\r\n if (this.separator.length && this._searchInput.value && this.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 text = this._searchInput.value;\r\n this._add(text, null);\r\n return;\r\n }\r\n }\r\n\r\n // Adjust input width to current content\r\n this._adjustWidth();\r\n\r\n // Check if we should display suggestions\r\n if (this._searchInput.value.length >= this.suggestionsThreshold) {\r\n if (this.liveServer) {\r\n this._searchFunc();\r\n } else {\r\n this._showSuggestions();\r\n }\r\n } else {\r\n this._hideSuggestions();\r\n }\r\n });\r\n this._searchInput.addEventListener(\"focus\", (event) => {\r\n if (this._searchInput.value.length >= this.suggestionsThreshold) {\r\n this._showSuggestions();\r\n }\r\n });\r\n this._searchInput.addEventListener(\"focusout\", (event) => {\r\n this._hideSuggestions();\r\n if (this.keepOpen) {\r\n this._resetSearchInput();\r\n }\r\n });\r\n // keypress doesn't send arrow keys, so we use keydown\r\n this._searchInput.addEventListener(\"keydown\", (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 // Keyboard keys\r\n switch (key) {\r\n case 13:\r\n case \"Enter\":\r\n event.preventDefault();\r\n let selection = this.getActiveSelection();\r\n if (selection) {\r\n selection.click();\r\n } else {\r\n // We use what is typed if not selected and not empty\r\n if (this.allowNew && this._searchInput.value) {\r\n let text = this._searchInput.value;\r\n this._add(text, null);\r\n }\r\n }\r\n break;\r\n case 38:\r\n case \"ArrowUp\":\r\n event.preventDefault();\r\n this._keyboardNavigation = true;\r\n let newSelection = this._moveSelectionUp();\r\n // If we use arrow up without input and there is no new selection, hide suggestions\r\n if (this._searchInput.value.length == 0 && this._dropElement.classList.contains(\"show\") && !newSelection) {\r\n this._hideSuggestions();\r\n }\r\n break;\r\n case 40:\r\n case \"ArrowDown\":\r\n event.preventDefault();\r\n this._keyboardNavigation = true;\r\n this._moveSelectionDown();\r\n // If we use arrow down without input, show suggestions\r\n if (this._searchInput.value.length == 0 && !this._dropElement.classList.contains(\"show\")) {\r\n this._showSuggestions();\r\n }\r\n break;\r\n case 8:\r\n case \"Backspace\":\r\n if (this._searchInput.value.length == 0) {\r\n this.removeLastItem();\r\n this._adjustWidth();\r\n this._hideSuggestions();\r\n }\r\n break;\r\n case 27:\r\n case \"Escape\":\r\n // We may wish to not use the suggestions\r\n this._hideSuggestions();\r\n break;\r\n }\r\n });\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 _add(text, value = null, data = {}) {\r\n if (!this.canAdd(text, value)) {\r\n return;\r\n }\r\n this.addItem(text, value, data);\r\n if (this.keepOpen) {\r\n this._showSuggestions();\r\n } else {\r\n this._resetSearchInput();\r\n }\r\n }\r\n\r\n /**\r\n * @returns {HTMLElement}\r\n */\r\n _moveSelectionUp() {\r\n let active = this.getActiveSelection();\r\n if (active) {\r\n let prev = active.parentNode;\r\n do {\r\n prev = prev.previousSibling;\r\n } while (prev && prev.style.display == \"none\");\r\n if (!prev) {\r\n return null;\r\n }\r\n active.classList.remove(...ACTIVE_CLASSES);\r\n prev.querySelector(\"a\").classList.add(...ACTIVE_CLASSES);\r\n // Don't use scrollIntoView as it scrolls the whole window\r\n prev.parentNode.scrollTop = prev.offsetTop - prev.parentNode.offsetTop;\r\n return prev;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * @returns {HTMLElement}\r\n */\r\n _moveSelectionDown() {\r\n let active = this.getActiveSelection();\r\n let next = null;\r\n if (active) {\r\n next = active.parentNode;\r\n do {\r\n next = next.nextSibling;\r\n } while (next && next.style.display == \"none\");\r\n if (!next) {\r\n return null;\r\n }\r\n active.classList.remove(...ACTIVE_CLASSES);\r\n next.querySelector(\"a\").classList.add(...ACTIVE_CLASSES);\r\n // This is the equivalent of scrollIntoView(false) but only for parent node\r\n if (next.offsetTop > next.parentNode.offsetHeight - next.offsetHeight) {\r\n next.parentNode.scrollTop += next.offsetHeight;\r\n }\r\n return next;\r\n }\r\n return next;\r\n }\r\n\r\n /**\r\n * @param {string} text\r\n * @param {string} size\r\n * @returns {Number}\r\n */\r\n _calcTextWidth(text, size = null) {\r\n var 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) + 8;\r\n document.body.removeChild(span);\r\n return width;\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 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.placeholder.length > 0 ? this.placeholder.length : 1;\r\n this._searchInput.placeholder = this.placeholder;\r\n }\r\n }\r\n\r\n // If the string contains ascii chars or strange font, input size may be wrong\r\n const v = this._searchInput.value || this._searchInput.placeholder;\r\n const computedFontSize = window.getComputedStyle(this._holderElement).fontSize;\r\n const w = this._calcTextWidth(v, computedFontSize);\r\n this._searchInput.style.minWidth = w + \"px\";\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 for (let i = 0; i < suggestions.length; i++) {\r\n let suggestion = suggestions[i];\r\n if (!suggestion[this.valueField]) {\r\n continue;\r\n }\r\n\r\n // initial selection\r\n if (suggestion.selected || this.selected.includes(suggestion[this.valueField])) {\r\n this._add(suggestion[this.labelField], suggestion[this.valueField], suggestion.data);\r\n continue; // no need to add as suggestion\r\n }\r\n\r\n let newChild = document.createElement(\"li\");\r\n let newChildLink = document.createElement(\"a\");\r\n newChild.append(newChildLink);\r\n newChildLink.classList.add(...[\"dropdown-item\", \"text-truncate\"]);\r\n newChildLink.setAttribute(VALUE_ATTRIBUTE, suggestion[this.valueField]);\r\n newChildLink.setAttribute(\"href\", \"#\");\r\n newChildLink.textContent = suggestion[this.labelField];\r\n if (suggestion.data) {\r\n for (const [key, value] of Object.entries(suggestion.data)) {\r\n newChildLink.dataset[key] = value;\r\n }\r\n }\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.removeActiveSelection();\r\n newChild.querySelector(\"a\").classList.add(...ACTIVE_CLASSES);\r\n });\r\n // Moving the mouse means no longer using keyboard\r\n newChildLink.addEventListener(\"mousemove\", (event) => {\r\n this._keyboardNavigation = false;\r\n });\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(newChildLink.textContent, newChildLink.getAttribute(VALUE_ATTRIBUTE), newChildLink.dataset);\r\n });\r\n }\r\n }\r\n\r\n reset() {\r\n this.removeAll();\r\n\r\n // Reset doesn't fire change event\r\n this._fireEvents = false;\r\n let initialValues = this._selectElement.querySelectorAll(\"option[data-init]\");\r\n for (let j = 0; j < initialValues.length; j++) {\r\n let initialValue = initialValues[j];\r\n this.addItem(initialValue.textContent, initialValue.value);\r\n }\r\n this._adjustWidth();\r\n this._fireEvents = true;\r\n }\r\n\r\n /**\r\n * @param {bool} 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\r\n this._searchInput.dispatchEvent(new Event(\"input\"));\r\n }\r\n\r\n // We use visibility instead of display to keep layout intact\r\n if (this.max && this.getSelectedValues().length >= this.max) {\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 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 let selected = this._selectElement.querySelectorAll(\"option[selected]\");\r\n return Array.from(selected).map((el) => el.value);\r\n }\r\n\r\n /**\r\n * The element create with buildSuggestions\r\n */\r\n _showSuggestions() {\r\n if (this._searchInput.style.visibility == \"hidden\") {\r\n return;\r\n }\r\n\r\n // Get search value\r\n let search = this._searchInput.value.toLocaleLowerCase();\r\n\r\n // Get current values\r\n let values = this.getSelectedValues();\r\n\r\n // Filter the list according to search string\r\n let list = this._dropElement.querySelectorAll(\"li\");\r\n let found = false;\r\n let firstItem = null;\r\n let hasPossibleValues = false;\r\n for (let i = 0; i < list.length; i++) {\r\n let item = list[i];\r\n let text = item.textContent.toLocaleLowerCase();\r\n let link = item.querySelector(\"a\");\r\n\r\n // Remove previous selection\r\n link.classList.remove(...ACTIVE_CLASSES);\r\n\r\n // Hide selected values\r\n if (values.indexOf(link.getAttribute(VALUE_ATTRIBUTE)) != -1) {\r\n item.style.display = \"none\";\r\n continue;\r\n }\r\n\r\n hasPossibleValues = true;\r\n\r\n // Check search length since we can trigger dropdown with arrow\r\n let isMatched = search.length === 0 || text.indexOf(search) !== -1;\r\n if (this.showAllSuggestions || this.suggestionsThreshold === 0 || isMatched) {\r\n item.style.display = \"list-item\";\r\n found = true;\r\n if (!firstItem && isMatched) {\r\n firstItem = item;\r\n }\r\n } else {\r\n item.style.display = \"none\";\r\n }\r\n }\r\n\r\n if (firstItem || this.showAllSuggestions) {\r\n this._holderElement.classList.remove(\"is-invalid\");\r\n // Always select first item\r\n if (firstItem) {\r\n firstItem.querySelector(\"a\").classList.add(...ACTIVE_CLASSES);\r\n firstItem.parentNode.scrollTop = firstItem.offsetTop;\r\n }\r\n } else {\r\n // No item and we don't allow new items => error\r\n if (!this.allowNew && !(search.length === 0 && !hasPossibleValues)) {\r\n this._holderElement.classList.add(\"is-invalid\");\r\n } else if (this.validationRegex && this.isInvalid()) {\r\n this._holderElement.classList.remove(\"is-invalid\");\r\n }\r\n }\r\n\r\n // Remove dropdown if not found or to show validation message\r\n if (!found || this.isInvalid()) {\r\n this._dropElement.classList.remove(\"show\");\r\n } else {\r\n // Or show it if necessary\r\n this._dropElement.classList.add(\"show\");\r\n\r\n if (this.fullWidth) {\r\n // Use full input width\r\n this._dropElement.style.left = -1 + \"px\";\r\n this._dropElement.style.width = this._holderElement.offsetWidth + \"px\";\r\n } else {\r\n // Position next to search input\r\n let left = this._searchInput.offsetLeft;\r\n\r\n // Overflow right\r\n const w = document.body.offsetWidth - 1; // avoid rounding issues\r\n const scrollbarOffset = 30; // scrollbars are not taken into account\r\n const wdiff = w - (left + this._dropElement.offsetWidth) - scrollbarOffset;\r\n\r\n // If the dropdowns goes out of the viewport, remove the diff from the left position\r\n if (wdiff < 0) {\r\n left = left + wdiff;\r\n }\r\n this._dropElement.style.left = left + \"px\";\r\n\r\n // Overflow bottom\r\n const h = document.body.offsetHeight;\r\n let bottom = this._searchInput.getBoundingClientRect().y + window.pageYOffset + this._dropElement.offsetHeight;\r\n const hdiff = h - bottom;\r\n if (hdiff < 0) {\r\n // We display above input\r\n this._dropElement.style.transform = \"translateY(calc(-100% - \" + scrollbarOffset + \"px))\";\r\n } else {\r\n this._dropElement.style.transform = \"none\";\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * The element create with buildSuggestions\r\n */\r\n _hideSuggestions() {\r\n this._dropElement.classList.remove(\"show\");\r\n this._holderElement.classList.remove(\"is-invalid\");\r\n this.removeActiveSelection();\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 if (window.jQuery && $.fn.tooltip != undefined && $.fn.tooltip.Constructor != undefined) {\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.validationRegex.trim());\r\n return regex.test(value);\r\n }\r\n\r\n /**\r\n * @returns {HTMLElement}\r\n */\r\n getActiveSelection() {\r\n return this._dropElement.querySelector(\"a.\" + ACTIVE_CLASS);\r\n }\r\n\r\n removeActiveSelection() {\r\n let selection = this.getActiveSelection();\r\n if (selection) {\r\n selection.classList.remove(...ACTIVE_CLASSES);\r\n }\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) {\r\n let items = this._containerElement.querySelectorAll(\"span\");\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 /**\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 isInvalid() {\r\n return this._holderElement.classList.contains(\"is-invalid\");\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 * @param {string} text\r\n * @param {string} value\r\n * @returns {boolean}\r\n */\r\n canAdd(text, value = null) {\r\n if (!value) {\r\n value = text;\r\n }\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._isSelected(text)) {\r\n return false;\r\n }\r\n // Check for max\r\n if (this.max && this.getSelectedValues().length >= this.max) {\r\n return false;\r\n }\r\n // Check for regex\r\n if (this.validationRegex && !this._validateRegex(text)) {\r\n this._holderElement.classList.add(\"is-invalid\");\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 */\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 const bver = this._getBootstrapVersion();\r\n let opt = this._selectElement.querySelector('option[value=\"' + value + '\"]');\r\n if (opt) {\r\n data = opt.dataset;\r\n }\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.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.baseClass) {\r\n // custom style\r\n bver === 5 ? classes.push(\"me-2\") : classes.push(\"mr-2\");\r\n classes.push(...this.baseClass.split(\" \"));\r\n } else if (bver === 5) {\r\n //https://getbootstrap.com/docs/5.1/components/badge/\r\n classes = [...classes, ...[\"me-2\", \"bg-\" + badgeStyle, \"mw-100\"]];\r\n } else {\r\n // https://getbootstrap.com/docs/4.6/components/badge/\r\n classes = [...classes, ...[\"mr-2\", \"badge-\" + badgeStyle]];\r\n }\r\n span.classList.add(...classes);\r\n span.setAttribute(VALUE_ATTRIBUTE, value);\r\n\r\n if (this.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.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\r\n if (this.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 document.activeElement.blur();\r\n this._adjustWidth();\r\n }\r\n });\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 }\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 // Fire change event\r\n if (this._fireEvents) {\r\n this._selectElement.dispatchEvent(new Event(\"change\", { bubbles: true }));\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 let item = this._containerElement.querySelector(\"span[\" + VALUE_ATTRIBUTE + '=\"' + value + '\"]');\r\n if (!item) {\r\n return;\r\n }\r\n item.remove();\r\n\r\n // update select\r\n let opt = this._selectElement.querySelector('option[value=\"' + value + '\"]');\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.max && this.getSelectedValues().length < this.max) {\r\n this._searchInput.style.visibility = \"visible\";\r\n }\r\n }\r\n}\r\n\r\nexport default Tags;\r\n"], + "mappings": "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", "names": [] }