jQuery floating table header plugin

A jQuery plugin that makes the header of a table floating if the original header isn't visible due to scrolling. The plugin will automatically choose the thead tag as the header for a table. If thead isn't found it will search for rows marked with the class 'floating'. The behavior can be changed by the settings forceClass and markingClass.

News

2010-07-08
1.2.0! Fixed a few bugs and added reinit and recalculate functions to the table.

2009-10-19
1.1.0! Better compatibility, better tested. There are still some problems with IE6 that i would like to have some help with.

2009-10-15
1.0.7 is out! With all fixes made by Vasilianskiy Sergey. I've also removed class marking of table rows. Also the plugin doesn't clone the whole table, just thead.

2009-10-07
1.0.6 is released with better compatibility with IE6/7. Big thanks to Glen for providing the patches!

2009-08-22
1.0.5 is released! Compatibility issues with IE7 and IE8 are still there but since i've limited access to Windows it will take some time to fix them.

2009-08-21
I've done some small changes and got the plugin to work with IE8 in all supported modes except (quirks mode). I will create a new release on jquery later today.

Usage

Just call floatHeader on a table in the page.
jQuery("#table").floatHeader(options);

Configuration options

An optional configuration dictionary can be passed to the plugin. Accepted options are:
fadeOutThe length of the fade out animation in ms. Default: 250
faceInThe length of the face in animation in ms. Default: 250
forceClassForces the plugin to use the marker class when searching for a header instead of thead. Default: false
floatClassThe class of the div that contains the floating header. The style should contain an appropriate z-index value. Default: 'floatHeader'
markerClassThe class name that is used for marking which rows that should be floating. Default: floating
cbFadeOutA callback that is called when the floating header should be faded out. The method is called with the wrapped header as argument.
cbFadeInA callback that is called when the floating header should be faded in. The method is called with the wrapped header as argument.
recalculateRecalculate the column width on every scroll event.

Functions

The plugin defines two functions on the source table which can be called if the header is changed.
fhRecalculateRecalculated the column width of the floater.
fhInitRecreates the floater from the source table header.
$("#table").get(0).fhInit();
$("#table").get(0).fhRecalculate();

Known issues and bug reporting

Please use the issue tracker on the project page at jquery.com to view and report bugs.

Acknowledgements

Just want to acknowledge a few people who have contributed to the development.

Diego Arbelaez - Contributed code to support resize events.
Stephen J. Fuhry - A test case for huge tables and testing of the horizontal-scroll-bug.
Glenn Gilbert - Compatibility for IE6/7
Vasilianskiy Sergey - Lots of jQuery fixes

Download and demo

Files can be downloaded at:
   jquery.floatheader.js
   jquery.floatheader.min.js

A demo can be found at:
   http://static.slackers.se/pages/javascript/jquery-floatheader/

41 comments:

Diego Arbelaez 07 July, 2009 21:24  

Great stuff!... works pretty well in IE7+ and FF3+.. doesnt work on IE6 or Chrome

IE7+ and FF3+ have one minor bug when resizing the browser window, where the header row no longer line up(width wise) with the data rows.

looking forward to an updated version..

Diego Arbelaez 07 July, 2009 22:24  

Hey Guys, i fixed the issue with the floating header width not matching the width of the data.
Below is the updated code - new stuff is marked with a comment

(edit by Erik) Removed the code to save some space on the page, sorry Diego.

Diego Arbelaez 07 July, 2009 23:14  

Correction on my notes above, this does in fact work in Google's Chrome, i have a conflict with legacy prototype.js code

Erik 08 July, 2009 00:29  

Big thanks for the fix, I'll check in the changes in SVN and create a new release at jquery.com.

Duane 17 July, 2009 23:14  

This script is awesome! I'm using it on a page where the datatable is rendered in a ajax gridview (asp.net) .. If the table is visible before the page load, it works great.

If not - then it doesnt float the headers on the postback - any ideas why? or, if the headers are in float, and there is a ajax postback, the float sticks to the top of the page.

Erik 20 July, 2009 15:05  

