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>
         &nbsp;
-        <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">&nbsp;</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=&amp;quot;q&amp;quot;]',
+    selector: 'input[name=&quot;q&quot;]',
     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