Mario
Mario

Reputation: 4988

Is it possible to know when scrolling a div with overflow: scroll reached the end?

I am trying to get new data when reaching the end of the content of a div element with overflow: scroll

I have searched for an example of this but to with no success. I have researched on MDN and found the wheel event, in the event I found the LayerY property

The method I thought might work is as follows. When scrolling down and if the value of the LayerY property is repeated n times, it is at the end of the content, so I make the call to the resource.

For example

let repeat = 0;
let value = 0;

const div = document.querySelector('div');

div.addEventListener('wheel', wheelHandler);

function wheelHandler(event) {
    if (value > 150 && value === event.layerY) {
        repeat += 1;
    }

    if (value > 150 && repeat > 3) {
        console.log('fetch data');
        repeat = 0; // set repeat to 0 after fetch data
    }

    value = event.layerY;
}
* {
  box-sizing: border-box;
}

div {
 width: 500px;
 height: 200px;
 border: 1px solid gray;
 overflow: scroll;
 padding: 10px;
}
<div>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed exercitationem
    doloribus cum, atque quibusdam nemo dolorem, quia omnis, libero consequatur
    molestiae error facilis maxime pariatur delectus aliquam sunt porro vel.
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed exercitationem
    doloribus cum, atque quibusdam nemo dolorem, quia omnis, libero consequatur
    molestiae error facilis maxime pariatur delectus aliquam sunt porro vel.
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed exercitationem
    doloribus cum, atque quibusdam nemo dolorem, quia omnis, libero consequatur
    molestiae error facilis maxime pariatur delectus aliquam sunt porro vel.
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed exercitationem
    doloribus cum, atque quibusdam nemo dolorem, quia omnis, libero consequatur
    molestiae error facilis maxime pariatur delectus aliquam sunt porro vel.
</div>

There are other scenarios, for example handle if you scroll up

Is there a native way to achieve the expected result? either is this path correct

I appreciate your advice and ideas

Upvotes: 0

Views: 247

Answers (1)

Amir Rahman
Amir Rahman

Reputation: 1119

actually i have spent a bit more time and explained it a bit more but if you spent some time reading it will be useful to understand everything

so i have created a little widget that's shows current details and also i have attached a diagram to clear things visually

diagram image

const main = document.querySelector(".items")
const vals = document.querySelectorAll(".vals")
    
main.onscroll = e => {
    let st = main.scrollTop,
        sh = main.scrollHeight,
        ch = main.clientHeight,
        scrollEnded = st + ch >= sh
    vals[0].innerHTML = st
    vals[1].innerHTML = sh
    vals[2].innerHTML = ch
    vals[3].innerHTML = st + ch
    vals[4].innerHTML = scrollEnded ? `<div class="bg-green-500 p-1 px-2 rounded-md text-white">end</div>`:`<div class="bg-red-500 p-1 px-2 rounded-md text-white">not-end</div>`
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet"/>
<div class="root flex justify-start">    
    <!-- main scroll element -->
    <div class="items p-5 border bg-gray-50 w-64 h-36 overflow-y-scroll">
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Iste dolorem doloribus consequatur modi eius necessitatibus. Doloremque, eligendi rerum consequuntur delectus quisquam voluptatum harum, architecto eveniet commodi fugiat aliquid nemo iste?
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Iste dolorem doloribus consequatur modi eius necessitatibus. Doloremque, eligendi rerum consequuntur delectus quisquam voluptatum harum, architecto eveniet commodi fugiat aliquid nemo iste?
    </div>
    
<!-- extra demo thing -->
    <div class="details p-2 text-sm font-normal top-0 w-[400px] bg-gray-100">
        <div class="each-values flex">
            <div class="mr-2">scroll-top</div>
            <div class="vals"></div>
        </div>
        
        <div class="each-values flex">
            <div class="mr-2">scroll-height</div>
            <div class="vals"></div>
        </div>
        <div class="each-values flex">
            <div class="mr-2">client-height</div>
            <div class="vals"></div>
        </div>
        <div class="each-values flex">
            <div class="mr-2">scroll-top + client-height</div>
            <div class="vals"></div>
        </div>
        <div class="each-values flex">
            <div class="mr-2">scroll-top + client-height >= scroll-height</div>
            <div class="vals"></div>
        </div>
    </div>

</div>

here i have made a class function to sum up all the work in one function updated : (when reaching bottom event can be triggered multiple times to avoid this the class function is also tracking last trigger point)

class scroll_bottom {
    constructor(el,obe){
        const obj = this
        this.el = el
        this.lastPoint = 0;
        this.onBottomEvent = obe

        function forScroll(){
            let st = obj.el.scrollTop,
            sh = obj.el.scrollHeight,
            ch = obj.el.clientHeight,
            sp = st + ch,
            scrollEnded = sp >= sh

            if(scrollEnded){
                if(this.lastPoint != sp){obj.onBottomEvent(sp)}
                this.lastPoint = sp
            }
        }
        this.el.onscroll = forScroll
    }
}



// example use 
const main = document.querySelector(".items")
let index = 1
new scroll_bottom(main,function(e){
// #code for scroll bottom here
    main.innerHTML += `Lorem ipsum dolor sit amet consectetur adipisicing elit. Quas qui totam vel, et iste autem unde distinctio iure non. Suscipit autem, officiis dolorem eaque rerum quia facere voluptates repudiandae laudantium!`    
    console.log("changed " + index +" time" + (index > 1 ? "s" : ""))
    index++
})
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet"/>
    <!-- main scroll element -->
    <div class="items mt-5 p-5 border bg-gray-50 w-64 h-36 overflow-y-scroll">
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Iste dolorem doloribus consequatur modi eius necessitatibus. Doloremque, eligendi rerum consequuntur delectus quisquam voluptatum harum, architecto eveniet commodi fugiat aliquid nemo iste?
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Iste dolorem doloribus consequatur modi eius necessitatibus. Doloremque, eligendi rerum consequuntur delectus quisquam voluptatum harum, architecto eveniet commodi fugiat aliquid nemo iste?
    </div>

Upvotes: 2

Related Questions