From 3fe56ff4635e52d6b1733bb88e431894a3637309 Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Thu, 7 Mar 2024 21:21:50 +0530 Subject: [PATCH] Add `unbind()`. --- docs/floatype.min.js | 2 +- docs/index.html | 4 +++- floatype.js | 6 ++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/floatype.min.js b/docs/floatype.min.js index 68913c0..d15f906 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,a=[];const c=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 u(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 a=function(e){const t=e.value.substring(0,e.selectionStart);if(/\S$/.test(t))return t.match(/\S*$/)[0];return""}(e);a?(l=a,clearTimeout(s),s=setTimeout(r,n.debounce)):p()}async function r(){l&&(a=await n.onQuery(l),a.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";c.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`,a.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+a.length)%a.length,o.querySelector(`:nth-child(${i+1})`).classList.add("floatype-sel")}function f(t){const o=n.onSelect?n.onSelect(a[t]):a[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(){a=[],i=0,l=null,o&&(o.remove(),o=null)}["input","keydown","blur"].forEach((t=>e.addEventListener(t,u)))}export default floatype; +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 diff --git a/docs/index.html b/docs/index.html index 5c958f2..020024e 100644 --- a/docs/index.html +++ b/docs/index.html @@ -92,7 +92,7 @@

floatype.js

// Example 1. // Simple string results. - floatype(document.querySelector("textarea"), { + 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. @@ -105,6 +105,8 @@

floatype.js

return WORDS.filter(s => s.startsWith(q)).slice(0, 10); } }); + + // f.unbind() to remove the binding. \ No newline at end of file diff --git a/floatype.js b/floatype.js index 0134b54..8fa3a5d 100644 --- a/floatype.js +++ b/floatype.js @@ -188,6 +188,12 @@ export function floatype(el, options = {}) { el.value = el.value.substring(0, start) + val + (el.value[el.selectionStart] !== " " ? " " : "") + el.value.substring(el.selectionStart); el.setSelectionRange(start + val.length + 1, start + val.length + 1); } + + return { + unbind: function() { + ["input", "keydown", "blur"].forEach(k => el.removeEventListener(k, handleEvent)); + } + } } export default floatype;