Yes i've also seen this bug, but i did't have time to fix it before my vacation. Please report these issues on the plugin page at jquery.com. I will take a look at them when i get back in the beginning of august :)
Thanks a lot for the feedback

Stephen J. Fuhry 04 August, 2009 16:51  

I'm having problems with tables wider than the monitor width.. I'll try and post a demo and run some tests if I get a chance, but for now, here are a couple sample screenshots:
http://steve.thefuhry.com/screenshot.normal.jpg
http://steve.thefuhry.com/screenshot.suck.jpg

lindsay 04 August, 2009 18:47  

Anyone else have problems with IE 8?
in IE 8 my table header jumps to the bottom of the screen.

Erik 04 August, 2009 19:32  

I've created an issue for this bug at jquery.com (http://plugins.jquery.com/project/issues/floatHeader). I'll try to have a look at them as soon as possible, thanks for the input.

alx 20 August, 2009 11:10  

Same here, IE8 and IE7 not working — headers falling to the footer of the page.

Rivka 21 August, 2009 01:51  

Doesn't work for me in IE 7 or 8, either. I was really hoping this would work, too!

alx 21 August, 2009 08:12  

It seems I have found solution for IE 7-8: just add doctype to your document - it will switch explorer to standard-mode and table headers will work like in other browsers.

Erik 21 August, 2009 09:26  

Thanks, i will verify this workaround today and update this page.

slackers.se» Blog Archive » jQuery floating header plugin 1.0.5 released 22 August, 2009 18:21  

[...] new version can be downloaded from the project page, jQuery or from the subversion [...]

Stephen J. Fuhry 22 August, 2009 20:26  

http://steve.thefuhry.com/floatheaderbug/maax_browser.php.htm

Sam 06 October, 2009 01:36  

Hey, great script - is it possible to get it to work with tabs?

I have a number of tables in tabs - it works on the first page, then throws an uncaught exception on the other pages and the table header goes nowhere.

I guess it could also be solved by adding a destroy method? That way I could destroy/initialise the floating header as I need it for each tab.

Anyone be able to help with this?

Cheers

Glenn Gilbert 06 October, 2009 11:17  

