// ==UserScript==
// @name Resizer for readcomiconline.to
// @namespace http://tampermonkey.net/
// @version 0.6
// @description Make comic book pages fit on screen, because you're worth it.
// @author itsnotlupus
// @match https://readcomiconline.to/*
// @grant GM_xmlhttpRequest
// @require https://unpkg.com/[email protected]/dist/jquery.min.js
// ==/UserScript==
(function() {
'use strict';
// remedial ad cleanup, for the adblock-impaired.
try { document.getElementById('cus-exo').parentElement.remove() } catch (e){};
setInterval(()=> {
$('script,iframe[src^="/Ads"],iframe[src*="ads"],iframe:not([src*="disqus.com"]),[style="position: static !important;"],[id*="ads"],.top_page_alert,#fb-root,#stcpDiv,#stwrapper,#stOverlay').remove();
}, 100);
// add some basic image sizing so pages are quickly readable before the fitScreen thing finishes
// and hide the zoom controls. just use your browser zoom, it works better.
$(`<style type=text/css>
#divImage img {
height: ${innerHeight}px;
}
#divImage > p:not(:first-child) {
display: inline-block;
}
.btnZoom-container {
display: none;
}
#status {
position: fixed;
bottom: 0;
background: black;
color: #ccc;
}
</style>`).appendTo('head');
const images = "#divImage>p>img";
const msg = n => n>0 ? 'done.' : [
'Run batman, run!',
'This page is brought to you by Porn doritos. Porn Doritos, it\'s what for dinner. In bed.',
'Do you ever wonder what would happen if...'
][~~(Math.random()*3)]
const fitScreen = async () => {
const status= $('<div id=status>loading...').appendTo('body');
const pageWidth = document.body.clientWidth;
const pages = $(images);
const totalPages = pages.length;
let processedPages = 0;
const updateTimer = setInterval(() => {
status.text(`processing ${processedPages}/${totalPages} pages...`);
if (processedPages >= totalPages) {
clearInterval(updateTimer);
status.text(msg(totalPages));
setTimeout(()=>status.fadeOut(2000,()=>status.remove()), 2000);
}
}, 250);
for (let i = 0; i < totalPages; i++) {
const elt = pages[i];
let url, width, height;
if (elt.src.indexOf('blob:') === 0) {
return;
} else {
({ url, width, height } = await removeBanner(await blobify(elt.src), i));
}
elt.src = url;
elt.onload = () => {
URL.revokeObjectURL(url);
elt.onload = null;
};
elt.style.maxWidth = "inherit";
elt.style.maxHeight = "inherit";
if (i===0) { // force cover to sit by itself.
elt.style.display="block";
elt.style.marginLeft = elt.style.marginRight = "auto";
} else {
elt.parentElement.style.display="inline-block";
}
if (width>height) {
// double pages. make it fit, even if you need to upscale.
if (width/height > pageWidth/innerHeight) {
elt.style.width = (pageWidth*0.95)+"px";
} else {
elt.style.height = innerHeight + "px";
}
} else {
// single page. we don't upscale for now. maybe we should.
elt.style.maxWidth = pageWidth/2+"px";
elt.style.maxHeight = innerHeight + "px";
}
processedPages += 1;
}
};
addEventListener('keydown', e => {
let nextImage;
if (e.ctrlKey || e.altKey) return;
switch (e.keyCode){
case 34:
case 39:
case 40:
nextImage = Array.from($(images)).find(img=>img.offsetTop>scrollY);
break;
case 33:
case 37:
case 38:
nextImage = Array.from($(images)).reverse().find(img=>img.offsetTop<scrollY);
break;
}
if (nextImage) {
nextImage.scrollIntoView();
e.preventDefault();
}
});
const blobify = url => new Promise(resolve => {
GM_xmlhttpRequest({
method: 'GET',
url,
responseType: 'blob',
onload: xhr => resolve(URL.createObjectURL(xhr.response))
});
});
const loadImg = url => new Promise(resolve => {
const img = new Image;
img.src = url;
img.onload = e => { img.onload = null; resolve(img); }
});
const removeBanner = blobUrl => new Promise(async resolve => {
const img = await loadImg(blobUrl);
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// sad test for banner.
const data = ctx.getImageData(0, img.height - 11, 40, 10).data;
let found = false;
for (let i=0;i<data.length;i++) if (data[i] !== (i%4===3?255:0)) { found = true; break }
if (!found) {
canvas.height -= 80; // remove banner
ctx.drawImage(img, 0, 0);
canvas.toBlob( blob => {
const url = URL.createObjectURL(blob);
resolve({
url,
width: canvas.width,
height: canvas.height
});
URL.revokeObjectURL(blobUrl);
});
} else {
// no banner, do nothing.
resolve({ url: blobUrl, width: img.width, height: img.height });
}
});
fitScreen();
})();