Skip to content

Instantly share code, notes, and snippets.

@joelstein
Last active August 29, 2015 13:57
Show Gist options
  • Save joelstein/9370369 to your computer and use it in GitHub Desktop.
Save joelstein/9370369 to your computer and use it in GitHub Desktop.
Angular sticky list (requires jQuery)
// Sticky list directive.
angular.module('stickylist', []).directive('stickyList', function() {
// Stick header by setting the position to fixed, top to 0, and adding a
// "sticky" class so additional CSS can be applied. Padding is added to
// parent <li>.
var stick = function($header) {
$header.css({position: 'fixed', top: 0}).addClass('sticky');
$header.parent().css('paddingTop', $header.outerHeight());
}
// Unstick by resetting what was done above, plus clearing out original top.
var unstick = function($header) {
$header.css({position: '', top: ''}).removeClass('sticky').data('stickyOriginalTop', '');
$header.parent().css('paddingTop', '');
}
return {
link: function(scope, element, attrs) {
// Store list element.
var $list = $(element);
// When window scrolls.
$(window).scroll(function() {
// Unstick unselected headers which are are still sticky.
unstick($('li > a.sticky:not(.selected)'));
// Skip if no header is selected.
var $header = $('li > a.selected', $list);
if ($header.length == 0) {
return;
}
// Store original header top.
if (!$header.data('stickyOriginalTop')) {
$header.data('stickyOriginalTop', $header.offset().top);
}
// Get positions.
var scrollTop = $(this).scrollTop();
var headerTop = $header.data('stickyOriginalTop');
var bodyBottom = $header.next().offset().top + $header.next().outerHeight() - $header.outerHeight();
// Stick/unstick header.
if (scrollTop > headerTop && scrollTop < bodyBottom) {
if (!$header.hasClass('sticky')) {
stick($header);
}
}
else {
if ($header.hasClass('sticky')) {
unstick($header);
}
}
});
}
}
});
<ul sticky-list>
<li ng-repeat="row in rows">
<a class="{selected: row.selected}" ng-click="row.selected = !row.selected">
Some title stuff here.
</a>
<div ng-show="row.selected">
Long body text here.
</div>
</li>
</ul>
/* You'll probably want to style the "stuck" header */
[sticky-list] .sticky {
background: #fff;
z-index: 100;
width: 100%;
}
@eadolf
Copy link

eadolf commented Feb 9, 2015

When trying to use this, and adding an array through a controller, I'm not getting any sticky headers. Can you post a quick Plunker as a demo?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment