diff --git a/docs/floatype.min.js b/docs/floatype.min.js index d15f906..8d06d64 100644 --- a/docs/floatype.min.js +++ b/docs/floatype.min.js @@ -1 +1 @@ -export function floatype(e,t={}){const n={onQuery:null,onNavigate:null,onSelect:null,onRender:null,debounce:100,...t};let o,l,s,i=0,r=[];const u=function(){const t=document.createElement("div");document.querySelector("body").appendChild(t);const n=window.getComputedStyle(e);for(const e of n)t.style[e]=n[e];return t.style.visibility="hidden",t.style.position="absolute",t.style.left="-500%",t.style.top="-500%",t}();function a(t){if("keydown"===t.type&&function(e){if(!o)return!0;switch(e.keyCode){case 38:return d(-1,e);case 40:return d(1,e);case 9:case 32:case 13:return e.preventDefault(),f(i),void p();case 27:return p(),!0}}(t))return;if("blur"===t.type)return void p();const r=function(e){const t=e.value.substring(0,e.selectionStart);if(/\S$/.test(t))return t.match(/\S*$/)[0];return""}(e);r?(l=r,clearTimeout(s),s=setTimeout(c,n.debounce)):p()}async function c(){l&&(r=await n.onQuery(l),r.length?(o||(o=document.createElement("div"),Object.assign(o.style,{width:window.getComputedStyle(e).width,position:"fixed",left:`${e.offsetLeft}px`,top:`${e.offsetTop+e.offsetHeight}px`}),o.classList.add("floatype"),e.parentNode.insertBefore(o,e.nextSibling)),function(){o.innerHTML="";const t=function(e){const t=e.value.substring(0,e.selectionStart),n=Math.max(t.lastIndexOf("\n"),t.lastIndexOf(" "))+1,o="floatype-caret";u.innerHTML=e.value.substring(0,n)+`${e.value.substring(n)}`;const l=document.getElementById(o),s=e.getBoundingClientRect();return{x:s.left+l.offsetLeft-e.scrollLeft,y:s.top+l.offsetTop-e.scrollTop+(parseInt(getComputedStyle(l).height)+5)}}(e);o.style.left=`${t.x}px`,o.style.top=`${t.y}px`,r.forEach(((e,t)=>{const l=document.createElement("div");l.classList.add("floatype-item"),n.onRender?l.appendChild(n.onRender(e)):l.innerText=e,t===i&&l.classList.add("floatype-sel"),l.addEventListener("mousedown",(()=>f(t))),o.appendChild(l)}))}()):p())}function d(e,t){t.preventDefault();const n=o.querySelector(`:nth-child(${i+1})`);n&&n.classList.remove("floatype-sel"),i=(i+e+r.length)%r.length,o.querySelector(`:nth-child(${i+1})`).classList.add("floatype-sel")}function f(t){const o=n.onSelect?n.onSelect(r[t]):r[t];!function(e,t){const n=Math.max(e.value.lastIndexOf(" ",e.selectionStart-1),e.value.lastIndexOf("\n",e.selectionStart-1))+1;e.value=e.value.substring(0,n)+t+(" "!==e.value[e.selectionStart]?" ":"")+e.value.substring(e.selectionStart),e.setSelectionRange(n+t.length+1,n+t.length+1)}(e,o),setTimeout((()=>e.focus()),50)}function p(){r=[],i=0,l=null,o&&(o.remove(),o=null)}return["input","keydown","blur"].forEach((t=>e.addEventListener(t,a))),{unbind:function(){["input","keydown","blur"].forEach((t=>e.removeEventListener(t,a)))}}}export default floatype; \ No newline at end of file +export function floatype(e,t={}){const n={onQuery:null,onNavigate:null,onSelect:null,onRender:null,debounce:100,...t};let o,l,s,i=0,r=[];const u=function(){const t=document.createElement("div");document.querySelector("body").appendChild(t);const n=window.getComputedStyle(e);for(const e of n)t.style[e]=n[e];return t.style.visibility="hidden",t.style.position="absolute",t.style.left="-500%",t.style.top="-500%",t}();function a(t){if("keydown"===t.type&&function(e){if(!o)return!0;switch(e.keyCode){case 38:return d(-1,e);case 40:return d(1,e);case 9:case 32:case 13:return e.preventDefault(),f(i),void p();case 27:return p(),!0}}(t))return;if("blur"===t.type)return void p();const r=function(e){const t=e.value.substring(0,e.selectionStart);if(/\S$/.test(t))return t.match(/\S*$/)[0];return""}(e);r?(l=r,clearTimeout(s),s=setTimeout(c,n.debounce)):p()}async function c(){l&&(r=await n.onQuery(l),r.length?(o||(o=document.createElement("div"),Object.assign(o.style,{width:window.getComputedStyle(e).width,position:"fixed",left:`${e.offsetLeft}px`,top:`${e.offsetTop+e.offsetHeight}px`}),o.classList.add("floatype"),e.parentNode.insertBefore(o,e.nextSibling)),function(){o.innerHTML="";const t=function(e){const t=e.value.substring(0,e.selectionStart),n=Math.max(t.lastIndexOf("\n"),t.lastIndexOf(" "))+1,o="floatype-caret";u.innerHTML=e.value.substring(0,n)+`${e.value.substring(n)}`;const l=document.getElementById(o),s=e.getBoundingClientRect();return{x:s.left+l.offsetLeft-e.scrollLeft,y:s.top+l.offsetTop-e.scrollTop+(parseInt(getComputedStyle(l).height)+5)}}(e);o.style.left=`${t.x}px`,o.style.top=`${t.y}px`,r.forEach(((e,t)=>{const l=document.createElement("div");l.classList.add("floatype-item"),n.onRender?l.appendChild(n.onRender(e)):l.innerText=e,t===i&&l.classList.add("floatype-sel"),l.addEventListener("mousedown",(()=>f(t))),o.appendChild(l)}))}()):p())}function d(e,t){t.preventDefault();const n=o.querySelector(`:nth-child(${i+1})`);n&&n.classList.remove("floatype-sel"),i=(i+e+r.length)%r.length,o.querySelector(`:nth-child(${i+1})`).classList.add("floatype-sel")}function f(t){const o=n.onSelect?n.onSelect(r[t]):r[t];!function(e,t){const n=Math.max(e.value.lastIndexOf(" ",e.selectionStart-1),e.value.lastIndexOf("\n",e.selectionStart-1))+1;e.value=e.value.substring(0,n)+t+(" "!==e.value[e.selectionStart]?" ":"")+e.value.substring(e.selectionStart),e.setSelectionRange(n+t.length+1,n+t.length+1)}(e,o),setTimeout((()=>e.focus()),50)}function p(){r=[],i=0,l=null,o&&(o.remove(),o=null)}return["input","keydown","blur"].forEach((t=>e.addEventListener(t,a))),{unbind:function(){["input","keydown","blur"].forEach((t=>e.removeEventListener(t,a))),p(),u.remove()}}}export default floatype; \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 020024e..51826c3 100644 --- a/docs/index.html +++ b/docs/index.html @@ -77,6 +77,7 @@

