drupal/misc/tableheader.js

106 lines
3.2 KiB
JavaScript
Raw Normal View History

// $Id$
Drupal.behaviors.tableHeader = function (context) {
// This breaks in anything less than IE 7. Prevent it from running.
if (jQuery.browser.msie && parseInt(jQuery.browser.version) < 7) {
return;
}
// Keep track of all cloned table headers.
var headers = [];
$('table thead:not(.tableHeader-processed)', context).each(function () {
// Clone table and remove unwanted elements so it inherits original properties.
var headerClone = $(this.parentNode).clone(true).insertBefore(this.parentNode).addClass('sticky-header').css({
position: 'fixed',
visibility: 'hidden',
top: '0px'
});
// Sets an id for cloned table header.
var headerID = headerClone.attr('id');
if (headerID != '') {
headerClone.attr('id', headerID + '-header');
}
// Everything except thead must be removed. See theme_table().
$('tbody', headerClone).remove();
$('caption', headerClone).remove();
var headerClone = $(headerClone)[0];
headers.push(headerClone);
// Store parent table.
var table = $(this).parent('table')[0];
headerClone.table = table;
// Finish initialzing header positioning.
headerClone.resizeWidths = true;
tracker(headerClone);
$(table).addClass('sticky-table');
$(this).addClass('tableHeader-processed');
});
// Track positioning and visibility.
function tracker(e) {
// Save positioning data.
var viewHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
if (e.viewHeight != viewHeight || e.resizeWidths) {
e.viewHeight = viewHeight;
e.vPosition = $(e.table).offset().top;
e.hPosition = $(e.table).offset().left;
e.vLength = $(e.table).height();
}
// Track horizontal positioning relative to the viewport and set visibility.
var hScroll = document.documentElement.scrollLeft || document.body.scrollLeft;
var vScroll = document.documentElement.scrollTop || document.body.scrollTop;
var vOffset = vScroll - e.vPosition - 4;
var visState = (vOffset > 0 && vOffset < e.vLength - 100) ? 'visible' : 'hidden';
$(e).css({left: -hScroll + e.hPosition +'px', visibility: visState});
// Resize cell widths.
if (e.resizeWidths) {
var cellCount = 0;
$('th', e).each(function() {
var cellWidth = parseInt($('th', e.table).eq(cellCount).css('width'));
// Exception for IE7.
if (!cellWidth) {
var cellWidth = $('th', e.table).eq(cellCount).width();
}
cellCount++;
$(this).css('width', cellWidth +'px');
});
$(e).css('width', $(e.table).width() +'px');
e.resizeWidths = false;
}
};
// Track scrolling.
var scroll = function() {
$(headers).each(function () {
tracker(this);
});
};
$(window).scroll(scroll);
$(document.documentElement).scroll(scroll);
// Track resizing.
var time = null;
var resize = function () {
// Ensure minimum time between adjustments.
if (time) {
return;
}
time = setTimeout(function () {
$(headers).each(function () {
this.resizeWidths = true;
tracker(this);
});
// Reset timer
time = null;
}, 250);
};
$(window).resize(resize);
};