Fixed table headers

Only a question, i use the code in the post #33 but the header doesn't 're-attaches' when i scroll up. Any solution? :(
 
Only a question, i use the code in the post #33 but the header doesn't 're-attaches' when i scroll up. Any solution? :(
See post #37. Try using the code I added to the Wiki. That provides better instructions, is less complex, and will always be the most current.
 
I came across that same issue the other day when using Firefox.
So (thanks to you:)) I started looking into this today.
It looks like, Firefox is always returning zero for var tgBodyTop !

After doing a little research, here's the fix...
Find the line
JavaScript:
var tgBodyTop = jQuery('body.site').scrollTop();
...and replace it with...
JavaScript:
var tgBodyTop = jQuery(window).scrollTop();

I'm just about to fix it in the Wiki. Thanks for bringing it to my attention.
 
Thank you very much Bauer!
It's perfect, it works very well.
Only a litle thing, the header's background appears to be transparent, so that the labels of the fields are superimposed to the data below.
How to make opaque the header's background ?
Thank you for your help.:)

JP
 
By default the boostrap table background is transparent.
But you can just include the css as needed, in your list template's custom_css.php file
CSS:
tr.fabrik___heading {
    background-color: #cecece;
}
(That should take care of both the header and footer.)

If you have elements that seem to overlay the fixed header or footer when the page is scrolled - just include higher z-index value for the header (thead) or footer (tfoot) tags.
CSS:
thead, tfoot {
    z-index: 1;
}
(Just change the '1' to a higher number as needed - until it comes 'to the top'. Or use your browser's development tool to identify the z-index value used for the object that is overlaying the fixed header or footer and just set the z-index value for thead and tfoot higher than that.)
 
Hello,

Thank you for your quick reply.
I added the css in custom_css.php and, impeccable, it works perfectly.
One final note: In the fixed header, borders disappear and labels are all shifted to the right because the column containing the buttons (Edit, Delete, etc.) disappears in the fixed header when I scroll to the bottom. How to make the labels are not shifted and that the borders reappear in the fixed header ?
Note that I have set the widths of my columns in% in the css of each element in the table.
For the footer no problem :).
Thanks a lot for your help.

JP
 
I can't tell you what the problem is. What template are you using for Joomla? My code has only been tested using the protostar Joomla template and the Fabrik default bootstrap list template.

But you can try this... With the page scrolled so that the fixed header is docked at the top, examine the HTML (using the browser development tool for viewing the HTML source code) and verify that the last 2 'th' tags in thead tr have 'fabrik_select' - then 'fabrik_actions' as a class name. Those are the classes for the 2 column headers that you say are missing. Maybe they are there but have been hidden, or for some reason the z-index value for the buttons need to be raised to bring them to the forefront? Does the checkbox show in the fixed header, or is that missing too?

If you change the template for this particular page (in the menu configuration) to protostar - and use the fabrik bootstrap template for the fabrik list - and still have issues, then I'm really lost - because I use that code on numerous lists with no problems.:confused:
 
Hello Bauer,

