Free-Scrolling Sticky Sidebar Без jQuery

Я пытаюсь достичь того, что описано в этом вопросе, без зависимости от jQuery: qaru.site/info/108631/...

Но я не хотел уволить этот вопрос.

В принципе, я хочу, чтобы содержимое на боковой панели было независимо прокручиваемо, но фиксировано, когда область просмотра достигает любого конца содержимого боковых панелей в прокрутке.

Мой главный камнем преткновения кажется, что он не может вычислить переменную elementTop, когда боковая панель абсолютно расположена, и между верхней и нижней частью контейнера, которые я установил для полной высоты.

Полный код ниже:

var StickySidebar = function(eventie) {

var container, containerTop, containerHeight,  // container
element, elementTop, elementHeight, elStyle,  // element
viewportTop = -1, viewportHeight, documentTop, // viewport
lastViewportTop, scrollingDown, top = false , bottom = false,// sticky vars

scroll = window.requestAnimationFrame ||
         window.webkitRequestAnimationFrame ||
         window.mozRequestAnimationFrame ||
         window.msRequestAnimationFrame ||
         window.oRequestAnimationFrame ||
         function(callback){ window.setTimeout(callback, 1000/60); },

options =  {
    container : document.querySelector('.sidebar-container'),
    element : document.querySelector('.sidebar'),
    sidebarClass : 'sidebar',
    bottomOffset : -15,
    topOffset: 90,
},

_updateValue = function() {
    viewportHeight = window.innerHeight;
},

_offset = function(obj) {    
    var ol = ot = 0;
    if (obj.offsetParent) {
        do {
            ol += obj.offsetLeft;
            ot += obj.offsetTop;
        } while (obj = obj.offsetParent);
    }
    return {
        left: ol,
        top: ot
    };
},


init = function(){
    if(options.element !== null) {

        container = options.container;
        containerTop = offset(container).top;
        containerHeight = container.clientHeight;

        element = options.element;
        elementTop = offset(element).top;
        elementHeight = options.element.clientHeight;

        lastViewportTop = window.scrollY;
        viewportHeight = window.innerHeight;

        eventie.bind(document, "scroll", _loop);
        eventie.bind(window, "resize", _updateValue);

    }
},

_loop = function() {
    if (viewportTop == window.pageYOffset) {
        scroll(_loop);
        return false;
    } else viewportTop = window.pageYOffset;

    _updateValue();

    var viewportBottom, elementTooBig, topOffset;

    elementTop = offset(element).top;

    elementHeight = element.clientHeight;
    containerHeight = container.clientHeight;
    scrollingDown = viewportTop > lastViewportTop;
    elementTooBig = elementHeight > viewportHeight;

    console.log("elementTop : " + elementTop);
    console.log("viewportTop : " + viewportTop);

    if (scrollingDown) {

        if (viewportTop + viewportHeight >= elementTop + elementHeight) {
            element.setAttribute('style','position:fixed; bottom:30px;');
        } else {
            element.setAttribute('style','position:absolute; top:'+ elementTop +'px;'); // issue 1
    }

    if (viewportTop + viewportHeight > containerTop + containerHeight) {
        element.setAttribute('style','position:absolute; bottom:0;');
    }

} else {

    if (viewportTop < containerTop - 60) {
        element.removeAttribute('style');
        return;
    }

    if (viewportTop <= elementTop) {
        element.setAttribute('style','position:fixed; top:90px;');
    } else {
        element.setAttribute('style','position:absolute; top:'+ elementTop +'px;');
        elementTop = viewportTop + elementTop;
    }

}

lastViewportTop = viewportTop;

};


return {
    init: init
};

}(eventie);

Я пытался решить эту проблему в течение нескольких недель, и это сбило меня с ума. Любая помощь будет принята с благодарностью.

Ответы

Ответ 1

Если вы просто пытаетесь достичь желаемого результата, не обязательно создавая это самостоятельно - ну, есть много библиотек JavaScript, которые предоставляют это.

Например, Stickyfill на самом деле является polyfill для position: sticky, который поддерживается только в Firefox 41+ и Safari 8+. Вот демо со всеми видами липкости, которые вы можете себе представить:)

P.S. На первый взгляд вы можете заметить что-то о jQuery, но это чистый JavaScript и просто добавляет расширение jQuery.