4

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>.

000
  • 26,951
  • 10
  • 71
  • 101
chongzixin
  • 1,951
  • 4
  • 28
  • 55
  • Any html - css - javascript code to provide ? Also, your codepen example is NOT about table. Those are dividers. div's. Anyway, go take a look at : http://imakewebthings.com/jquery-waypoints/shortcuts/sticky-elements/ – Milche Patern Jul 08 '13 at 17:18
  • You can also take a look at : http://stackoverflow.com/questions/9590087/using-jquery-sticky-elements?rq=1 – Milche Patern Jul 08 '13 at 17:24
  • Yeah I realised my tags (div and table and tr and td) didnt show initially until I enclosed them in code tags. – chongzixin Jul 09 '13 at 02:37
  • @user1258600 Your issue is a Client Side issue, so you have to supply your PHP's HTML output in your code example. Modify this jsfiddle example and http://jsfiddle.net/dCKmL/ – SaidbakR Jul 10 '13 at 22:48
  • @sємsєм my code is now on CodePen @ http://codepen.io/anon/pen/zxpkr ! :) – chongzixin Jul 11 '13 at 13:57
  • is this what you're after? - http://jsfiddle.net/apaul34208/s5wZJ/7/ – apaul Jul 14 '13 at 17:56
  • @apaul34208 thanks for the help. we are getting closer with your jsfiddle but this doesnt have the pushing up effect (like in instagram) as one header pushes away the other. – chongzixin Jul 16 '13 at 05:01

3 Answers3

2

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.

Community
  • 1
  • 1
apaul
  • 16,092
  • 8
  • 47
  • 82
  • this seems like what I need! one tiny part though, the column header seems to extend itself only when it is scrolled down which is not intended. Is there a way to have the header kept at the same width throughout? Once again, I really appreciate your help. :) – chongzixin Jul 18 '13 at 15:43
  • yes that looks awesome! thank you so much! It seems like my bounty has expired apparently, is there a way I can still award it to you? – chongzixin Jul 19 '13 at 04:42
  • Not really, once a bounty expires its gone. Don't sweat it the points don't matter – apaul Jul 19 '13 at 13:34
  • This adds a div around a tr and therefore isn't valid HTML. It causes lots of issues. :( – GazB Jun 07 '17 at 11:25
1

Replaced all divs with a table and trs, added some styling, and it works :P

Code: Codepen

Altough it wraps up all header trs with a div. It's not really allowed by the specs but it works.

assembly_wizard
  • 2,034
  • 1
  • 17
  • 10
  • Hi thanks for the answer. I tried to edit it more to my purpose but my colspan doesnt seem to be working. Is there something I am missing? http://codepen.io/anon/pen/olhbI – chongzixin Jul 11 '13 at 08:22
  • I have modified the CodePen (now at http://codepen.io/anon/pen/zxpkr) such that it resembles exactly what I am trying to achieve now. It didnt seem to work as smoothly for me like it did for you. :( – chongzixin Jul 11 '13 at 13:58
  • Altough I did not quite understand the difference between your two codepens, I understood you want the same thing but with colspan="3". The problem is that I am not near a computer and codepen does not play well with my iPhone browser. If you could move the code to JSfiddle or JSbin I might be able to help. Also, if the colspan fails, will it be ok if I do it with div's instead but make it look like a table? – assembly_wizard Jul 11 '13 at 14:53
  • Hello! Thank you so much for your help so far! In the second code, the table is put inside a `div` with a fixed height and `overflow-y:scroll`. `table` is most ideal for me but I guess out of desperation `div` will work too as long as it is easy for me to add more columns later when I need to. jsFiddle code is here: http://jsfiddle.net/p9Dgh/ – chongzixin Jul 12 '13 at 14:17
1

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.com/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;
}
user1721135
  • 6,864
  • 8
  • 34
  • 63
  • hi. but i have multiple "headers" for each date and I am trying to achieve that scrolling effect of one "header" popping off the other. this doesnt achieve it, does it? – chongzixin Jul 16 '13 at 04:59
  • i didnt notice that. in that case you should work with jquery and change css based on scrolling position. – user1721135 Jul 16 '13 at 06:40
  • hmmm is that not what my current unsuccessful code is attempting to do now? or are there alternatives to achieve what you mentioned. :) – chongzixin Jul 16 '13 at 20:39