sticky.js 2.1 KB
/**
 * Makes element sticky to the top of the window (offset by pixels specified in sticky-offset) when page is scolled to or bellow the element.
 */
export default function () {
    return {
        restrict: 'A',
        link: function ($scope, $elem, $attrs) {
            var offsetTop = $attrs.stickyOffset || 0,
                $window = angular.element(window),
                stickyLine = $elem.offset().top,
                scrollTop,
                state = 'free';

            // Run this on every scroll.
            function onScroll(e) {
                // Get scroll position.
                scrollTop = $window.scrollTop();

                // Check if the window has passed the sticky line.
                if (state == 'free' && scrollTop > stickyLine - offsetTop) {
                    // Scroll bellow browser chrome.
                    if ($(document).height() - $window.height() <= scrollTop) {
                        return;
                    }

                    if (!$elem.next('.sticky-dummy')[0]) {
                        $elem.after($('<div>').addClass('sticky-dummy').height($elem.outerHeight()));
                    }

                    $elem.addClass('sticky');

                    state = 'fixed';
                } else if (state == 'fixed' && scrollTop < stickyLine - offsetTop) {
                    $elem.removeClass('sticky');
                    $elem.next('.sticky-dummy').remove();
                    state = 'free';
                }
            }

            // Attach scroll and resize listeners.
            $window.on('scroll', onScroll);

            // Watch height of the element so that we can adjust dummy height too.
            $scope.$watch(
                function () {
                    return $elem.outerHeight();
                },

                function (newValue, oldValue) {
                    if (newValue != oldValue) {
                        if ($elem.next('.sticky-dummy')[0]) {
                            $elem.next('.sticky-dummy').height($elem.outerHeight());
                        }
                    }
                }
            );
        },
    };
}