Greasy Fork is available in English.

Sort Hacker News

Adds a dropdown for sorting Hacker News (Y Combinator) by various criteria

  1. // ==UserScript==
  2. // @name Sort Hacker News
  3. // @description Adds a dropdown for sorting Hacker News (Y Combinator) by various criteria
  4. // @match https://news.ycombinator.com/
  5. // @match https://news.ycombinator.com/news
  6. // @grant none
  7. // @namespace http://foo.at/
  8. // @version 1.0
  9. // ==/UserScript==
  10.  
  11. /*
  12. * Copyright 2015-2016 Stefan Weiss <weiss@foo.at>
  13. * License: Public Domain
  14. * Please let me know if the HN layout changes and this script stops working for you.
  15. */
  16.  
  17. /* jshint esversion: 6 */
  18. (function () {
  19.  
  20. "use strict";
  21.  
  22. const COMM_WEIGHT = 1.0, // how much comments are worth ("auto" mode)
  23. VOTE_WEIGHT = 1.0; // how much votes are worth ("auto" mode)
  24.  
  25. const haufna = [],
  26. things = document.getElementsByClassName("athing"),
  27. initialSort = localStorage.gm__hn_sort || "score";
  28.  
  29. if (things.length != 30) {
  30. console.error("Page doesn't contain the 30 expected items.");
  31. return;
  32. }
  33.  
  34. analyzePage();
  35. insertDropdown();
  36. sortEm(initialSort);
  37.  
  38.  
  39. /// functions //////////////////////////////////////////////////////////////
  40.  
  41. function _qs (sel, base)
  42. {
  43. return (base || document).querySelector(sel);
  44. }
  45.  
  46. function analyzePage ()
  47. {
  48. for (let i = 0; i < things.length; ++i) {
  49. let line0 = things[i],
  50. line1 = line0.nextElementSibling,
  51. idEle = _qs(".age > a", line1),
  52. votesEle = _qs(".score", line1),
  53. commEle = _qs(".subtext > a:last-child", line1),
  54. votes = votesEle && parseInt(votesEle.textContent),
  55. comments = 0,
  56. id = 0;
  57.  
  58. if (idEle && idEle.href) {
  59. id = +(idEle.href.match(/item\?id=(\d+)/) || [])[1] || 0;
  60. }
  61. if (commEle && /\d+ comments?/.test(commEle.textContent)) {
  62. comments = parseInt(commEle.textContent);
  63. }
  64.  
  65. haufna.push({
  66. rank: i + 1,
  67. comments: comments,
  68. votes: votes,
  69. score: votes * VOTE_WEIGHT + comments * COMM_WEIGHT,
  70. id: id,
  71. line0: line0,
  72. line1: line1,
  73. spacer: line1.nextElementSibling,
  74. });
  75. }
  76. }
  77.  
  78. function sortEm (crit)
  79. {
  80. const tbody = things[0].parentNode;
  81. localStorage.gm__hn_sort = crit;
  82. tbody.innerHTML = "";
  83. haufna.sort(getSorter(crit)).forEach(function(item) {
  84. tbody.appendChild(item.line0);
  85. tbody.appendChild(item.line1);
  86. tbody.appendChild(item.spacer);
  87. });
  88. }
  89.  
  90. function getSorter (crit)
  91. {
  92. let inverter = 1;
  93. if (crit == "age-old") {
  94. crit = "id";
  95. } else if (crit == "age-new") {
  96. crit = "id";
  97. inverter = -1;
  98. } else if (crit == "score" || crit == "comments" || crit == "votes") {
  99. inverter = -1;
  100. }
  101. return function (a, b) {
  102. return a[crit] < b[crit] ? -1 * inverter : a[crit] > b[crit] ? 1 * inverter : 0;
  103. };
  104. }
  105.  
  106. function insertDropdown ()
  107. {
  108. const menu = _qs("span.pagetop > a[href=submit]").parentNode,
  109. sel = document.createElement("select");
  110.  
  111. sel.style.WebkitAppearance = "none";
  112. sel.style.MozAppearance = "none";
  113. sel.style.appearance = "none";
  114. sel.style.border = "0";
  115. sel.style.backgroundColor = "inherit";
  116. sel.style.color = "#000";
  117. sel.style.verticalAlign = "baseline";
  118. sel.style.fontSize = "inherit";
  119. sel.style.padding = "0";
  120. sel.style.margin = "0";
  121.  
  122. sel.options[0] = new Option("sort by rank", "rank");
  123. sel.options[1] = new Option("sort by auto", "score");
  124. sel.options[2] = new Option("sort by votes", "votes");
  125. sel.options[3] = new Option("sort by comments", "comments");
  126. sel.options[4] = new Option("sort by newest", "age-new");
  127. sel.options[5] = new Option("sort by oldest", "age-old");
  128. sel.value = initialSort;
  129.  
  130. menu.appendChild(document.createTextNode(" | "));
  131. menu.appendChild(sel);
  132. sel.onchange = function () {
  133. sortEm(sel.value);
  134. };
  135. }
  136.  
  137. })();