Hackernews Scroll to Next/Previous Top-Level Comment

Adds a button and keyboard shortcuts (down and up arrows) that scroll to quickly and smoothly navigate to the next/previous top-level comment. This scroller saves time by allowing you to skip comment threads you're not interested in. An alternative to collapsing the thread.

  1. // ==UserScript==
  2. // @name Hackernews Scroll to Next/Previous Top-Level Comment
  3. // @namespace https://news.ycombinator.com/
  4. // @version 0.2
  5. // @description Adds a button and keyboard shortcuts (down and up arrows) that scroll to quickly and smoothly navigate to the next/previous top-level comment. This scroller saves time by allowing you to skip comment threads you're not interested in. An alternative to collapsing the thread.
  6. // @author Jonathan Woolf
  7. // @match https://news.ycombinator.com/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. 'use strict';
  13. const button = document.createElement('button');
  14. button.textContent = '⬇️';
  15. button.style.cssText = `
  16. position: fixed;
  17. bottom: 10px;
  18. left: 10px;
  19. z-index: 999;
  20. background-color: rgb(255, 198, 156);
  21. color: #fff;
  22. border: 6px solid rgb(255, 102, 0);
  23. background-color: rgb(255, 198, 156);
  24. border-radius: 50%;
  25. width: 40px;
  26. height: 40px;
  27. font-size: 24px;
  28. text-align: center;
  29. line-height: 40px;
  30. cursor: pointer;
  31. display: flex;
  32. justify-content: center;
  33. align-items: center;
  34. font-size: 91%;
  35. `;
  36. document.body.appendChild(button);
  37.  
  38. const comments = [...document.querySelectorAll('td.ind[indent="0"]')];
  39. let currentCommentIndex = 0;
  40.  
  41. button.addEventListener('click', scrollToNextComment);
  42. document.addEventListener("keydown", handleKeyPress);
  43.  
  44. function handleKeyPress(event) {
  45. if (event.code === "ArrowDown") {
  46. event.preventDefault();
  47. scrollToNextComment();
  48. } else if (event.code === "ArrowUp") {
  49. event.preventDefault();
  50. scrollToPreviousComment();
  51. }
  52. }
  53.  
  54. function scrollToNextComment() {
  55. if (currentCommentIndex === comments.length - 1) {
  56. currentCommentIndex = 0;
  57. } else {
  58. currentCommentIndex++;
  59. }
  60. comments[currentCommentIndex].closest('tr').scrollIntoView({ behavior: 'smooth', block: 'start' });
  61. }
  62.  
  63. function scrollToPreviousComment() {
  64. if (currentCommentIndex === 0) {
  65. currentCommentIndex = comments.length - 1;
  66. } else {
  67. currentCommentIndex--;
  68. }
  69. comments[currentCommentIndex].closest('tr').scrollIntoView({ behavior: 'smooth', block: 'start' });
  70. }
  71. })();