brijeshb42 / HackerNews Infinite Scroll

// ==UserScript==
// @name         HackerNews Infinite Scroll
// @namespace    http://openuserjs.org/users/brijeshb42
// @version      0.1.6
// @description  Adds infinite scroll to hackernews front page
// @author       Brijesh Bittu
// @match        https://news.ycombinator.com/
// @match        https://news.ycombinator.com/news
// @match        https://news.ycombinator.com/newest
// @grant        none
// @license      MIT
// ==/UserScript==
(function () {
  'use strict';

  var pageLoading = false;
  var moreLink = document.querySelector('.morelink');
  var observer;

  function loadNextPage() {
    if (pageLoading) {
      return;
    }

    var lastMoreLink = moreLink;
    moreLink = document.querySelector('.morelink');
    pageLoading = true;
    if (!moreLink) {
      return;
    }

    var link = moreLink.href;
    var xhr = new XMLHttpRequest();
    xhr.open('GET', link);
    moreLink.innerHTML = 'Loading page: ' + link.split('p=').pop();

    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
        var tmpNode = document.createElement('div');
        tmpNode.innerHTML = xhr.responseText;
        var tableData = tmpNode.querySelector('.itemlist>tbody');
        var originalTable = document.querySelector('.itemlist>tbody');
        originalTable.removeChild(moreLink.parentElement.parentElement);
        originalTable.innerHTML += tableData.innerHTML;
        pageLoading = false;
        moreLink = document.querySelector('.morelink');
        if (observer) {
          observer.unobserve(lastMoreLink);
          observer.observe(moreLink);
        }
      }
    };

    xhr.send();
  }

  function moveSearch() {
    var form = document.querySelector('form');
    if (!form) {
      return;
    }
    form.parentNode.removeChild(form);
    form.setAttribute('style', 'float:right;margin:0;padding:0;color: #000');
    var pageTop = document.querySelector('.pagetop');
    pageTop.parentNode.appendChild(form);
    form.querySelector('input').focus();
  }

  moveSearch();

  function handleIntersection(entries, observer) {
    entries.forEach(function (entry) {
      if (!entry.isIntersecting) {
        return;
      }
      loadNextPage();
    });
  }

  observer = new IntersectionObserver(handleIntersection, {
    threshold: 1.0
  });
  observer.observe(moreLink);
})();