UNPKG

@tomickigrzegorz/autocomplete

Version:

A lightweight, dependency-free autocomplete component in vanilla JavaScript with WAI-ARIA support.

9 lines (8 loc) 8.72 kB
/*! * @name autocomplete * @version 3.0.0 * @author Grzegorz Tomicki * @link https://github.com/tomickigrzegorz/autocomplete * @license MIT */ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Autocomplete=t()}(this,(function(){"use strict";var e=function(e,t){Object.entries(t).forEach((function(t){var i=t[0],n=t[1];"addClass"===i||"removeClass"===i?o(e,"addClass"===i?"add":"remove",n):e.setAttribute(i,n)}))},t=function(e){return(e.firstElementChild||e).textContent.trim()},i=function(e,t){e.scrollTop=e.offsetTop-t.offsetHeight},n=function(e,t){e&&(o(e,"remove","hidden"),d(e,"click",t))},o=function(e,t,i){return e.classList[t](i)},s=function(t,i){e(t,{"aria-activedescendant":i||""})},a=function(e,t,i,n){var o=n.previousSibling,s=o?o.offsetHeight:0;if("0"===e.getAttribute("aria-posinset")&&(n.scrollTop=e.offsetTop-function(e,t){var i=document.querySelectorAll("#"+e+" > li:not(."+t+")");return Array.from(i).reduce((function(e,t){return e+t.offsetHeight}),0)}(t,i)),e.offsetTop-s<n.scrollTop)n.scrollTop=e.offsetTop-s;else{var a=e.offsetTop+e.offsetHeight-s;a>n.scrollTop+n.offsetHeight&&(n.scrollTop=a-n.offsetHeight)}},r=function(e){return document.createElement(e)},u=function(e){return document.querySelector(e)},d=function(e,t,i){e.addEventListener(t,i)},c=function(e,t,i){e.removeEventListener(t,i)},l=function(e){return{"aria-owns":e,"aria-expanded":"false","aria-autocomplete":"list",role:"combobox",removeClass:"auto-expanded"}},h=Object.freeze({ESC:27,ENTER:13,UP:38,DOWN:40,TAB:9});return function(f,v){var m,p=this,b=v.delay,x=void 0===b?500:b,y=v.clearButton,k=void 0===y||y,j=v.clearButtonOnInitial,C=void 0!==j&&j,O=v.howManyCharacters,g=void 0===O?1:O,w=v.selectFirst,T=void 0!==w&&w,V=v.insertToInput,A=void 0!==V&&V,N=v.showValuesOnClick,$=void 0!==N&&N,E=v.inline,S=void 0!==E&&E,B=v.cache,J=void 0!==B&&B,P=v.disableCloseOnSelect,q=void 0!==P&&P,z=v.preventScrollUp,D=void 0!==z&&z,G=v.removeResultsWhenInputIsEmpty,I=void 0!==G&&G,R=v.regex,U=void 0===R?{expression:/[|\\{}()[\]^$+*?]/g,replacement:"\\$&"}:R,W=v.classGroup,F=v.classPreventClosing,H=v.classPrefix,K=v.ariaLabelClear,L=v.onSearch,M=v.onResults,Q=void 0===M?function(){}:M,X=v.onSubmit,Y=void 0===X?function(){}:X,Z=v.onOpened,_=void 0===Z?function(){}:Z,ee=v.onReset,te=void 0===ee?function(){}:ee,ie=v.onRender,ne=void 0===ie?function(){}:ie,oe=v.onClose,se=void 0===oe?function(){}:oe,ae=v.noResults,re=void 0===ae?function(){}:ae,ue=v.onSelectedItem,de=void 0===ue?function(){}:ue;this.t=function(){p.i();var t,i,o,s,a,r=l(p.o);if(e(p.u,r),t=p.u,i=p.l,o=p.o,s=p.h,a=p.v,e(i,{id:o,role:"listbox"}),e(s,{addClass:a+"-results-wrapper"}),s.insertAdjacentElement("beforeend",i),t.parentNode.insertBefore(s,t.nextSibling),d(p.u,"input",p.m),p.p&&d(p.u,"click",p.m),p.k){var u={root:p.u,type:"load"};d(p.u,"load",p.m(u))}p.j({element:p.u,results:p.l}),p.C&&n(p.O,p.destroy)},this.T=function(e,t){p.V&&("update"===e?p.u.setAttribute(p.A,null==t?void 0:t.value):"remove"===e?p.u.removeAttribute(p.A):p.u.value=p.u.getAttribute(p.A))},this.m=function(e){var t,i=e.target,n=e.type;if("true"!==p.u.getAttribute("aria-expanded")||"click"!==n){var o=null==(t=i=p.k?p.u:i)?void 0:t.value.replace(p.N.expression,p.N.replacement);p.T("update",i);var s=p.p||p.k&&"load"===n?0:p.$;clearTimeout(p.S),p.S=setTimeout((function(){var e;if(p.B&&0===(null==(e=i)?void 0:e.value.length))return void p.destroy();p.J(null==o?void 0:o.trim())}),s)}},this.P=function(){var t;o(p.h,"remove",p.q);var i=l(p.o),n=p.D?i:Object.assign({},i,{"aria-activedescendant":""});e(p.u,n),p.D||(p.G(u("."+p.I)),p.R=p.U?0:-1),(0==(null==(t=p.W)?void 0:t.length)&&!p.F||p.p)&&(p.l.textContent=""),p.H()},this.J=function(e){p.K=e,p.L(!0),n(p.O,p.destroy),e&&0!==(null==e?void 0:e.length)||!p.M||p.C||o(p.O,"add","hidden"),p.X>(null==e?void 0:e.length)&&!p.p&&!p.k?p.L():p.Y({currentValue:e,element:p.u}).then((function(t){var i=p.u.value.length,n=t.length;p.W=Array.isArray(t)?t:JSON.parse(JSON.stringify(t)),p.L(),p.Z(),0===n&&0===i&&o(p.O,"add","hidden"),0===n&&i?(o(p.u,"remove","auto-expanded"),p.P(),p._({element:p.u,currentValue:e,template:p.ee}),p.te()):(n>0||function(e){return e&&"object"==typeof e&&e.constructor===Object}(t))&&(p.R=p.U?0:-1,p.ee(),p.te())})).catch((function(){p.L(),p.P()}))},this.L=function(e){return p.u.parentNode.classList[e?"add":"remove"](p.ie)},this.Z=function(){return o(p.u,"remove",p.ne)},this.te=function(){d(p.u,"keydown",p.oe),d(p.u,"click",p.se),p.k||d(document,"click",p.ae),["mousemove","click"].map((function(e){d(p.l,e,p.re)}))},this.ee=function(t){e(p.u,{"aria-expanded":"true",addClass:p.v+"-expanded"}),p.l.textContent="";var n=0===p.W.length?p.ue({currentValue:p.K,matches:0,template:t}):p.ue({currentValue:p.K,matches:p.W,classGroup:p.de});p.l.insertAdjacentHTML("afterbegin",n),o(p.h,"add",p.q);var s,a=p.de?":not(."+p.de+")":"";p.ce=document.querySelectorAll("#"+p.o+" > li"+a),(s=p.ce).forEach((function(t,i){e(t,{role:"option",tabindex:"-1","aria-selected":"false","aria-setsize":s.length,"aria-posinset":i+1})})),p.le({type:"results",element:p.u,results:p.l}),p.he(),i(p.l,p.h)},this.ae=function(e){var t=e.target,i=null;(t.closest("ul")&&p.fe||t.closest("."+p.ve))&&(i=!0),t.id===p.me||i||p.P()},this.he=function(){if(p.G(u("."+p.I)),p.U){var t=p.l.firstElementChild,i=p.de&&p.W.length>0&&p.U?t.nextElementSibling:t;p.pe({index:p.R,element:p.u,object:p.W[p.R],currentValue:p.u.value}),e(i,{id:p.be+"-0",addClass:p.I,"aria-selected":"true"}),s(p.u,p.be+"-0")}},this.se=function(){if(p.l.textContent.length>0&&!o(p.h,"contains",p.q)){if(e(p.u,{"aria-expanded":"true",addClass:p.v+"-expanded"}),o(p.h,"add",p.q),p.D||(i(p.l,p.h),p.he()),p.le({type:"showItems",element:p.u,results:p.l}),!p.V)return;p.T("update",p.u)}},this.re=function(e){e.preventDefault();var t=e.target,i=e.type,n=t.closest("li"),s=null==n?void 0:n.hasAttribute("role"),a=p.I,r=u("."+a);n&&s&&!t.closest("."+p.ve)&&("click"===i&&p.xe(n),"mousemove"!==i||o(n,"contains",a)||(p.G(r),p.ye(n),p.R=p.ke(n),p.pe({index:p.R,element:p.u,object:p.W[p.R]}),p.u.value.length>0&&p.M&&o(p.O,"remove","hidden")))},this.xe=function(e){e&&0!==p.W.length?(p.M&&o(p.O,"remove","hidden"),p.u.value=t(e),p.je({index:p.R,element:p.u,object:p.W[p.R],results:p.l}),p.fe||(p.D||p.G(e),p.P()),p.T("remove")):!p.fe&&p.P()},this.ke=function(e){return Array.prototype.indexOf.call(p.ce,e)},this.oe=function(e){var i=e.keyCode,n=o(p.h,"contains",p.q),a=p.W.length+1;switch(p.Ce=u("."+p.I),i){case h.UP:case h.DOWN:if(e.preventDefault(),a<=1&&p.U||!n)return;if(i===h.UP?(p.R<0&&(p.R=a-1),p.R-=1):(p.R+=1,p.R>=a&&(p.R=0)),p.G(p.Ce),p.R>=0&&p.R<a-1){var r=p.ce[p.R];p.F&&n&&(p.u.value=t(r),p.M&&o(p.O,"remove","hidden")),p.pe({index:p.R,element:p.u,object:p.W[p.R]}),p.ye(r)}else p.T(),s(p.u),p.pe({index:null,element:p.u,object:null});break;case h.ENTER:e.preventDefault(),p.xe(p.Ce);break;case h.TAB:case h.ESC:e.stopPropagation(),p.k||p.P()}},this.ye=function(t){var i=p.be+"-"+p.ke(t);e(t,{id:i,"aria-selected":"true",addClass:p.I}),s(p.u,i),a(t,p.o,p.de,p.l)},this.G=function(t){t&&e(t,{id:"",removeClass:p.I,"aria-selected":"false"})},this.i=function(){p.M&&(e(p.O,{type:"button",class:p.v+"-clear hidden",title:p.Oe,"aria-label":p.Oe}),p.u.insertAdjacentElement("afterend",p.O))},this.rerender=function(e){var t=null!=e&&e.trim()?e.trim():p.u.value;null!=e&&e.trim()&&(p.u.value=e.trim(),p.T("update",p.u));var i=t.replace(p.N.expression,p.N.replacement);p.J(i.trim())},this.destroy=function(){p.M&&o(p.O,"add","hidden"),p.u.value="",p.u.focus(),p.l.textContent="",p.k||p.P(),p.k&&p.H(),p.Z(),p.ge(p.u),p.L(),c(p.u,"keydown",p.oe),c(p.u,"click",p.se),c(document,"click",p.ae)},this.me=f,this.u=document.getElementById(f),this.Y=(m=L,Boolean(m&&"function"==typeof m.then)?L:function(e){var t=e.currentValue,i=e.element;return Promise.resolve(L({currentValue:t,element:i}))}),this.ue=Q,this.j=ne,this.je=Y,this.pe=de,this.le=_,this.ge=te,this._=re,this.H=se,this.$=x,this.X=g,this.M=k,this.C=C,this.U=T,this.F=A,this.p=$,this.k=S,this.de=W,this.ve=F,this.Oe=K||"clear the search query",this.v=H?H+"-auto":"auto",this.fe=q,this.D=D,this.B=I,this.V=J,this.S=null,this.o=this.v+"-"+this.me+"-results",this.A="data-cache-auto-"+this.me,this.ie=this.v+"-is-loading",this.q=this.v+"-is-active",this.I=this.v+"-selected",this.be=this.v+"-selected-option",this.ne=this.v+"-error",this.h=r("div"),this.l=r("ul"),this.O=r("button"),this.N=Object.assign({},{expression:/[|\\{}()[\]^$+*?]/g,replacement:"\\$&"},U),this.N.replacement||(this.N.replacement=this.we.replacement),this.N.expression||(this.N.expression=this.we.expression),this.t()}}));