UNPKG

@tomickigrzegorz/autocomplete

Version:

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

9 lines (8 loc) 8.53 kB
/*! * @name autocomplete * @version 3.0.0 * @author Grzegorz Tomicki * @link https://github.com/tomickigrzegorz/autocomplete * @license MIT */ var Autocomplete=function(){"use strict";var t=function(t,e){Object.entries(e).forEach((function(e){var i=e[0],n=e[1];"addClass"===i||"removeClass"===i?o(t,"addClass"===i?"add":"remove",n):t.setAttribute(i,n)}))},e=function(t){return(t.firstElementChild||t).textContent.trim()},i=function(t,e){t.scrollTop=t.offsetTop-e.offsetHeight},n=function(t,e){t&&(o(t,"remove","hidden"),c(t,"click",e))},o=function(t,e,i){return t.classList[e](i)},s=function(e,i){t(e,{"aria-activedescendant":i||""})},a=function(t,e,i,n){var o=n.previousSibling,s=o?o.offsetHeight:0;if("0"===t.getAttribute("aria-posinset")&&(n.scrollTop=t.offsetTop-function(t,e){var i=document.querySelectorAll("#"+t+" > li:not(."+e+")");return Array.from(i).reduce((function(t,e){return t+e.offsetHeight}),0)}(e,i)),t.offsetTop-s<n.scrollTop)n.scrollTop=t.offsetTop-s;else{var a=t.offsetTop+t.offsetHeight-s;a>n.scrollTop+n.offsetHeight&&(n.scrollTop=a-n.offsetHeight)}},r=function(t){return document.createElement(t)},u=function(t){return document.querySelector(t)},c=function(t,e,i){t.addEventListener(e,i)},d=function(t,e,i){t.removeEventListener(e,i)},l=function(t){return{"aria-owns":t,"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(v,f){var m,p=this,b=f.delay,x=void 0===b?500:b,k=f.clearButton,y=void 0===k||k,j=f.clearButtonOnInitial,C=void 0!==j&&j,O=f.howManyCharacters,w=void 0===O?1:O,V=f.selectFirst,A=void 0!==V&&V,g=f.insertToInput,N=void 0!==g&&g,T=f.showValuesOnClick,$=void 0!==T&&T,E=f.inline,S=void 0!==E&&E,B=f.cache,J=void 0!==B&&B,P=f.disableCloseOnSelect,q=void 0!==P&&P,z=f.preventScrollUp,D=void 0!==z&&z,G=f.removeResultsWhenInputIsEmpty,I=void 0!==G&&G,R=f.regex,U=void 0===R?{expression:/[|\\{}()[\]^$+*?]/g,replacement:"\\$&"}:R,W=f.classGroup,F=f.classPreventClosing,H=f.classPrefix,K=f.ariaLabelClear,L=f.onSearch,M=f.onResults,Q=void 0===M?function(){}:M,X=f.onSubmit,Y=void 0===X?function(){}:X,Z=f.onOpened,_=void 0===Z?function(){}:Z,tt=f.onReset,et=void 0===tt?function(){}:tt,it=f.onRender,nt=void 0===it?function(){}:it,ot=f.onClose,st=void 0===ot?function(){}:ot,at=f.noResults,rt=void 0===at?function(){}:at,ut=f.onSelectedItem,ct=void 0===ut?function(){}:ut;this.t=function(){p.i();var e,i,o,s,a,r=l(p.o);if(t(p.u,r),e=p.u,i=p.l,o=p.o,s=p.h,a=p.v,t(i,{id:o,role:"listbox"}),t(s,{addClass:a+"-results-wrapper"}),s.insertAdjacentElement("beforeend",i),e.parentNode.insertBefore(s,e.nextSibling),c(p.u,"input",p.m),p.p&&c(p.u,"click",p.m),p.k){var u={root:p.u,type:"load"};c(p.u,"load",p.m(u))}p.j({element:p.u,results:p.l}),p.C&&n(p.O,p.destroy)},this.V=function(t,e){p.A&&("update"===t?p.u.setAttribute(p.N,null==e?void 0:e.value):"remove"===t?p.u.removeAttribute(p.N):p.u.value=p.u.getAttribute(p.N))},this.m=function(t){var e,i=t.target,n=t.type;if("true"!==p.u.getAttribute("aria-expanded")||"click"!==n){var o=null==(e=i=p.k?p.u:i)?void 0:e.value.replace(p.T.expression,p.T.replacement);p.V("update",i);var s=p.p||p.k&&"load"===n?0:p.$;clearTimeout(p.S),p.S=setTimeout((function(){var t;if(p.B&&0===(null==(t=i)?void 0:t.value.length))return void p.destroy();p.J(null==o?void 0:o.trim())}),s)}},this.P=function(){var e;o(p.h,"remove",p.q);var i=l(p.o),n=p.D?i:Object.assign({},i,{"aria-activedescendant":""});t(p.u,n),p.D||(p.G(u("."+p.I)),p.R=p.U?0:-1),(0==(null==(e=p.W)?void 0:e.length)&&!p.F||p.p)&&(p.l.textContent=""),p.H()},this.J=function(t){p.K=t,p.L(!0),n(p.O,p.destroy),t&&0!==(null==t?void 0:t.length)||!p.M||p.C||o(p.O,"add","hidden"),p.X>(null==t?void 0:t.length)&&!p.p&&!p.k?p.L():p.Y({currentValue:t,element:p.u}).then((function(e){var i=p.u.value.length,n=e.length;p.W=Array.isArray(e)?e:JSON.parse(JSON.stringify(e)),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:t,template:p.tt}),p.et()):(n>0||function(t){return t&&"object"==typeof t&&t.constructor===Object}(e))&&(p.R=p.U?0:-1,p.tt(),p.et())})).catch((function(){p.L(),p.P()}))},this.L=function(t){return p.u.parentNode.classList[t?"add":"remove"](p.it)},this.Z=function(){return o(p.u,"remove",p.nt)},this.et=function(){c(p.u,"keydown",p.ot),c(p.u,"click",p.st),p.k||c(document,"click",p.rt),["mousemove","click"].map((function(t){c(p.l,t,p.ut)}))},this.tt=function(e){t(p.u,{"aria-expanded":"true",addClass:p.v+"-expanded"}),p.l.textContent="";var n=0===p.W.length?p.ct({currentValue:p.K,matches:0,template:e}):p.ct({currentValue:p.K,matches:p.W,classGroup:p.dt});p.l.insertAdjacentHTML("afterbegin",n),o(p.h,"add",p.q);var s,a=p.dt?":not(."+p.dt+")":"";p.lt=document.querySelectorAll("#"+p.o+" > li"+a),(s=p.lt).forEach((function(e,i){t(e,{role:"option",tabindex:"-1","aria-selected":"false","aria-setsize":s.length,"aria-posinset":i+1})})),p.ht({type:"results",element:p.u,results:p.l}),p.vt(),i(p.l,p.h)},this.rt=function(t){var e=t.target,i=null;(e.closest("ul")&&p.ft||e.closest("."+p.bt))&&(i=!0),e.id===p.xt||i||p.P()},this.vt=function(){if(p.G(u("."+p.I)),p.U){var e=p.l.firstElementChild,i=p.dt&&p.W.length>0&&p.U?e.nextElementSibling:e;p.kt({index:p.R,element:p.u,object:p.W[p.R],currentValue:p.u.value}),t(i,{id:p.yt+"-0",addClass:p.I,"aria-selected":"true"}),s(p.u,p.yt+"-0")}},this.st=function(){if(p.l.textContent.length>0&&!o(p.h,"contains",p.q)){if(t(p.u,{"aria-expanded":"true",addClass:p.v+"-expanded"}),o(p.h,"add",p.q),p.D||(i(p.l,p.h),p.vt()),p.ht({type:"showItems",element:p.u,results:p.l}),!p.A)return;p.V("update",p.u)}},this.ut=function(t){t.preventDefault();var e=t.target,i=t.type,n=e.closest("li"),s=null==n?void 0:n.hasAttribute("role"),a=p.I,r=u("."+a);n&&s&&!e.closest("."+p.bt)&&("click"===i&&p.jt(n),"mousemove"!==i||o(n,"contains",a)||(p.G(r),p.Ct(n),p.R=p.Ot(n),p.kt({index:p.R,element:p.u,object:p.W[p.R]}),p.u.value.length>0&&p.M&&o(p.O,"remove","hidden")))},this.jt=function(t){t&&0!==p.W.length?(p.M&&o(p.O,"remove","hidden"),p.u.value=e(t),p.wt({index:p.R,element:p.u,object:p.W[p.R],results:p.l}),p.ft||(p.D||p.G(t),p.P()),p.V("remove")):!p.ft&&p.P()},this.Ot=function(t){return Array.prototype.indexOf.call(p.lt,t)},this.ot=function(t){var i=t.keyCode,n=o(p.h,"contains",p.q),a=p.W.length+1;switch(p.Vt=u("."+p.I),i){case h.UP:case h.DOWN:if(t.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.Vt),p.R>=0&&p.R<a-1){var r=p.lt[p.R];p.F&&n&&(p.u.value=e(r),p.M&&o(p.O,"remove","hidden")),p.kt({index:p.R,element:p.u,object:p.W[p.R]}),p.Ct(r)}else p.V(),s(p.u),p.kt({index:null,element:p.u,object:null});break;case h.ENTER:t.preventDefault(),p.jt(p.Vt);break;case h.TAB:case h.ESC:t.stopPropagation(),p.k||p.P()}},this.Ct=function(e){var i=p.yt+"-"+p.Ot(e);t(e,{id:i,"aria-selected":"true",addClass:p.I}),s(p.u,i),a(e,p.o,p.dt,p.l)},this.G=function(e){e&&t(e,{id:"",removeClass:p.I,"aria-selected":"false"})},this.i=function(){p.M&&(t(p.O,{type:"button",class:p.v+"-clear hidden",title:p.At,"aria-label":p.At}),p.u.insertAdjacentElement("afterend",p.O))},this.rerender=function(t){var e=null!=t&&t.trim()?t.trim():p.u.value;null!=t&&t.trim()&&(p.u.value=t.trim(),p.V("update",p.u));var i=e.replace(p.T.expression,p.T.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.gt(p.u),p.L(),d(p.u,"keydown",p.ot),d(p.u,"click",p.st),d(document,"click",p.rt)},this.xt=v,this.u=document.getElementById(v),this.Y=(m=L,Boolean(m&&"function"==typeof m.then)?L:function(t){var e=t.currentValue,i=t.element;return Promise.resolve(L({currentValue:e,element:i}))}),this.ct=Q,this.j=nt,this.wt=Y,this.kt=ct,this.ht=_,this.gt=et,this._=rt,this.H=st,this.$=x,this.X=w,this.M=y,this.C=C,this.U=A,this.F=N,this.p=$,this.k=S,this.dt=W,this.bt=F,this.At=K||"clear the search query",this.v=H?H+"-auto":"auto",this.ft=q,this.D=D,this.B=I,this.A=J,this.S=null,this.o=this.v+"-"+this.xt+"-results",this.N="data-cache-auto-"+this.xt,this.it=this.v+"-is-loading",this.q=this.v+"-is-active",this.I=this.v+"-selected",this.yt=this.v+"-selected-option",this.nt=this.v+"-error",this.h=r("div"),this.l=r("ul"),this.O=r("button"),this.T=Object.assign({},{expression:/[|\\{}()[\]^$+*?]/g,replacement:"\\$&"},U),this.T.replacement||(this.T.replacement=this.Nt.replacement),this.T.expression||(this.T.expression=this.Nt.expression),this.t()}}();