// ==UserScript== // @name Arrow Keys: Next/Prev Chapter // @namespace https://greasyfork.org/users/45933 // @version 0.0.2 // @author Fizzfaldt // @description Arrow Key Keyboard shortcuts for Multiple Sites (next/prev chapter) // @run-at document-end // @grant none // @noframes // @nocompat Chrome // @match *://*.wuxiaworld.co/* // @match *://*.wuxiaworld.com/* // @match *://*.fanfiction.net/* // @downloadURL none // ==/UserScript== /* jshint esversion: 6 */ function xPathResultToUniqueNode(x, context) { 'use strict'; if (!x) { alert("NULL xPathResult! " + context); } let first = x.iterateNext(); if (!first) { alert("No xPathResult node! " + context); return; } let second = x.iterateNext(); while (second != null && second.value == first.value) { second = x.iterateNext(); } if (second != null && second.value != first.value) { alert("xPathResult had unique second node! [" + second + " ] " + context); } return first; } const prev = "prev"; const next = "next"; function getXpaths() { 'use strict'; var xpaths = { "wuxiaworld.co" : { prev : '//a[@class="prev" and @href]/@href', next : '//a[@class="next" and @href]/@href', }, "wuxiaworld.com" : { prev : '//li[@class="prev"]/a[contains(@class, "btn-link") and @href]/@href', next : '//li[@class="next"]/a[contains(@class, "btn-link") and @href]/@href', }, "fanfiction.net" : { prev : '//button[@class="btn" and contains(@onclick, "self.location=") and text()="< Prev"]/@onclick', next : '//button[@class="btn" and contains(@onclick, "self.location=") and text()="Next >"]/@onclick', }, }; var domain = location.hostname; while (domain != '') { if (domain in xpaths) { return xpaths[domain]; } // Strip one subdomain and try again let temp = domain.split('.'); temp.shift(); domain = temp.join('.'); } return null; } var pathsForHost = getXpaths(); function arrows(e) { 'use strict'; var result; switch (e.keyCode) { case 37: // Left result = document.evaluate(pathsForHost[prev], document, null, XPathResult.ANY_TYPE, null); break; case 39: // Right result = document.evaluate(pathsForHost[next], document, null, XPathResult.ANY_TYPE, null); break; // case 38: // Up // case 40: // Down default: return; } let linkHref = xPathResultToUniqueNode(result); let href = linkHref.value; // Handle location actually being javascript command href = href.replace(/^self.location='(.*)'$/, '$1'); location.href=href; } if (pathsForHost) { document.addEventListener('keyup', arrows, false); }