2021-10-20 Infinite Scroll Part 4

by Ttt Yyy

HTML

<div id='container'>
<!--   <div class="list-item">
    <img class="list-item__image" src="https://" />
    <span class="list-item__label">Label</span>
  </div> -->
</div>

CSS

#container {
  /* position: relative; */
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: auto;
}

.list-item {
  align-items: center;
  display: flex;
  position: absolute;
}

.list-item__image {
  height: 50px;
  width: 50px;
}

.list-item__label {
  margin-left: 12px;
}

JavaScript

let container = document.getElementById("container");
let currentTopPosition = 0;
const ROW_HEIGHT = 50;
const reapedNodes = [];
let currentIndex = 0;
function createRow(url, label) {
  let row;
  if (reapedNodes.length > 0) {
    row = reapedNodes.shift();
  } else {
    row = document.createElement("div");
    row.className = "list-item";
    row.innerHTML = `<img src=${url} class='list-item__image'>
    <span class="list-item__label">${label}</span>`;
    // given container now has position: relative, row has position: absolute
  }
  row.style.top = `${currentTopPosition}px`;
  currentTopPosition += ROW_HEIGHT;
  return row;
}

// assuming rows looks like: [{url: 'https://' label: 'Test Label'}]
const addRowsBulk = (rows, amount) => {
  const fragment = document.createDocumentFragment();
  for (let i = currentIndex; i < amount; i++) {
    const { url, label } = rows[i];
    const row = createRow(url, label);
    fragment.appendChild(row);
    currentIndex++;
  }
  container.appendChild(fragment);
};

function removeUnseenToReaped() {
  for (let i = 0; i < container.children.length; i++) {
    const row = container.children[i];
    const topPosition = parseInt(row.style.top);

    // if already passed row
    if (container.scrollTop >= topPosition + ROW_HEIGHT) {
      reapedNodes.push(row);
      let newRow = rows[currentIndex++];
      createRow(newRow.url, newRow.label);
    }
  }
}

container.addEventListener("scroll", function () {
  if (container.scrollHeight - container.scrollTop === container.clientHeight) {
    removeUnseenToReaped();
  }
});

const rows = [
  {
    url: "https://img.pokemondb.net/sprites/omega-ruby-alpha-sapphire/dex/normal/zapdos.png",
    label: "Zapdos",
  },
  {
    url: "https://img.pokemondb.net/sprites/omega-ruby-alpha-sapphire/dex/normal/moltres.png",
    label: "Moltres",
  },
  {
    url: "https://img.pokemondb.net/sprites/omega-ruby-alpha-sapphire/dex/normal/articuno.png",
    label: "Articuno",
  },
  {
    url:...