Last active
April 18, 2022 08:02
-
-
Save v3rm0n/f96d98fdf4d24aca86ea10700808553d to your computer and use it in GitHub Desktop.
This file contains 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
// ==UserScript== | |
// @name OnVoteMoveDownReddit | |
// @description Simple script that allows using a/z for voting and on vote will move to next element and expand it in Reddit. x will expand the thing if it is not already expanded. When at the end of the page, new content is loaded automatically | |
// @exclude https://old.reddit.com/r/*/comments/* | |
// @match https://old.reddit.com/r/* | |
// @match https://old.reddit.com/ | |
// ==/UserScript== | |
// CSS for the active thing | |
const style = document.createElement("style"); | |
style.type = "text/css"; | |
style.innerHTML = | |
".thing.active { border-style: dotted; border-color: cornflowerblue; }"; | |
document.getElementsByTagName("head")[0].appendChild(style); | |
// Things are content | |
const things = document.getElementsByClassName("thing"); | |
const makeActive = (element) => element.classList.add("active"); | |
const makeInactive = (element) => element.classList.remove("active"); | |
const clearPreviousActive = () => { | |
for (let thing of things) { | |
makeInactive(thing); | |
} | |
}; | |
// Event listeners for activating a thing by clicking on it | |
for (let thing of things) { | |
thing.addEventListener("click", (event) => { | |
clearPreviousActive(); | |
makeActive(event.currentTarget); | |
}); | |
} | |
// Activate first thing by default | |
makeActive(things[0]); | |
// Loads next page of 100 things and parses out the list of them | |
const loadNext = async (lastThing) => { | |
const id = lastThing.getAttribute("data-fullname"); | |
const response = await fetch( | |
`${window.location.href.split("?")[0]}?count=100&after=${id}` | |
); | |
const allContent = await response.text(); | |
const parser = new DOMParser(); | |
const htmlDocument = parser.parseFromString(allContent, "text/html"); | |
const siteTable = htmlDocument.documentElement.querySelector("#siteTable"); | |
return siteTable.children; | |
}; | |
// Removes nav buttons and appends new things to the content. New content has its own nav buttons. | |
const addContentToPage = (lastThing, content) => { | |
document.querySelector(".nav-buttons").remove(); | |
for (let thing of content) { | |
lastThing.parentElement.append(thing); | |
} | |
}; | |
const getLastThing = () => { | |
const allThings = document.querySelectorAll(".thing"); | |
return allThings[allThings.length - 1]; | |
}; | |
const loadMoreContent = async () => { | |
const lastThing = getLastThing(); | |
const content = await loadNext(lastThing); | |
addContentToPage(lastThing, content); | |
}; | |
const expand = (thing) => { | |
const expandButton = thing.querySelector("div.expando-button.collapsed"); | |
if (expandButton) { | |
expandButton.click(); | |
} | |
}; | |
const collapse = (thing) => { | |
const collapseButton = thing.querySelector("div.expando-button.expanded"); | |
if (collapseButton) { | |
collapseButton.click(); | |
} | |
}; | |
const getNextSibling = (elem, selector) => { | |
// Get the next sibling element | |
let sibling = elem.nextElementSibling; | |
// If the sibling matches our selector, use it | |
// If not, jump to the next sibling and continue the loop | |
while (sibling) { | |
if (sibling.matches(selector)) return sibling; | |
sibling = sibling.nextElementSibling; | |
} | |
}; | |
let autoExpand = false; | |
const moveToNext = (current) => { | |
collapse(current); | |
// Get next thing that is not an ad | |
const nextThing = getNextSibling(current, ".thing:not(.promoted)"); | |
clearPreviousActive(); | |
makeActive(nextThing); | |
if (autoExpand) { | |
expand(nextThing); | |
} | |
nextThing.scrollIntoView(true); | |
if (window.innerHeight + window.scrollY >= document.body.offsetHeight) { | |
// you're at the bottom of the page | |
loadMoreContent(); | |
} | |
}; | |
document.addEventListener( | |
"keydown", | |
(event) => { | |
const keyName = event.key; | |
const currentActive = document.querySelector(".thing.active"); | |
if (currentActive) { | |
switch (keyName) { | |
case "a": | |
const upArrow = currentActive.querySelector(".arrow.up"); | |
upArrow.click(); | |
moveToNext(currentActive); | |
break; | |
case "z": | |
const downArrow = currentActive.querySelector(".arrow.down"); | |
downArrow.click(); | |
moveToNext(currentActive); | |
break; | |
case "x": | |
autoExpand = !autoExpand; | |
if (autoExpand) { | |
expand(currentActive); | |
} else { | |
collapse(currentActive); | |
} | |
break; | |
} | |
} | |
}, | |
false | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment