causeway-standard-theme
Version:
400 lines (323 loc) • 11.2 kB
JavaScript
/*!
* Fixed Table Header and Left Column
*
* Copyright (c) 2013,2014 nkmrshn
*
* Released under the MIT License.
* http://www.opensource.org/licenses/MIT
*/
(function($) {
$.fn.extend({
fixedTblHdrLftCol: function(options) {
var cfg = $.extend(true, {
scroll: {
height: null,
width: null,
headRow: {
className: 'fTHLC-head-row',
enabled: true,
overflow: 'auto'
},
leftCol : {
className: 'fTHLC-left-col',
enabled: true,
overflow: 'auto',
fixedSpan: 1
},
syncWith: null
},
wrapper: {
outer: {
idName: null,
className: 'fTHLC-outer-wrapper'
},
inner: {
idName: null,
className: 'fTHLC-inner-wrapper'
}
},
corner: {
append: true,
deepClone: false,
outer: {
idName: null,
className: 'fTHLC-outer-corner'
},
inner: {
idName: null,
className: 'fTHLC-inner-corner'
}
}
}, options);
var scrollWidth = cfg.scroll.width;
var scrollHeight = cfg.scroll.height;
var fixedLeftWidth = null;
var fixedHeadHeight = null;
function getScrollWidth(table) {
var width = scrollWidth;
if(!width)
width = table.outerWidth(true) - getFixedLeftWidth(table);
return width;
}
function getScrollHeight(table) {
var height = scrollHeight;
if(!height)
height = table.outerHeight(true) - getFixedHeadHeight(table);
return height;
}
function getHeadRowCount(table) {
return table.find('thead tr').length;
}
function getFixedHeadRows(table) {
var rows = $([]);
for(var i = 0; i < getHeadRowCount(table); i++) {
var row = $([]);
for(var j = 0; j < cfg.scroll.leftCol.fixedSpan; j++) {
row.push(table.find('thead tr:nth-child('+(i + 1)+') th:nth-child('+(j + 1)+')'));
}
rows.push(row);
}
return rows;
}
function getHeadFirstRows(table) {
var rows = $([]);
for(var i = 0; i < getHeadRowCount(table); i++) {
rows.push(table.find('thead tr:nth-child('+(i + 1)+') th:first-child'));
}
return rows;
}
function getHeadCols(table, n) {
return table.find('thead tr:nth-child('+(n + 1)+') th');
}
function getFixedHeadHeight(table) {
var height = fixedHeadHeight;
if(!height) {
var rows = getHeadFirstRows(table);
rows.each(function() {
height += $(this).outerHeight(true);
});
fixedHeadHeight = height;
}
return height;
}
function getFixedLeftCols(table) {
var cols =$([]);
for(var i = 0; i < cfg.scroll.leftCol.fixedSpan; i++) {
cols.push(table.find('tbody tr:first-child td:nth-child('+(i + 1)+')'));
}
return cols;
}
function getFixedLeftWidth(table) {
var width = fixedLeftWidth;
if(!width) {
var cols = getFixedLeftCols(table);
cols.each(function() {
width += $(this).outerWidth(true);
});
fixedLeftWidth = width;
}
return width;
}
function getTableWidth(table) {
var width = 0;
table.find('tbody tr:first-child td').each(function() {
width += $(this).outerWidth(true);
});
return width;
}
function createOuter(table) {
table
.wrap($(document.createElement('div'))
.attr('id', cfg.wrapper.outer.idName)
.addClass(cfg.wrapper.outer.className)
.css('width', getScrollWidth(table))
.css('height', getScrollHeight(table))
.css('position', 'relative')
.css('padding-left', getFixedLeftWidth(table)+'px')
.css('padding-top', getFixedHeadHeight(table)+'px')
.css('overflow', 'hidden'));
}
function createInner(table) {
table
.wrap($(document.createElement('div'))
.attr('id', cfg.wrapper.inner.idName)
.addClass(cfg.wrapper.inner.className)
.css('overflow-x', cfg.scroll.headRow.overflow)
.css('overflow-y', cfg.scroll.leftCol.overflow)
.css('width', getScrollWidth(table))
.css('height', getScrollHeight(table)));
}
function setTableCSS(table) {
var leftCornerWidth = getFixedLeftWidth(table);
var tableWidth = getTableWidth(table);
table
.css('border-collapse', 'collapse')
.css('width', (tableWidth - leftCornerWidth)+'px');
}
function setTheadCSS(table) {
var rows = getHeadFirstRows(table);
var totalHeight = 0;
rows.each(function(i) {
var cols = getHeadCols(table, i);
var totalWidth = 0;
cols.each(function(j) {
var width = $(this).outerWidth(true);
var height = $(this).outerHeight(true);
totalWidth += width;
if(j == 0)
totalHeight += height;
$(this)
.addClass(cfg.scroll.headRow.className)
.css('position', 'absolute')
.css('top', (totalHeight - height)+'px')
.css('left', (totalWidth - width)+'px');
});
});
}
function setTbodyCSS(table) {
var leftCornerWidth = getFixedLeftWidth(table);
var tableWidth = getTableWidth(table);
table.find('tbody tr').each(function() {
$(this).css('width', (tableWidth - leftCornerWidth)+'px');
});
}
function setLeftColumnCSS(table) {
var total = 0;
var cols = getFixedLeftCols(table);
cols.each(function(i) {
var width = $(this).outerWidth(true);
total += width;
table
.find('tbody tr td:nth-child('+(i + 1)+')')
.addClass(cfg.scroll.leftCol.className)
.css('position', 'absolute')
.css('left', (total - width)+'px');
});
}
function recalHeight(table) {
table.find('tbody tr').each(function() {
var maxHeight = 0;
for(var i = 0; i < cfg.scroll.leftCol.fixedSpan; i++) {
var h = $(this).find('td:nth-child('+(i + 1)+')').height();
if(h > maxHeight)
maxHeight = h;
}
$(this)
.find('td:nth-child('+(cfg.scroll.leftCol.fixedSpan + 1)+')')
.height(maxHeight);
$(this).hide().fadeIn(0);
});
}
function appendCorner(table) {
var corner = $('<div></div>')
.attr('id', cfg.corner.outer.idName)
.addClass(cfg.corner.outer.className)
.css('position', 'absolute')
.css('left', '0px')
.css('top', '0px')
.css('margin', '0')
.css('padding', '0')
.css('width', getFixedLeftWidth(table)+'px')
.css('height', getFixedHeadHeight(table)+'px');
var innerTable = $('<table></table>')
.attr('id', cfg.corner.inner.idName)
.addClass(cfg.corner.inner.className)
.css('border-collapse', 'collapse');
var thead = $('<thead></thead>');
var rows = getFixedHeadRows(table);
rows.each(function() {
var tr = $('<tr></tr>');
$(this).each(function() {
var th = $(this).clone(cfg.corner.deepClone);
$(this).removeAttr('id');
$(this).unbind();
th.appendTo(tr);
});
tr.appendTo(thead);
});
thead.appendTo(innerTable);
innerTable.appendTo(corner);
corner.appendTo(table.parent());
}
function recalHeaderPosition(table) {
var leftPosition = [];
table.find('tbody tr:first').each(function() {
$(this).find('td').each(function() {
var position = $(this).position();
leftPosition.push(position.left);
});
});
table.find('thead tr').each(function() {
$(this).find('th').each(function(i) {
$(this).css('left', leftPosition[i]+'px');
});
});
}
function init(table) {
setLeftColumnCSS(table);
setTbodyCSS(table);
setTheadCSS(table);
setTableCSS(table);
createOuter(table);
createInner(table);
recalHeight(table);
if(cfg.corner.append)
appendCorner(table);
recalHeaderPosition(table);
}
function scrollCols(table) {
table.find('tbody tr').each(function() {
for(var i = 0; i < cfg.scroll.leftCol.fixedSpan; i++) {
$(this)
.find('td:nth-child('+(i + 1)+')')
.css('top', $(this)
.find('td:nth-child('+(cfg.scroll.leftCol.fixedSpan + 1)+')')
.position()
.top+'px');
}
});
}
function scrollRows(table) {
table.find('thead tr').each(function(i) {
if(i < getHeadRowCount(table)) {
$(this).find('th').each(function(j) {
$(this)
.css('left', table
.find('tbody tr:first-child td:nth-child('+(j + 1)+')')
.position()
.left+'px');
});
}
});
}
function scrollOther(table, other) {
other.scrollTop(table.scrollTop());
other.scrollLeft(table.scrollLeft());
}
function syncTables(table) {
var syncWith = cfg.scroll.syncWith;
if($.isArray(syncWith)) {
$.each(syncWith, function() {
scrollOther(table, $(this.toString()).parent());
});
} else
scrollOther(table, $(syncWith).parent());
}
return this.each(function() {
if($(this)[0].tagName.toLowerCase() != "table")
return true;
init($(this));
if(cfg.scroll.leftCol.enabled || cfg.scroll.headRow.enabled) {
$(this).parent().scroll(function() {
if(cfg.scroll.headRow.enabled)
scrollRows($(this));
if(cfg.scroll.leftCol.enabled)
scrollCols($(this));
if(cfg.scroll.syncWith)
syncTables($(this));
});
}
});
}
});
})(jQuery);