cats webcomic tool

initial scrolling and a hotkey

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        cats webcomic tool
// @description initial scrolling and a hotkey
// @namespace   gnblizz
// @include     http://*
// @noframes
// @version     2.01
// @icon        data:image/gif;base64,R0lGODdhIAAgAMIGAAAAACsrK1VVVYCAgKqqqtTU1P///////ywAAAAAIAAgAAAD/mi63P4wyhmFGKPQrcIwxSAQ3HRpioiWzrkUBMkWrjHEL5Hlq0PrFkzoRbMEAJ7dQ1BownQEprN4ITSZD0wjCoVdR87op/UI3VLmy4gQ8IAWOEbzNjTEMgOP+a0UbDEyfiBaP1EXGFh1KTorYzYfMCNrMVhxjzYwRwAoFyA6Qk1RaCmQH3cWTQEkZqqhI6N1SqGrACSGTJSOY6+YDDhsp09iDKa8ip4GFjoAN0AyCx8BdZaDyZIWQT2kJGM0KyFFA0htWA5RGjuRL4htAWDn5oJDzUFq7QJ6kRhKogrD0IgAAMB2CEMrBoL8JbRhaKAaGPu02YnwxJ20KKpYeLKCMEeNghA1KJxj88EPMDkcvBVw18SfRT0lpLj5KG6ShZQ3YC5A9dHbBkNnBvFc96xBAgA7
// @grant       GM_registerMenuCommand
// @grant       GM_xmlhttpRequest
// ==/UserScript==
"use strict";
var HotKey = 'ArrowRight'; // You can customize the hotkey here.

try { GM_registerMenuCommand('configure Cats Webcomic Tool', CatsConfig, 'w'); } catch(e){
  console.log('couldn\'t add menu.');
}
try { if(document.domain=='www.egscomics.com') { if(document.getElementById('newsarea').textContent.match(/^No DVD movie style commentary/))
  document.getElementById('news').textContent = 'No comments'; 
  document.getElementById('leftarea').removeChild(document.getElementById('boxad'));
  document.getElementById('leftarea').removeChild(document.getElementById('ibar'));
}} catch(e){}
(function Cats2(d) {
  if(d) { 
    d = d.split('|');
    Set(parseInt(d[0]), parseInt(d[1]), decodeURIComponent(d[2]));
  }
}(GetCookie('CatsWebcomicTool')));

/* Set function:
 * x	  int, optional		amount of pixels to scroll right
 * y	  int			amount of pixels to scroll down
 * name   string		identifier of the next button (see FindLink function)
 * style  string, optional	css style string to apply
 * return boolean		success */
function Set(x, y, name, style) {
  if(!FindLink(name)) {
    console.log('CatsWebcomicTool: "'+name+'" not found at '+document.domain);
    return false;
  }
  document.body.style.minHeight = (y + window.outerHeight) + 'px';
  if(window.scrollY < y)
    window.scroll(x, y);
  if(obj('#us_MiniClock')) obj('#us_MiniClock').style.opacity='.2';//test
  if(name != '/') document.body.onkeypress=function(event) {
    if(event.key == HotKey) {
      var l = FindLink(name);
      if(l) {
	if(l.nodeName == 'LINK')
	  window.location.assign(l.getAttribute('href'));
	else
	  l.click();
	event.preventDefault();
      }
    }
  };
  return true;
}

/* GetLinkAdr function:
 * node   object		the next button
 * return text  		URL next page */
function GetLinkAdr(o) {
  if(!o) return;
  var x = o.getAttribute('href');
  if(x) return x;
  x = o.querySelector('*[href]');
  if(x) return x.getAttribute('href');
  do {
    o = o.parentNode;
    switch(o.nodeName) { case 'BODY': case 'HTML': return; }
    x = o.getAttribute('href');
  } while(!x);
  return x;
}

/* FindLink function:
 * name   string		identifier of the next button
 * return object		next button
identifier format:
!	the head contains a link with rel="next" attribute
*	the link has a rel="next" attribute
#name	name is an id tag
.name	name is a class id
/name	name is part of a path to an image
$name	name is the textContent of a link */
function FindLink(name) {
  var i, o, l;
  switch(name.charAt(0)) {
  case '#':
  case '.':
    return obj(name);
  case '!':
    return document.head.querySelector('link[rel="next"][href]');
  case '$':
    name = decodeURIComponent(name.slice(1));
    o = document.links;
    i = o.length;
    if(i) do {
      l = o[--i];
      if(l.textContent == name) {
	return l;
      }
    } while(i);
    return null;
  case '*':
    return document.body.querySelector('a[rel="next"]');
  case '/':
    o = document.images;
    i = o.length;
    if(i) do {
      l = o[--i];
      if(('/'+l.getAttribute('src')).search(name) >= 0)
	return l;
    } while(i);
    return null;
  case '?': // new, undok
    return document.body.querySelector('a[title="'+name.slice(1)+'"]');
  default:
    throw('Undefined string type in FindLink('+name+')');
  }
  return null;
}

function obj(str){var node = null;switch (str.charAt(0)){case '#':node=document.getElementById(str.slice(1));break;case '.':node=document.getElementsByClassName(str.slice(1))[0];break;case '+':node=document.createElement(str.slice(1).toUpperCase());break;default:node=document.getElementsByTagName(str)[0];break;}return node;}
function parent(path) { path = path.match(/^(.*)\/[^/]+\/?$/); return (path && path[1]) ? path[1] : '/'; }

function SetCookie(name, value, days, path) {
  if(!path) path='/';
  var d = new Date();
  d.setTime(days*86400000+d.getTime());
  document.cookie=name+'='+value+';expires='+ d.toUTCString()+';'+'path='+path;
}

