Add link navigation and following
[hnim.git] / hnim.js
CommitLineData
ffe0b2f4 1(() => {
cf7b74e9 2 const comments = document.querySelectorAll("tr.comtr");
b9913766 3 const items = document.querySelectorAll("table.itemlist tr.athing");
cf7b74e9
JC
4 const morelink = document.querySelectorAll("a.morelink");
5
b9913766
JC
6 const elements = [
7 ...Array.from(items),
8 ...Array.from(comments),
9 ...Array.from(morelink),
10 ];
ffe0b2f4 11
cf7b74e9 12 let elementsIndex = 0;
b9913766
JC
13 let selectedElement = elements[elementsIndex];
14 selectedElement.style.outline = '1px dashed black';
ffe0b2f4
JC
15
16 const visible = (element) => {
17 let bounds = element.getBoundingClientRect();
18 return bounds.top >= 0 && bounds.bottom <= window.innerHeight;
19 }
20
21 const changeWithVisibleCallback = (comment, callback) => {
22 if (comment == null) {
23 return;
24 }
b9913766
JC
25 selectedElement.style.outline = '';
26 selectedElement = comment;
27 selectedElement.style.outline = '1px dashed black';
ffe0b2f4
JC
28 if (!visible(comment)) {
29 callback();
30 }
31 }
32
33 const change = (comment) => {
cf7b74e9 34 elementsIndex = elements.indexOf(comment);
ffe0b2f4
JC
35 changeWithVisibleCallback(comment, () => {});
36 }
37
38 // Curry callback for moving downpage
cf7b74e9
JC
39 const changeDownpage = () => {
40 elementsIndex = Math.min(elementsIndex + 1, elements.length);
b9913766 41 changeWithVisibleCallback(elements[elementsIndex], () => {window.scrollTo(0, window.scrollY + selectedElement.offsetHeight)});
ffe0b2f4
JC
42 }
43
44 // Curry callback for moving up page
cf7b74e9
JC
45 const changeUppage = () => {
46 elementsIndex = Math.max(elementsIndex - 1, 0);
b9913766 47 changeWithVisibleCallback(elements[elementsIndex], () => {window.scrollTo(0, window.scrollY - selectedElement.offsetHeight)});
ffe0b2f4 48 }
ec8ce8db 49
ffe0b2f4
JC
50 document.addEventListener("click", (e) => {
51 change(e.target.closest("tr.athing"));
52 })
53 document.addEventListener("keydown", (e) => {
54 if (e.isComposing) {
ec8ce8db 55 return;
ffe0b2f4 56 }
ec8ce8db
JC
57 switch (e.key) {
58 case "j":
59 do {
cf7b74e9 60 changeDownpage();
b9913766 61 } while (selectedElement.classList.contains("noshow"));
ec8ce8db
JC
62 break;
63 case "k":
64 do {
cf7b74e9 65 changeUppage();
b9913766 66 } while (selectedElement.classList.contains("noshow"));
ec8ce8db
JC
67 break;
68 case "m":
69 case "Enter":
b9913766 70 let togg = selectedElement.querySelector(".togg");
ec8ce8db
JC
71 if (togg) {
72 togg.click();
73 }
cf7b74e9 74 else if (elementsIndex == elements.length - 1) {
b9913766 75 selectedElement.click();
ec8ce8db
JC
76 }
77 break;
b9913766
JC
78 case "o":
79 window.location.href = "https://news.ycombinator.com/item?id=" + selectedElement.id;
ec8ce8db 80 case "p":
b9913766 81 while (selectedElement.querySelector("td.ind").firstElementChild.width != 0) {
cf7b74e9 82 changeUppage();
ec8ce8db
JC
83 }
84 break;
85 default:
86 //noop
ffe0b2f4
JC
87 }
88 })
89})();