datatable.js - jscancer - Javascript crap (relatively small)
 (HTM) git clone git://git.codemadness.org/jscancer
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       datatable.js (9134B)
       ---
            1 var datatable_parse_date = Date.parse,
            2     datatable_parse_float = parseFloat,
            3     datatable_parse_int = parseInt,
            4     datatable_parse_string = String;
            5 
            6 function datatable_sort_default(x, y) {
            7         return x > y ? 1 : (x == y ? 0 : -1);
            8 }
            9 
           10 function datatable_init(el) {
           11         var thead = el.tHead;
           12         var ths = thead.children[0].children,
           13             cols = [];
           14         for (var i = 0; i < ths.length; i++)
           15                 cols.push({
           16                         filterable: ["1", "true"].indexOf(ths[i].getAttribute("data-filterable")   || "true") != -1,
           17                         parsefn:    window["datatable_parse_" + (ths[i].getAttribute("data-parse") || "string")],
           18                         sortfn:     window["datatable_sort_" + (ths[i].getAttribute("data-sort")   || "default")],
           19                         sortable:   ["1", "true"].indexOf(ths[i].getAttribute("data-sortable")     || "true") != -1
           20                 });
           21         var d = {
           22                 table: el,
           23                 thead: thead,
           24                 ths:   ths,
           25                 tbody: el.tBodies[0],
           26                 cols:  cols,
           27                 sort:  [], // sort options: [colidx, order (ASC = 0, DESC = 1)].
           28                 lazyscroll: ["1", "true"].indexOf(el.getAttribute("data-lazyscroll") || "") != -1,
           29                 search: "" // previous search text.
           30         };
           31         d.data_raw = d.data = datatable_data_parse(d);
           32 
           33         if (d.lazyscroll) {
           34                 var bodytable = document.createElement("table");
           35                 bodytable.className = el.className;
           36                 bodytable.cellSpacing = bodytable.cellPadding = bodytable.border = "0";
           37 
           38                 var tr = document.createElement("tr");
           39                 for (var i = 0; i < ths.length; i++) {
           40                         var th = ths[i].cloneNode(true);
           41                         th.innerHTML = "";
           42                         tr.appendChild(th);
           43                 }
           44                 var bodythead = document.createElement("thead");
           45                 bodythead.appendChild(tr);
           46 
           47                 tr = document.createElement("tr");
           48                 var newths = [];
           49                 for (var i = 0; i < ths.length; i++)
           50                         newths.push(tr.appendChild(ths[i].cloneNode(true)));
           51                 d.ths = newths; // set new columns (for sorting etc)..
           52                 var elthead = document.createElement("thead");
           53                 elthead.appendChild(tr);
           54 
           55                 var headerstable = document.createElement("table");
           56                 headerstable.cellSpacing = headerstable.cellPadding = headerstable.border = "0";
           57                 headerstable.className = el.className;
           58                 headerstable.appendChild(elthead);
           59 
           60                 var headersel = document.createElement("div");
           61                 headersel.className = "datatable-lazyscroll-headers";
           62                 headersel.appendChild(headerstable);
           63 
           64                 bodytable.appendChild(bodythead);
           65 
           66                 var bodyel = document.createElement("div");
           67                 bodyel.className = "datatable-lazyscroll-body";
           68                 bodyel.appendChild(bodytable);
           69 
           70                 var containerel = document.createElement("div");
           71                 containerel.className = "datatable-lazyscroll-container";
           72                 containerel.appendChild(headersel);
           73                 containerel.appendChild(bodyel);
           74 
           75                 var bodytbody = bodytable.appendChild(document.createElement("tbody"));
           76                 var startfiller = bodytbody.appendChild(document.createElement("tr"));
           77                 var endfiller = bodytbody.appendChild(document.createElement("tr"));
           78 
           79                 el.parentNode.insertBefore(containerel, el);
           80 
           81                 var rowheight = 25;
           82                 d.display = function(data) {
           83                         var nrows = data.length;
           84 
           85                         bodytable.style.height = (nrows * rowheight) + "px";
           86 
           87                         var start = parseInt(bodyel.scrollTop / rowheight),
           88                             end = Math.min(parseInt((bodyel.scrollTop + bodyel.offsetHeight) / rowheight), nrows - 1);
           89 
           90                         startfiller.style.height = (start * rowheight) + "px";
           91                         endfiller.style.height = ((nrows - end - 1) * rowheight) + "px";
           92 
           93                         // remove nodes but keep first startfiller and endfiller.
           94                         for (var c = bodytbody.childNodes; c.length > 2; )
           95                                 bodytbody.removeChild(startfiller.nextSibling);
           96 
           97                         for (var i = start, prev = startfiller, p = bodytbody; i <= end; i++)
           98                                 prev = p.insertBefore(d.data[i].tr, prev.nextSibling);
           99                 };
          100                 d.scroll = function(y) {
          101                         bodyel.scrollTop = y;
          102                 };
          103 
          104                 var curscrollleft, verticalscrolltimer;
          105                 var scroll = function() {
          106                         // handle left / right scroll.
          107                         var scrolleft = bodyel.scrollLeft;
          108                         if (curscrollleft !== scrolleft)
          109                                 headersel.scrollLeft = curscrollleft = scrolleft;
          110                         // handle up/down scroll.
          111                         clearTimeout(verticalscrolltimer);
          112                         verticalscrolltimer = setTimeout(function() {
          113                                 d.display(d.data);
          114                         }, 16);
          115                 };
          116                 window.addEventListener("resize", scroll);
          117                 bodyel.addEventListener("scroll", scroll);
          118                 d.display(d.data);
          119         } else {
          120                 d.display = function(data) {
          121                         var tbody = document.createElement("tbody");
          122                         for (var i = 0; i < data.length; i++)
          123                                 tbody.appendChild(data[i].tr);
          124                         d.table.replaceChild(tbody, d.tbody);
          125                         tbody.style.display = data.length ? "table-row-group" : "none";
          126                         d.tbody = tbody;
          127                 };
          128         }
          129         // setup click event handlers for sorting.
          130         for (var i = 0; i < d.ths.length; i++)
          131                 d.cols[i].sortable && d.ths[i].addEventListener("click", function(idx) {
          132                         return function(e) {
          133                                 // shift-click for multi-select modifier.
          134                                 datatable_sort_column_toggle(d, idx, e.shiftKey);
          135                                 d.data = datatable_sort(d, d.data);
          136                                 d.display(d.data);
          137                         };
          138                 }(i), false);
          139         return d;
          140 }
          141 
          142 function datatable_sort_column_get(d, idx) {
          143         for (var i = 0; i < d.sort.length; i++)
          144                 if (d.sort[i][0] == idx)
          145                         return i;
          146         return -1;
          147 }
          148 
          149 function datatable_sort_column_set(d, idx, order, multi) {
          150         var c = datatable_sort_column_get(d, idx);
          151         if (multi)
          152                 if (c != -1)
          153                         d.sort[c][1] = order;
          154                 else
          155                         d.sort.push([ idx, order ]);
          156         else
          157                 d.sort = [ [idx, order] ];
          158 
          159         for (var i = 0; i < d.ths.length; i++) {
          160                 var c = " " + d.ths[i].className + " ";
          161                 d.ths[i].className = c.replace(/ sort-(asc|desc) /g, " ").replace(/\s+/g, " ").trim();
          162         }
          163         for (var i = 0; i < d.sort.length; i++)
          164                 d.ths[d.sort[i][0]].className += " sort-" + (d.sort[i][1] ? "desc" : "asc");
          165 }
          166 
          167 // toggle sort or use default order: ASC.
          168 function datatable_sort_column_toggle(d, idx, multi) {
          169         var c = datatable_sort_column_get(d, idx);
          170         datatable_sort_column_set(d, idx, c == -1 || d.sort[c][1] ? 0 : 1, multi);
          171 }
          172 
          173 function datatable_data_parse(d) {
          174         var data = [], trs = d.tbody.children;
          175         // NOTE: assumes each tr has only "<td>" childnodes.
          176         for (var i = 0; i < trs.length; i++) {
          177                 var values = [], fv = [];
          178                 for (var j = 0, trc = trs[i].children; j < trc.length; j++) {
          179                         var td = trc[j], v = td.getAttribute("data-value");
          180                         // prefer data-value attribute, else use cell contents,
          181                         // also set preprocess values to filter on cell content
          182                         // and data-value (case-insensitive).
          183                         var s = td.textContent || td.innerText;
          184                         if (typeof(v) != "undefined" && v !== null) {
          185                                 fv.push([ s.toLowerCase(), v.toLowerCase() ]);
          186                                 values.push(d.cols[j].parsefn(v));
          187                         } else {
          188                                 fv.push([ s.toLowerCase() ]);
          189                                 values.push(d.cols[j].parsefn(s));
          190                         }
          191                 }
          192                 data.push({
          193                         filtervalues: fv,
          194                         tr:           trs[i],
          195                         values:       values
          196                 });
          197         }
          198         return data;
          199 }
          200 
          201 function datatable_sort(d, data) {
          202         // setup sort functions once (in order for multi-select).
          203         var sortfns = d.sort.map(function(s) {
          204                 return (function(c, o, fn) {
          205                         if (o)
          206                                 return function(xvals, yvals) {
          207                                         return -fn(xvals[c], yvals[c]);
          208                                 };
          209                         else
          210                                 return function(xvals, yvals) {
          211                                         return fn(xvals[c], yvals[c]);
          212                                 };
          213                 })(s[0], s[1], d.cols[s[0]].sortfn);
          214         });
          215         return data.sort(function(x, y) {
          216                 for (var i = 0, r; i < sortfns.length; i++)
          217                         if ((r = sortfns[i](x.values, y.values)) != 0)
          218                                 return r;
          219                 return r;
          220         });
          221 }
          222 
          223 function datatable_filter(d, data, s) {
          224         var ret = [], tok = s.toLowerCase().split(" ");
          225         for (var i = 0; i < data.length; i++) {
          226                 var fc = 0;
          227                 for (var k = 0; k < tok.length && fc < tok.length; k++) {
          228                         var f = false;
          229                         for (var j = 0; j < data[i].filtervalues.length && fc < tok.length && !f; j++)
          230                                 for (var l = 0; l < data[i].filtervalues[j].length && !f &&
          231                                                     d.cols[j].filterable; l++)
          232                                         if (data[i].filtervalues[j][l].indexOf(tok[k]) != -1)
          233                                                 f = true;
          234                         if (f)
          235                                 fc++;
          236                 }
          237                 // all tokens (separated by space) must match.
          238                 if (fc == tok.length)
          239                         ret.push(data[i]);
          240         }
          241         return ret;
          242 }
          243 
          244 function datatable_filter_text(d, s) {
          245         s = s.toLowerCase();
          246         if (d.search == s)
          247                 return;
          248         // if token string is different or string not in previous search: use raw data,
          249         // else filter on existing data and no need to sort.
          250         if ((d.search.split(" ").length != s.split(" ").length) ||
          251             s.indexOf(d.search) == -1) {
          252                 d.data = datatable_sort(d, datatable_filter(d, d.data_raw, s));
          253         } else {
          254                 d.data = datatable_filter(d, d.data, s);
          255         }
          256         d.search = s;
          257         d.display(d.data);
          258         if (d.scroll)
          259                 d.scroll(0);
          260 }
          261 
          262 function datatable_filter_delayed(d, fn, e) {
          263         clearTimeout(d.filter_timer);
          264         d.filter_timer = setTimeout(function() {
          265                 fn(e);
          266         }, 150); // filter delay in ms.
          267 }
          268 
          269 function datatable_autoload() {
          270         // convert to Array (not changed in-place, mandatory).
          271         var ds = [], dl = [], els = document.getElementsByClassName && document.getElementsByClassName("datatable") || [];
          272         for (var i = 0; i < els.length; i++)
          273                 dl.push(els[i]);
          274         for (var i = 0, d; i < dl.length; i++) {
          275                 if ((d = datatable_init(dl[i])) === null)
          276                         continue;
          277                 var input = dl[i].parentNode.getElementsByClassName("filter-text");
          278                 // delayed filtering.
          279                 for (var j = 0; j < input.length; j++) {
          280                         input[j].addEventListener("input", (function(d, el) {
          281                                 return function(e) {
          282                                         datatable_filter_delayed(d, function() {
          283                                                 datatable_filter_text(d, el.value);
          284                                         }, e);
          285                                 };
          286                         })(d, input[j]), false);
          287                 }
          288                 ds.push(d);
          289         }
          290         return ds;
          291 }