Similar behavior to RES

/*
==UserScript==
@name             kbin nav
@match            https://kbin.social/*
@version          1.0
==/UserScript==
*/

var css = [
".selected-dark {",
"    background-color: darkslategray;",
"    color: white;",
"}",
"",
".selected-light {",
"    background-color: antiquewhite;",
"}"
].join("\n");

if (typeof GM_addStyle != "undefined") {
    GM_addStyle(css);
} else if (typeof PRO_addStyle != "undefined") {
    PRO_addStyle(css);
} else if (typeof addStyle != "undefined") {
    addStyle(css);
} else {
    var node = document.createElement("style");
    node.type = "text/css";
    node.appendChild(document.createTextNode(css));
    var heads = document.getElementsByTagName("head");
    if (heads.length > 0) {
        heads[0].appendChild(node);
    } else {
        // no head yet, stick it whereever
        document.documentElement.appendChild(node);
    }
}

const selectedClass = document.body.classList.toString().includes("light") ? "selected-light" : "selected-dark";
let currentEntryIndex = 0;
let entries = document.querySelectorAll(".entry,.post,.comment");
let numEntries = entries.length;

const resizeObserver = new ResizeObserver(observerEntries => {
    init();
});
resizeObserver.observe(document.body);

function init() {
    entries = document.querySelectorAll(".entry,.post,.comment");
    numEntries = entries.length;
    if (entries && numEntries > 0) {
        // If jumping to comment from anchor link
        if (window.location.hash) {
            const anchoredEntry = Array.from(entries).findIndex(entry => entry.id === window.location.hash.substring(1));

            if (anchoredEntry > -1) {
                selectEntry(anchoredEntry);
            }
        }

        Array.from(entries).forEach(entry => {
            entry.removeEventListener('click', handleClick, true);
            entry.addEventListener('click', handleClick, true);
        });

        document.removeEventListener("keydown", handleKeydown);
        document.addEventListener("keydown", handleKeydown);
    }
}

function handleKeydown(event) {
    if (["TEXTAREA", "INPUT"].indexOf(event.target.tagName) > -1) {
        return;
    }

    let selectEntryIndex;

    // j pressed
    if (event.code === "KeyJ") {
        // if shift key also pressed
        if (event.shiftKey) {
            let nextSameLevelEntry = getNextEntrySameLevel(currentEntryIndex);

            if (nextSameLevelEntry) {
                selectEntryIndex = nextSameLevelEntry;
            }
        } else {
            if (currentEntryIndex + 1 < numEntries) {
                selectEntryIndex = currentEntryIndex + 1;
            }
        }
    }

    // k pressed
    if (event.code === "KeyK") {
        // if shift key also pressed
        if (event.shiftKey) {
            let prevSameLevelEntry = getPrevEntrySameLevel(currentEntryIndex);

            if (prevSameLevelEntry >= 0) {
                selectEntryIndex = prevSameLevelEntry;
            }
        } else {
            if (currentEntryIndex - 1 >= 0) {
                selectEntryIndex = currentEntryIndex - 1;
            }
        }
    }

    if (selectEntryIndex >= 0) {
        selectEntry(selectEntryIndex);

        if (
            entries[selectEntryIndex].getBoundingClientRect().top < 0 ||
            entries[selectEntryIndex].getBoundingClientRect().bottom > window.innerHeight
        ) {
            const y = entries[selectEntryIndex].getBoundingClientRect().top + window.pageYOffset - (document.getElementById("header").offsetHeight + 10);
            window.scrollTo({
                top: y
            });
        }
    }

    // x pressed
    if (event.code === "KeyX") {
        let previewButton = entries[currentEntryIndex].getElementsByClassName("show-preview");

        if (previewButton.length > 0) {
            previewButton[0].click();
        }
    }
}

function getNextEntrySameLevel(i) {
    const parentId = entries[i].getAttribute("data-subject-parent-value");

    let siblingIndex = i + 1;
    while (siblingIndex < numEntries) {
        if (entries[siblingIndex].getAttribute("data-subject-parent-value") === parentId) {
            return siblingIndex;
        }

        // If no more child entries of same level, go to next root entry
        const siblingParentId = entries[siblingIndex].getAttribute("data-subject-parent-value");
        if (!siblingParentId || siblingParentId === "") {
            return siblingIndex;
        }

        siblingIndex = siblingIndex + 1;
    }
}

function getPrevEntrySameLevel(i) {
    const parentId = entries[i].getAttribute("data-subject-parent-value");

    let siblingIndex = i - 1;
    while (siblingIndex >= 0) {
        if (entries[siblingIndex].getAttribute("data-subject-parent-value") === parentId) {
            return siblingIndex;
        }

        // If no more child entries of same level, go to next root entry
        const siblingParentId = entries[siblingIndex].getAttribute("data-subject-parent-value");
        if (!siblingParentId || siblingParentId === "") {
            return siblingIndex;
        }

        siblingIndex = siblingIndex - 1;
    }
}

function handleClick(event) {
    const elementIndex = Array.from(entries).indexOf(event.currentTarget);

    // Deselect if already selected, also ignore if clicking on any link/button
    if (elementIndex === currentEntryIndex && entries[currentEntryIndex].classList.contains(selectedClass) &&
        !(
            event.target.parentElement.tagName.toLowerCase() === "button" || event.target.tagName.toLowerCase() === "button" ||
            event.target.parentElement.tagName.toLowerCase() === "a" || event.target.tagName.toLowerCase() === "a"
        )
    ) {
        entries[currentEntryIndex].classList.remove(selectedClass);
    } else {
        selectEntry(elementIndex);
    }
}

function selectEntry(i) {
    entries[currentEntryIndex].classList.remove(selectedClass);
    currentEntryIndex = i;
    entries[currentEntryIndex].classList.add(selectedClass);
}