// ==UserScript==
// @name ExHentai Viewer
// @namespace Violentmonkey Scripts
// @description A script that helps you browse ehentai more conveniently.
// @match *://exhentai.org/*
// @match *://e-hentai.org/*
// @grant GM_setValue
// @grant GM_getValue
// @version 0.32
// ==/UserScript==
var custom_filter = GM_getValue('custom_filter', []);
custom_filter.forEach(function(v, i, a){
if (v == undefined || v.tag == undefined || v.name == undefined){
a.splice(i, 1);
GM_setValue('custom_filter', custom_filter);
}
})
if (window.location.href.includes("/s/")) {
EhViewer();
} else if (window.location.href.includes("/g/")) {
addNewStyle('input{margin:2px 2px!important;}');
filterForGallery();
} else if (document.getElementById('searchbox') !== null) {
addNewStyle('input{margin:2px 2px!important;}');
addFilter(document.getElementsByClassName("nopm")[0]);
}
function addNewStyle(newStyle) {
var styleElement = document.getElementById('styles_js');
if (!styleElement) {
styleElement = document.createElement('style');
styleElement.type = 'text/css';
styleElement.id = 'styles_js';
document.getElementsByTagName('head')[0].appendChild(styleElement);
styleElement.appendChild(document.createTextNode(newStyle));
} else {
styleElement.innerText = newStyle;
}
}
function filterForGallery(){
// var galleryFilter = document.getElementsByClassName('gm')[0].appendChild(document.createElement("form"));
var galleryFilter = document.body.insertBefore(document.createElement('form'), document.getElementsByClassName('gm')[0]);
galleryFilter.innerHTML = '<p id="galleryFilter" class="nopm"><input type="text" name="f_search" placeholder="Search Keywords" value="" size="50"><input type="submit" name="f_apply" value="Apply Filter"></p>';
galleryFilter.setAttribute('style', 'display: none; width: 30%; text-align: center; margin: 10px auto; border: 2px ridge black; padding: 10px;');
galleryFilter.setAttribute('action', 'https://exhentai.org/');
galleryFilter.setAttribute('method', 'get');
addFilter(document.getElementById('galleryFilter'));
var tb = document.getElementById('taglist').firstElementChild.firstElementChild;
tb.innerHTML += '<tr><td class="tc">EHV:</td><td><div id="show_filter" class="gt" style="cursor:pointer">show filter</div></td></tr>';
document.getElementById('show_filter').addEventListener('click', function(e){
if (e.target.innerText === 'show filter'){
galleryFilter.style.display = "block";
e.target.innerText = 'hide filter'
} else {
galleryFilter.style.display = "none";
e.target.innerText = 'show filter'
}
})
for(var i=0; i<document.all.length; i++){
if (document.all[i].id.slice(0, 3) === 'ta_') {
document.all[i].addEventListener('contextmenu', addGalleryTag, false);
}
}
function addGalleryTag(e) {
e.preventDefault();
var searchBox = galleryFilter.firstElementChild.firstElementChild;
var tagValue = '"'+e.target.innerText+'"';
if (searchBox.value.includes(tagValue)){
console.log('del?');
searchBox.value = searchBox.value.replace(tagValue, '');
}else {
searchBox.value += tagValue;
}
}
}
function addFilter(boxPos){
var ipColor1;
var ipColor2;
var fontColor;
if (window.location.host === 'e-hentai.org'){
ipColor1 = 0xedeada;
ipColor2 = ipColor1 - 0x202020;
} else {
ipColor1 = 0x34353b;
ipColor2 = ipColor1 + 0x202020;
}
ipColor1 = '#' + ipColor1.toString('16');
ipColor2 = '#' + ipColor2.toString('16');
var search_box = boxPos.firstElementChild;
var p = document.getElementById('custom_filter');
if(p == null) {
boxPos.appendChild(document.createElement('br'));
boxPos.appendChild(document.createElement('br'));
p = boxPos.appendChild(document.createElement('p'));
boxPos.appendChild(document.createElement('br'));
p.setAttribute('class', 'nopm');
p.setAttribute('id', 'custom_filter');
} else {
p.innerHTML = '';
}
for (var i in custom_filter) {
var filter = custom_filter[i];
var t = p.appendChild(document.createElement('input'));
t.setAttribute('type', 'button');
t.setAttribute('value', filter.name);
t.setAttribute('tag', filter.tag);
t.addEventListener('click', addTag, false);
t.addEventListener('contextmenu', delTag, false);
if (search_box.value.includes(filter.tag)){
t.style.backgroundColor=ipColor2;
} else {
t.style.backgroundColor=ipColor1;
}
}
t=p.appendChild(document.createElement('input'));
t.setAttribute('type', 'button');
t.setAttribute('value', "+");
t.addEventListener('click', newTag, false);
function addTag(e){
var t = e.target;
var tag = t.getAttribute('tag');
if (search_box.value.includes(tag)){
search_box.value = search_box.value.replace(('"'+tag+'"'), "");
t.style.backgroundColor=ipColor1;
} else {
search_box.value += ('"'+tag+'"');
t.style.backgroundColor=ipColor2;
}
}
function delTag(e){
e.preventDefault();
if (window.confirm('Delete this tag?') == true){
var t = e.target;
var tag = t.getAttribute('tag');
for (var i in custom_filter) {
if(custom_filter[i].tag == tag){
custom_filter.splice(i, 1);
break;
}
}
GM_setValue('custom_filter', custom_filter);
addFilter(e.target.parentElement.parentElement);
}
return false;
}
function newTag(e){
var tagStr = window.prompt("Add filter like format below", "name@value").split("@");
if(tagStr.length == 2){
custom_filter.push({'name':tagStr[0], 'tag':tagStr[1]});
GM_setValue('custom_filter', custom_filter);
addFilter(e.target.parentElement.parentElement);
} else {
window.alert("Invalid value... :(");
}
}
}
function EhViewer(){
var zoomInterval;
var oldSi = si;
var firstPage = document.getElementsByClassName("sn")[0].firstChild.href;
var lastPage = document.getElementsByClassName("sn")[0].lastChild.href;
var float_icon = new Array([]);
var float_link = new Array([]);
var currentScale = 1;
var float_list = document.createElement("ul");
var newStyle = 'h1, #i2, #i5, #i6, #i7, .ip, .sn{display:none!important;}.float_list{display:block; position:fixed; bottom:10px; right:10px; list-style:none;z-index:1005;}.float_icon{user-select:none;background-color:btColor1; margin:5px; width:50px; height:50px; line-height:50px; font-size:12px; border-radius:50%; cursor:pointer;}.float_icon:hover{transition-duration:0.2s;font-size:13px; background-color:btColor2; box-shadow:0 0 2px 1px shadowColor;}.float_icon:active{transition-duration:0.2s;font-size:12px; }::-webkit-scrollbar{display:none;}';
var btColor1;
var btColor2;
var shadowColor;
if (window.location.host === 'e-hentai.org'){
btColor1 = 0xe3e0d1 - 0x101010;
btColor2 = btColor1 - 0x050505;
shadowColor = btColor1 + 0x050505;
} else {
btColor1 = 0x34353b + 0x101010;
btColor2 = btColor1 + 0x050505;
shadowColor = btColor1 - 0x050505;
}
newStyle = newStyle.replace('btColor1', '#'+btColor1.toString('16'));
newStyle = newStyle.replace('btColor2', '#'+btColor2.toString('16'));
newStyle = newStyle.replace('shadowColor', '#'+shadowColor.toString('16'));
document.body.appendChild(float_list);
for(var i=0; i<5; i++){
float_icon[i]=document.createElement("li");
float_link[i]=document.createElement("a");
float_list.appendChild(float_icon[i]);
float_icon[i].appendChild(float_link[i]);
}
float_list.setAttribute("class", "float_list");
float_icon[0].setAttribute("class", "float_icon prev_page");
float_icon[1].setAttribute("class", "float_icon next_page");
float_icon[2].setAttribute("class", "float_icon zoom_in");
float_icon[3].setAttribute("class", "float_icon zoom_out");
float_icon[4].setAttribute("class", "float_icon gallery");
float_icon[0].innerText="➕";
float_icon[1].innerText="➖";
float_icon[2].innerText="👈";
float_icon[3].innerText="👉";
float_icon[4].innerText="📚";
document.addEventListener("keydown", keyDown);
float_icon[0].addEventListener('mousedown', zoomIn, false);
float_icon[1].addEventListener('mousedown', zoomOut, false);
float_icon[2].addEventListener('click', prevPage, false);
float_icon[3].addEventListener('click', nextPage, false);
document.addEventListener('mouseup', function(){clearInterval(zoomInterval);});
float_icon[4].setAttribute("onclick", "window.open(document.getElementsByClassName('sb')[0].firstChild.href,'_self');");
function keyDown(e) {
var keycode = e.which;
switch(keycode){
case 37: {
setNewPage();
break;
}
case 39: {
setNewPage();
break;
}
case 187: {
setScale("zoomIn");
break;
}
case 189: {
setScale("zoomOut");
break;
}
case 188: {
window.scrollBy(0, -window.innerHeight);
break;
}
case 190: {
window.scrollBy(0, window.innerHeight);
break;
}
case 219: {
window.scrollBy(0, -window.innerHeight*0.3);
break;
}
case 221: {
window.scrollBy(0, window.innerHeight*0.3);
break;
}
default: {
// console.log(keycode);
}
}
}
function setNewPage() {
var listenChange = setInterval(function(){
if(oldSi != si){
var pic = document.getElementById("img");
var width = Number(pic.style.width.replace("px", ""));
var height = Number(pic.style.height.replace("px", ""));
var page = document.getElementsByTagName('span');
var footMark = document.getElementById('i4').firstChild;
var currentPage = page[0].innerText;
var totalPage = page[1].innerText;
footMark.innerText = currentPage +"P / "+ totalPage +"P :: "+ footMark.innerText;
width *= currentScale;
height *= currentScale;
pic.style.width = width + "px";
pic.style.height = height + "px";
oldSi = si;
clearInterval(listenChange);
}
}, 200);
}
function setScale(scale){
var pic = document.getElementById("img");
var width = Number(pic.style.width.replace("px", ""));
var height = Number(pic.style.height.replace("px", ""));
// console.log(pic.src, width, height, max_width);
switch(scale){
case 'zoomIn': {
var max_width = Number(pic.style.maxWidth.replace("px", ""));
if (width < max_width){
width *= 1.1;
height *= 1.1;
currentScale *= 1.1;
} else{
}
break;
}
case 'zoomOut': {
if (height >= window.innerHeight){
width /= 1.1;
height /= 1.1;
currentScale /= 1.1;
} else {
}
break;
}
}
pic.style.width = width + "px";
pic.style.height = height + "px";
}
function prevPage(e){
e.preventDefault();
if (window.location.href !== firstPage){
document.getElementById('prev').onclick();
} else {
window.alert("The first page (⊙_⊙)")
}
setNewPage();
}
function nextPage(e){
e.preventDefault();
if (window.location.href !== lastPage){
document.getElementById('next').onclick();
} else {
window.alert("The last page (⊙ω⊙)")
}
setNewPage();
}
function zoomIn(e){
e.preventDefault();
setScale('zoomIn');
zoomInterval = setInterval(function(){
setScale('zoomIn');
}, 200);
}
function zoomOut(e){
e.preventDefault();
setScale('zoomOut');
zoomInterval = setInterval(function(){
setScale('zoomOut');
}, 200);
}
addNewStyle(newStyle);
}