Been using the code on a project that requires IE6 (it's an intranet application). Had to make various fixes for IE and a couple of enhancements. I'll post each fix separately.

Glenn

Glenn Gilbert 06 October, 2009 11:34  

Fix 1 - Crashes when using IE6 and IE7

This is caused by the code constantly triggering the $(window).resize event. This is because of a bug in IE's handling of resizing where you have to check document.documentElement.clientHeight/Width.

Above the call to createFloater(table, self, config); add the following two lines:

self.IEWindowWidth = document.documentElement.clientWidth;
self.IEWindowHeight = document.documentElement.clientHeight;

These are local variables to hold the current width and height of the window to test on the event.

The $(window).resize event needs to be replaced with the following:

// bind to the resize event
/* Unfortunately IE gets rather stroppy with the non-IE version, constantly resizing, thus cooking your
* CPU with 100% usage whilst the browser crashes. So, test for IE and add additional code.
*/
if ( $.browser.msie && $.browser.version <= 7 ) {
$(window).resize(function() {
// Check if the window size has changed ()
if ( (self.IEWindowWidth != document.documentElement.clientWidth) || (self.IEWindowHeight != document.documentElement.clientHeight) ) {
// Update the client width and height with the Microsoft version.
self.IEWindowWidth = document.documentElement.clientWidth
self.IEWindowHeight = document.documentElement.clientHeight
table.children().remove();
createFloater(table, self, config);
}
});
} else {
$(window).resize(function() {
// recreate the floating table
table.children().remove();
createFloater(table, self, config);
});
}


Glenn

Glenn Gilbert 06 October, 2009 12:19  

Fix 2 - postion:fixed doesn't work with IE6

There's loads written about this where IE6 ignores position:fixed and needs to use position:absolute instead. Unfortunately there's some CSS tricks required to simulate this on IE6.

Most of these have been somewhat documented in Stu Nichols' CSSplay.co.uk website.

In summary you have to move the document scrolling down to the body. This should be done using conditional comments to import the usual IE6 override file. Typically youd' use something like this:

* html { overflow:hidden; }
* html body { height:100%; overflow:scroll; }

Once done, absolute positioning will work like fixed positioning.

The jquery.floatingheader.js file needs to be modified to allow scrolling to be detected on the body as $(window).scroll won't trigger if the CSS was changed as above.


The config needs to have a new flag:
IE6Fix_DetectScrollOnBody:false

This enables the client to move the scroll detection in IE6 down to the body element.

Replace the line:
$(window).scroll(function() {

With the following:
--------------------------
/* This is very specific to IE6 only if using position:fixed fixes. This requires the window overflow to be set to
* hidden and the containing 'body' tag to have overflow:auto.
*/
if ( !$.browser.msie ) {
config.IE6Fix_DetectScrollOnBody = false;
} else {
if ( $.browser.version > 7) {
config.IE6Fix_DetectScrollOnBody = false;
}
}
var scrollElement = config.IE6Fix_DetectScrollOnBody ? $('body') : $(window);
// bind to the scroll event
scrollElement.scroll(function() {
-------------------------


In this function, replace the line:
self.floatBox.css('position', 'fixed');

With the following code:
--------------------------
if ( $.browser.msie && $.browser.version < 7 ) {
// IE6 can't handle fixed positioning; has to use absolute and additional calculation to position correctly
self.floatBox.css('position', 'absolute'); // strictly speaking, this isn't necessary as it is position:absolute
} else {
self.floatBox.css('position', 'fixed');
}
--------------------------


Glenn

erik 06 October, 2009 20:41  

Good work Glen! I'll merge this in the trunk as soon as i can.

Sergey 13 October, 2009 22:00  

Some mods to your code:

1) huge table incorect table width. Especialy in FF
fix: target.width(template.outerWidth());
2) everywhere instend of table.children().remove();
fix: better to use table.empty(); //children().remove();
fic: floatRow.empty(); //children().remove();
3) Maybe usefull in some scripts - to not duplicate ids
target.removeAttr('id');
$('*', target).removeAttr('id');
4) floatBoxVisible not defined
self.floatBoxVisible = false; //after self.floatBox.append(table);

Vasilianskiy Sergey 14 October, 2009 09:32  

Especialy for IE
inspite of IE TH reports padding = 1, floatCell shoud be set in 0
after floatCell.css('width', cell.width());
fix: if ($.browser.msie) {
floatCell.css('padding', '0 0 0 0');
};

amit 15 October, 2009 12:53  

Hi,

I am not able to make it work on ie6...

ie6 is getting hang on scroll.

Please let me know if i am doing something wrong

erik 15 October, 2009 13:03  

@amit I don't know what might be wrong. I will merge the changes suggested by Sergey some time this week. That release might work better with IE6, but that's just a guess...

amit 15 October, 2009 16:13  

Even demo page is getting hanged on ie6.

Please see...

erik 15 October, 2009 16:29  

@amit, unfortunately i don't have access to IE6 so it's hard to fix these issues. I've just integrated Sergeys changes into the plugin. Please try the demo again, if it doesn't work. Contact me on my email, it's on my blogger profile page. Thanks

Vasilianskiy Sergey 16 October, 2009 12:13  

first of all in 1.0.7 version self.clone() was remove -(
previous
// copy all style and class properties -)
var table = self.clone();
table.empty();

and the second one
//after
// append the floatBox to the dom
$(self).after(self.floatBox);
// specialy fix for Safari browser
$(window).one('scroll', function() {
table.empty();
createHeader(table, self, config);
});
and the last one
thanks for include in Contributors

William Shostak 16 October, 2009 12:44  

The changes in 1.0.7 are great for IE6.

But I agree with Vasilianskiy Sergey put back in the self.clone.
// copy all style and class properties -)
var table = self.clone();
table.empty();

Also I found that in IE (all versions) the header columns to not always size correctly I had to change the code:

floatCell.css('width', cell.width());
if ($.browser.msie) {
floatCell.css('padding', '0 0 0 0');
};

to

if ($.browser.msie) floatCell.css('width', cell.outerWidth());
else floatCell.css('width', cell.width());

Nice little plugin thanks for writing it.

erik 16 October, 2009 15:09  

Thanks for testing the plugin. I'm not really a JS-developer but i'm learning a lot from all comments and suggestions. I'll put back the self.clone and include a flag for only using the thead instead as an optimization for huge tables.
If you have more issues and/or suggestions you can always contact me through my email which is on my profile page.

Vasilianskiy Sergey 18 October, 2009 00:13  

some hints to your code to look more beautifie and stable
1) when use console, always check if it presents: not all browsers use right libs. -)
if (console) { console.log("The table contains no header"); };
2) after every command add ;, as not all packers likes \n
example: return;