function GetCookie(name) {
  var r = new RegExp(name+'=([^;]+)', '')
  var m = document.cookie.match(r);
  return(m ? m[1] : '');
}

function BiggestImage() {
  var a=document.images, i, img, biggestSize=0;
  if(!a || !(i=a.length)) { alert('No image found.'); return null; }
  do {
    var o = a[--i], size=o.offsetWidth*o.offsetHeight;
    if(size>biggestSize) { biggestSize=size; img=o; }
  } while(i);
  return img;
}

function CatsConfig() {
  try {
    var ctrl = obj('#CatsWebcomicTool'); if(ctrl) ctrl.parentNode.removeChild(ctrl);
    var img=BiggestImage(),rect=img.getBoundingClientRect(),cwctX=parseInt(rect.left+window.scrollX),cwctY=parseInt(rect.top+window.scrollY),cwctKey,key2,path,
    akey='!|*|.comic-nav-next|.next|.navi-next|.arrow_next|.comic-nav-next|/next|/arrow_next|/next_day|/next button|/nnxt|/foward|/Nav_ForwardOne|/NavigationNext|/arrow_nexttop|#next|#cndnextt|$next|$Next|$Next >|$Next Page|?next|?Next|$%20%C2%A0next%C2%A0%3E%C2%A0%20|/'.split('|');
    while(cwctKey=key2=akey.shift()) {
      if(cwctKey.charAt(0) == '/') { if(FindLink(cwctKey+='.gif')) break; if(FindLink(cwctKey=key2+'.png')) break; cwctKey=key2+'.jpg'; }
      if(FindLink(cwctKey)) break;
    }
    window.scroll(cwctX, cwctY);
    confirm();
  } catch(e) {
    console.log(e);
  }
function confirm() {
  var frm = obj('+FORM'), style = obj('+STYLE'), opt, sel = 0;
  frm.id = 'CatsWebcomicTool';
  addCtrl('x', cwctX, 'set this to "0", if page centers horizontally');
  ctrl.onchange = function() { window.scroll(cwctX = parseInt(this.value), cwctY); }
  addCtrl('y', cwctY, 'vertical offset');
  ctrl.onchange = function() { window.scroll(cwctX, cwctY = parseInt(this.value)); }
  addCtrl('next', cwctKey, 'identifier for the next button\n\n!\tthe page head contains a link with rel="next" attribute\n*\tthe link has a rel="next" attribute\n#name\tname is an id tag\n.name\tname is a class id\n/name\tname is part of a path to an image\n$name\tname is the textContent of a link\n\nif unsure type in "/", which disables the hotkey.');
  ctrl.onchange = function() { ctrl.title = (/^([!*/]|[#./$].+)$/.test(cwctKey = this.value) && FindLink(cwctKey)) ? 'store settings and close this bar' : 'discard settings and close this bar'; }
  if(!(path = location.pathname)) path = '/';
  if(path != '/') {
    addCtrl('path', [], 'select the part of the URL, which is common to all pages\nif unsure, select "/"');
    if(path.slice(-1) == '/') {
      sel++;
      ctrl.add(opt = obj('+OPTION'));
      opt.innerHTML = path = path.slice(0,-1);
    } else if(/\d[^/]*$/.test(parent(path))) sel++;
    do {
      ctrl.add(opt = obj('+OPTION'));
      opt.text = path = parent(path);
    } while(path.length > 1);
    ctrl.selectedIndex = sel;
    path = ctrl.value;
    ctrl.onchange = function() { if(GetCookie('CatsWebcomicTool')) SetCookie('CatsWebcomicTool', '', -1, path); path = this.value; }
  }
  addCtrl(' OK ', undefined, 'store settings and close this bar');
  ctrl.onclick = function() {
    try { 
      if(cwctKey) {
	SetCookie('CatsWebcomicTool', cwctX + '|' + cwctY + '|' + encodeURIComponent(cwctKey), 182, path); // 182 = half a year
	Set(cwctX, cwctY, cwctKey);
      } else
	SetCookie('CatsWebcomicTool', '', -1, path);
    } catch(e){}
    document.body.removeChild(this.parentNode);
  };
  style.innerHTML = 'form#CatsWebcomicTool{z-index:2147483647;position:fixed;left:0px;right:0px;bottom:0px;margin:0px;padding:2px;color:white;background-color:gray;}form#CatsWebcomicTool label{display:inline}form#CatsWebcomicTool input,form#CatsWebcomicTool select{display:inline;width:unset;margin-right:7px;}form#CatsWebcomicTool input[type="number"]{width:45px;text-align:end;}';
  frm.appendChild(style);
  document.body.appendChild(frm);

function addCtrl(name, value, title) {
  var lbl;
  ctrl = obj((name!='path') ? '+INPUT' : '+SELECT');
  switch(typeof(value)) {
  case 'undefined':
    ctrl.setAttribute('type', 'button');
    ctrl.setAttribute('value', name);
    break;
  case 'number':
    ctrl.setAttribute('type', 'number');
    ctrl.setAttribute('min', '0');
  default:
    lbl = obj('+LABEL');
    lbl.setAttribute('for', name);
    lbl.innerHTML = name+':';
    frm.appendChild(lbl);
    ctrl.setAttribute('name', name);
    if(value) ctrl.setAttribute('value', value);
  }
  ctrl.id = name;
  ctrl.title = title;
  frm.appendChild(ctrl);
  return ctrl;
}}}

// public domain by gnblizz
// contact me with my username + '@web.de'