datatable: optimize filter and sort, small cleanups - jscancer - Javascript crap (relatively small)
 (HTM) git clone git://git.codemadness.org/jscancer
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 556bb20940c177102090c1cc0e0c2d5142e3ced1
 (DIR) parent 8cfbc8714f9cade06d8bd0bc50e9d26c332a1370
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Thu,  2 Jun 2016 18:59:51 +0200
       
       datatable: optimize filter and sort, small cleanups
       
       Diffstat:
         M datatable/datatable.js              |      52 +++++++++++++++++++------------
       
       1 file changed, 32 insertions(+), 20 deletions(-)
       ---
 (DIR) diff --git a/datatable/datatable.js b/datatable/datatable.js
       @@ -32,7 +32,8 @@ function datatable_init(el) {
                        tbody: tbody[0],
                        cols:  cols,
                        sort:  [], /* sort options: [colidx, order (ASC = 0, DESC = 1)]. */
       -                lazyscroll: ["1", "true"].indexOf(el.getAttribute("data-lazyscroll") || "") != -1
       +                lazyscroll: ["1", "true"].indexOf(el.getAttribute("data-lazyscroll") || "") != -1,
       +                search: "" /* previous search text. */
                };
                d.data_raw = d.data = datatable_data_parse(d);
        
       @@ -56,7 +57,7 @@ function datatable_init(el) {
                        var newths = [];
                        for (var i = 0; i < ths.length; i++)
                                newths.push(tr.appendChild(ths[i].cloneNode(true)));
       -                d.ths = newths; // set new columns (for sorting etc)..
       +                d.ths = newths; /* set new columns (for sorting etc).. */
                        var elthead = document.createElement("thead");
                        elthead.appendChild(tr);
        
       @@ -89,7 +90,7 @@ function datatable_init(el) {
                        el.parentNode.insertBefore(containerel, el);
        
                        var rowheight = 25;
       -                d.display = function(d, data) {
       +                d.display = function(data) {
                                var nrows = data.length;
        
                                bodytable.style.height = (nrows * rowheight) + "px";
       @@ -100,7 +101,7 @@ function datatable_init(el) {
                                startfiller.style.height = (start * rowheight) + "px";
                                endfiller.style.height = ((nrows - end - 1) * rowheight) + "px";
        
       -                        // remove nodes but keep first startfiller and endfiller.
       +                        /* remove nodes but keep first startfiller and endfiller. */
                                for (var c = bodytbody.childNodes; c.length > 2; )
                                        bodytbody.removeChild(startfiller.nextSibling);
        
       @@ -110,23 +111,23 @@ function datatable_init(el) {
        
                        var curscrollleft, curscrolltop, verticalscrolltimer;
                        bodyel.addEventListener("scroll", function() {
       -                        // handle left / right scroll
       +                        /* handle left / right scroll */
                                var scrolleft = bodyel.scrollLeft;
                                if (curscrollleft !== scrolleft)
                                        headersel.scrollLeft = curscrollleft = scrolleft;
       -                        // handle up/down scroll
       +                        /* handle up/down scroll */
                                var scrolltop = bodyel.scrollTop;
                                if (curscrolltop !== scrolltop) {
                                        clearTimeout(verticalscrolltimer);
                                        verticalscrolltimer = setTimeout(function() {
       -                                        datatable_display(d, d.data);
       +                                        d.display(d.data);
                                        }, 32);
                                        curscrolltop = scrolltop;
                                }
                        });
       -                datatable_display(d, d.data);
       +                d.display(d.data);
                } else {
       -                d.display = function(d, data) {
       +                d.display = function(data) {
                                var tbody = document.createElement("tbody");
                                for (var i = 0; i < data.length; i++)
                                        tbody.appendChild(data[i].tr);
       @@ -141,16 +142,12 @@ function datatable_init(el) {
                                        /* shift-click for multi-select modifier. */
                                        datatable_sort_column_toggle(d, idx, e.shiftKey);
                                        d.data = datatable_sort(d, d.data);
       -                                datatable_display(d, d.data);
       +                                d.display(d.data);
                                };
                        }(i), false);
                return d;
        }
        
       -function datatable_display(d, data) {
       -        return d.display(d, data);
       -}
       -
        function datatable_sort_column_get(d, idx) {
                for (var i = 0; i < d.sort.length; i++)
                        if (d.sort[i][0] == idx)
       @@ -173,7 +170,7 @@ function datatable_sort_column_set(d, idx, order, multi) {
                        d.ths[i].className = c.replace(/ sort-(asc|desc) /g, " ").replace(/\s+/g, " ").trim();
                }
                for (var i = 0; i < d.sort.length; i++)
       -                d.ths[d.sort[i][0]].className += d.sort[i][1] ? " sort-desc" : " sort-asc";
       +                d.ths[d.sort[i][0]].className += " sort-" + (d.sort[i][1] ? "desc" : "asc");
        }
        
        /* toggle sort or use default order: ASC. */
       @@ -191,7 +188,7 @@ function datatable_data_parse(d) {
                                var td = trc[j], v = td.getAttribute("data-value");
                                /* prefer data-value attribute, else use cell contents,
                                 * also set preprocess values to filter on cell content
       -                         * and data-value (lower-case string). */
       +                         * and data-value (case-insensitive). */
                                var s = (td.textContent || td.innerText).toLowerCase();
                                if (typeof(v) != "undefined" && v !== null) {
                                        fv.push([ v.toLowerCase(), s ]);
       @@ -224,7 +221,6 @@ function datatable_sort(d, data) {
                                        };
                        })(s[0], s[1], d.cols[s[0]].sortfn);
                });
       -
                return data.sort(function(x, y) {
                        for (var i = 0, r; i < sortfns.length; i++)
                                if ((r = sortfns[i](x.values, y.values)) != 0)
       @@ -254,6 +250,22 @@ function datatable_filter(d, data, s) {
                return ret;
        }
        
       +function datatable_filter_text(d, s) {
       +        s = s.toLowerCase();
       +        if (d.search == s)
       +                return;
       +        // if token string is different or string not in previous search: use raw data,
       +        // else filter on existing data and no need to sort.
       +        if ((d.search.split(" ").length != s.split(" ").length) ||
       +            s.indexOf(d.search) == -1) {
       +                d.data = datatable_sort(d, datatable_filter(d, d.data_raw, s));
       +        } else {
       +                d.data = datatable_filter(d, d.data, s);
       +        }
       +        d.search = s;
       +        d.display(d.data);
       +}
       +
        function datatable_filter_delayed(d, fn, e) {
                clearTimeout(d.filter_timer);
                d.filter_timer = setTimeout(function() {
       @@ -271,15 +283,15 @@ function datatable_autoload() {
                                continue;
                        var input = dl[i].parentNode.getElementsByClassName("filter-text");
                        /* delayed filtering. */
       -                for (var j = 0; j < input.length; j++)
       +                for (var j = 0; j < input.length; j++) {
                                input[j].addEventListener("input", (function(d, el) {
                                        return function(e) {
                                                datatable_filter_delayed(d, function() {
       -                                                d.data = datatable_filter(d, d.data_raw, el.value);
       -                                                datatable_display(d, d.data);
       +                                                datatable_filter_text(d, el.value);
                                                }, e);
                                        };
                                })(d, input[j]), false);
       +                }
                        ds.push(d);
                }
                return ds;