URI:
       improve onblur (did not work in all browsers), cleanup - jscancer - Javascript crap (relatively small)
  HTML git clone git://git.codemadness.org/jscancer
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 24a8497f1f0b9734fb410110bf817966e228040e
   DIR parent 1d3b222c38a79a8c0e1823b30ac5f7c8eb28a0a1
  HTML Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Fri, 27 May 2016 19:27:12 +0200
       
       improve onblur (did not work in all browsers), cleanup
       
       Diffstat:
         M autocomplete/README                 |       6 +++---
         M autocomplete/TODO                   |       5 -----
         M autocomplete/complete.js            |     102 ++++++++++++++++---------------
       
       3 files changed, 56 insertions(+), 57 deletions(-)
       ---
   DIR diff --git a/autocomplete/README b/autocomplete/README
       @@ -8,8 +8,8 @@ FEATURES
        --------
        
        - Small:
       -  - Filesize: +- 4.6KB, +- 2.2KB minified, +- 1KB GZIP'd.
       -  - Lines: +- 160, not much code, so hopefully easy to understand.
       +  - Filesize: +- 4.7KB, +- 2.3KB minified, +- 1KB GZIP'd.
       +  - Lines: +- 162, not much code, so hopefully easy to understand.
          - No dependencies on other libraries like jQuery.
        - (Graceful) fallback to HTML5 datalist if Javascript is disabled.
        - Filtering values: case-insensitively, tokenized (separated by space).
       @@ -32,7 +32,7 @@ See example.html and style.css for an example. A stylesheet file style.css
        is also included.
        
        An input should have the classname "autocomplete" set with the attribute
       -data-list="idoflist". The id should be of the datalist:
       +list="idoflist". The id should be of the datalist:
        
        <datalist name="nameoflist" id="idoflist">
                <option>Item 1</option>
   DIR diff --git a/autocomplete/TODO b/autocomplete/TODO
       @@ -1,6 +1 @@
        - improve README and documentation.
       -
       -WONTFIX?
       -- IE 11-: clicking scrollbar in dropdown calls onblur event of input box
       -  in < IE Edge. Javascript / IE event handling is retarded. Will accept a
       -  simple solution if it doesn't make the code too complex.
   DIR diff --git a/autocomplete/complete.js b/autocomplete/complete.js
       @@ -1,80 +1,80 @@
       -function autocomplete_init(oel) {
       -        var attrlist = oel.getAttribute("list"), ellist = document.getElementById(attrlist);
       +function autocomplete_init(input) {
       +        var attrlist = input.getAttribute("list"), ellist = document.getElementById(attrlist);
                if (attrlist === null || ellist === undefined)
                        return;
       -        oel.removeAttribute("list");
       -        oel.autocomplete = "off";
       -        var odropdown = document.createElement("div"),
       -                oitems = [],
       -                omouse = true, // enable mouse event handling.
       -                osel = null;
       -        odropdown.className = "autocomplete-dropdown";
       -        odropdown.style.left = String(oel.offsetLeft) + "px";
       +        input.removeAttribute("list");
       +        input.autocomplete = "off";
       +        var dropdown = document.createElement("div"),
       +                items = [],
       +                mouse = true, // enable mouse event handling.
       +                cursel = null;
       +        dropdown.className = "autocomplete-dropdown";
       +        dropdown.style.left = String(input.offsetLeft) + "px";
        
                var autocomplete_match = function(s) {
                        var matches = [], tok = s.toLowerCase().split(" ");
       -                for (var i = 0; i < oitems.length; i++) {
       +                for (var i = 0; i < items.length; i++) {
                                var fc = 0;
                                for (var k = 0; k < tok.length && fc < tok.length; k++) {
                                        var f = false;
       -                                for (var j = 0; j < oitems[i].search.length && fc < tok.length && !f; j++)
       -                                        for (var l = 0; l < oitems[i].search.length && !f; l++)
       -                                                if (oitems[i].search[l].indexOf(tok[k]) != -1)
       +                                for (var j = 0; j < items[i].search.length && fc < tok.length && !f; j++)
       +                                        for (var l = 0; l < items[i].search.length && !f; l++)
       +                                                if (items[i].search[l].indexOf(tok[k]) != -1)
                                                                f = true;
                                        if (f)
                                                fc++;
                                }
                                /* all tokens (separated by space) must match. */
                                if (fc == tok.length)
       -                                matches.push(oitems[i]);
       +                                matches.push(items[i]);
                        }
                        return matches;
                };
                var autocomplete_render = function(m) {
       -                var p = odropdown.parentNode;
       -                var dd = odropdown.cloneNode(false);
       +                var p = dropdown.parentNode;
       +                var dd = dropdown.cloneNode(false);
                        for (var i = 0; i < m.length; i++)
                                dd.appendChild(m[i].el);
       -                p.replaceChild(dd, odropdown)
       -                odropdown = dd;
       +                p.replaceChild(dd, dropdown)
       +                dropdown = dd;
                };
                var autocomplete_show = function(status) {
       -                odropdown.className = "autocomplete-dropdown " + (status ? "visible" : "");
       +                dropdown.className = "autocomplete-dropdown " + (status ? "visible" : "");
                };
                var autocomplete_setsel = function(el) {
       -                if (osel)
       -                        osel.className = "";
       -                if ((osel = el))
       +                if (cursel)
       +                        cursel.className = "";
       +                cursel = el;
       +                if (el)
                                el.className = "sel";
                };
        
                for (var i = 0, ec = ellist.children; i < ec.length; i++) {
                        var div = document.createElement("div");
                        div.innerHTML = ec[i].innerHTML;
       -                // NOTE: mousedown triggers before onblur.
                        div.onmousedown = function() {
       -                        oel.value = this.textContent;
       +                        input.value = this.textContent;
                                autocomplete_show(false);
                        };
                        div.onmousemove = function() {
       -                        if (omouse)
       +                        if (mouse)
                                        autocomplete_setsel(this);
                        };
       -                oitems.push({ el: div, search: (div.textContent.toLowerCase() || "").split(" ") });
       +                items.push({ el: div, search: (div.textContent.toLowerCase() || "").split(" ") });
                }
       -        oel.onkeydown = function(e) {
       -                omouse = false;
       +        input.onkeydown = function(e) {
       +                mouse = false;
                        switch (e.which) {
                        case 13: // return
       -                        if (osel)
       -                                this.value = osel.textContent;
       +                        if (cursel)
       +                                this.value = cursel.textContent;
                                autocomplete_show(false);
                        case 27: break; // escape
                        case 33: // page up.
                        case 34: // page down.
                        case 38: // arrow up
                        case 40: // arrow down
       -                        var sel = osel, dd = odropdown, dc = odropdown.children;
       +                        var sel = cursel, dd = dropdown, dc = dropdown.children;
        
                                // if last and down arrow switch to first item, if first and up arrow switch to last item.
                                if (dc.length) {
       @@ -88,7 +88,7 @@ function autocomplete_init(oel) {
                                                sel = dc[0];
                                        }
                                }
       -                        if (osel && (e.which == 33 || e.which == 34)) {
       +                        if (cursel && (e.which == 33 || e.which == 34)) {
                                        var n = sel.offsetHeight ? (dd.clientHeight / sel.offsetHeight) : 0;
                                        if (e.which == 33) { // page up.
                                                for (; n > 0 && sel && sel.previousSibling;
       @@ -111,12 +111,12 @@ function autocomplete_init(oel) {
                                }
                        }
                };
       -        oel.oninput = function() {
       +        input.oninput = function() {
                        var m = autocomplete_match(this.value);
                        // check if selection is still active in matches.
       -                if (osel) {
       +                if (cursel) {
                                var hassel = false;
       -                        for (var i = 0; i < m.length && !(hassel = (m[i].el === osel)); i++)
       +                        for (var i = 0; i < m.length && !(hassel = (m[i].el === cursel)); i++)
                                        ;
                                if (!hassel)
                                        autocomplete_setsel(null);
       @@ -130,25 +130,29 @@ function autocomplete_init(oel) {
                        }
                        autocomplete_show(!!m.length);
                };
       -        oel.onkeyup = function(e) {
       -                omouse = true;
       +        input.onkeyup = function(e) {
       +                mouse = true;
                        // return key or escape was not pressed.
                        if (e.which == 13 || e.which == 27)
                                autocomplete_show(false);
                };
       -        oel.onblur = function() {
       -                autocomplete_setsel(null);
       -                autocomplete_show(false);
       -        };
       -        oel.onfocus = oel.onclick = function() {
       +
       +        var focuschange = function(e) {
                        autocomplete_setsel(null);
       -                var m = autocomplete_match(this.value);
       -                if (m.length)
       -                        autocomplete_render(m);
       -                autocomplete_show(!!m.length);
       -                odropdown.scrollTop = 0; // reset scroll.
       +                if (e.target === input) {
       +                        var m = autocomplete_match(input.value);
       +                        if (m.length)
       +                                autocomplete_render(m);
       +                        autocomplete_show(!!m.length);
       +                        dropdown.scrollTop = 0; // reset scroll.
       +                } else {
       +                        autocomplete_show(false);
       +                }
                };
       -        oel.parentNode.insertBefore(odropdown, oel.nextSibling);
       +        document.addEventListener("focus", focuschange, false);
       +        document.addEventListener("click", focuschange, false);
       +
       +        input.parentNode.insertBefore(dropdown, input.nextSibling);
        }
        
        var els = document.getElementsByClassName("autocomplete");