17

I want to avoid using jQuery or another library for the sake of keeping my code minimal, I need very little in the way of features, I just want to append to a list when the user scrolls to the bottom. How would I do this in plain Javascript?

Wladimir Palant
  • 53,866
  • 11
  • 93
  • 123
Abhinav Sharma
  • 1,075
  • 4
  • 11
  • 12
  • 6
    Keeping your code minimal and avoiding a library such as jQuery seem like goals that are at odds with one another, to be perfectly honest. So why the desire not to use one? – Anthony Grist Jun 23 '11 at 15:50
  • 4
    If you're worried about using a huge framework like jQuery to achieve this simple effect consider using a micro framework you can find a good list at microjs.com. Achieving pure js infinite scroll that is also cross platform compatible is going to be quite difficult. – JaredMcAteer Jun 23 '11 at 15:56
  • 1
    @Anthony Grist: jQuery is not always good choice: if you are good at javascript, you are able to write better code in particular situation; if you are NOT good at it, you write worse code with some framework than without it. In conclusion, jQuery is good only for closed solutions like lightbox or in case you do not have time/money for thinking out. I think this one is not the case. – Jan Turoň Jun 23 '11 at 16:02
  • Are you lookin something like this: http://jsfiddle.net/rathoreahsan/LAR7w/ – Ahsan Rathod Jun 23 '11 at 16:08
  • I want to avoid a library because this is not a website - its a Firefox addon that creates a page, I want to avoid it because I've managed to do a lot so far. To add specificity to the problem, you can assume this is Firefox 4+ we're talking about – Abhinav Sharma Jun 23 '11 at 16:15
  • 2
    @Anthony: In this case he means to minimize the total amount of code, not the amount of code he has to write. – Gabe Jun 23 '11 at 16:43

6 Answers6

14

Basicaly you just need to hook the event scroll, check if the user scrolled down enough and add some content if so:

<html><body>
<div id="test">scroll to understand</div>
<div id="wrapper" style="height: 400px; overflow: auto;">
  <div id="content"> </div>
</div>

<script language="JavaScript">
  // we will add this content, replace for anything you want to add
  var more = '<div style="height: 1000px; background: #EEE;"></div>';

  var wrapper = document.getElementById("wrapper");
  var content = document.getElementById("content");
  var test = document.getElementById("test");
  content.innerHTML = more;

  // cross browser addEvent, today you can safely use just addEventListener
  function addEvent(obj,ev,fn) {
    if(obj.addEventListener) obj.addEventListener(ev,fn,false);
    else if(obj.attachEvent) obj.attachEvent("on"+ev,fn);    
  }

  // this is the scroll event handler
  function scroller() {
    // print relevant scroll info
    test.innerHTML = wrapper.scrollTop+"+"+wrapper.offsetHeight+"+100>"+content.offsetHeight;

    // add more contents if user scrolled down enough
    if(wrapper.scrollTop+wrapper.offsetHeight+100>content.offsetHeight) {
      content.innerHTML+= more;
    }
  }

  // hook the scroll handler to scroll event
  addEvent(wrapper,"scroll",scroller);
