Created
February 26, 2025 15:13
-
-
Save AsafGartner/38867fc1440bb78332e4b99e575a998c to your computer and use it in GitHub Desktop.
Hackernews helper - bookmarklet that lists comments by date and greys out comments that you've replied to
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| javascript: (() => { let commentEls = document.querySelectorAll(".comment-tree tr[id]"); let comments = []; let commentMap = {}; let myUsername = ""; myUsername = localStorage.getItem("__my_username") || ""; for (let i = 0; i < commentEls.length; ++i) { let el = commentEls[i]; let navs = el.querySelectorAll(".navs a"); let parent = null; if (navs[0].textContent == "parent") { parent = navs[0].getAttribute("href").slice(1); } if (navs[1].textContent == "parent") { parent = navs[1].getAttribute("href").slice(1); } let comment = { el: el, id: el.id, timestamp: parseInt(el.querySelector(".age").title.split(" ")[1], 10), age: el.querySelector(".age a").textContent, parent: parent, answered: false, answeredChild: false, author: el.querySelector(".hnuser").textContent, }; comments.push(comment); commentMap[comment.id] = comment; } comments.sort(function(a, b) { return b.timestamp - a.timestamp; }); function updateAnswered() { function markGrandparents(c) { if (c.parent) { c = commentMap[c.parent]; c.answeredChild = true; markGrandparents(c); } } for (let i = 0; i < comments.length; ++i) { let comment = comments[i]; comment.answered = false; comment.answeredChild = false; } for (let i = 0; i < comments.length; ++i) { let comment = comments[i]; if (comment.author == myUsername) { comment.answered = true; if (comment.parent) { let parent = commentMap[comment.parent]; parent.answered = true; markGrandparents(parent); } } } } let container = null; let list = null; let usernameInput = null; function usernameUpdated() { let val = usernameInput.value; myUsername = val; localStorage.setItem("__my_username", myUsername); updateAnswered(); render(); } function click(ev) { let id = ev.target.getAttribute("data-id"); let comment = commentMap[id]; comment.el.scrollIntoView({ behavior: "smooth", block: "center" }); for (let i = 0; i < comments.length; ++i) { comments[i].el.classList.remove("__active"); } comment.el.classList.add("__active"); ev.preventDefault(); return false; } function render() { if (!container) { container = document.createElement("DIV"); container.style.boxSizing = "border-box"; container.style.position = "fixed"; container.style.right = "0px"; container.style.top = "0px"; container.style.height = "100vh"; container.style.width = "15vw"; container.style.background = "black"; container.style.padding = "8px"; container.style.overflowY = "scroll"; container.style.borderLeft = "2px solid skyblue"; usernameInput = document.createElement("INPUT"); usernameInput.style.width = "100%"; usernameInput.value = myUsername; usernameInput.addEventListener("input", usernameUpdated); container.appendChild(usernameInput); list = document.createElement("DIV"); container.appendChild(list); document.body.appendChild(container); document.querySelector(".comment-tree").style.marginRight = "15vw"; let style = document.createElement("STYLE"); style.textContent = ` .comment-tree tr[id] { transition: background 0.5s linear; } .__active { background: burlywood; } `; document.head.appendChild(style); } list.innerHTML = ""; for (let i = 0; i < comments.length; ++i) { let comment = comments[i]; let el = document.createElement("A"); el.href = "#" + comment.id; el.textContent = comment.age + " | " + comment.author; el.style.color = (comment.answered ? "grey" : (comment.answeredChild ? "purple" : "skyblue")); el.style.display = "block"; el.style.padding = "4px"; el.setAttribute("data-id", comment.id); el.addEventListener("click", click); list.appendChild(el); } } updateAnswered(); render(); })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| let commentEls = document.querySelectorAll(".comment-tree tr[id]"); | |
| let comments = []; | |
| let commentMap = {}; | |
| let myUsername = ""; | |
| myUsername = localStorage.getItem("__my_username") || ""; | |
| for (let i = 0; i < commentEls.length; ++i) { | |
| let el = commentEls[i]; | |
| let navs = el.querySelectorAll(".navs a"); | |
| let parent = null; | |
| if (navs[0].textContent == "parent") { | |
| parent = navs[0].getAttribute("href").slice(1); | |
| } | |
| if (navs[1].textContent == "parent") { | |
| parent = navs[1].getAttribute("href").slice(1); | |
| } | |
| let comment = { | |
| el: el, | |
| id: el.id, | |
| timestamp: parseInt(el.querySelector(".age").title.split(" ")[1], 10), | |
| age: el.querySelector(".age a").textContent, | |
| parent: parent, | |
| answered: false, | |
| answeredChild: false, | |
| author: el.querySelector(".hnuser").textContent, | |
| }; | |
| comments.push(comment); | |
| commentMap[comment.id] = comment; | |
| } | |
| comments.sort(function(a, b) { | |
| return b.timestamp - a.timestamp; | |
| }); | |
| function updateAnswered() { | |
| function markGrandparents(c) { | |
| if (c.parent) { | |
| c = commentMap[c.parent]; | |
| c.answeredChild = true; | |
| markGrandparents(c); | |
| } | |
| } | |
| for (let i = 0; i < comments.length; ++i) { | |
| let comment = comments[i]; | |
| comment.answered = false; | |
| comment.answeredChild = false; | |
| } | |
| for (let i = 0; i < comments.length; ++i) { | |
| let comment = comments[i]; | |
| if (comment.author == myUsername) { | |
| comment.answered = true; | |
| if (comment.parent) { | |
| let parent = commentMap[comment.parent]; | |
| parent.answered = true; | |
| markGrandparents(parent); | |
| } | |
| } | |
| } | |
| } | |
| let container = null; | |
| let list = null; | |
| let usernameInput = null; | |
| function usernameUpdated() { | |
| let val = usernameInput.value; | |
| myUsername = val; | |
| localStorage.setItem("__my_username", myUsername); | |
| updateAnswered(); | |
| render(); | |
| } | |
| function click(ev) { | |
| let id = ev.target.getAttribute("data-id"); | |
| let comment = commentMap[id]; | |
| comment.el.scrollIntoView({ behavior: "smooth", block: "center" }); | |
| for (let i = 0; i < comments.length; ++i) { | |
| comments[i].el.classList.remove("__active"); | |
| } | |
| comment.el.classList.add("__active"); | |
| ev.preventDefault(); | |
| return false; | |
| } | |
| function render() { | |
| if (!container) { | |
| container = document.createElement("DIV"); | |
| container.style.boxSizing = "border-box"; | |
| container.style.position = "fixed"; | |
| container.style.right = "0px"; | |
| container.style.top = "0px"; | |
| container.style.height = "100vh"; | |
| container.style.width = "15vw"; | |
| container.style.background = "black"; | |
| container.style.padding = "8px"; | |
| container.style.overflowY = "scroll"; | |
| container.style.borderLeft = "2px solid skyblue"; | |
| usernameInput = document.createElement("INPUT"); | |
| usernameInput.style.width = "100%"; | |
| usernameInput.value = myUsername; | |
| usernameInput.addEventListener("input", usernameUpdated); | |
| container.appendChild(usernameInput); | |
| list = document.createElement("DIV"); | |
| container.appendChild(list); | |
| document.body.appendChild(container); | |
| document.querySelector(".comment-tree").style.marginRight = "15vw"; | |
| let style = document.createElement("STYLE"); | |
| style.textContent = ` | |
| .comment-tree tr[id] { | |
| transition: background 0.5s linear; | |
| } | |
| .__active { | |
| background: burlywood; | |
| } | |
| `; | |
| document.head.appendChild(style); | |
| } | |
| list.innerHTML = ""; | |
| for (let i = 0; i < comments.length; ++i) { | |
| let comment = comments[i]; | |
| let el = document.createElement("A"); | |
| el.href = "#" + comment.id; | |
| el.textContent = comment.age + " | " + comment.author; | |
| el.style.color = (comment.answered ? "grey" : (comment.answeredChild ? "purple" : "skyblue")); | |
| el.style.display = "block"; | |
| el.style.padding = "4px"; | |
| el.setAttribute("data-id", comment.id); | |
| el.addEventListener("click", click); | |
| list.appendChild(el); | |
| } | |
| } | |
| updateAnswered(); | |
| render(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment