I am trying to implement a calendar list view like the iOS one. Basically, what I am doing now is to loop through my array of events. If it is a new date, print a date header, else print the calendar event. I want to make the DATE HEADER rows sticky until they get "scrolled away".
How can I achieve that? I see lots of examples on sticky headers but there's no actual one that applies this "sticky" feature to table rows only. My <table
is also put within its own scrollable fixed height and I want the header to stick at the top of the <div>
instead of at top:0;
I have put my code into a pen at and now I am left with fixing the colspan
because my <td>
doesnt span across the cells, and getting the <tr>
to stick at the top of the <div>
.
I am trying to implement a calendar list view like the iOS one. Basically, what I am doing now is to loop through my array of events. If it is a new date, print a date header, else print the calendar event. I want to make the DATE HEADER rows sticky until they get "scrolled away".
How can I achieve that? I see lots of examples on sticky headers but there's no actual one that applies this "sticky" feature to table rows only. My <table
is also put within its own scrollable fixed height and I want the header to stick at the top of the <div>
instead of at top:0;
I have put my code into a pen at http://codepen.io/anon/pen/zxpkr and now I am left with fixing the colspan
because my <td>
doesnt span across the cells, and getting the <tr>
to stick at the top of the <div>
.
I had to wrap the scrollable div with a container div and play with the if statements a bit, but it works.
Working Example
JS
function stickyTitles(stickies) {
this.load = function () {
stickies.each(function () {
var thisSticky = jQuery(this).wrap('<div class="followWrap" />');
thisSticky.parent().height(thisSticky.outerHeight());
jQuery.data(thisSticky[0], 'pos', thisSticky.offset().top);
});
};
this.scroll = function () {
stickies.each(function (i) {
var thisSticky = jQuery(this),
nextSticky = stickies.eq(i + 1),
prevSticky = stickies.eq(i - 1),
pos = jQuery.data(thisSticky[0], 'pos'),
h = $('.mytable').offset().top;
if (pos <= jQuery('.mytable').scrollTop() + h) {
thisSticky.addClass("fixed");
if (nextSticky.length > 0 && jQuery('.mytable').scrollTop() + h >= jQuery.data(thisSticky[0], 'pos') - prevSticky.outerHeight()) {
thisSticky.addClass("absolute").css("top", jQuery.data(nextSticky[0], 'pos') - $('.mytable').scrollTop() - prevSticky.outerHeight() - h);
}
} else {
thisSticky.removeClass("fixed");
if (prevSticky.length > 0 && jQuery('.mytable').scrollTop() + h <= jQuery.data(thisSticky[0], 'pos') - prevSticky.outerHeight()) {
prevSticky.removeClass("absolute").removeAttr("style");
}
}
});
};
}
jQuery(document).ready(function () {
var newStickies = new stickyTitles(jQuery(".followMeBar"));
newStickies.load();
jQuery('.mytable').on("scroll", function () {
newStickies.scroll();
});
});
CSS
body {
height:2000px;
margin: 0;
background: #333;
color: #fff;
overflow: auto;
}
table {
width: 100%;
}
table tr {
height: 100px;
}
.followMeBar {
display: block;
background: #222;
border-bottom: solid 1px #111;
border-top: solid 1px #444;
position: relative;
z-index: 1;
width: 200%;
}
.followMeBar.fixed {
position: absolute;
top: 0;
width: 90%;
z-index: 0;
}
.followMeBar.fixed.absolute {
position: absolute;
}
.mytable {
overflow-y: scroll;
height: 250px;
}
#hidden {
overflow:hidden;
position:absolute;
width:100%;
}
HTML
<h1>Test</h1>
<p>My table in a div below...</p>
<div id="hidden">
<div class='mytable'>
<table>
<tr class='followMeBar'>
<td colspan="4">12-07-2013</td>
</tr>
<tr>
<td>4:35 PM</td>
<td>1729</td>
<td>2</td>
<td>jack</td>
</tr>
<tr>
<td>4:40 PM</td>
<td>KSKS</td>
<td>4</td>
<td>jason</td>
</tr>
<tr>
<td>5:35 PM</td>
<td>1714</td>
<td>4</td>
<td>raymond</td>
</tr>
etc...
</table>
</div>
</div>
Please note that this method was based off of this answer, I had to adjust things a bit to make it work for a scrollable div, but I want to give credit where credit is due.
Replaced all div
s with a table and tr
s, added some styling, and it works :P
Code: Codepen
Altough it wraps up all header tr
s with a div
. It's not really allowed by the specs but it works.
Instead of making a row absolute position, which btw may not work very well across browsers, I would rather have a table at the top which works as the table head (and sticks to the top of the parent div) and have the data table scroll below it.
You dont even need to use jQuery for this!
http://jsbin./ucevuy/1/edit
* {
margin:0;
padding:0;
}
div {
border:solid red;
height:300px;
overflow:auto;
}
table {
width:400px;
}
td {
border:solid black 1px;
width:50%;
}
.head {
position:absolute;
top:0;
background-color:#fff;
}
.data {
margin-top:20px;
}