Vasilianskiy Sergey 18 October, 2009 00:28  

Finally) Incorect big table th position with floatCell.css('width', cell.outerWidth()); fix: removed
floatCell.css('padding', '0 0 0 0') rules

erik 18 October, 2009 00:30  

Oh damn, did i forget a console.log in there? Now that i think about it, i didn't even run it through jslint... I'll have a look at it as soon as possible, thanks.

Bac2Day1 06 November, 2009 20:51  

I'm having a problem with code. In my setup, I'm having the floating header applied to a div with an overflow. It works flawlessly on that. My issue is that if I apply an update to the contents of the overflow'd div via... say ajax, the code (I'm assuming) loses track of the original floated header. The result is that I get duplicate headers. Outside of size, this normally wouldn't be a huge deal, except once this occurs and I scroll the page scrollbar (not the overflow scrollbar) only the current header seems to get the new positioning... the others (as this happens repeatedly) start scrolling with the page. Any ideas on how to remedy this? Thanks!

erik 06 November, 2009 20:56  

The plugin adds the floating header right after the table in the dom. This might have something to do with that?
Please contact me through email, it's on my profile page.

Anonymous 29 December, 2009 05:36  

Thanks, very nice. Just need this for a CMS so IE support not needed. Works very well.

patrik r 02 February, 2010 13:53  

Hi, first of all, thanks for a great plugin.

I have tried to implement it in a asp.net application using AJAX. It seems that it has some problems with async programming?

The header works fine the first time I enter a page, but if I click a button on the page or re-sorting a datagrid, I get an javasrcipt error message "Unspecified error", char 35440

I have tried a "clean" asp.net page(.aspx) without any AJAX or updatepanels and then it works fine.

erik 02 February, 2010 17:48  

Thanks. Are you using the latest version and are you sure you initialize the plugin on each AJAX load? If so please post a bug report at the jQuery project page at http://plugins.jquery.com/project/floatHeader.

patrik r 03 February, 2010 10:59  

Hi, this is how I initialize the plugin:


function pageLoad() {
jQuery('#example1').floatHeader ({
fadeIn: 250,
fadeOut: 250
});
}


At first I used:
jQuery(document).ready(function() but after some reading on internet I found out that pageLoad is more suitable

Trixmoto 25 February, 2010 15:08  

I had to use this code to make it work for me...

$("#"+id).floatHeader(opt).css("display","");

$("div.floatHeader #"+id).attr("id","").css("display","").find("tr").attr("id","");

Mike B 03 May, 2010 21:38  

patrik r, I had that same AJAX issue that you are discussing.

What I ultimately did was every time I refreshed the page I did called the following code:

jQuery(window).unbind(); jQuery("#myTable").floatHeader();

The Error in the Jquery.js script your getting at like 5000something is because basically it is trying to double bind to the window. In IE this is handled as an error. So to correct that just unbind the window before recalling floatHeader().

Hope that helps!

Adam Malcontenti-Wilson 29 May, 2010 08:42  

Great plugin, works great for me.

It would be great if you could extend this plugin to do the same with the table footer (e.g. when scrolling up and the footer isn't visible, it gets moved to the bottom of the screen, opposite to the header functionality)

  © Blogger templates 'Sunshine' by Ourblogtemplates.com 2008

Back to TOP