floatype.js


Zero dependencies (~1200 bytes minified + gzipped). Type below to try.

+

For dropdown suggestions on inputs, see autocomp.js

@@ -92,21 +93,34 @@

floatype.js

// Example 1. // Simple string results. - const f = floatype(document.querySelector("textarea"), { - onQuery: async (val) => { - // This callback returns an array of search results. - // Typically, this will be a server side fetch() request. - // Example: - // const resp = await fetch(`/search?q=${query}`); - // const res = await response.json(); - // return res; + function bind() { + return floatype(document.querySelector("textarea"), { + onQuery: async (val) => { + // This callback returns an array of search results. + // Typically, this will be a server side fetch() request. + // Example: + // const resp = await fetch(`/search?q=${query}`); + // const res = await response.json(); + // return res; - const q = val.trim().toLowerCase(); - return WORDS.filter(s => s.startsWith(q)).slice(0, 10); + const q = val.trim().toLowerCase(); + return WORDS.filter(s => s.startsWith(q)).slice(0, 10); + } + }); + } + + window._fl = bind(); + + document.querySelector("button").onclick = (e) => { + if (window._fl) { + window._fl.unbind(); + window._fl = null; + } else { + window._fl = bind(); } - }); - // f.unbind() to remove the binding. + document.querySelector("textarea").focus(); + } \ No newline at end of file diff --git a/floatype.js b/floatype.js index 8fa3a5d..5ec9bc5 100644 --- a/floatype.js +++ b/floatype.js @@ -192,6 +192,8 @@ export function floatype(el, options = {}) { return { unbind: function() { ["input", "keydown", "blur"].forEach(k => el.removeEventListener(k, handleEvent)); + destroy(); + shadow.remove(); } } } diff --git a/package.json b/package.json index a5c85ef..f65b75f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@knadh/floatype", - "version": "1.2.0", + "version": "1.2.1", "description": "A tiny, zero-dependency, floating autocomplete / autosuggestion widget for textarea.", "main": "floatype.js", "files": [