Lock selected item while scrolling

I have a requirement when I need to freeze a selected item from the list of items in the container on top when the selected item is at the top of the container. and when the selected item is in the bottom fold of the container, I need to attach it to the bottom.

If the selected item is in the visible fold, nothing should happen. I mean that the selected item should be in a normal flow with other neighboring items.

I somehow managed to somehow solve this. But when I scroll up when the selected item is pasted above the container, the selected item is hidden. This behavior happens even when I scroll down when the selected item is attached to the bottom of the container.

Here is the script

enter image description here

$('.item').click(function () {
    $('.item').removeClass('select').removeClass('pAbsolute');
    $(this).addClass('select');
});

$('.parent').scroll(function () {
    var $selected = $('.item.select');
    var cTop = $selected.offset().top;
    var cHeight = $selected.height();
    var pHeight = $(this).height();
    if (cTop < 0) {
        $selected.css({
            'top': $(this).scrollTop(),
                'bottom': ''
        }).addClass('pAbsolute');
    } else if (cTop > pHeight - cHeight) {
        $selected.css({
            'bottom': -$(this).scrollTop(),
                'top': ''
        }).addClass('pAbsolute');
    } else {
        $selected.css({
            'top': '',
                'bottom': ''
        }).removeClass('pAbsolute');
    }
});
+4
2

, / :

JavaScript:

function stickItems($parent, itemClass, selectClass) {
    // Attach dummy element items
    $parent.prepend('<div class="' + itemClass + ' sticky top"></div>');
    $parent.append('<div class="' + itemClass + ' sticky bottom"></div>');

    var $items = $('.' + itemClass),
        $stickyTop = $('.' + itemClass + '.sticky.top'),
        $stickyBottom = $('.' + itemClass + '.sticky.bottom');

    // Click event registering 
    $items.click(function (e) {
        if (!$(e.target).hasClass('sticky')) {
            $items.removeClass(selectClass);
            $stickyTop.css('display', 'none');
            $stickyBottom.css('display', 'none');
            $(this).addClass(selectClass);
        }
    });



    // Scroll event
    $parent.scroll(function () {
        var $self = $(this);
        var $selected = $('.' + itemClass + '.' + selectClass);
        var cTop = $selected.offset().top;
        var pTop = $self.offset().top;
        var cHeight = $selected.height();
        var pHeight = $self.height();
        if (cTop - pTop <= 0) {
            $stickyTop.html($selected.html()).css({
                'display': 'block',
                    'top': $(this).scrollTop()
            });
            $stickyBottom.css('display', 'none');
        } else if (cTop > pTop && cTop < pTop + pHeight) {
            $stickyTop.css('display', 'none');
            $stickyBottom.css('display', 'none');
        } else {
            $stickyTop.css('display', 'none');
            $stickyBottom.html($selected.html()).css({
                'display': 'block',
                    'bottom': -$(this).scrollTop()
            });
        }
    });
}

stickItems($('.parent'), 'item', 'select');

Css:

body, html {
    padding: 0;
    margin: 0;
}
body {
    padding-top: 200px;
}
.parent {
    overflow-x: hidden;
    overflow-y: auto;
    height: 200px;
    position: relative;
}
.item {
    padding: 10px 15px;
    background-color: tomato;
}
.item.select {
    background-color: beige;
}
.item.sticky {
    background-color: beige;
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    z-index: 1;
}

Html:

<div class="parent">
    <div class="item sticky top"></div>
    <div class="item select">1</div>
    <div class="item">2</div>
    <!-- ... -->
    <div class="item">39</div>
    <div class="item">40</div>
    <div class="item">41</div>
    <div class="item sticky bottom"></div>
</div>
+1

, .

,

  • cTop < 0, , .

  • cTop + cHeight > pHeight, , , .

  • .

:

, .pAbsolute attr, , / .

, scrollTop .

var offset;
$('.item').click(function () {
    // This is the offset in container before class change.
    offset = this.offsetTop;
    $('.item').removeClass('select').removeClass('pAbsolute');
    $(this).addClass('select');
    // Calculate the difference
    var distortion = offset - this.offsetTop;
    
    // Remove the distortion by manual scroll.
    var $parent = $(this).parent();
    $parent.scrollTop($parent.scrollTop() - distortion);
    
    offset = this.offsetTop;
});


$('.parent').scroll(function () {
    var $selected = $('.item.select');
    var cTop = offset - $(this).scrollTop();
    var cHeight = $selected.height();
    var pHeight = $(this).height();
    if (cTop < 0) {
        $selected.css({
            'top': $(this).scrollTop(),
                'bottom': ''
        }).addClass('pAbsolute');
    } else if (cTop + cHeight > pHeight) {
        $selected.css({
            'bottom': -$(this).scrollTop(),
                'top': ''
        }).addClass('pAbsolute');
    } else {
        $selected.css({
            'top': '',
                'bottom': ''
        }).removeClass('pAbsolute');
    }
});
body, html {
    padding: 0;
    margin: 0;
}
.parent {
    overflow: auto;
    height: 200px;
    position: relative;
}
.item {
    padding: 10px 15px;
    background-color: tomato;
    width: 100%;
}
.item.select {
    background-color: beige;
}
.pAbsolute {
    position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
    <div class="item select">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>
    <div class="item">10</div>
    <div class="item">11</div>
    <div class="item">12</div>
    <div class="item">13</div>
    <div class="item">14</div>
    <div class="item">15</div>
    <div class="item">16</div>
    <div class="item">17</div>
    <div class="item">18</div>
    <div class="item">19</div>
    <div class="item">20</div>
    <div class="item">21</div>
    <div class="item">22</div>
    <div class="item">23</div>
    <div class="item">24</div>
    <div class="item">25</div>
    <div class="item">26</div>
    <div class="item">27</div>
    <div class="item">28</div>
    <div class="item">29</div>
    <div class="item">30</div>
    <div class="item">31</div>
    <div class="item">32</div>
    <div class="item">33</div>
    <div class="item">34</div>
    <div class="item">35</div>
    <div class="item">36</div>
    <div class="item">37</div>
    <div class="item">38</div>
    <div class="item">39</div>
    <div class="item">40</div>
    <div class="item">41</div>
</div>
Hide result
+2

Source: https://habr.com/ru/post/1598172/


All Articles