Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 83 additions & 46 deletions stickyheader.jquery.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,85 @@
const STICK_HEADER = {
run: function () {
var $tables = $('table.stickyHeader');

$tables.each(function (i) {
var table = $tables[i];
var bodyHeight, cutoffTop, cutoffBottom, tableHeight, tableWidth;

var tableClone = $(table).clone(true).empty().removeClass('stickyHeader');
var theadClone = $(table).find('thead').clone(true);
var stickyHeader = $('<div></div>').addClass('stickyHeader hide').attr('aria-hidden', 'true');
stickyHeader.append(tableClone).find('table').append(theadClone);
$(table).after(stickyHeader);

var headerCells = $(table).find('thead th');
var headerCellHeight = $(headerCells[0]).height();

var noFixedSupport = (stickyHeader.css('position') === 'absolute');

var stickyHeaderCells = stickyHeader.find('th');

function evaluateHeaderPositionAndSize() {
bodyHeight = $('body').height()
tableHeight = $(table).height();
tableWidth = $(table).width() +
Number($(table).css('padding-left').replace(/px/ig,"")) +
Number($(table).css('padding-right').replace(/px/ig,"")) +
Number($(table).css('border-left-width').replace(/px/ig,"")) +
Number($(table).css('border-right-width').replace(/px/ig,""));
cutoffTop = $(table).offset().top;
cutoffBottom = tableHeight + cutoffTop - headerCellHeight;

for (var i = 0, l = headerCells.length; i < l; i++) {
if (headerCells[i].style.width.length > 0) {
// This takes into account other scripts that set header width
// such as DataTables
stickyHeaderCells[i].style.width = headerCells[i].style.width
} else {
stickyHeaderCells[i].style.width = headerCells[i].scrollWidth + 'px'
}
}

stickyHeader.css('width', tableWidth);
}

function setClassNames() {
for (var i = 0; i < stickyHeader.find('th').length; i++) {
stickyHeader.find('th')[i].className = $(table).find('thead th')[i].className
}
}

evaluateHeaderPositionAndSize()

window.onresize = function () {
evaluateHeaderPositionAndSize()
}

// Sometimes header class names change when clicked
// such as with dataTables sorting
$(table).find('th').click(setClassNames)
stickyHeader.find('th').click(setClassNames)

$(window).scroll(function() {
if (bodyHeight !== $('body').height()) {
evaluateHeaderPositionAndSize()
}

var currentPosition = $(window).scrollTop();
if (currentPosition > cutoffTop && currentPosition < cutoffBottom) {
stickyHeader.removeClass('hide');
if (noFixedSupport) {
stickyHeader.css('top', currentPosition + 'px');
}
}
else {
stickyHeader.addClass('hide');
}
});
});
}
}

jQuery(document).ready(function ($) {
var tables = $('table.stickyHeader');
tables.each(function(i){
var table = tables[i];
var tableClone = $(table).clone(true).empty().removeClass('stickyHeader');
var theadClone = $(table).find('thead').clone(true);
var stickyHeader = $('<div></div>').addClass('stickyHeader hide').attr('aria-hidden', 'true');
stickyHeader.append(tableClone).find('table').append(theadClone);
$(table).after(stickyHeader);

var tableHeight = $(table).height();
var tableWidth = $(table).width() + Number($(table).css('padding-left').replace(/px/ig,"")) + Number($(table).css('padding-right').replace(/px/ig,"")) + Number($(table).css('border-left-width').replace(/px/ig,"")) + Number($(table).css('border-right-width').replace(/px/ig,""));

var headerCells = $(table).find('thead th');
var headerCellHeight = $(headerCells[0]).height();

var no_fixed_support = false;
if (stickyHeader.css('position') == "absolute") {
no_fixed_support = true;
}

var stickyHeaderCells = stickyHeader.find('th');
stickyHeader.css('width', tableWidth);
var cellWidths = [];
for (var i = 0, l = headerCells.length; i < l; i++) {
cellWidths[i] = $(headerCells[i]).width();
}
for (var i = 0, l = headerCells.length; i < l; i++) {
$(stickyHeaderCells[i]).css('width', cellWidths[i]);
}

var cutoffTop = $(table).offset().top;
var cutoffBottom = tableHeight + cutoffTop - headerCellHeight;

$(window).scroll(function() {
var currentPosition = $(window).scrollTop();
if (currentPosition > cutoffTop && currentPosition < cutoffBottom) {
stickyHeader.removeClass('hide');
if (no_fixed_support) {
stickyHeader.css('top', currentPosition + 'px');
}
}
else {
stickyHeader.addClass('hide');
}
});
});
STICK_HEADER.run()
});