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