</script>
</body></html>
Jan Turoň
  • 26,696
  • 21
  • 102
  • 153
  • Thanks, I'll try it out, something else I noticed that seems to work (at least at prelim testing) is testing comparing window.scrollY against window.scrollMaxY, I don't know about its cross-browser compatibility though. – Abhinav Sharma Jun 23 '11 at 17:02
  • 1
    window.scrollMaxY is not cross-browser. On [quirksmode](http://www.quirksmode.org/dom/w3c_cssom.html) there is some compatibility research. – Jan Turoň Jun 23 '11 at 17:50
4

Excellent demo code for infinite scroll. Goes to show that you don't need jQuery and Angular for any browser independent work. But new boys today are out of touch with pure Javascript that we old guys still trust and use. Here I have simplified the code further:

// we will add this content, replace for anything you want to add
var wrapper, content, test;
var more = '<div style="height:1000px; background:#EEE;"></div>';

// this is the scroll event handler
function scroller() {
  // print relevant scroll info
  test.innerHTML = wrapper.scrollTop + " + " + wrapper.offsetHeight + " + 100 > " + content.offsetHeight;

  // add more contents if user scrolled down enough
  if (wrapper.scrollTop + wrapper.offsetHeight + 100 > content.offsetHeight) {
    content.innerHTML += more; // NK: Here you can make an Ajax call and fetch content to append to content.innerHTML
  }
}

wrapper = document.getElementById("wrapper");
content = document.getElementById("content");
test = document.getElementById("test");

content.innerHTML = more;

// hook the scroll handler to scroll event
if (wrapper.addEventListener) // NK: Works on all new browsers
  wrapper.addEventListener("scroll", scroller, false);

else if (wrapper.attachEvent) // NK: Works on old IE
  wrapper.attachEvent("onscroll", scroller);
<div id="test">scroll to understand</div>

<div id="wrapper" style="height: 400px; overflow: auto;">
  <div id="content"> </div>
</div>
Lee Taylor
  • 6,091
  • 14
  • 26
  • 43
Nairit
  • 49
  • 1
2

For achieving this behaviour you don't need jQuery or a jQuery plugin. You can use only CSS or JavaScript (if you want to cover all browsers).

But don't use onScroll: you can do all of this with just vanilla JS and the Intersection Observer API.

All you need to do is place elements and listen for when they become available in the screen. The Intersection Observer API is very customisable to fit all your needs.

In summary: you accomplish that with a few JavaScript & HTML lines and it's much more performant than listening for scroll events in the browser.

ggorlen
  • 26,337
  • 5
  • 34
  • 50
Jose Greinch
  • 275
  • 1
  • 12
0

I see great answers to your question, but for a scrolling that is not associated with any HTML element or content (just an empty HTML page), here is how I did it:

document.querySelector("body").style.height = "1000px";

window.addEventListener("scroll", function() {
    var body = document.querySelector("body");
    var height = body.style.height;
    height = height.slice(0, -2);
    height = Number(height);
    return function() {
        if(height - window.scrollY < 700) {
            height += height / 2;
        }
        body.style.height = height + "px";
    };
}());
<!DOCTYPE html>
<html>
<head>

</head>
<body>

</body>
</html>

I hope this helps someone out there :)

Fouad Boukredine
  • 1,037
  • 11
  • 14
0
domElem.addEventListener(
        'scroll',
        function(evt) { ... },
        false
    ); 

and handle evt/scroll position appropriately.

c-smile
  • 24,546
  • 7
  • 54
  • 79
-1

Sample snippet with cross browser support: Read inline comments for how it works

window.onscroll = function(ev) {
    if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
       //User is currently at the bottom of the page
        addNewItem();
    }
};


function addNewItem(){
   var itemCount = document.getElementById("movieList").childElementCount;
const itemLimit = 10; //total number of items to retrieve
//retrieve the next list of items from wherever
var nextTopItems = getNextItemSimulator(itemCount); 
nextTopItems.forEach(function(item) {
//add the items to your view
  document.getElementById("movieList").innerHTML += "<p>"+item+"</p>"; 
     document.getElementById("footer").style.display = "block";
});
setTimeout(function(){
     //remove footer info message
     document.getElementById("footer").style.display = "none";}, 500);
}

function getNextItemSimulator(currentItem){ 
   //Just some dummy data to simulate an api response
const dummyItemCount = 50;
var dummyItems = []; 
var nextTopDummyItems = [];
for(i = 1; i <= dummyItemCount; i++){
//add to main dummy list
    dummyItems.push("Movie " + i);
}
var countTen = 10;
var nextItem = currentItem + 1;
for(i = nextItem; i <= dummyItems.length; i++){
    //get next 10 records from dummy list
    nextTopDummyItems.push(dummyItems[i - 1]);
    countTen--;
    if(countTen == 0)break;
}
   return nextTopDummyItems;
}
#footer {
    position: fixed;
    bottom: 0;
    width: 100%;
    display:none;
    background: #eee;
}

#movieList{
margin-bottom: 20px;
}
<h3> Movies 2019 </h3>

<div id="movieList">
<p>Movie 1</p>
<p>Movie 2</p>
<p>Movie 3</p>
<p>Movie 4</p>
<p>Movie 5</p>
<p>Movie 6</p>
<p>Movie 7</p>
<p>Movie 8</p>
<p>Movie 9</p>
<p>Movie 10</p>
</div>
<div id="footer">Loading more movies</div>
Giddy Naya
  • 2,202
  • 10
  • 23