// ==UserScript==
// @name HotKey Next Page
// @namespace hzhbest
// @author hzhbest
// @version 1.2
// @description 按左右键快速翻页,也可点击浮动按钮快速翻页
// @include http://*
// @include https://*
// @license MIT
// ==/UserScript==
// original author : [email protected] (https://userscripts-mirror.org/scripts/show/87895)
// mod by hzhbest : add hilite and float buttons
const nextStrs = [
"下一页",
"下页",
"下一节",
"下一章",
"下一篇",
"后一章",
"后一篇",
"后页>",
"»",
"next",
"next page",
"old",
"older",
"earlier",
"下頁",
"下一頁",
"后一页",
"后一頁",
"翻下页",
"翻下頁",
"后页",
"后頁",
"下翻",
"下一个",
"下一张",
"下一幅",
];
const lastStrs = [
"上一页",
"上页",
"上一节",
"上一章",
"上一篇",
"前一章",
"前一篇",
"<前页",
"«",
"previous",
"prev",
"previous page",
"new",
"newer",
"later",
"上頁",
"上一頁",
"前一页",
"前一頁",
"翻上页",
"翻上頁",
"前页",
"前頁",
"上翻",
"上一个",
"上一张",
"上一幅",
];
const GeneralXpaths = [
["//a[(text()='", "')]"],
["//a[@class='", "']"],
["//input[@type='button' and @value='", "']"],
];
//编辑下面的数组来自定义规则
const SpecialXpaths = [
{
//匹配的url
urls: ["http://www.google.com"],
//上一页节点的xpath
last: "//a[@id='pnprev']",
//下一页节点的xpath
next: "//a[@id='pnnext']",
},
{
urls: ["bilibili.com"],
last: '//li[@class="be-pager-prev"]',
next: '//li[@class="be-pager-next"]',
},
];
const LEFT = 37;
const RIGHT = 39;
const css = `.__hkbtn {outline: 3px solid #bb1a6a; font-size: larger;}
.__hkbse {position: fixed; z-index: 1000; right: 2em; bottom: 5em; background: #fff9;}
.__hkbse>div:first-of-type {display: none;}
.__hkbse:hover>div:first-of-type {display: inline-block;}
.__hkfbtn {width: 4em; height: 3em; display: inline-block; border: 2px solid #8a8a8a8a;
cursor: pointer; text-align: center; font-size: 1.5em; line-height: 3em; opacity: 0.7;}
.__hkfbtn.disabled {opacity: 0.3;}
.__hkfbtn:hover {opacity: 1; background: #fbcf84dd;}
`;
addCSS(css);
var lnode = getNode(LEFT);
var rnode = getNode(RIGHT);
if (!!lnode || !!rnode) {
var bnode = creaElemIn('div', document.body);
bnode.className = '__hkbse';
var lbutton = creaElemIn('div', bnode);
var rbutton = creaElemIn('div', bnode);
lbutton.className = rbutton.className = '__hkfbtn disabled';
lbutton.innerHTML = "<";
rbutton.innerHTML = ">";
if (!!lnode && lnode.style.display !== 'none') {
lnode.classList.add('__hkbtn') ;
lbutton.classList.remove('disabled');
lbutton.innerHTML = lnode.textContent.substring(0,3);
lbutton.title = lnode.textContent + ((!!lnode.href)? '\n' + lnode.href : '');
lbutton.addEventListener('click', ()=>{click(lnode);}, false);
}
if (!!rnode && rnode.style.display !== 'none') {
rnode.classList.add('__hkbtn') ;
rbutton.classList.remove('disabled');
rbutton.innerHTML = rnode.textContent.substring(0,3);
rbutton.title = rnode.textContent + ((!!rnode.href)? '\n' + rnode.href : '');
rbutton.addEventListener('click', ()=>{click(rnode);}, false);
}
}
function creaElemIn(tagname, destin) {
let theElem = destin.appendChild(document.createElement(tagname));
return theElem;
}
function addCSS(css) {
let stylenode = creaElemIn('style',document.getElementsByTagName('head')[0]);
stylenode.textContent = css;
stylenode.type = 'text/css';
stylenode.id = 'ali_c_toc';
}
function checkKey(e) {
if (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) return;
if (checkTextArea(e.target)) return;
var node;
if (e.keyCode == LEFT && !!lnode) {
click(lnode);
}
if (e.keyCode == RIGHT && !!rnode) {
click(rnode);
}
}
function checkTextArea(node) {
var name = node.localName.toLowerCase();
if (name == "textarea" || name == "input" || name == "select") {
return true;
}
if (name == "div" && (node.id.toLowerCase().indexOf("textarea") != -1 || node.contentEditable !== false)) {
return true;
}
return false;
}
function click(node) {
if (node.onclick) node.onclick();
if (node.click) node.click();
if (node.href) location.href = node.href;
}
function xpath(query) {
return unsafeWindow.document.evaluate(
query,
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null
);
}
function getNode(keyCode) {
var node = getNodeByGeneralXpath(keyCode);
if (!node) node = getNodeBySpecialXpath(keyCode);
return node;
}
function getNodeByGeneralXpath(keyCode) {
var strs;
if (keyCode == LEFT) strs = lastStrs;
else if (keyCode == RIGHT) strs = nextStrs;
else return null;
var x = GeneralXpaths;
for (var i in x) {
for (var j in strs) {
var query = x[i][0] + strs[j] + x[i][1];
var nodes = xpath(query);
if (nodes.snapshotLength > 0) return nodes.snapshotItem(0);
}
}
return null;
}
function getNodeBySpecialXpath(keyCode) {
var s = SpecialXpaths;
for (var i in s) {
if (checkXpathUrl(s[i].urls)) {
if (keyCode == LEFT) {
return xpath(s[i].last).snapshotItem(0);
} else if (keyCode == RIGHT) {
return xpath(s[i].next).snapshotItem(0);
}
}
}
return null;
}
function checkXpathUrl(urls) {
for (var i in urls) if (location.href.indexOf(urls[i]) >= 0) return true;
return false;
}
if (top.location != self.location) return;
unsafeWindow.document.addEventListener("keydown", checkKey, false);