mirror of
https://github.com/Mottie/tablesorter.git
synced 2024-11-15 23:54:22 +00:00
sort multiple tbodies
This commit is contained in:
parent
64b63632ec
commit
28e9a07d59
@ -235,7 +235,7 @@
|
||||
if (e > rows.length ) {
|
||||
e = rows.length;
|
||||
}
|
||||
$(table.tBodies[0]).empty();
|
||||
$.tablesorter.clearTableBody(table);
|
||||
for (i = s; i < e; i++) {
|
||||
o = rows[i];
|
||||
l = o.length;
|
||||
|
@ -26,6 +26,7 @@
|
||||
cssAsc: "tablesorter-headerSortUp",
|
||||
cssDesc: "tablesorter-headerSortDown",
|
||||
cssChildRow: "expand-child",
|
||||
cssInfoBlock: "tablesorter-infoOnly",
|
||||
sortInitialOrder: "asc",
|
||||
sortMultiSortKey: "shiftKey",
|
||||
sortForce: null,
|
||||
@ -196,42 +197,44 @@
|
||||
|
||||
/* utils */
|
||||
function buildCache(table) {
|
||||
var b = table.tBodies[0],
|
||||
totalRows = (b && b.rows.length) || 0,
|
||||
totalCells = (b.rows[0] && b.rows[0].cells.length) || 0,
|
||||
parsers = table.config.parsers,
|
||||
cache = {
|
||||
row: [],
|
||||
normalized: []
|
||||
},
|
||||
var b = table.tBodies,
|
||||
tc = table.config,
|
||||
totalRows,
|
||||
totalCells,
|
||||
parsers = tc.parsers,
|
||||
t, i, j, c, cols, cacheTime;
|
||||
if (table.config.debug) {
|
||||
tc.cache = {};
|
||||
if (tc.debug) {
|
||||
cacheTime = new Date();
|
||||
}
|
||||
for (i = 0; i < totalRows; ++i) {
|
||||
/** Add the table data to main data array */
|
||||
c = $(b.rows[i]);
|
||||
cols = [];
|
||||
// if this is a child row, add it to the last row's children and continue to the next row
|
||||
if (c.hasClass(table.config.cssChildRow)) {
|
||||
cache.row[cache.row.length - 1] = cache.row[cache.row.length - 1].add(c);
|
||||
// go to the next for loop
|
||||
continue;
|
||||
for (k = 0; k < b.length; k++) {
|
||||
tc.cache[k] = { row: [], normalized: [] };
|
||||
totalRows = (b[k] && b[k].rows.length) || 0;
|
||||
totalCells = (b[k].rows[0] && b[k].rows[0].cells.length) || 0;
|
||||
|
||||
for (i = 0; i < totalRows; ++i) {
|
||||
/** Add the table data to main data array */
|
||||
c = $(b[k].rows[i]);
|
||||
cols = [];
|
||||
// if this is a child row, add it to the last row's children and continue to the next row
|
||||
if (c.hasClass(tc.cssChildRow)) {
|
||||
tc.cache[k].row[tc.cache[k].row.length - 1] = tc.cache[k].row[tc.cache[k].row.length - 1].add(c);
|
||||
// go to the next for loop
|
||||
continue;
|
||||
}
|
||||
tc.cache[k].row.push(c);
|
||||
for (j = 0; j < totalCells; ++j) {
|
||||
t = trimAndGetNodeText(tc, c[0].cells[j], j);
|
||||
// don't bother parsing if the string is empty - previously parsing would change it to zero
|
||||
cols.push( parsers[j].format(t, table, c[0].cells[j], j) );
|
||||
}
|
||||
cols.push(tc.cache[k].normalized.length); // add position for rowCache
|
||||
tc.cache[k].normalized.push(cols);
|
||||
}
|
||||
cache.row.push(c);
|
||||
for (j = 0; j < totalCells; ++j) {
|
||||
t = trimAndGetNodeText(table.config, c[0].cells[j], j);
|
||||
// don't bother parsing if the string is empty - previously parsing would change it to zero
|
||||
cols.push( parsers[j].format(t, table, c[0].cells[j], j) );
|
||||
}
|
||||
cols.push(cache.normalized.length); // add position for rowCache
|
||||
cache.normalized.push(cols);
|
||||
}
|
||||
if (table.config.debug) {
|
||||
if (tc.debug) {
|
||||
benchmark("Building cache for " + totalRows + " rows", cacheTime);
|
||||
}
|
||||
table.config.cache = cache;
|
||||
return cache;
|
||||
}
|
||||
|
||||
function getWidgetById(name) {
|
||||
@ -259,30 +262,35 @@
|
||||
}
|
||||
}
|
||||
|
||||
function appendToTable(table, cache) {
|
||||
function appendToTable(table) {
|
||||
var c = table.config,
|
||||
r = cache.row,
|
||||
n = cache.normalized,
|
||||
totalRows = n.length,
|
||||
checkCell = totalRows ? (n[0].length - 1) : 0,
|
||||
b = table.tBodies,
|
||||
rows = [],
|
||||
f = document.createDocumentFragment(),
|
||||
i, j, l, pos, appendTime;
|
||||
r, n, totalRows, checkCell,
|
||||
f, i, j, l, pos, appendTime;
|
||||
if (c.debug) {
|
||||
appendTime = new Date();
|
||||
}
|
||||
for (i = 0; i < totalRows; i++) {
|
||||
pos = n[i][checkCell];
|
||||
rows.push(r[pos]);
|
||||
// removeRows used by the pager plugin
|
||||
if (!c.appender || !c.removeRows) {
|
||||
l = r[pos].length;
|
||||
for (j = 0; j < l; j++) {
|
||||
f.appendChild(r[pos][j]);
|
||||
for (k = 0; k < b.length; k++) {
|
||||
f = document.createDocumentFragment();
|
||||
r = c.cache[k].row;
|
||||
n = c.cache[k].normalized;
|
||||
totalRows = n.length;
|
||||
checkCell = totalRows ? (n[0].length - 1) : 0;
|
||||
|
||||
for (i = 0; i < totalRows; i++) {
|
||||
pos = n[i][checkCell];
|
||||
rows.push(r[pos]);
|
||||
// removeRows used by the pager plugin
|
||||
if (!c.appender || !c.removeRows) {
|
||||
l = r[pos].length;
|
||||
for (j = 0; j < l; j++) {
|
||||
f.appendChild(r[pos][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
table.tBodies[k].appendChild(f);
|
||||
}
|
||||
table.tBodies[0].appendChild(f);
|
||||
if (c.appender) {
|
||||
c.appender(table, rows);
|
||||
}
|
||||
@ -464,46 +472,50 @@
|
||||
}
|
||||
|
||||
/* sorting methods - reverted sorting method back to version 2.0.3 */
|
||||
function multisort(table,sortList,cache) {
|
||||
var dynamicExp = "var sortWrapper = function(a,b) {",
|
||||
col, mx = 0, dir = 0, tc = table.config, lc = cache.normalized.length,
|
||||
l = sortList.length, sortTime, i, j, c, s, e, order, orgOrderCol;
|
||||
function multisort(table, sortList) {
|
||||
var dynamicExp, col, mx = 0, dir = 0, tc = table.config,
|
||||
l = sortList.length, bl = table.tBodies.length,
|
||||
sortTime, i, j, c, cache, lc, s, e, order, orgOrderCol;
|
||||
if (tc.debug) { sortTime = new Date(); }
|
||||
for (i=0; i < l; i++) {
|
||||
c = sortList[i][0];
|
||||
order = sortList[i][1];
|
||||
s = getCachedSortType(tc.parsers,c) === "text" ? "Text" : "Numeric";
|
||||
s += order === 0 ? "" : "Desc";
|
||||
e = "e" + i;
|
||||
// get max column value (ignore sign)
|
||||
if (/Numeric/.test(s) && tc.strings[c]) {
|
||||
for (j=0; j < lc; j++) {
|
||||
col = Math.abs(parseFloat(cache.normalized[j][c]));
|
||||
mx = Math.max( mx, isNaN(col) ? 0 : col );
|
||||
}
|
||||
// sort strings in numerical columns
|
||||
if (typeof(tc.string[tc.strings[c]]) === 'boolean') {
|
||||
dir = (order === 0 ? 1 : -1) * (tc.string[tc.strings[c]] ? -1 : 1);
|
||||
} else {
|
||||
dir = (tc.strings[c]) ? tc.string[tc.strings[c]] || 0 : 0;
|
||||
for (k = 0; k < bl; k++) {
|
||||
dynamicExp = "var sortWrapper = function(a,b) {";
|
||||
cache = tc.cache[k];
|
||||
lc = cache.normalized.length;
|
||||
for (i = 0; i < l; i++) {
|
||||
c = sortList[i][0];
|
||||
order = sortList[i][1];
|
||||
s = getCachedSortType(tc.parsers,c) === "text" ? "Text" : "Numeric";
|
||||
s += order === 0 ? "" : "Desc";
|
||||
e = "e" + i;
|
||||
// get max column value (ignore sign)
|
||||
if (/Numeric/.test(s) && tc.strings[c]) {
|
||||
for (j = 0; j < lc; j++) {
|
||||
col = Math.abs(parseFloat(cache.normalized[j][c]));
|
||||
mx = Math.max( mx, isNaN(col) ? 0 : col );
|
||||
}
|
||||
// sort strings in numerical columns
|
||||
if (typeof(tc.string[tc.strings[c]]) === 'boolean') {
|
||||
dir = (order === 0 ? 1 : -1) * (tc.string[tc.strings[c]] ? -1 : 1);
|
||||
} else {
|
||||
dir = (tc.strings[c]) ? tc.string[tc.strings[c]] || 0 : 0;
|
||||
}
|
||||
}
|
||||
dynamicExp += "var " + e + " = sort" + s + "(a[" + c + "],b[" + c + "]," + c + "," + mx + "," + dir + "); ";
|
||||
dynamicExp += "if (" + e + ") { return " + e + "; } ";
|
||||
dynamicExp += "else { ";
|
||||
}
|
||||
dynamicExp += "var " + e + " = sort" + s + "(a[" + c + "],b[" + c + "]," + c + "," + mx + "," + dir + "); ";
|
||||
dynamicExp += "if (" + e + ") { return " + e + "; } ";
|
||||
dynamicExp += "else { ";
|
||||
}
|
||||
// if value is the same keep orignal order
|
||||
orgOrderCol = (cache.normalized && cache.normalized[0]) ? cache.normalized[0].length - 1 : 0;
|
||||
dynamicExp += "return a[" + orgOrderCol + "]-b[" + orgOrderCol + "];";
|
||||
for (i=0; i < l; i++) {
|
||||
// if value is the same keep orignal order
|
||||
orgOrderCol = (cache.normalized && cache.normalized[0]) ? cache.normalized[0].length - 1 : 0;
|
||||
dynamicExp += "return a[" + orgOrderCol + "]-b[" + orgOrderCol + "];";
|
||||
for (i=0; i < l; i++) {
|
||||
dynamicExp += "}; ";
|
||||
}
|
||||
dynamicExp += "return 0; ";
|
||||
dynamicExp += "}; ";
|
||||
eval(dynamicExp);
|
||||
cache.normalized.sort(sortWrapper); // sort using eval expression
|
||||
}
|
||||
dynamicExp += "return 0; ";
|
||||
dynamicExp += "}; ";
|
||||
eval(dynamicExp);
|
||||
cache.normalized.sort(sortWrapper); // sort using eval expression
|
||||
if (tc.debug) { benchmark("Sorting on " + sortList.toString() + " and dir " + order+ " time", sortTime); }
|
||||
return cache;
|
||||
}
|
||||
|
||||
// Natural sort modified from: http://www.webdeveloper.com/forum/showthread.php?t=107909
|
||||
@ -588,7 +600,7 @@
|
||||
// if no thead or tbody quit.
|
||||
if (!this.tHead || this.tBodies.length === 0) { return; }
|
||||
// declare
|
||||
var $this, $headers, cache, config,
|
||||
var $this, $headers, config,
|
||||
totalRows, $cell, c, i, j, k, a, s, o;
|
||||
// new blank config object
|
||||
this.config = {};
|
||||
@ -605,14 +617,14 @@
|
||||
// try to auto detect column type, and store in tables config
|
||||
c.parsers = buildParserCache(this, $headers);
|
||||
// build the cache for the tbody cells
|
||||
cache = buildCache(this);
|
||||
buildCache(this);
|
||||
// fixate columns if the users supplies the fixedWidth option
|
||||
fixColumnWidth(this);
|
||||
// apply event handling to headers
|
||||
// this is to big, perhaps break it out?
|
||||
$headers
|
||||
.click(function(e) {
|
||||
totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0;
|
||||
// totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0;
|
||||
if (!this.sortDisabled) {
|
||||
// Only call sortStart if sorting is enabled.
|
||||
$this.trigger("sortStart", tbl[0]);
|
||||
@ -680,7 +692,7 @@
|
||||
$this.trigger("sortBegin", tbl[0]);
|
||||
// set css for headers
|
||||
setHeadersCss($this[0], $headers, c.sortList);
|
||||
appendToTable($this[0], multisort($this[0], c.sortList, cache));
|
||||
appendToTable($this[0], multisort($this[0], c.sortList));
|
||||
// stop normal event by returning false
|
||||
return false;
|
||||
}
|
||||
@ -697,45 +709,44 @@
|
||||
// apply easy methods that trigger binded events
|
||||
$this
|
||||
.bind("update", function(e, resort) {
|
||||
var t = this, c = t.config;
|
||||
// remove rows/elements before update
|
||||
$(c.selectorRemove, t.tBodies[0]).remove();
|
||||
$(c.selectorRemove, this).remove();
|
||||
// rebuild parsers.
|
||||
c.parsers = buildParserCache(t, $headers);
|
||||
c.parsers = buildParserCache(this, $headers);
|
||||
// rebuild the cache map
|
||||
cache = buildCache(t);
|
||||
buildCache(this);
|
||||
if (resort !== false) { $this.trigger("sorton", [c.sortList]); }
|
||||
})
|
||||
.bind("updateCell", function(e, cell, resort) {
|
||||
// get position from the dom.
|
||||
var pos = [(cell.parentNode.rowIndex - 1), cell.cellIndex];
|
||||
var pos = [(cell.parentNode.rowIndex - 1), cell.cellIndex],
|
||||
// update cache - format: function(s, table, cell, cellIndex)
|
||||
cache.normalized[pos[0]][pos[1]] = c.parsers[pos[1]].format(getElementText(c, cell, pos[1]), $this, cell, pos[1]);
|
||||
c.cache = cache;
|
||||
tbodyindex = $(cell).closest('tbody').index();
|
||||
table.cache[tbodyindex].normalized[pos[0]][pos[1]] = c.parsers[pos[1]].format(getElementText(c, cell, pos[1]), $this, cell, pos[1]);
|
||||
if (resort !== false) { $this.trigger("sorton", [c.sortList]); }
|
||||
})
|
||||
.bind("addRows", function(e, row, resort) {
|
||||
var i, rows = row.filter('tr').length,
|
||||
dat = [], l = row[0].cells.length;
|
||||
.bind("addRows", function(e, $row, resort) {
|
||||
var i, rows = $row.filter('tr').length,
|
||||
dat = [], l = $row[0].cells.length,
|
||||
tbodyindex = $row.closest('tbody').index();
|
||||
// add each row
|
||||
for (i = 0; i < rows; i++) {
|
||||
// add each cell
|
||||
for (j = 0; j < l; j++) {
|
||||
dat[j] = c.parsers[j].format(getElementText(c, row[i].cells[j], j), $this, row[i].cells[j], j );
|
||||
dat[j] = c.parsers[j].format(getElementText(c, $row[i].cells[j], j), $this, $row[i].cells[j], j );
|
||||
}
|
||||
// add the row index to the end
|
||||
dat.push(cache.row.length);
|
||||
dat.push(c.cache[tbodyindex].row.length);
|
||||
// update cache
|
||||
cache.row.push([row[i]]);
|
||||
cache.normalized.push(dat);
|
||||
c.cache[tbodyindex].row.push([$row[i]]);
|
||||
c.cache[tbodyindex].normalized.push(dat);
|
||||
dat = [];
|
||||
}
|
||||
c.cache = cache;
|
||||
// resort using current settings
|
||||
if (resort !== false) { $this.trigger("sorton", [c.sortList]); }
|
||||
})
|
||||
.bind("sorton", function(e, list) {
|
||||
$(this).trigger("sortStart", tbl[0]);
|
||||
$this.trigger("sortStart", tbl[0]);
|
||||
c.sortList = list;
|
||||
// update and store the sortlist
|
||||
var sortList = c.sortList;
|
||||
@ -744,10 +755,10 @@
|
||||
// set css for headers
|
||||
setHeadersCss(this, $headers, sortList);
|
||||
// sort the table and append it to the dom
|
||||
appendToTable(this, multisort(this, sortList, cache));
|
||||
appendToTable(this, multisort(this, sortList));
|
||||
})
|
||||
.bind("appendCache", function () {
|
||||
appendToTable(this, cache);
|
||||
appendToTable(this);
|
||||
})
|
||||
.bind("applyWidgetId", function (e, id) {
|
||||
getWidgetById(id).format(this);
|
||||
@ -769,6 +780,8 @@
|
||||
applyWidget(this);
|
||||
}
|
||||
this.hasInitialized = true;
|
||||
$this.trigger('tablesorter-initialized', this);
|
||||
if (typeof c.initialized === 'function') { c.initialized(this); }
|
||||
});
|
||||
};
|
||||
this.addParser = function(parser) {
|
||||
@ -807,7 +820,7 @@
|
||||
return (/^[\-+(]?\d*[)]?$/).test($.trim(s.replace(/[,.'\s]/g, '')));
|
||||
};
|
||||
this.clearTableBody = function (table) {
|
||||
$(table.tBodies[0]).empty();
|
||||
$(table.tBodies).filter(':not(.' + table.config.cssInfoBlock + ')').empty();
|
||||
};
|
||||
}
|
||||
})();
|
||||
@ -970,9 +983,10 @@
|
||||
ts.addWidget({
|
||||
id: "zebra",
|
||||
format: function(table) {
|
||||
var $tr, row = 0, even, time,
|
||||
var $tr, row, even, time, k,
|
||||
c = table.config,
|
||||
child = c.cssChildRow,
|
||||
b = table.tBodies,
|
||||
css = [ "even", "odd" ];
|
||||
// maintain backwards compatibility
|
||||
css = c.widgetZebra && c.hasOwnProperty('css') ? c.widgetZebra.css :
|
||||
@ -980,16 +994,22 @@
|
||||
if (table.config.debug) {
|
||||
time = new Date();
|
||||
}
|
||||
// loop through the visible rows
|
||||
$("tr:visible", table.tBodies[0]).each(function() {
|
||||
$tr = $(this);
|
||||
// style children rows the same way the parent row was styled
|
||||
if (!$tr.hasClass(child)) { row++; }
|
||||
even = (row % 2 === 0);
|
||||
$tr
|
||||
.removeClass(css[even ? 1 : 0])
|
||||
.addClass(css[even ? 0 : 1]);
|
||||
});
|
||||
for (k = 0; k < b.length; k++ ) {
|
||||
row = 0;
|
||||
// loop through the visible rows
|
||||
$tr = $(b[k]).filter(':not(' + c.cssInfoBlock + ')').find('tr:visible:not(.' + c.cssInfoBlock + ')');
|
||||
if ($tr.length > 1) {
|
||||
$tr.each(function() {
|
||||
$tr = $(this);
|
||||
// style children rows the same way the parent row was styled
|
||||
if (!$tr.hasClass(child)) { row++; }
|
||||
even = (row % 2 === 0);
|
||||
$tr
|
||||
.removeClass(css[even ? 1 : 0])
|
||||
.addClass(css[even ? 0 : 1]);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (table.config.debug) {
|
||||
$.tablesorter.benchmark("Applying Zebra widget", time);
|
||||
}
|
||||
|
@ -125,8 +125,9 @@ $.tablesorter.addWidget({
|
||||
$.tablesorter.addWidget({
|
||||
id: "columns",
|
||||
format: function(table) {
|
||||
var $td, time, i, last, rmv,
|
||||
var $tr, $td, time, i, last, rmv, k,
|
||||
c = table.config,
|
||||
b = table.tBodies,
|
||||
list = c.sortList,
|
||||
len = list.length,
|
||||
css = [ "primary", "secondary", "tertiary" ]; // default options
|
||||
@ -140,21 +141,24 @@ $.tablesorter.addWidget({
|
||||
}
|
||||
// check if there is a sort (on initialization there may not be one)
|
||||
if (list && list[0]) {
|
||||
// loop through the visible rows
|
||||
$("tr:visible", table.tBodies[0]).each(function (i) {
|
||||
$td = $(this).children().removeClass(rmv);
|
||||
// primary sort column class
|
||||
$td.eq(list[0][0]).addClass(css[0]);
|
||||
if (len > 1) {
|
||||
for (i=1; i<len; i++){
|
||||
// secondary, tertiary, etc sort column classes
|
||||
$td.eq(list[i][0]).addClass( css[i] || css[last] );
|
||||
for (k = 0; k < b.length; k++ ) {
|
||||
// loop through the visible rows
|
||||
$tr = $(b[k]).filter(':not(' + c.cssInfoBlock + ')').find('tr:visible:not(.' + c.cssInfoBlock + ')');
|
||||
$tr.each(function (i) {
|
||||
$td = $(this).children().removeClass(rmv);
|
||||
// primary sort column class
|
||||
$td.eq(list[0][0]).addClass(css[0]);
|
||||
if (len > 1) {
|
||||
for (i=1; i<len; i++){
|
||||
// secondary, tertiary, etc sort column classes
|
||||
$td.eq(list[i][0]).addClass( css[i] || css[last] );
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// remove all column classes if sort is cleared (sortReset)
|
||||
$("td", table.tBodies[0]).removeClass(rmv);
|
||||
$("td", table).removeClass(rmv);
|
||||
}
|
||||
if (c.debug) {
|
||||
$.tablesorter.benchmark("Applying Columns widget", time);
|
||||
@ -192,7 +196,7 @@ $.tablesorter.addWidget({
|
||||
if (v.join('') === '') {
|
||||
$t.find('tr').show();
|
||||
} else {
|
||||
$t.find('tbody').find('tr:not(.' + c.cssChildRow + ')').each(function(){
|
||||
$t.find('tbody').find('tr:not(.' + c.cssChildRow + '):not(.' + c.cssInfoBlock + ')').each(function(){
|
||||
r = true;
|
||||
cr = $(this).nextUntil('tr:not(.' + c.cssChildRow + ')');
|
||||
// so, if "table.config.widgetOptions.filter_childRows" is true and there is
|
||||
@ -238,6 +242,7 @@ $.tablesorter.addWidget({
|
||||
css = wo.stickyHeaders || 'tablesorter-stickyHeader',
|
||||
innr = '.tablesorter-header-inner',
|
||||
firstCell = hdrCells.eq(0),
|
||||
tfoot = $table.find('tfoot'),
|
||||
sticky = header.find('tr.tablesorter-header:not(.sticky-false)').clone()
|
||||
.removeClass('tablesorter-header')
|
||||
.addClass(css)
|
||||
@ -284,7 +289,8 @@ $.tablesorter.addWidget({
|
||||
.scroll(function(){
|
||||
var offset = firstCell.offset(),
|
||||
sTop = win.scrollTop(),
|
||||
vis = ((sTop > offset.top) && (sTop < offset.top + $table.find('tbody').height())) ? 'visible' : 'hidden';
|
||||
tableHt = $table.height() - (firstCell.height() + (tfoot.height() || 0)),
|
||||
vis = (sTop > offset.top) && (sTop < offset.top + tableHt) ? 'visible' : 'hidden';
|
||||
sticky.css({
|
||||
left : offset.left - win.scrollLeft(),
|
||||
visibility : vis
|
||||
|
Loading…
Reference in New Issue
Block a user