diff --git a/components/dist/input.js b/components/dist/input.js index f8a5c4e..682fe87 100644 --- a/components/dist/input.js +++ b/components/dist/input.js @@ -1,4 +1,3 @@ -//Input const smInput = document.createElement('template') smInput.innerHTML = `
-
`; customElements.define('sm-input', class extends HTMLElement { - + #validationState = { + validatedFor: undefined, + isValid: false + } constructor() { super(); this.attachShadow({ @@ -255,25 +264,11 @@ customElements.define('sm-input', this.outerContainer = this.shadowRoot.querySelector('.outer-container'); this.optionList = this.shadowRoot.querySelector('.datalist'); this._helperText = ''; - this._errorText = 'Invalid'; + this._errorText = 'Please fill out this field.'; this.isRequired = false; this.datalist = []; this.validationFunction = undefined; this.reflectedAttributes = ['value', 'required', 'disabled', 'type', 'inputmode', 'readonly', 'min', 'max', 'pattern', 'minlength', 'maxlength', 'step', 'list', 'autocomplete']; - - this.reset = this.reset.bind(this); - this.clear = this.clear.bind(this); - this.focusIn = this.focusIn.bind(this); - this.focusOut = this.focusOut.bind(this); - this.fireEvent = this.fireEvent.bind(this); - this.checkInput = this.checkInput.bind(this); - this.showError = this.showError.bind(this); - this.allowOnlyNum = this.allowOnlyNum.bind(this); - this.handleOptionClick = this.handleOptionClick.bind(this); - this.handleInputNavigation = this.handleInputNavigation.bind(this); - this.handleDatalistNavigation = this.handleDatalistNavigation.bind(this); - this.handleFocus = this.handleFocus.bind(this); - this.handleBlur = this.handleBlur.bind(this); } static get observedAttributes() { @@ -287,6 +282,7 @@ customElements.define('sm-input', set value(val) { if (val === this.input.value) return; this.input.value = val; + this._value = val; this.checkInput(); } @@ -332,12 +328,13 @@ customElements.define('sm-input', } } set customValidation(val) { - this.validationFunction = val; + if (val) + this.validationFunction = val; } set errorText(val) { this._errorText = val; } - showError(errorText) { + showError = (errorText = this._errorText) => { this.feedbackText.className = 'feedback-text error'; this.feedbackText.innerHTML = ` @@ -348,44 +345,44 @@ customElements.define('sm-input', this._helperText = val; } get isValid() { - if (this.input.value !== '') { - const _isValid = this.input.checkValidity(); - let _validity = { - isValid: _isValid, - errorText: '' - } - if (this.validationFunction) { - _validity = this.validationFunction(this.input.value); - } - if (_isValid && _validity.isValid) { - this.feedbackText.className = 'feedback-text success'; - this.feedbackText.textContent = ''; - } else { - if (_validity.errorText || this._errorText) { - this.showError(_validity.errorText || this._errorText); - } - } - return (_isValid && _validity.isValid); + if (this.input.value === '') return; + if (this.#validationState.validatedFor === this.input.value) + return this.#validationState.isValid; // if the input is empty or the value is not changed, return the previous validity + const _isValid = this.input.checkValidity(); + let _validity = { isValid: true, errorText: '' } + if (this.validationFunction) { + _validity = this.validationFunction(this.input.value); } + if (_isValid && _validity.isValid) { + this.feedbackText.className = 'feedback-text success'; + this.feedbackText.textContent = ''; + } else { + if (_validity.errorText || this._errorText) { + this.showError(_validity.errorText || this._errorText); + } + } + this.#validationState.validatedFor = this.input.value; + this.#validationState.isValid = _isValid && _validity.isValid; + return this.#validationState.isValid; } - reset() { + reset = () => { this.value = ''; } - clear() { + clear = () => { this.value = ''; this.input.focus(); this.fireEvent(); } - focusIn() { + focusIn = () => { this.input.focus(); } - focusOut() { + focusOut = () => { this.input.blur(); } - fireEvent() { + fireEvent = () => { let event = new Event('input', { bubbles: true, cancelable: true, @@ -394,7 +391,7 @@ customElements.define('sm-input', this.dispatchEvent(event); } - searchDatalist(searchKey) { + searchDatalist = (searchKey) => { const filteredData = this.datalist.filter(item => item.toLowerCase().includes(searchKey.toLowerCase())); // sort the filtered data based on the input value filteredData.sort((a, b) => { @@ -427,7 +424,7 @@ customElements.define('sm-input', } } - checkInput(e) { + checkInput = (e) => { if (!this.hasAttribute('readonly')) { if (this.input.value !== '') { this.clearBtn.classList.remove('hidden'); @@ -437,10 +434,9 @@ customElements.define('sm-input', } if (!this.hasAttribute('placeholder') || this.getAttribute('placeholder').trim() === '') return; if (this.input.value !== '') { - if (this.animate) + if (this.shouldAnimateLabel) this.inputParent.classList.add('animate-placeholder'); - else - this.label.classList.add('hidden'); + this.label.classList.toggle('hidden', !this.shouldAnimateLabel); if (this.datalist.length) { // debounce the search if (this.searchTimeout) { @@ -451,10 +447,9 @@ customElements.define('sm-input', }, 100); } } else { - if (this.animate) + if (this.shouldAnimateLabel) this.inputParent.classList.remove('animate-placeholder'); - else - this.label.classList.remove('hidden'); + this.label.classList.remove('hidden'); this.feedbackText.textContent = ''; if (this.datalist.length) { this.optionList.innerHTML = ''; @@ -462,7 +457,7 @@ customElements.define('sm-input', } } } - allowOnlyNum(e) { + allowOnlyNum = (e) => { if (e.key.length === 1) { if (e.key === '.' && (e.target.value.includes('.') || e.target.value.length === 0)) { e.preventDefault(); @@ -471,13 +466,13 @@ customElements.define('sm-input', } } } - handleOptionClick(e) { + handleOptionClick = (e) => { this.input.value = e.target.textContent; this.optionList.classList.add('hidden'); this.input.focus(); } // handle arrow key navigation on input - handleInputNavigation(e) { + handleInputNavigation = (e) => { if (e.key === 'ArrowDown') { e.preventDefault(); if (this.optionList.children.length) { @@ -491,7 +486,7 @@ customElements.define('sm-input', } } // handle arrow key navigation on datalist - handleDatalistNavigation(e) { + handleDatalistNavigation = (e) => { if (e.key === 'ArrowUp') { e.preventDefault(); this.shadowRoot.activeElement.previousElementSibling ? this.shadowRoot.activeElement.previousElementSibling.focus() : this.input.focus(); @@ -505,19 +500,26 @@ customElements.define('sm-input', this.input.focus(); } } - handleFocus(e) { + handleFocus = (e) => { if (this.datalist.length) { this.searchDatalist(this.input.value.trim()); } } - handleBlur(e) { + handleBlur = (e) => { if (this.datalist.length) { this.optionList.classList.add('hidden'); } } connectedCallback() { - this.animate = this.hasAttribute('animate'); + const uuid = crypto.randomUUID() + this.input.id = uuid; + this.label.htmlFor = uuid + this.shouldAnimateLabel = this.hasAttribute('animate'); + if (this.shouldAnimateLabel && this.placeholder !== '' && this.value) { + this.inputParent.classList.add('animate-placeholder'); + this.label.classList.remove('hidden'); + } this.setAttribute('role', 'textbox'); this.input.addEventListener('input', this.checkInput); this.clearBtn.addEventListener('click', this.clear); diff --git a/components/dist/input.min.js b/components/dist/input.min.js index 4df7250..de1c401 100644 --- a/components/dist/input.min.js +++ b/components/dist/input.min.js @@ -1 +1 @@ -const smInput=document.createElement("template");smInput.innerHTML='\n \n
\n \n \n

\n
\n ',customElements.define("sm-input",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smInput.content.cloneNode(!0)),this.inputParent=this.shadowRoot.querySelector(".input"),this.input=this.shadowRoot.querySelector("input"),this.clearBtn=this.shadowRoot.querySelector(".clear"),this.label=this.shadowRoot.querySelector(".label"),this.feedbackText=this.shadowRoot.querySelector(".feedback-text"),this.outerContainer=this.shadowRoot.querySelector(".outer-container"),this.optionList=this.shadowRoot.querySelector(".datalist"),this._helperText="",this._errorText="Invalid",this.isRequired=!1,this.datalist=[],this.validationFunction=void 0,this.reflectedAttributes=["value","required","disabled","type","inputmode","readonly","min","max","pattern","minlength","maxlength","step","list","autocomplete"],this.reset=this.reset.bind(this),this.clear=this.clear.bind(this),this.focusIn=this.focusIn.bind(this),this.focusOut=this.focusOut.bind(this),this.fireEvent=this.fireEvent.bind(this),this.checkInput=this.checkInput.bind(this),this.showError=this.showError.bind(this),this.allowOnlyNum=this.allowOnlyNum.bind(this),this.handleOptionClick=this.handleOptionClick.bind(this),this.handleInputNavigation=this.handleInputNavigation.bind(this),this.handleDatalistNavigation=this.handleDatalistNavigation.bind(this),this.handleFocus=this.handleFocus.bind(this),this.handleBlur=this.handleBlur.bind(this)}static get observedAttributes(){return["value","placeholder","required","disabled","type","inputmode","readonly","min","max","pattern","minlength","maxlength","step","helper-text","error-text","list"]}get value(){return this.input.value}set value(t){t!==this.input.value&&(this.input.value=t,this.checkInput())}get placeholder(){return this.getAttribute("placeholder")}set placeholder(t){this.setAttribute("placeholder",t)}get type(){return this.getAttribute("type")}set type(t){this.setAttribute("type",t)}get validity(){return this.input.validity}get disabled(){return this.hasAttribute("disabled")}set disabled(t){t?(this.inputParent.classList.add("disabled"),this.setAttribute("disabled","")):(this.inputParent.classList.remove("disabled"),this.removeAttribute("disabled"))}get readOnly(){return this.hasAttribute("readonly")}set readOnly(t){t?this.setAttribute("readonly",""):this.removeAttribute("readonly")}set customValidation(t){this.validationFunction=t}set errorText(t){this._errorText=t}showError(t){this.feedbackText.className="feedback-text error",this.feedbackText.innerHTML=`\n \n ${t}`}set helperText(t){this._helperText=t}get isValid(){if(""!==this.input.value){const t=this.input.checkValidity();let e={isValid:t,errorText:""};return this.validationFunction&&(e=this.validationFunction(this.input.value)),t&&e.isValid?(this.feedbackText.className="feedback-text success",this.feedbackText.textContent=""):(e.errorText||this._errorText)&&this.showError(e.errorText||this._errorText),t&&e.isValid}}reset(){this.value=""}clear(){this.value="",this.input.focus(),this.fireEvent()}focusIn(){this.input.focus()}focusOut(){this.input.blur()}fireEvent(){let t=new Event("input",{bubbles:!0,cancelable:!0,composed:!0});this.dispatchEvent(t)}searchDatalist(t){const e=this.datalist.filter(e=>e.toLowerCase().includes(t.toLowerCase()));if(e.sort((e,n)=>{const i=e.toLowerCase().indexOf(t.toLowerCase()),s=n.toLowerCase().indexOf(t.toLowerCase());return i-s}),e.length){if(this.optionList.children.length>e.length){const t=this.optionList.children.length-e.length;for(let e=0;e{if(this.optionList.children[e])this.optionList.children[e].textContent=t;else{const e=document.createElement("li");e.textContent=t,e.classList.add("datalist-item"),e.setAttribute("tabindex","0"),this.optionList.appendChild(e)}}),this.optionList.classList.remove("hidden")}else this.optionList.classList.add("hidden")}checkInput(t){this.hasAttribute("readonly")||(""!==this.input.value?this.clearBtn.classList.remove("hidden"):this.clearBtn.classList.add("hidden")),this.hasAttribute("placeholder")&&""!==this.getAttribute("placeholder").trim()&&(""!==this.input.value?(this.animate?this.inputParent.classList.add("animate-placeholder"):this.label.classList.add("hidden"),this.datalist.length&&(this.searchTimeout&&clearTimeout(this.searchTimeout),this.searchTimeout=setTimeout(()=>{this.searchDatalist(this.input.value.trim())},100))):(this.animate?this.inputParent.classList.remove("animate-placeholder"):this.label.classList.remove("hidden"),this.feedbackText.textContent="",this.datalist.length&&(this.optionList.innerHTML="",this.optionList.classList.add("hidden"))))}allowOnlyNum(t){1===t.key.length&&(("."!==t.key||!t.target.value.includes(".")&&0!==t.target.value.length)&&["0","1","2","3","4","5","6","7","8","9","."].includes(t.key)||t.preventDefault())}handleOptionClick(t){this.input.value=t.target.textContent,this.optionList.classList.add("hidden"),this.input.focus()}handleInputNavigation(t){"ArrowDown"===t.key?(t.preventDefault(),this.optionList.children.length&&this.optionList.children[0].focus()):"ArrowUp"===t.key&&(t.preventDefault(),this.optionList.children.length&&this.optionList.children[this.optionList.children.length-1].focus())}handleDatalistNavigation(t){"ArrowUp"===t.key?(t.preventDefault(),this.shadowRoot.activeElement.previousElementSibling?this.shadowRoot.activeElement.previousElementSibling.focus():this.input.focus()):"ArrowDown"===t.key?(t.preventDefault(),this.shadowRoot.activeElement.nextElementSibling?this.shadowRoot.activeElement.nextElementSibling.focus():this.input.focus()):"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this.input.value=t.target.textContent,this.optionList.classList.add("hidden"),this.input.focus())}handleFocus(t){this.datalist.length&&this.searchDatalist(this.input.value.trim())}handleBlur(t){this.datalist.length&&this.optionList.classList.add("hidden")}connectedCallback(){this.animate=this.hasAttribute("animate"),this.setAttribute("role","textbox"),this.input.addEventListener("input",this.checkInput),this.clearBtn.addEventListener("click",this.clear),this.datalist.length&&(this.optionList.addEventListener("click",this.handleOptionClick),this.input.addEventListener("keydown",this.handleInputNavigation),this.optionList.addEventListener("keydown",this.handleDatalistNavigation)),this.input.addEventListener("focusin",this.handleFocus),this.addEventListener("focusout",this.handleBlur)}attributeChangedCallback(t,e,n){if(e!==n)switch(this.reflectedAttributes.includes(t)&&(this.hasAttribute(t)?this.input.setAttribute(t,this.getAttribute(t)?this.getAttribute(t):""):this.input.removeAttribute(t)),t){case"placeholder":this.label.textContent=n,this.setAttribute("aria-label",n);break;case"value":this.checkInput();break;case"type":this.hasAttribute("type")&&"number"===this.getAttribute("type")?(this.input.setAttribute("inputmode","decimal"),this.input.addEventListener("keydown",this.allowOnlyNum)):this.input.removeEventListener("keydown",this.allowOnlyNum);break;case"helper-text":this._helperText=n;break;case"error-text":this._errorText=n;break;case"required":this.isRequired=this.hasAttribute("required"),this.isRequired?this.setAttribute("aria-required","true"):this.setAttribute("aria-required","false");break;case"readonly":this.hasAttribute("readonly")?this.inputParent.classList.add("readonly"):this.inputParent.classList.remove("readonly");break;case"disabled":this.hasAttribute("disabled")?this.inputParent.classList.add("disabled"):this.inputParent.classList.remove("disabled");break;case"list":this.hasAttribute("list")&&""!==this.getAttribute("list").trim()&&(this.datalist=this.getAttribute("list").split(","))}}disconnectedCallback(){this.input.removeEventListener("input",this.checkInput),this.clearBtn.removeEventListener("click",this.clear),this.input.removeEventListener("keydown",this.allowOnlyNum),this.optionList.removeEventListener("click",this.handleOptionClick),this.input.removeEventListener("keydown",this.handleInputNavigation),this.optionList.removeEventListener("keydown",this.handleDatalistNavigation),this.input.removeEventListener("focusin",this.handleFocus),this.removeEventListener("focusout",this.handleBlur)}}); \ No newline at end of file +const smInput=document.createElement("template");smInput.innerHTML='\n \n
\n
\n \n
\n \n \n
\n \n \n
\n \n \n
\n ',customElements.define("sm-input",class extends HTMLElement{#validationState={validatedFor:void 0,isValid:!1};constructor(){super(),this.attachShadow({mode:"open"}).append(smInput.content.cloneNode(!0)),this.inputParent=this.shadowRoot.querySelector(".input"),this.input=this.shadowRoot.querySelector("input"),this.clearBtn=this.shadowRoot.querySelector(".clear"),this.label=this.shadowRoot.querySelector(".label"),this.feedbackText=this.shadowRoot.querySelector(".feedback-text"),this.outerContainer=this.shadowRoot.querySelector(".outer-container"),this.optionList=this.shadowRoot.querySelector(".datalist"),this._helperText="",this._errorText="Please fill out this field.",this.isRequired=!1,this.datalist=[],this.validationFunction=void 0,this.reflectedAttributes=["value","required","disabled","type","inputmode","readonly","min","max","pattern","minlength","maxlength","step","list","autocomplete"]}static get observedAttributes(){return["value","placeholder","required","disabled","type","inputmode","readonly","min","max","pattern","minlength","maxlength","step","helper-text","error-text","list"]}get value(){return this.input.value}set value(val){val!==this.input.value&&(this.input.value=val,this._value=val,this.checkInput())}get placeholder(){return this.getAttribute("placeholder")}set placeholder(val){this.setAttribute("placeholder",val)}get type(){return this.getAttribute("type")}set type(val){this.setAttribute("type",val)}get validity(){return this.input.validity}get disabled(){return this.hasAttribute("disabled")}set disabled(value){value?(this.inputParent.classList.add("disabled"),this.setAttribute("disabled","")):(this.inputParent.classList.remove("disabled"),this.removeAttribute("disabled"))}get readOnly(){return this.hasAttribute("readonly")}set readOnly(value){value?this.setAttribute("readonly",""):this.removeAttribute("readonly")}set customValidation(val){val&&(this.validationFunction=val)}set errorText(val){this._errorText=val}showError=(errorText=this._errorText)=>{this.feedbackText.className="feedback-text error",this.feedbackText.innerHTML=`\n \n ${errorText}`};set helperText(val){this._helperText=val}get isValid(){if(""===this.input.value)return;if(this.#validationState.validatedFor===this.input.value)return this.#validationState.isValid;const _isValid=this.input.checkValidity();let _validity={isValid:!0,errorText:""};return this.validationFunction&&(_validity=this.validationFunction(this.input.value)),_isValid&&_validity.isValid?(this.feedbackText.className="feedback-text success",this.feedbackText.textContent=""):(_validity.errorText||this._errorText)&&this.showError(_validity.errorText||this._errorText),this.#validationState.validatedFor=this.input.value,this.#validationState.isValid=_isValid&&_validity.isValid,this.#validationState.isValid}reset=()=>{this.value=""};clear=()=>{this.value="",this.input.focus(),this.fireEvent()};focusIn=()=>{this.input.focus()};focusOut=()=>{this.input.blur()};fireEvent=()=>{let event=new Event("input",{bubbles:!0,cancelable:!0,composed:!0});this.dispatchEvent(event)};searchDatalist=searchKey=>{const filteredData=this.datalist.filter((item=>item.toLowerCase().includes(searchKey.toLowerCase())));if(filteredData.sort(((a,b)=>a.toLowerCase().indexOf(searchKey.toLowerCase())-b.toLowerCase().indexOf(searchKey.toLowerCase()))),filteredData.length){if(this.optionList.children.length>filteredData.length){const optionsToRemove=this.optionList.children.length-filteredData.length;for(let i=0;i{if(this.optionList.children[index])this.optionList.children[index].textContent=item;else{const option=document.createElement("li");option.textContent=item,option.classList.add("datalist-item"),option.setAttribute("tabindex","0"),this.optionList.appendChild(option)}})),this.optionList.classList.remove("hidden")}else this.optionList.classList.add("hidden")};checkInput=e=>{this.hasAttribute("readonly")||(""!==this.input.value?this.clearBtn.classList.remove("hidden"):this.clearBtn.classList.add("hidden")),this.hasAttribute("placeholder")&&""!==this.getAttribute("placeholder").trim()&&(""!==this.input.value?(this.shouldAnimateLabel&&this.inputParent.classList.add("animate-placeholder"),this.label.classList.toggle("hidden",!this.shouldAnimateLabel),this.datalist.length&&(this.searchTimeout&&clearTimeout(this.searchTimeout),this.searchTimeout=setTimeout((()=>{this.searchDatalist(this.input.value.trim())}),100))):(this.shouldAnimateLabel&&this.inputParent.classList.remove("animate-placeholder"),this.label.classList.remove("hidden"),this.feedbackText.textContent="",this.datalist.length&&(this.optionList.innerHTML="",this.optionList.classList.add("hidden"))))};allowOnlyNum=e=>{1===e.key.length&&(("."!==e.key||!e.target.value.includes(".")&&0!==e.target.value.length)&&["0","1","2","3","4","5","6","7","8","9","."].includes(e.key)||e.preventDefault())};handleOptionClick=e=>{this.input.value=e.target.textContent,this.optionList.classList.add("hidden"),this.input.focus()};handleInputNavigation=e=>{"ArrowDown"===e.key?(e.preventDefault(),this.optionList.children.length&&this.optionList.children[0].focus()):"ArrowUp"===e.key&&(e.preventDefault(),this.optionList.children.length&&this.optionList.children[this.optionList.children.length-1].focus())};handleDatalistNavigation=e=>{"ArrowUp"===e.key?(e.preventDefault(),this.shadowRoot.activeElement.previousElementSibling?this.shadowRoot.activeElement.previousElementSibling.focus():this.input.focus()):"ArrowDown"===e.key?(e.preventDefault(),this.shadowRoot.activeElement.nextElementSibling?this.shadowRoot.activeElement.nextElementSibling.focus():this.input.focus()):"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),this.input.value=e.target.textContent,this.optionList.classList.add("hidden"),this.input.focus())};handleFocus=e=>{this.datalist.length&&this.searchDatalist(this.input.value.trim())};handleBlur=e=>{this.datalist.length&&this.optionList.classList.add("hidden")};connectedCallback(){const uuid=crypto.randomUUID();this.input.id=uuid,this.label.htmlFor=uuid,this.shouldAnimateLabel=this.hasAttribute("animate"),this.shouldAnimateLabel&&""!==this.placeholder&&this.value&&(this.inputParent.classList.add("animate-placeholder"),this.label.classList.remove("hidden")),this.setAttribute("role","textbox"),this.input.addEventListener("input",this.checkInput),this.clearBtn.addEventListener("click",this.clear),this.datalist.length&&(this.optionList.addEventListener("click",this.handleOptionClick),this.input.addEventListener("keydown",this.handleInputNavigation),this.optionList.addEventListener("keydown",this.handleDatalistNavigation)),this.input.addEventListener("focusin",this.handleFocus),this.addEventListener("focusout",this.handleBlur)}attributeChangedCallback(name,oldValue,newValue){if(oldValue!==newValue)switch(this.reflectedAttributes.includes(name)&&(this.hasAttribute(name)?this.input.setAttribute(name,this.getAttribute(name)?this.getAttribute(name):""):this.input.removeAttribute(name)),name){case"placeholder":this.label.textContent=newValue,this.setAttribute("aria-label",newValue);break;case"value":this.checkInput();break;case"type":this.hasAttribute("type")&&"number"===this.getAttribute("type")?(this.input.setAttribute("inputmode","decimal"),this.input.addEventListener("keydown",this.allowOnlyNum)):this.input.removeEventListener("keydown",this.allowOnlyNum);break;case"helper-text":this._helperText=newValue;break;case"error-text":this._errorText=newValue;break;case"required":this.isRequired=this.hasAttribute("required"),this.isRequired?this.setAttribute("aria-required","true"):this.setAttribute("aria-required","false");break;case"readonly":this.hasAttribute("readonly")?this.inputParent.classList.add("readonly"):this.inputParent.classList.remove("readonly");break;case"disabled":this.hasAttribute("disabled")?this.inputParent.classList.add("disabled"):this.inputParent.classList.remove("disabled");break;case"list":this.hasAttribute("list")&&""!==this.getAttribute("list").trim()&&(this.datalist=this.getAttribute("list").split(","))}}disconnectedCallback(){this.input.removeEventListener("input",this.checkInput),this.clearBtn.removeEventListener("click",this.clear),this.input.removeEventListener("keydown",this.allowOnlyNum),this.optionList.removeEventListener("click",this.handleOptionClick),this.input.removeEventListener("keydown",this.handleInputNavigation),this.optionList.removeEventListener("keydown",this.handleDatalistNavigation),this.input.removeEventListener("focusin",this.handleFocus),this.removeEventListener("focusout",this.handleBlur)}}); \ No newline at end of file