diff --git a/auto-complete.css b/auto-complete.css index 4261b1d..76a9488 100644 --- a/auto-complete.css +++ b/auto-complete.css @@ -1,9 +1,19 @@ .autocomplete-suggestions { text-align: left; cursor: default; border: 1px solid #ccc; border-top: 0; background: #fff; box-shadow: -1px 1px 3px rgba(0,0,0,.1); - - /* core styles should not be changed */ - position: absolute; display: none; z-index: 9999; max-height: 254px; overflow: hidden; overflow-y: auto; box-sizing: border-box; + position: absolute; /* display: none; z-index: 9999; */ max-height: 254px; overflow: hidden; overflow-y: auto; box-sizing: border-box; + left: auto; top: 100%; width: 100%; margin: 0; contain: content; /* 1.2.0 */ } .autocomplete-suggestion { position: relative; padding: 0 .6em; line-height: 23px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 1.02em; color: #333; } .autocomplete-suggestion b { font-weight: normal; color: #1f8dd6; } .autocomplete-suggestion.selected { background: #f0f0f0; } + +autocomplete-holder { + overflow: visible; position: absolute; left: auto; top: auto; width: 100%; height: 0; z-index: 9999; box-sizing: border-box; margin:0; padding:0; border:0; contain: size layout; +} + +autocomplete-holder[position="top"] { + margin-top: 0 !important; +} +autocomplete-holder[position="top"] .autocomplete-suggestions { + transform: translateY(-100%); +} \ No newline at end of file diff --git a/auto-complete.js b/auto-complete.js index fba735f..7526f89 100644 --- a/auto-complete.js +++ b/auto-complete.js @@ -1,11 +1,11 @@ /* - JavaScript autoComplete v1.1.0 + JavaScript autoComplete v1.2.0 Copyright (c) 2014 Simon Steinberger / Pixabay GitHub: https://github.com/Pixabay/JavaScript-autoComplete License: http://www.opensource.org/licenses/mit-license.php */ -// Chrome 38+, Edge 13+, Safari 8+, Firefox 26+, Opera 25+, all mobile browsers +// Chrome 41+, Edge 15+, Safari 9+, Firefox 35+, Opera 28+, all mobile browsers var autoComplete = (function(){ // "use strict"; @@ -13,10 +13,10 @@ var autoComplete = (function(){ if (!document.querySelector) return; // helpers - function live(elClass, event, cb, context){ - (context || document).addEventListener(event, function(e){ - for (var t = e.target || e.srcElement; t; t = t.parentElement) - t.classList.contains(elClass) && (cb.call(t, e), t = 1); + function live(selector, event, cb, context){ + context.addEventListener(event, function(e){ + var t = (e.target || e.srcElement).closest(selector); + t && cb.call(t, e); }, true); } @@ -29,6 +29,8 @@ var autoComplete = (function(){ offsetTop: 1, cache: 1, menuClass: '', + clickToShow: 1, + closeOnTap: 1, renderItem: function(item, search){ // escape special characters var si = document.createElement('div'); @@ -42,193 +44,257 @@ var autoComplete = (function(){ } return si; }, - renderItems: function (data, search, that){ + renderItems: function (data, search, ipt){ var tp = document.createElement('template'); var df = tp.content; - for (var i=0;i<data.length;i++){ + for (var i = 0; i < data.length; i++) { var item = data[i]; var si = o.renderItem(item, search); - if (typeof si === 'string') tp.innerHTML += si; - else if (si && si.nodeType === 1) df.appendChild(si); + if (typeof si == 'string') tp.innerHTML += si; + else if (si && si.nodeType == 1) df.appendChild(si); } - var _sc = that.sc; + var _sc = ipt.sc; var firstChild; - while (firstChild = _sc.firstChild) { - firstChild.remove(); - } + while (firstChild = _sc.firstChild) firstChild.remove(); _sc.appendChild(df); }, - onSelect: function(e, term, item){} + onSelect: function(e, term, item){}, + onRender: function(data, val, ipt){}, }; for (var k in options) { if (options.hasOwnProperty(k)) o[k] = options[k]; } - // init - var elems = typeof o.selector == 'object' ? [o.selector] : document.querySelectorAll(o.selector); - var forEach = function (that) { + var forEach = function (ipt) { - that._currentRequestId = 0; + ipt._currentRequestId = 0; // create suggestions container "sc" - that.sc = document.createElement('div'); - that.sc.className = 'autocomplete-suggestions '+o.menuClass; - - that.autocompleteAttr = that.getAttribute('autocomplete'); - that.setAttribute('autocomplete', 'off'); - that.cache = new Map(); // changed from {} to Map; related to PR#37 PR#38 - that.last_val = ''; - - that.updateSC = function(resize, next){ // see issue mentioned in PR#49 - if(that != document.activeElement) return; // issue#51 PR#52 - var rect = that.getBoundingClientRect(); - that.sc.style.left = Math.round(rect.left + (window.pageXOffset || document.documentElement.scrollLeft) + o.offsetLeft) + 'px'; - that.sc.style.top = Math.round(rect.bottom + (window.pageYOffset || document.documentElement.scrollTop) + o.offsetTop) + 'px'; - that.sc.style.width = Math.round(rect.right - rect.left) + 'px'; // outerWidth - if (!resize) { - that.sc.style.display = 'block'; - if (!that.sc.maxHeight) { that.sc.maxHeight = parseInt((window.getComputedStyle ? getComputedStyle(that.sc, null) : that.sc.currentStyle).maxHeight); } - if (!that.sc.suggestionHeight) that.sc.suggestionHeight = that.sc.querySelector('.autocomplete-suggestion').offsetHeight; - if (that.sc.suggestionHeight) - if (!next) that.sc.scrollTop = 0; - else { - var scrTop = that.sc.scrollTop, selTop = next.getBoundingClientRect().top - that.sc.getBoundingClientRect().top; - if (selTop + that.sc.suggestionHeight - that.sc.maxHeight > 0) { - that.sc.scrollTop = selTop + that.sc.suggestionHeight + scrTop - that.sc.maxHeight; - } else if (selTop < 0){ - that.sc.scrollTop = selTop + scrTop; - } + ipt.sc = document.createElement('div'); + ipt.sc.className = 'autocomplete-suggestions '+o.menuClass; + ipt.sc.style.display = 'none'; + + ipt.pivot = document.createElement('autocomplete-holder'); + ipt.autocompleteAttr = ipt.getAttribute('autocomplete'); + ipt.setAttribute('autocomplete', 'off'); + ipt.cache = new Map(); // changed from {} to Map; related to PR#37 PR#38 + ipt.last_val = ''; + + ipt.updateSize = function(){ + var pivot = ipt.pivot; + var rect = ipt.getBoundingClientRect(); + pivot.style.width = rect.width+'px'; + // pivot.style.height = rect.height+'px'; + pivot.style.marginTop = rect.height+'px'; + // pivot.style.marginBottom = -rect.height+'px'; + } + + ipt.isSCVisible = function(){ + var style = ipt.sc.style; + return style.display != 'none'; + } + ipt.hideSC = function(){ + var style = ipt.sc.style; + style.display != 'none' && (style.display = 'none'); + } + + ipt.showSC = function(){ + var style = ipt.sc.style; + style.display == 'none' && (style.display = 'block'); + } + + ipt.updateSC = function(next){ // see issue mentioned in PR#49 + + ipt.updateSize(); + var pivot = ipt.pivot; + var _sc = ipt.sc; + (_sc.parentNode == pivot) || pivot.appendChild(_sc); + (ipt.nextSibling == pivot) || ipt.parentNode.insertBefore(pivot, ipt); + ipt.showSC(); + + if (!next) _sc.scrollTop = 0; + else { + var rectSC = _sc.getBoundingClientRect(); + if (rectSC.height > 0) { + var rectNext = next.getBoundingClientRect(); + var a = rectNext.top - rectSC.top; + var b = rectNext.bottom - rectSC.bottom; + if (b > 0) { + _sc.scrollTop += b; + } else if (a < 0) { + _sc.scrollTop += a; } + } } + }; - window.addEventListener('resize', that.updateSC); - document.body.appendChild(that.sc); + // window.addEventListener('resize', ipt.updateSC); + + // ipt.pivot.appendChild(ipt.sc); + ipt.parentNode.insertBefore(ipt.pivot, ipt); // avoid Safari's minor layout bug - that.sc.addEventListener('mouseleave', function(e){ - var sel = that.sc.querySelector('.autocomplete-suggestion.selected'); - if (sel) setTimeout(function(){ sel.classList.remove('selected'); }, 20); + ipt.sc.addEventListener('mouseleave', function(e){ + var sel = ipt.sc.querySelector('.autocomplete-suggestion.selected'); + sel.classList.remove('selected'); }); - live('autocomplete-suggestion', 'mouseenter', function(e){ - var sel = that.sc.querySelector('.autocomplete-suggestion.selected'); + live('.autocomplete-suggestion', 'mouseenter', function(e){ + var sel = ipt.sc.querySelector('.autocomplete-suggestion.selected'); if (sel) sel.classList.remove('selected'); this.classList.add('selected'); - }, that.sc); + }, ipt.sc); - live('autocomplete-suggestion', 'mousedown', function(e){ + live('.autocomplete-suggestion', 'pointerdown', function(e){ e.stopPropagation(); - var v = this.getAttribute('data-val'); - that.value = v; - o.onSelect(e, v, this); - that.sc.style.display = 'none'; - }, that.sc); - - that.blurHandler = function(){ - try { var over_sb = document.querySelector('.autocomplete-suggestions:hover'); } catch(e){ var over_sb = 0; } - if (!over_sb) { - that.last_val = that.value; - that.sc.style.display = 'none'; - setTimeout(function(){ that.sc.style.display = 'none'; }, 350); // hide suggestions on fast input - } else if (that !== document.activeElement) setTimeout(function(){ that.focus(); }, 20); - }; - that.addEventListener('blur', that.blurHandler); + e.preventDefault(); + if (!e.button) { // only left click + var v = ipt.value = this.getAttribute('data-val'); + o.onSelect(e, v, this); + o.closeOnTap && ipt.hideSC(); + } + }, ipt.sc); - var suggest = function(data, val){ - val = val || that.value; // PR#28 - that.cache.set(val, data); - that.triggerSC(data, val, val.length >= o.minChars); + var suggest = function(data, val){ // see PR#28 + if (typeof val == 'string') { + (data instanceof Array) && ipt.cache.set(val, data); + ipt.triggerSC(data, val, val.length >= o.minChars); + } }; + // PR#40 // Optional method to trigger results programatically - that.triggerSC = function(data, val, b){ - if (data.length && b!==false) { - o.renderItems(data, (val || ''), that); - that.updateSC(0); + ipt.triggerSC = function(data, val, b){ + if (data.length && b !== false) { + o.renderItems(data, val, ipt); + ipt.updateSC(); + o.onRender(data, val, ipt); } else { - that.sc.style.display = 'none'; + ipt.hideSC(); } }; - that.keydownHandler = function(e){ - var key = window.event ? e.keyCode : e.which; - // down (40), up (38) - if ((key == 40 || key == 38) && that.sc.innerHTML) { - var next, sel = that.sc.querySelector('.autocomplete-suggestion.selected'); - if (!sel) { - next = (key == 40) ? that.sc.querySelector('.autocomplete-suggestion') : that.sc.childNodes[that.sc.childNodes.length - 1]; // first : last - next.classList.add('selected'); - that.value = next.getAttribute('data-val'); - } else { - next = (key == 40) ? sel.nextSibling : sel.previousSibling; - sel.classList.remove('selected'); + var inputCounter = 0; + + ipt.iptHandlers = { + blur(){ + ipt.last_val = ipt.value; + ipt.hideSC(); + }, + keydown(e){ + var key = window.event ? e.keyCode : e.which; + // down (40), up (38) + if ((key == 40 || key == 38) && ipt.sc.lastChild) { + var next, sel = ipt.sc.querySelector('.autocomplete-suggestion.selected'); + if (!sel) { + next = (key == 40) ? ipt.sc.querySelector('.autocomplete-suggestion') : ipt.sc.lastChild; // first : last + } else { + next = (key == 40) ? sel.nextSibling : sel.previousSibling; + sel.classList.remove('selected'); + } if (next) { next.classList.add('selected'); - that.value = next.getAttribute('data-val'); + ipt.value = next.getAttribute('data-val'); } else { - that.value = that.last_val; + ipt.value = ipt.last_val; next = 0; } - } - that.updateSC(0, next); - return false; - } - // esc - else if (key == 27) { that.value = that.last_val; that.sc.style.display = 'none'; } - // enter - else if (key == 13 || key == 9) { - var tsc = that.sc; - if (tsc.style.display !== 'none') { // PR#8 + ipt.updateSC(next); e.preventDefault(); } - var sel = tsc.querySelector('.autocomplete-suggestion.selected'); - if (sel && tsc.style.display != 'none') { - o.onSelect(e, sel.getAttribute('data-val'), sel); - setTimeout(function(){ tsc.style.display = 'none'; }, 20); - e.preventDefault(); + // esc + else if (key == 27) { ipt.value = ipt.last_val; ipt.hideSC(); } + // enter + else if (key == 13 || key == 9) { + var tsc = ipt.sc; + var isVisible = ipt.isSCVisible(); + var sel = tsc.querySelector('.autocomplete-suggestion.selected'); + if (sel && isVisible) { + o.onSelect(e, sel.getAttribute('data-val'), sel); + ipt.hideSC(); + } + if (isVisible) { // PR#8 + e.preventDefault(); + } + ipt.last_val = ipt.value; } - } - }; - that.addEventListener('keydown', that.keydownHandler); - - that.keyupHandler = function(e){ - var key = window.event ? e.keyCode : e.which; - if (!key || (key < 35 || key > 40) && key != 13 && key != 27) { - var val = that.value; - if (val.length >= o.minChars) { - if (val != that.last_val) { - that.last_val = val; - clearTimeout(that.timer); + }, + input(){ + inputCounter++; + }, + keyup(e){ + + if (!inputCounter) return; + inputCounter = 0; + var key = window.event ? e.keyCode : e.which; + if (!key || (key < 35 || key > 40) && key != 13 && key != 27) { + var val = ipt.value; + ipt.last_val = val; + if (val.length >= o.minChars) { + ipt.timer && clearTimeout(ipt.timer); + ipt.timer = 0; if (o.cache) { - var c = that.cache; - if (c.has(val)) { suggest(c.get(val)); return; } + var c = ipt.cache; + if (c.has(val)) { suggest(c.get(val), val); return; } // no requests if previous suggestions were empty var k = o.minChars; - for (var j=val.length-1; j>=k; j--) { + for (var j = val.length; --j >= k;) { var part = val.slice(0, j); - if (c.has(part) && !c.get(part).length) { suggest([]); return; } + if (c.has(part) && !c.get(part).length) { suggest([], val); return; } } } // PR#5 - that.timer = setTimeout(function(){ - var thisRequestId = ++that._currentRequestId; - o.source(val, function (data, val){ - if (thisRequestId === that._currentRequestId) return suggest(data, val); + ipt.timer = setTimeout(function(){ + var thisRequestId = ++ipt._currentRequestId; + var _val = ipt.value; + o.source(_val, function (data, val){ + if (thisRequestId == ipt._currentRequestId){ + suggest(data, typeof val === 'string' ? val : _val); + } }); }, o.delay); + } else { + ipt.sc.style.display = 'none'; } - } else { - that.last_val = val; - that.sc.style.display = 'none'; + } + }, + // focus(e){ + // if (!o.minChars) { + // ipt.last_val = '\n'; + // ipt.iptHandlers.keyup(e); + // } + // }, + + click(){ + if (o.clickToShow && ipt.isContentNotEmpty()) { + ipt.showSC(); } } - }; - that.addEventListener('keyup', that.keyupHandler); - that.focusHandler = function(e){ - that.last_val = '\n'; - that.keyupHandler(e) - }; - if (!o.minChars) that.addEventListener('focus', that.focusHandler); + } + + for (var h of Object.keys(ipt.iptHandlers)) { + ipt.addEventListener(h, ipt.iptHandlers[h]); + } + + ipt.destroyAutoComplete = function(){ + if (ipt) { + // window.removeEventListener('resize', ipt.updateSC); + for (var h of Object.keys(ipt.iptHandlers)) { + ipt.removeEventListener(h, ipt.iptHandlers[h]); + } + if (ipt.autocompleteAttr) ipt.setAttribute('autocomplete', ipt.autocompleteAttr); + else ipt.removeAttribute('autocomplete'); + ipt.pivot && ipt.pivot.remove(); // issue#92 PR#93 + ipt = null; + } + } + + ipt.isContentNotEmpty = function () { + return (ipt.value || '').length > 0 && (ipt.sc.textContent || '').length > 0; + } + } - for (var i=0; i<elems.length; i++) { + // init + var elems = typeof o.selector == 'object' ? [o.selector] : document.querySelectorAll(o.selector); + for (var i = 0; i < elems.length; i++) { forEach(elems[i]); } @@ -237,19 +303,9 @@ var autoComplete = (function(){ var elems = this.elems; if (elems) { this.elems = null; - for (var i=0; i<elems.length; i++) { - var that = elems[i]; - window.removeEventListener('resize', that.updateSC); - that.removeEventListener('blur', that.blurHandler); - that.removeEventListener('focus', that.focusHandler); - that.removeEventListener('keydown', that.keydownHandler); - that.removeEventListener('keyup', that.keyupHandler); - if (that.autocompleteAttr) that.setAttribute('autocomplete', that.autocompleteAttr); - else that.removeAttribute('autocomplete'); - that.sc && that.sc.remove(); // issue#92 PR#93 - that = null; - } + for (var i = 0; i < elems.length; i++) elems[i].destroyAutoComplete(); } + o = null; }; this.elems = elems; // PR#40 diff --git a/demo.html b/demo.html index d650010..97c40ce 100644 --- a/demo.html +++ b/demo.html @@ -54,12 +54,14 @@ <div style="max-width:900px;padding:0 10px;margin:40px auto;text-align:center"> <h1>autoComplete</h1> <h2>An extremely lightweight and powerful vanilla JavaScript completion suggester.</h2> - <a style="margin:5px 0" href="https://cdn.jsdelivr.net/gh/cyfung1031/JavaScript-autoComplete@1.1.0/" class="pure-button pure-button-primary button-lg">Download</a> + <a style="margin:5px 0" href="https://cdn.jsdelivr.net/gh/culefa/JavaScript-autoComplete@1.2.0/" class="pure-button pure-button-primary button-lg">Download</a> - <a style="margin:5px 0" href="https://github.com/cyfung1031/JavaScript-autoComplete/tree/1.1.0" class="pure-button button-lg">View on GitHub</a> + <a style="margin:5px 0" href="https://github.com/culefa/JavaScript-autoComplete/tree/1.2.0" class="pure-button button-lg">View on GitHub</a> </div> <form onsubmit="return false;" class="pure-form" style="border-top: 1px solid #eee;border-bottom:1px solid #eee;background:#fafafa;margin:30px 0;padding:20px 10px;text-align:center"> - <input id="hero-demo" autofocus type="text" name="q" placeholder="Programming languages ..." style="width:100%;max-width:600px;outline:0"> + <div> + <input id="hero-demo" autofocus type="text" name="q" placeholder="Programming languages ..." style="width:100%;max-width:600px;outline:0"> + </div> </form> <div style="max-width:900px;margin:auto;padding:0 10px 50px"> <h3>Overview and Features</h3> @@ -111,6 +113,8 @@ <h3>Settings</h3> <tr><td>offsetLeft</td><td><i>0</i></td><td>Optional left offset of the suggestions container.</td></tr> <tr><td>offsetTop</td><td><i>1</i></td><td>Optional top offset of the suggestions container.</td></tr> <tr><td>cache</td><td><i>1</i></td><td>Determines if performed searches should be cached.</td></tr> + <tr><td>clickToShow</td><td><i>1</i></td><td>Determines if clicking input should show dropdown.</td></tr> + <tr><td>closeOnTap</td><td><i>1</i></td><td>Determines if dropdown should close after tapping item.</td></tr> <tr> <td>menuClass</td><td><i>''</i></td> <td>Custom class/es that get/s added to the dropdown menu container. @@ -136,6 +140,12 @@ <h3>Settings</h3> <span class="inline-code">term</span> is the selected value. and <span class="inline-code">item</span> is the item rendered by the renderItem function. </td></tr> + <tr><td>onRender(data, val, ipt)</td><td colspan="2"> + A callback function that fires after the suggestion list is rendered (and shown). + <span class="inline-code">data</span> is the data, + <span class="inline-code">val</span> is the value of input. + and <span class="inline-code">ipt</span> is the input element. + </td></tr> <tr><td colspan="3"> </td></tr> <tr><th>Public Memebers</th><th colspan="2"></th></tr> @@ -167,6 +177,46 @@ <h4 style="margin-top:.5em">Searching in local data</h4> Simple as that. </p> + <h4 style="margin-top:.5em">Searching in local data, position="top" if available space below is not sufficient</h4> + <p> + Move dropdown upwards if available space below is not sufficent + </p> + <pre class="prettyprint"><code>var updateDropDownPosition = function(ipt){ + const pivot = ipt.pivot; + const sc = ipt.sc; + if(pivot && sc){ + const rectSC = sc.getBoundingClientRect(); + const rectIpt = ipt.getBoundingClientRect(); + pivot.setAttribute('position', (rectSC.height+rectIpt.bottom>document.documentElement.clientHeight)?'top':'bottom'); + } +} +var demoDynamic = new autoComplete({ + selector: '#dynamic-demo', + minChars: 0, + source: function(term, response){ + term = term.toLowerCase(); + var choices = ['ActionScript', 'AppleScript', 'Asp', 'Assembly', 'BASIC', 'Batch', 'C', 'C++', 'CSS', 'Clojure', 'COBOL', 'ColdFusion', 'Erlang', 'Fortran', 'Groovy', 'Haskell', 'HTML', 'Java', 'JavaScript', 'Lisp', 'Perl', 'PHP', 'PowerShell', 'Python', 'Ruby', 'Scala', 'Scheme', 'SQL', 'TeX', 'XML']; + var suggestions = []; + for (var i=0;i<choices.length;i++) // PR#77 + if (choices[i].toLowerCase().indexOf(term)>=0) suggestions.push(choices[i]); + response(suggestions); + }, + onRender: function(data, val, ipt){ + updateDropDownPosition(ipt); + } +}); +document.addEventListener('scroll', function(){ + let ipt = document.querySelector('#dynamic-demo'); + updateDropDownPosition(ipt); +}, true);</code></pre> + <p> + Move dropdown upwards if available space below is not sufficent. + </p> + + <form onsubmit="return false;" class="pure-form" style="margin:30px 0 40px"> + <input id="dynamic-demo" autofocus type="text" placeholder="Programming languages ..." style="width:100%;max-width:600px;outline:0"> + </form> + <h4>AJAX requests</h4> <p> AJAX requests may come with very different requirements: JSON, JSONP, GET, POST, additionaly params, authentications, etc. @@ -269,7 +319,7 @@ <h4>Advanced suggestions handling and custom layout</h4> Source code for this example: </p> <pre class="prettyprint"><code>new autoComplete({ - selector: 'input[name=&quot;q&quot;]', + selector: 'input[name="q"]', minChars: 1, source: function(term, response){ term = term.toLowerCase(); @@ -322,7 +372,29 @@ <h4>Advanced suggestions handling and custom layout</h4> <script> var demo1 = new autoComplete({ selector: '#hero-demo', - minChars: 1, + minChars: 0, + source: function(term, response){ + term = term.toLowerCase(); + var choices = ['ActionScript', 'AppleScript', 'Asp', 'Assembly', 'BASIC', 'Batch', 'C', 'C++', 'CSS', 'Clojure', 'COBOL', 'ColdFusion', 'Erlang', 'Fortran', 'Groovy', 'Haskell', 'HTML', 'Java', 'JavaScript', 'Lisp', 'Perl', 'PHP', 'PowerShell', 'Python', 'Ruby', 'Scala', 'Scheme', 'SQL', 'TeX', 'XML']; + var suggestions = []; + for (var i=0;i<choices.length;i++) // PR#77 + if (choices[i].toLowerCase().indexOf(term)>=0) suggestions.push(choices[i]); + response(suggestions); + } + }); + + var updateDropDownPosition = function(ipt){ + const pivot = ipt.pivot; + const sc = ipt.sc; + if(pivot && sc){ + const rectSC = sc.getBoundingClientRect(); + const rectIpt = ipt.getBoundingClientRect(); + pivot.setAttribute('position', (rectSC.height+rectIpt.bottom>document.documentElement.clientHeight)?'top':'bottom'); + } + } + var demoDynamic = new autoComplete({ + selector: '#dynamic-demo', + minChars: 0, source: function(term, response){ term = term.toLowerCase(); var choices = ['ActionScript', 'AppleScript', 'Asp', 'Assembly', 'BASIC', 'Batch', 'C', 'C++', 'CSS', 'Clojure', 'COBOL', 'ColdFusion', 'Erlang', 'Fortran', 'Groovy', 'Haskell', 'HTML', 'Java', 'JavaScript', 'Lisp', 'Perl', 'PHP', 'PowerShell', 'Python', 'Ruby', 'Scala', 'Scheme', 'SQL', 'TeX', 'XML']; @@ -330,8 +402,15 @@ <h4>Advanced suggestions handling and custom layout</h4> for (var i=0;i<choices.length;i++) // PR#77 if (choices[i].toLowerCase().indexOf(term)>=0) suggestions.push(choices[i]); response(suggestions); + }, + onRender: function(data, val, ipt){ + updateDropDownPosition(ipt); } }); + document.addEventListener('scroll', function(){ + let ipt = document.querySelector('#dynamic-demo'); + updateDropDownPosition(ipt); + }, true); (function(){ diff --git a/readme.md b/readme.md index 3f72833..95edc96 100644 --- a/readme.md +++ b/readme.md @@ -11,12 +11,12 @@ We have implemented this piece of software in production on [plainJS](https://pl ## Links -https://cdn.jsdelivr.net/gh/cyfung1031/JavaScript-autoComplete@1.1.0/auto-complete.js -https://cdn.jsdelivr.net/gh/cyfung1031/JavaScript-autoComplete@1.1.0/auto-complete.min.js +https://cdn.jsdelivr.net/gh/culefa/JavaScript-autoComplete@1.2.0/auto-complete.js +https://cdn.jsdelivr.net/gh/culefa/JavaScript-autoComplete@1.2.0/auto-complete.min.js ## Usage ```html -<script src="https://cdn.jsdelivr.net/gh/cyfung1031/JavaScript-autoComplete@1.1.0/auto-complete.min.js"></script> +<script src="https://cdn.jsdelivr.net/gh/culefa/JavaScript-autoComplete@1.2.0/auto-complete.min.js"></script> <form onsubmit="return false;" class="pure-form" style="border-top: 1px solid #eee;border-bottom:1px solid #eee;background:#fafafa;margin:30px 0;padding:20px 10px;text-align:center"> <input id="hero-demo" autofocus type="text" name="q" placeholder="Programming languages ..." style="width:100%;max-width:600px;outline:0"> </form> @@ -39,7 +39,7 @@ https://cdn.jsdelivr.net/gh/cyfung1031/JavaScript-autoComplete@1.1.0/auto-comple ## Demo and Documentation -https://raw.githack.com/cyfung1031/JavaScript-autoComplete/1.1.0/demo.html +https://raw.githack.com/culefa/JavaScript-autoComplete/1.2.0/demo.html ## Features @@ -50,6 +50,10 @@ https://raw.githack.com/cyfung1031/JavaScript-autoComplete/1.1.0/demo.html ## Changelog +### Version 1.2.0 - 2023/10/07 + +* Performance Fix with changes in CSS Layout, and Enhancement in Functionality + ### Version 1.1.0 - 2023/10/06 * Rolling out Update for 2015 - 2023 PRs