Skip to content

Instantly share code, notes, and snippets.

@Cyken-Zeraux
Last active November 3, 2017 18:28
Show Gist options
  • Save Cyken-Zeraux/62cd2f6420ffc56e61bf79800583e544 to your computer and use it in GitHub Desktop.
Save Cyken-Zeraux/62cd2f6420ffc56e61bf79800583e544 to your computer and use it in GitHub Desktop.
function fixedtableheader (){
var tickingImages = false;
var allTables = document.getElementsByTagName('table');
Array.prototype.filter.call(allTables,function(table){
//Just get an array of all the tr's in the table
if(!$(table).hasClass( "stickyheader" ) return;
var trs = table.getElementsByTagName('tr');
//If there's more than one tr, then we proceed and treat the first one as the header
//Probably needs some change
if(trs.length < 2) return;
var firstTr = trs[0];
if(!firstTr) return;
//we clone our TR, making a face deepclone
var tickingPositions = null;
var tickingHeaders = null;
var tableOffsetTop = 0;
var tableHeight =100;
var headerHidden = true;
var oldScroll = 0;
var oldTableWidth = 0;
var oldFirstTrWidth = 0;
var oldTableOffset = null;
var trClone = firstTr.cloneNode(true);
table.style.overflowY='hidden'
//we set the proper styling basics.
trClone.style.visibility='hidden'
trClone.style.top='0'
trClone.style.position= 'fixed'
trClone.style.overflowX= 'hidden'
if(navigator.userAgent.match(/firefox/i)){
trClone.style.marginLeft = '-2px'
}
// we append the fake header child to the thead.
firstTr.insertAdjacentElement('afterend',trClone);
for(var i = 0 ; i < trClone.children.length ; i++){
trClone.children[i].addEventListener('click', function(e){
e.preventDefault(); //stop it from doing anything stupid
e.stopPropagation(); //stop it from bubbling
var j = 1;
var child = e.target;
while(child = child.previousSibling != null) j++
firstTr.children[j].click(); //trigger click event on real child element instead.
})
var spacer = document.createElement('div');
spacer.style.width = '10px';
spacer.style.height= '1px';
trClone.children[i].appendChild(spacer);
}
//recaling when page resizes.
table.addEventListener('resize', throttleRecalcPositions,false);
window.addEventListener('resize', throttleRecalcPositions,false);
table.addEventListener('resize', throttleRecalcHeaders,false);
window.addEventListener('resize', throttleRecalcHeaders,false);
//creating events for when the page gets scrolled.
document.addEventListener('scroll', throttleRecalcPositions,false); //this is an insurance policy.
//onhashtagh change for the tabs
window.addEventListener('hashchange', function(){
setTimeout(function(){
recalcTableSizes();
recalcHeaderSizes();
recalcPositions();
},33)
})
//hooking up fake scrollbar
trClone.addEventListener('scroll', function(e){
if(e.target!=trClone) return;
table.scrollLeft = trClone.scrollLeft ;
})
table.addEventListener('scroll', function(e){
if(e.target!=table) return;
trClone.scrollLeft = table.scrollLeft ;
})
function throttleRecalcHeaders(){
if (!tickingHeaders){
tickingHeaders = setTimeout(function(){
recalcTableSizes();
recalcHeaderSizes();
tickingHeaders = null;
},33);
}
}
function throttleRecalcPositions(){
if (!tickingPositions){
tickingPositions = window.requestAnimationFrame(function(){
recalcPositions();
if(window.pageYOffset > oldScroll + 100 || window.pageYOffset < oldScroll - 100){
recalcTableSizes();
oldScroll = window.pageYOffset
}
tickingPositions = null;
});
}
}
recalcTableSizes();
recalcHeaderSizes();
recalcPositions();
function recalcTableSizes(){
var rect = table.getBoundingClientRect();
tableOffsetTop = rect.top + window.pageYOffset;
tableHeight = rect.height
}
function recalcHeaderSizes(){
var tableRect = table.getBoundingClientRect();
var firstTrRect = firstTr.getBoundingClientRect();
var trCloneRect = trClone.getBoundingClientRect();
if(tableRect.width == oldTableWidth && firstTrRect.width == oldFirstTrWidth) return ; //nothing changed in the headers.
//acquire the exact width of the property without padding, margin, borders
try {trClone.style.width = window.getComputedStyle( table, null).getPropertyValue('width');}
catch(e) {trClone.style.width = table.currentStyle.width;}
for(var i = 0 ; i < trClone.children.length ;i++){
try {trClone.children[i].children[0].style.width = window.getComputedStyle( firstTr.children[i], null).getPropertyValue('width')}
catch(e) {trClone.children[i].children[0].style.width = firstTr.children[i].currentStyle.width;}
if(navigator.userAgent.match(/firefox/i)){
trClone.children[i].children[0].style.width =trClone.children[i].children[0].style.width -4;
}
}
oldTableWidth = tableRect.width;
oldFirstTrWidth = firstTrRect.width;
}
function recalcPositions(){
//first check if the table is still in range
if(window.pageYOffset > tableOffsetTop && window.pageYOffset < tableOffsetTop + tableHeight){
if(headerHidden == true) {
trClone.style.visibility = 'visible'
headerHidden = false;
}
}
else if( headerHidden == false ){
trClone.style.visibility = 'hidden'
headerHidden = true;
}
}
})
}
$(document).ready(fixedtableheader);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment