Hacker News - Highlight and navigate original poster's comments

Highlight original poster comments on Hackers News and navigate them with the keyboard

目前為 2017-11-21 提交的版本,檢視 最新版本

// ==UserScript==
// @name        Hacker News - Highlight and navigate original poster's comments
// @description Highlight original poster comments on Hackers News and navigate them with the keyboard
// @namespace   valacar
// @include     https://news.ycombinator.com/item?id=*
// @version     0.2
// @grant       none
// ==/UserScript==

function appendStyle(cssString)
{
    "use strict";
    var head = document.getElementsByTagName("head")[0];
    if (head)
    {
        var style = document.createElement("style");
        style.setAttribute("type", "text/css");
        style.textContent = cssString;
        head.appendChild(style);
        return style;
    }
    return null;
}

appendStyle(`
    .originalPoster, .opPostCountInfo {
        background: #ff9;
        background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, #ff9 100%);
    }
`);


var ENABLE_KEYBOARD_NAVIGATION = true;

// ----------------------------------------------------------------------------

var posterUserName = document.querySelector('.subtext a').textContent;

if (posterUserName)
{
    var commentUserLinks = document.querySelectorAll('.comhead a');

    if (commentUserLinks)
    {
        var opPostCount = 0;
        for (var i = 0; i < commentUserLinks.length; i++)
        {
            var commentUserName = commentUserLinks[i].textContent;
            if (posterUserName === commentUserName)
            {
                opPostCount++;
                commentUserLinks[i].classList.add('originalPoster');
                commentUserLinks[i].id = 'op-post-' + opPostCount;
            }
        }
    }
}


if (opPostCount > 0) {
    var newSpan = document.createElement('span');
    newSpan.textContent = ' (' + opPostCount + ' by original poster)';
    newSpan.className = 'opPostCountInfo';

    if (ENABLE_KEYBOARD_NAVIGATION) {
        newSpan.setAttribute('title', "Use the left/right arrow keys (or n/N or n/p) to scroll to OP comments.");
        newSpan.setAttribute('style', "cursor: help;");
    }

    var subText = document.querySelectorAll('.subtext a[href^="item?id="')[1];

    subText.appendChild(newSpan);
}


// http://stackoverflow.com/questions/8922107/javascript-scrollintoview-middle-alignment
Element.prototype.documentOffsetTop = function () {
    return this.offsetTop + (this.offsetParent ? this.offsetParent.documentOffsetTop() : 0);
};

// TODO : get rid of ID's and use a custom attribute instead (?)
function ScrollToID(elID) {
    var top = document.getElementById(elID).documentOffsetTop() - (window.innerHeight * 0.25);
    window.scrollTo(0, top);
}


if (ENABLE_KEYBOARD_NAVIGATION) {
    var num = 0;

    window.addEventListener("keydown", function (event) {
        // Should do nothing if the key event was already consumed.
        if (event.defaultPrevented) {
            return;
        }

        // don't break alt-left and alt-right history navigation
        // and exit if textarea is in focus
        if (event.altKey || /(input|textarea)/i.test(document.activeElement.nodeName)) {
            return;
        }


        switch (event.key) {
            case "n":
            case "ArrowRight":
            case "Right":
                if (num < opPostCount) {
                    num++;
                }
                break;

            case "N":
            case "p":
            case "ArrowLeft":
            case "Left":
                if (num > 1) {
                    num--;
                }
                break;

            default:
                return; // Quit when this doesn't handle the key event.
        }

        // Consume the event for suppressing "double action".
        event.preventDefault();

        //console.log('num = ' + num + ' focus = ' + document.activeElement.tagName);
        ScrollToID("op-post-" + num);

    }, true);

}