Looking at the html code (excuse me, I'm certainly not an expert ...) I noticed a problem: For a "normal" header label without scroll, css follow the rules (The commented lines of code are barred lines in CSS style firebug):
CSS:
element.style {
    text-align: center;
    vertical-align: middle;
    width: 86px;
}
http://site/templates/protostar/css/template.css ligne 1758:
.table-bordered thead:first-child tr:first-child > th:first-child, .table-bordered tbody:first-child tr:first-child > td:first-child, .table-bordered tbody:first-child tr:first-child > th:first-child {
    border-top-left-radius: 4px;
}
ligne 1747:
.table-bordered caption + thead tr:first-child th, .table-bordered caption + tbody tr:first-child th, .table-bordered caption + tbody tr:first-child td, .table-bordered colgroup + thead tr:first-child th, .table-bordered colgroup + tbody tr:first-child th, .table-bordered colgroup + tbody tr:first-child td, .table-bordered thead:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child td {
    border-top: 0 none;
}
ligne 1716:
.table caption + thead tr:first-child th, .table caption + thead tr:first-child td, .table colgroup + thead tr:first-child th, .table colgroup + thead tr:first-child td, .table thead:first-child tr:first-child th, .table thead:first-child tr:first-child td {
    /*border-top: 0 none;*/
}
ligne 1713:
.table thead th {
    /*vertical-align: bottom;*/
}
ligne 1743:
.table-bordered th, .table-bordered td {
    border-left: 1px solid #ddd;
}
Ligne 1730:
.table-condensed th, .table-condensed td {
    padding: 4px 5px;
}
Ligne 1710:
.table th {
    font-weight: bold;
}
Ligne 1702:
.table th, .table td {
    /*border-top: 1px solid #ddd;*/
    line-height: 18px;
    /*padding: 8px;
    text-align: left;
    vertical-align: top;*/
}
H?rit? de table#list_21_com_fabrik_21.table.table-striped.table-bordered.table-condensed.table-hover
Ligne 1734:
.table-bordered {
    border-collapse: separate;
}
Ligne 1692:
table {
    /*border-collapse: collapse;*/
    border-spacing: 0;
}
H?rit? de body.site.com_fabrik.view-list.no-layout.no-task.itemid-232-fluid
Ligne 205:
body {
    color: #333;
    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
    font-size: 13px;
    /*line-height: 18px;*/
}
H?rit? de html
Ligne 23
html {
    /*font-size: 100%;*/
For the fixed header the css follow the rules:
CSS:
element.style {
    text-align: center;
    vertical-align: middle;
    width: 86px;
}
Ligne 1716
.table caption + thead tr:first-child th, .table caption + thead tr:first-child td, .table colgroup + thead tr:first-child th, .table colgroup + thead tr:first-child td, .table thead:first-child tr:first-child th, .table thead:first-child tr:first-child td {
    border-top: 0 none;
}
Ligne 1713:
.table thead th {
   /* vertical-align: bottom;*/
}
Ligne 1710:
.table th {
    font-weight: bold;
}
Ligne 1702:
.table th, .table td {
   /* border-top: 1px solid #ddd;*/
    line-height: 18px;
    padding: 8px;
    /*text-align: left;
    vertical-align: top;*/
}
H?rit? de table.table.temptable
Ligne 1692
table {
    border-collapse: collapse;
    border-spacing: 0;
}
H?rit? de body.site.com_fabrik.view-list.no-layout.no-task.itemid-232-fluid
ligne 205:
body {
    color: #333;
    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
    font-size: 13px;
    /*line-height: 18px;*/
}
H?rit? de html
ligne 23
html {
    /*font-size: 100%;*/

There just see the css is not the same for the fixed header: 8 px for padding set which shifts all labels to the right and there is no border !! while class is the same: <tr class = "fabrik ___ heading"> and <th class = "heading fabrik_ordercell t_matable___monelement 166_order fabrik_list_21_group_31"
What problem could there be?
Thanks for your help.
 
I can't duplicate your problem. And I'm still having a hard time envisioning exactly what it is without an actual screen snip showing the fixed header 'problem'.

I tried changing the various 'Bootstrap list classes' settings in the Layout tab of the list configuration and still have no real issues - other than the loss of borders or condensed styling in the fixed header - and that's easy enough to fix. (I never checked for those special classes that get added to the table as those options are added - and they would need to be added to the fixed header too. I'll fix and change that in the Wiki)

But, for me, that still doesn't change or affect the fixed header width or padding in each 'th' cell. Both of those values are being cloned from the original thead - so I have no idea why it is happening for you.

I'd suggest using the browser developer tool and playing with the css in the fixed header until it looks just like the header when it is attached to the list. Then add those tweaked settings to your custom_css.php file. The only difference in the docked/fixed header is that the parent 'table' tag also has a class 'temptable' (so the css for each th in the fixed header would be would be nested as... table.temptable thead tr th ) with each 'th' also having a class identical to the full element name, or for the select checkbox column - 'fabrik_select', and for the action buttons column - 'fabrik_actions'.
 
Hello,

I added in the custom css.php:
table.temptable thead tr th {
padding: 5px 4px;
border-left: 1px solid #DDD;
}
And it works !
Thank you for all Bauer
 
Last edited:
Great! (no problem)
I'm assuming the change I added to the Wiki code will do the same thing. What the new additional (2 lines) code does is get the class names from the 'normal' table tag and add them to table.temptable used in the fixed header. (See the section in the updated Wiki js code that begins with the remark /* Create fixed header )
 
Last edited:
It looks like I never added anything to compensate for horizontal scrolls - only vertical.
Narrow screens would cause a horizontal scroll to be needed.
So I worked at fixing that today - and updated the Wiki.

There are 3 lines changed . The changes are...
After this line
JavaScript:
 var tgBodyTop = jQuery(window).scrollTop();
I added this line to get the horizontal scroll position (where ## is the list ID)
JavaScript:
var tgBodyLeft = document.getElementById("list_##_com_fabrik_##").offsetLeft - jQuery(window).scrollLeft();

Then use that to calculate the 'left' position in the code that sets the fixed header and footer css styling...
Line
JavaScript:
jQuery("table.temptable").css({"position":"fixed","top":window.fixedMenuHeight+"px"});
Changed to
JavaScript:
jQuery("table.temptable").css({"position":"fixed","top":window.fixedMenuHeight+"px","left":tgBodyLeft+"px"});
and Line
JavaScript:
jQuery(".docked").css({"position":"fixed","bottom":"0px","width":window.tablewidth+"px","display":"inherit","z-index":"1"});
Changed to
JavaScript:
jQuery(".docked").css({"position":"fixed","bottom":"0px","left":tgBodyLeft+"px","width":window.tablewidth+"px","display":"inherit","z-index":"1"});
Does that help?
 
Last edited:
Thank you, Bauer. I tried applying your recommendations; but the following was not in my existing list_6.js file...
jQuery(".docked").css({"position":"fixed","bottom":"0px","width":window.tablewidth+"px","display":"inherit","z-index":"1"});
So, I'm unsure where to place the the replacement code you recommended below...
jQuery(".docked").css({"position":"fixed","bottom":"0px","left":tgBodyLeft+"px","width":window.tablewidth+"px","display":"inherit","z-index":"1"});

Below is my original code in list_6.js file.
/*
* Creates Fixed table headers and footer in a Fabrik list using the default bootstrap template.
* How to use:
* 1 Open or create the list_#.js file for the list that contains the table you want to have fixed headers
* 2 Include a call to setHeaders() at the end of the requirejs(['fab/fabrik'] function (as shown below)
* 3 Copy the jQuery(window).scroll(function(event) and function setHeaders() code into that js file
* ( For a default Joomla protostar template using the default Fabrik bootstrap list template
you can skip steps 4-7 and just replace all instances of '260' in this code with your List id.)
* 4 Examine the page html and identify the id used for the form object
* 5 Replace all instances of "listform_6_com_fabrik_6" with that form id
* 6 Examine the page html and identify the id for the table object
* 7 Replace all instances of "list_6_com_fabrik_6" with that table id
* 8 Take note of any remarks in code beginning with /*** for additional options/settings.
* Enjoy your 'fixed header'!
* NOTE: It may be necessary to include the setHeaders() call in another fabrik *.js file instead
* - i.e. if you are also using a Fabrik list or form module on the same page which might affect when this list is shown.
*/

requirejs(['fab/fabrik'], function () {
setHeaders();
});

/* this function checks if passed jQuery object is in viewport of browser */
jQuery.fn.inView = function(){
//Window Object
var win = jQuery(window);
//Object to Check
obj = jQuery(this);
//the top Scroll Position in the page
var scrollPosition = win.scrollTop();
//the end of the visible area in the page, starting from the scroll position
var visibleArea = win.scrollTop() + win.height();
//the end of the object to check
var objEndPos = (obj.offset().top + obj.outerHeight());
return(visibleArea >= objEndPos && scrollPosition <= objEndPos ? true : false)
};

/* The scroll event listener */
jQuery(window).scroll(function(event){

/* Get the current table vertical position as page is scrolled */
window.tableFromTop = window.thisTable.getBoundingClientRect().top + window.scrollY;

/* Get the scroll position of entire document */
var tgBodyTop = jQuery(window).scrollTop();

/* detach/attach table header */
if(tgBodyTop > window.tableFromTop) {
if(jQuery("#listform_6_com_fabrik_6 div.fabrikDataContainer table.temptable").length==0){
var temphead = jQuery("table#list_6_com_fabrik_6 thead").clone();
jQuery(temphead).prop('id','temphead');

/* Create fixed header */
var tableclasses = document.getElementById("list_6_com_fabrik_6").className;
/* The z-index may have to be set higher if the fixed header is not 'on top' */
jQuery("#listform_6_com_fabrik_6 div.fabrikDataContainer").prepend('<table class="'+tableclasses+' temptable" style="width:'+window.tablewidth+'px;z-index:1"><thead>'+jQuery(temphead).html()+'</thead></table>');

/* Note: Set the "top:" fixed position for table header in function setHeaders() */
jQuery("table.temptable").css({"position":"fixed","top":window.fixedMenuHeight+"px"});
}
}else{
if(jQuery("#listform_6_com_fabrik_6 div.fabrikDataContainer table.temptable").length){
jQuery("#listform_6_com_fabrik_6 div.fabrikDataContainer table.temptable").remove();
}
}


});

/* Reset the fixed headers if window gets resized */
jQuery( window ).resize(function() {
setHeaders();
});

/* main function call for fixed headers/footer -
call this function as the last line in the requirejs(['fab/fabrik'], function () */
function setHeaders() {
/*** Set window.fixedMenuHeight to the height of fixed page header/menu - 0 if none) ***/
window.fixedMenuHeight = 34;

/* clear settings if any are set */
jQuery("#list_6_com_fabrik_6 tfoot").removeClass("docked");
jQuery("#listform_6_com_fabrik_6 div.fabrikDataContainer table.temptable").remove();
jQuery("#bottdiv").remove();

/* initialize window variables */
window.thisTable = document.getElementById("list_6_com_fabrik_6");
window.tableFromTop = window.thisTable.getBoundingClientRect().top + window.scrollY;
window.theadHeight = document.getElementById("list_6_com_fabrik_6").getElementsByTagName('thead')[0].clientHeight;
window.tfootHeight = document.getElementById("list_6_com_fabrik_6").getElementsByTagName('tfoot')[0].clientHeight;
window.viewHeight = jQuery(window).height();

/* Create an empty div to identify the bottom of the table view, where the footer would normally be */
jQuery(jQuery("<div>",{id:"bottdiv"})).appendTo("#listform_6_com_fabrik_6 div.fabrikDataContainer");

/* initializes vars for css styling of each table header (th) - width, padding */
window.tablewidth = document.getElementById("list_6_com_fabrik_6").clientWidth;
var xwidth,xpad;
// sets width and padding of each column as css style so cloned header will have it
jQuery("table#list_6_com_fabrik_6 thead tr th").each(function (){
xwidth = jQuery(this).width();
xpad = jQuery(this).css('padding');
jQuery(this).css({'width':xwidth+'px','padding':xpad});
});

/*** Note each remark for scrollTop options. ***/
/* This topPos value would scroll to the top of the list form */
// var topPos = document.getElementById("listform_6_com_fabrik_6").getBoundingClientRect().top + window.scrollY - window.fixedMenuHeight ;
/* This topPos value would scroll to the top of the table */
// var topPos = document.getElementById("list_6_com_fabrik_6").getBoundingClientRect().top + window.scrollY - window.fixedMenuHeight ;
/* If you have included a page class in the menu this would scroll to the top of the page (replace "onlinesurvey" with your page class name) */
var topPos = document.getElementsByClassName("onlinesurvey")[0].getBoundingClientRect().top + window.scrollY - window.fixedMenuHeight;
/*** Remark out the next line or remove this section if you don't want to scroll to the list/table/page on page load ***/
jQuery("html, body").animate({ scrollTop: topPos });
};
Any more suggestions?
Thanks in advance.
 
Last edited:
That line belongs in the section for setting the fixed footer. You must have removed that section of code (per the instructions) because you didn't want to have a fixed footer also. So you should be ok with doing just the first 2 changes in my last reply.

If that didn't fix your particular problem, I don't know what else to tell you, other than I'm sorry I couldn't help.:(
 
Ah, yes, I forgot I removed the sticky footer. My bad.
Strangely, your recommendations work on a computer with an iPad screen size simulator (reducing the browser size to the size of the iPad screen); but it doesn't work on the actual iPad. I still have the same issue with the headers not matching where the columns are once I start scrolling. I used Google Chrome on the computer with the simulator and the native safari app on the iPad. I also tried the Google iPad app and had the same results as safari. So, as a plan B for now, it would be better for the sticky header to vanish on the iPad; but remain on computers (it works great on computers). Is there any way to adjust the code to hide the sticky header when the resolution gets small as an iPad?
Thanks in advance.
 
Yeah worrying about smartphones and other mobile devices is a whole new can of worms that I'd rather not get into.

Nonetheless, try wrapping your code with this 'if' condition...
JavaScript:
if( !/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) {
// your code..
}
 
Last edited:
We are in need of some funding.
More details.

Thank you.

Members online

Back
Top