summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorGábor Hojtsy <gabor@hojtsy.hu>2008-01-09 09:56:39 +0000
committerGábor Hojtsy <gabor@hojtsy.hu>2008-01-09 09:56:39 +0000
commit6dcf2cccaa039764fc9c1895edde03e325c30372 (patch)
treedecbce5aa0a2aadb199830a6ddd8acb8c90557c2 /misc
parent33f455d2df47ef80dd5b3c736762cecd23b0ba63 (diff)
downloadbrdo-6dcf2cccaa039764fc9c1895edde03e325c30372.tar.gz
brdo-6dcf2cccaa039764fc9c1895edde03e325c30372.tar.bz2
#194590 by scor, JirkaRybka, attiks, dvessel; with heavy testing by catch: fix a dozen issues with sticky table headers
Diffstat (limited to 'misc')
-rw-r--r--misc/tableheader.js133
1 files changed, 60 insertions, 73 deletions
diff --git a/misc/tableheader.js b/misc/tableheader.js
index 0568e56a9..c4c000f56 100644
--- a/misc/tableheader.js
+++ b/misc/tableheader.js
@@ -6,70 +6,73 @@ Drupal.behaviors.tableHeader = function (context) {
return;
}
- // Keep track of all header cells.
- var cells = [];
+ // Keep track of all cloned table headers.
+ var headers = [];
- var z = 0;
$('table thead:not(.tableHeader-processed)', context).each(function () {
- // Find table height.
- var table = $(this).parent('table')[0];
- var height = $(table).addClass('sticky-table').height();
- var i = 0;
-
- // Find all header cells.
- $('th', this).each(function () {
-
- // Ensure each cell has an element in it.
- var html = $(this).html();
- if (html == ' ') {
- html = '&nbsp;';
- }
- if ($(this).children().size() == 0) {
- html = '<span>'+ html +'</span>';
- }
+ // 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'
+ });
+ // Everything except thead must be removed. See theme_table().
+ $('tbody', headerClone).remove();
+ $('caption', headerClone).remove();
- // Clone and wrap cell contents in sticky wrapper that overlaps the cell's padding.
- $('<div class="sticky-header" style="position: fixed; visibility: hidden; top: 0px;">'+ html +'</div>').prependTo(this);
- var div = $('div.sticky-header', this).css({
- 'marginLeft': '-'+ $(this).css('paddingLeft'),
- 'marginRight': '-'+ $(this).css('paddingRight'),
- 'paddingLeft': $(this).css('paddingLeft'),
- 'paddingTop': $(this).css('paddingTop'),
- 'paddingBottom': $(this).css('paddingBottom'),
- 'z-index': ++z
- })[0];
- cells.push(div);
+ var headerClone = $(headerClone)[0];
+ headers.push(headerClone);
- // Adjust width to fit cell/table.
- var ref = this;
- if (!i++) {
- // The first cell is as wide as the table to prevent gaps.
- ref = table;
- div.wide = true;
- }
- $(div).width(Math.max(0, $(ref).width() - parseInt($(div).css('paddingLeft'))));
+ // Store parent table.
+ var table = $(this).parent('table')[0];
+ headerClone.table = table;
+ // Finish initialzing header positioning.
+ headerClone.resizeWidths = true;
+ tracker(headerClone);
- // Get position and store.
- div.cell = this;
- div.table = table;
- div.stickyMax = height;
- div.stickyPosition = $(this).offset().top;
- });
+ $(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() {
- $(cells).each(function () {
- // Fetch scrolling position.
- var scroll = document.documentElement.scrollTop || document.body.scrollTop;
- var offset = scroll - this.stickyPosition - 4;
- if (offset > 0 && offset < this.stickyMax - 100) {
- $(this).css('visibility', 'visible');
- }
- else {
- $(this).css('visibility', 'hidden');
- }
+ $(headers).each(function () {
+ tracker(this);
});
};
$(window).scroll(scroll);
@@ -83,26 +86,10 @@ Drupal.behaviors.tableHeader = function (context) {
return;
}
time = setTimeout(function () {
-
- // Precalculate table heights
- $('table.sticky-table').each(function () {
- this.savedHeight = $(this).height();
+ $(headers).each(function () {
+ this.resizeWidths = true;
+ tracker(this);
});
-
- $('table.sticky-table div.sticky-header').each(function () {
- // Get position.
- this.stickyPosition = $(this.cell).offset().top;
- this.stickyMax = this.table.savedHeight;
-
- // Reflow the cell.
- var ref = this.cell;
- if (this.wide) {
- // Resize the first cell to fit the table.
- ref = this.table;
- }
- $(this).width(Math.max(0, $(ref).width() - parseInt($(this).css('paddingLeft'))));
- });
-
// Reset timer
time = null;
}, 250);