Usually we need a fixed header when showing big table.
In order to keep track of which column it was you need the header <thead> fixed.
Sometimes you even need the columns fixed in case you have a big horizontal scroll on table, i.e. when you have more than 10-15 columns.
Usually we duplicate the header <thead> and make it position fixed, but that causes irregularities in the header and table columns width.
Here is a solution to that:
jsFiddle Demo
HTML
In order to keep track of which column it was you need the header <thead> fixed.
Sometimes you even need the columns fixed in case you have a big horizontal scroll on table, i.e. when you have more than 10-15 columns.
Usually we duplicate the header <thead> and make it position fixed, but that causes irregularities in the header and table columns width.
Here is a solution to that:
jsFiddle Demo
HTML
<div class="tblScroll" id="fixedTable1">
<table class="table table-bordered">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
<th>Firstname 2</th>
<th>Lastname 2</th>
<th>Email 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Doe</td>
<td>john@example.com</td>
<td>John 2</td>
<td>Doe 2</td>
<td>john@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>john@example.com</td>
<td>John 2</td>
<td>Doe 2</td>
<td>john@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>john@example.com</td>
<td>John 2</td>
<td>Doe 2</td>
<td>john@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>john@example.com</td>
<td>John 2</td>
<td>Doe 2</td>
<td>john@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>john@example.com</td>
<td>John 2</td>
<td>Doe 2</td>
<td>john@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary@example.com</td>
<td>Mary 2</td>
<td>Moe 2</td>
<td>mary@example.com 2</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july@example.com</td>
<td>July 2</td>
<td>Dooley 2</td>
<td>july@example.com 2</td>
</tr>
</tbody>
</table>
</div>
CSSbody{padding-bottom:3000px; transform: translateZ(0); backface-visibility: hidden; perspective: 1000;} .clearfix:before, .clearfix:after { content: '.'; display: block; overflow: hidden; visibility: hidden; font-size: 0; line-height: 0; width: 0; height: 0; } .clearfix:after { clear: both; } .clearfix { zoom: 1; } .tblScrollWrap { overflow:auto; max-width:100%;margin-bottom:20px;margin:0; } .tblScroll {overflow:auto;} .tblScroll .table { max-width:initial; min-width:100%; width:auto; margin-bottom:0; border:none; } .tblScroll > .table { border-collapse: separate; } .table td { min-width:100px; padding:10px; } .table th { background:#ccc; padding:10px; } .tblScroll .table-bordered > tbody > tr > td, .tblScroll .table-bordered > tbody > tr > th, .tblScroll .table-bordered > tfoot > tr > td, .tblScroll .table-bordered > tfoot > tr > th, .tblScroll .table-bordered > thead > tr > td, .tblScroll .table-bordered > thead > tr > th { border:none; border-right:1px solid #ddd; border-bottom:1px solid #ddd; } .table td { background:#fff; } .fxHead, .fxCol { position:relative; -webkit-backface-visibility: hidden; -webkit-perspective: 1000; } .fxHead { z-index:20; } .opacityTransition { transition:opacity 200ms ease; } .fxCol { z-index:19; } .fxHead.fxCol { z-index:21; } .fxHead, .fxCol { } .tblHorScroll { width:100%; overflow-x:auto; overflow-y:hidden; transform:translate(0,-100%); -ms-transform:translate(0,-100%); } .tblHorWidth{ height:1px; }
JS
if("document" in self){if(!("classList" in document.createElement("_"))){(function(j){"use strict";if(!("Element" in j)){return}var a="classList",f="prototype",m=j.Element[f],b=Object,k=String[f].trim||function(){return this.replace(/^\s+|\s+$/g,"")},c=Array[f].indexOf||function(q){var p=0,o=this.length;for(;p<o;p++){if(p in this&&this[p]===q){return p}}return -1},n=function(o,p){this.name=o;this.code=DOMException[o];this.message=p},g=function(p,o){if(o===""){throw new n("SYNTAX_ERR","An invalid or illegal string was specified")}if(/\s/.test(o)){throw new n("INVALID_CHARACTER_ERR","String contains an invalid character")}return c.call(p,o)},d=function(s){var r=k.call(s.getAttribute("class")||""),q=r?r.split(/\s+/):[],p=0,o=q.length;for(;p<o;p++){this.push(q[p])}this._updateClassName=function(){s.setAttribute("class",this.toString())}},e=d[f]=[],i=function(){return new d(this)};n[f]=Error[f];e.item=function(o){return this[o]||null};e.contains=function(o){o+="";return g(this,o)!==-1};e.add=function(){var s=arguments,r=0,p=s.length,q,o=false;do{q=s[r]+"";if(g(this,q)===-1){this.push(q);o=true}}while(++r<p);if(o){this._updateClassName()}};e.remove=function(){var t=arguments,s=0,p=t.length,r,o=false,q;do{r=t[s]+"";q=g(this,r);while(q!==-1){this.splice(q,1);o=true;q=g(this,r)}}while(++s<p);if(o){this._updateClassName()}};e.toggle=function(p,q){p+="";var o=this.contains(p),r=o?q!==true&&"remove":q!==false&&"add";if(r){this[r](p)}if(q===true||q===false){return q}else{return !o}};e.toString=function(){return this.join(" ")};if(b.defineProperty){var l={get:i,enumerable:true,configurable:true};try{b.defineProperty(m,a,l)}catch(h){if(h.number===-2146823252){l.enumerable=false;b.defineProperty(m,a,l)}}}else{if(b[f].__defineGetter__){m.__defineGetter__(a,i)}}}(self))}else{(function(){var b=document.createElement("_");b.classList.add("c1","c2");if(!b.classList.contains("c2")){var c=function(e){var d=DOMTokenList.prototype[e];DOMTokenList.prototype[e]=function(h){var g,f=arguments.length;for(g=0;g<f;g++){h=arguments[g];d.call(this,h)}}};c("add");c("remove")}b.classList.toggle("c3",false);if(b.classList.contains("c3")){var a=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(d,e){if(1 in arguments&&!this.contains(d)===!e){return e}else{return a.call(this,d)}}}b=null}())}};
var opts = {
container: '#fixedTable1',
header: 'fixed',
topOffset: 50,
fixedcolumns: 2,
sizepolling: 200
}
function fixedTable(opts) {
var thisTable = {};
thisTable.preScroll = null;
thisTable.scrollStopEvents = [];
thisTable.scrollHorStopEvents = [];
var defaults = {
header: 'fixed',
fixedcolumns:0,
topOffset: 0
};
var init = function() {
for(x in defaults) {
if(! opts.hasOwnProperty(x)) {
opts[x] = defaults[x];
}
}
detectTable();
if(opts.header.toLowerCase() === 'fixed') {
initiateFixedHeader();
}
if(opts.fixedcolumns > 0) {
initiateFixedColumns();
}
handleTableEvents();
};
var handleTableEvents = function() {
thisTable.container.addEventListener("scroll",syncScroll);
thisTable.container.addEventListener("scroll",horScrollListener);
if(typeof thisTable.scrollCont != 'undefined') {
thisTable.scrollCont.addEventListener("scroll",syncScroll);
}
};
var horScrolldelay = 50;
var horScrolltimeout = null;
var horScrollListener = function(e) {
clearTimeout(horScrolltimeout);
horScrolltimeout = setTimeout(function(){
horizontalScrollStopDispatcher();
},horScrolldelay);
};
var syncScroll = function(e) {
if(thisTable.preScroll != null && thisTable.preScroll != e.target){return;}
if(thisTable.preScroll == null){
thisTable.onHorTableScrollStopped(function() {
thisTable.preScroll = null;
})
}
thisTable.preScroll = e.target;
var scrollLeft = (typeof e.explicitOriginalTarget != 'undefined')? parseInt(e.explicitOriginalTarget.scrollLeft) : parseInt(e.srcElement.scrollLeft);
if(e.target == thisTable.container) {
thisTable.scrollCont.scrollLeft = e.target.scrollLeft;
positionFixedCols(e.target.scrollLeft);
}
if(e.target == thisTable.scrollCont) {
positionFixedCols(e.target.scrollLeft);
thisTable.container.scrollLeft = e.target.scrollLeft
}
};
var positionFixedCols = function(scrollLeft) {
for(var i = 1; i <= opts.fixedcolumns; i++) {
var colHead = thisTable.container.querySelectorAll('table > thead > tr th:nth-child('+i+')');
var colBody = thisTable.container.querySelectorAll('table > tbody > tr td:nth-child('+i+')');
[].forEach.call(colHead,function(element, index, array) {
element.style.transform = setRule(element.style.transform,'translateX',(scrollLeft+'px'));
if(! element.classList.contains('fxCol')) {
element.classList.add('fxCol');
}
if(prefix.lowercase == 'ms') {
element.style.msTransform = setRule(element.style.msTransform,'translateX',(scrollLeft+'px'));
}
});
[].forEach.call(colBody,function(element, index, array) {
element.style.transform = setRule(element.style.transform,'translateX',(scrollLeft+'px'));
if(! element.classList.contains('fxCol')) {
element.classList.add('fxCol');
}
if(prefix.lowercase == 'ms') {
element.style.msTransform = setRule(element.style.msTransform,'translateX',(scrollLeft+'px'));
}
});
}
};
var initiateFixedColumns = function() {
thisTable.scrollCont = document.createElement('div');
thisTable.scrollCont.className = "tblHorScroll";
thisTable.scrollWidthCont = document.createElement('div');
thisTable.scrollWidthCont.className = "tblHorWidth";
thisTable.scrollWidthCont.style.width = thisTable.table.getBoundingClientRect().width + 'px';
thisTable.scrollCont.appendChild(thisTable.scrollWidthCont);
var parCont = thisTable.parentNode;
thisTable.container.parentNode.insertBefore(thisTable.scrollCont, thisTable.container.nextSibling);
};
var isIE = (function() {
var myNav = navigator.userAgent.toLowerCase();
if(myNav.indexOf('msie') != -1) {
var ieVer = parseInt(myNav.split('msie'))[1];
if(myNav.indexOf('msie 10') > -1 || myNav.indexOf('msie 9') > -1) {return true}
}
return false;
})();
var prefix = (function () {
var styles = window.getComputedStyle(document.documentElement, ''),
pre = (Array.prototype.slice
.call(styles)
.join('')
.match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o'])
)[1],
dom = ('WebKit|Moz|MS|O').match(new RegExp('(' + pre + ')', 'i'))[1];
return {
dom: dom,
lowercase: pre,
css: '-' + pre + '-',
js: pre[0].toUpperCase() + pre.substr(1)
};
})();
var detectTable = function() {
if(typeof opts.container == 'undefined' || opts.container.trim() == '') {
throw "Container missing";
}else {
thisTable.container = document.querySelector(opts.container);
if(typeof thisTable.container == "undefined" || thisTable.container === null) {
throw "Container missing";
}
thisTable.table = thisTable.container.querySelector('table');
if(typeof thisTable.table == "undefined" || thisTable.table === null) {
throw opts.container + " does not contain a table element";
}
thisTable.thead = thisTable.table.querySelector('thead');
thisTable.tbody = thisTable.table.querySelector('tbody');
}
};
var setRule = function(rule,prop,val) {
rule = rule || '';
var str = rule+'';
var regex = new RegExp(prop +"\\(.*?\\)","gi");
if (str.match(regex) != null) {
str = str.replace(regex,prop+'('+val+')')
}else {
str += ' ' + (prop+'('+val+')');
}
return str;
}
thisTable.onWindowScrollStopped = function(fnc) {
thisTable.scrollStopEvents.push(fnc);
};
thisTable.onHorTableScrollStopped = function(fnc) {
thisTable.scrollHorStopEvents.push(fnc);
};
var verticalScrollStopDispatcher = function() {
for(var i = 0; i < thisTable.scrollStopEvents.length; i++) {
thisTable.scrollStopEvents[i].call();
}
}
var horizontalScrollStopDispatcher = function() {
for(var i = 0; i < thisTable.scrollHorStopEvents.length; i++) {
thisTable.scrollHorStopEvents[i].call();
}
}
var scrolldelay = 500;
var scrolltimeout = null;
var winScrollListener = function() {
clearTimeout(scrolltimeout);
scrolltimeout = setTimeout(function(){
verticalScrollStopDispatcher();
},scrolldelay);
}
var moveHeader = function(e) {
var tableY = (typeof thisTable.table.getBoundingClientRect().y != 'undefined')? thisTable.table.getBoundingClientRect().y : thisTable.table.getBoundingClientRect().top;
var tableHeight = thisTable.table.getBoundingClientRect().height;
if(tableY < 0) {
applyHeaderStyles(tableY * -1);
}
if(tableY > 0) {
applyHeaderStyles(0);
}
thisTable.prevY = tableY;
};
var applyHeaderStyles = function(scrollTop) {
var headers = thisTable.table.querySelectorAll('thead th');
[].forEach.call(headers,function(element, index, array) {
if(isIE) {
element.style.opacity = 0;
element.classList.add('opacityTransition');
}
element.style.transform = setRule(element.style.transform,'translateY',( scrollTop+'px'));
if(! element.classList.contains('fxHead')) {
element.classList.add('fxHead');
}
if(prefix.lowercase == 'ms') {
element.style.msTransform = setRule(element.style.msTransform,'translateY',(scrollTop+'px'));
}
});
};
var initiateFixedHeader = function() {
window.addEventListener("scroll",moveHeader);
window.addEventListener("scroll",winScrollListener);
if(isIE) {
thisTable.onWindowScrollStopped(function(){
var headers = thisTable.table.querySelectorAll('thead th.opacityTransition');
[].forEach.call(headers,function(element, index, array) {
setTimeout(function(){
element.style.opacity = 1;
setTimeout(function(){
element.classList.remove('opacityTransition');
},200);
},500)
});
});
}
};
init();
return {
destroy : 'empty'
}
}
var b = fixedTable(opts);
No comments:
Post a Comment