Greasy Fork is available in English.

Manganelo Helper

Removes space between pages for user-specified series at Manganelo/Mangakakalot/Manganato, and enables arrow key navigation between chapters.

질문, 리뷰하거나, 이 스크립트를 신고하세요.
// ==UserScript==
// @name 			Manganelo Helper
// @namespace 		GF-Fear3d
// @version 		1.12
// @description 	Removes space between pages for user-specified series at Manganelo/Mangakakalot/Manganato, and enables arrow key navigation between chapters.
// @author 			Fear3d
// @match 			https://manganelo.com/*
// @match			https://mangakakalot.com/*
// @match           https://readmanganato.com/*
// @match           https://manganato.com/*
// @match           https://chapmanganato.com/*
// @match           https://chapmanganato.to/*
// @require 		https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js
// @grant			GM_registerMenuCommand
// @grant			GM_setValue
// @grant			GM_getValue
// ==/UserScript==

// ****Attention**** This script is not compatible with Greasemonkey 4.0+. Please use Tampermonkey or Violentmonkey instead.

(function() {
 	'use strict';

 	var nextUrl = "";
 	var prevUrl = "";
 	var currentTitle = "";
 	var uiInitialized = false;
 	var atChapter = false;
 	var atManga = false;
 	var atMangakakalot = false;
 	var atManganato = false;
 	var atManganelo = false;
 	var configOpen = false;
 	var curInList = false;

 	// ************************************************************************************************************************************
 	// ************ As of version 0.2 you should not add your new titles here.                             ********************************
 	// ************ You should now add/remove titles through the configuration menu.                       ********************************
 	// ************ Visit https://greasyfork.org/en/scripts/412420-manganelo-helper if you don't know how. ********************************
 	// ************ If you add them via the menu, your titles will be saved even when I update the script. ********************************
 	// ************************************************************************************************************************************
 	// Default list of titles that we want to have no image margines
 	var titleListDefault = [
 		"A Returner's Magic Should Be Special",
 		"God Of Martial Arts",
 		"I Am The Sorcerer King",
 		"I, Who Blocked The Demon King's Ultimate Attack, Ended Up As The Little Hero's Nanny!",
 		"Solo Leveling",
 		"Spirit Sword Sovereign",
 		"Tang Yin Zai Yi Jie",
 		"The Ghostly Doctor",
 		"The God Of High School",
 		"The Top Clan Leader In History",
 		"Tower Of God",
 		"Tomb Raider King"
 	];

 	var titleList;

 	// Configuration UI elements
 	var configWindow = document.createElement("div");
 	var lblTitleList = document.createElement("label");
 	var taTitleList = document.createElement("textarea");
 	var btnAddTitle = document.createElement("button");
 	var btnSave = document.createElement("button");
 	var btnCancel = document.createElement("button");
 	var btnRemoveTitle = document.createElement("button");
 	var divButtons = document.createElement("div");

 	function escapeRegExp(string) {
		return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
	}

 	function btnAddTitleClick()
 	{
 		let curTAVal = taTitleList.value.trim();

 		if (atChapter)
 			taTitleList.value = curTAVal + "\r\n" + currentTitle;
 		else if (atMangakakalot && atManga)
 			taTitleList.value = curTAVal + "\r\n" + $(".breadcrumb > p:nth-child(1) > span:nth-child(3) > a:nth-child(1) > span:nth-child(1)", window.top.document).text().trim();
 		else if (atManga)
 			taTitleList.value = curTAVal + "\r\n" + $(".panel-breadcrumb > a:nth-child(3)", window.top.document).text().trim();
 	}

 	function btnSaveClick()
 	{
 		titleList = [...new Set(taTitleList.value.trim().split(/\r?\n/).sort())];
 		GM_setValue("titleList", JSON.stringify(titleList));
 		configWindow.style.display = "none";
 		configOpen = false;

 		if (atChapter)
 			removeMargins();
 	}

 	function btnCancelClick()
 	{
 		configWindow.style.display = "none";
 		configOpen = false;
 	}

 	function btnRemoveTitleClick()
 	{
 		let curTAVal = taTitleList.value.trim();

 		if (atMangakakalot && atManga)
 			currentTitle = $(".breadcrumb > p:nth-child(1) > span:nth-child(3) > a:nth-child(1) > span:nth-child(1)", window.top.document).text().trim();
 		else if (atManga)
 			currentTitle = $(".panel-breadcrumb > a:nth-child(3)", window.top.document).text().trim();

 		var titleReg = new RegExp(escapeRegExp(currentTitle) + "\\r?\\n?", "gi");

 		taTitleList.value = curTAVal.replace(titleReg, "");
 	}

 	// Initializes configuration UI elements
 	function initConfigUI()
 	{
		lblTitleList.innerHTML = "Titles to remove gaps from: ";
		lblTitleList.setAttribute("for", "taTitleList");
		configWindow.appendChild(lblTitleList);
		configWindow.appendChild(document.createElement("br"));

		taTitleList.value = titleList.join("\r\n");
		taTitleList.setAttribute("id", "taTitleList");
		taTitleList.setAttribute("rows", "30");
		taTitleList.setAttribute("cols", "80");
		taTitleList.style.whiteSpace = "pre";
		taTitleList.style.width = "670px";
		configWindow.appendChild(taTitleList);

		btnRemoveTitle.innerHTML = "Remove Current Title";
		btnRemoveTitle.style.margin = "5px";
		btnRemoveTitle.style.marginLeft = "10px";
		btnRemoveTitle.style.marginBottom = "10px";
		btnRemoveTitle.style.fontSize = "18px";
		btnRemoveTitle.style.cssFloat = "left";
		btnRemoveTitle.onclick = function() { btnRemoveTitleClick() };
		divButtons.appendChild(btnRemoveTitle);

		btnAddTitle.innerHTML = "Add Current Title";
		btnAddTitle.style.margin = "5px";
		btnAddTitle.style.marginBottom = "10px";
		btnAddTitle.style.fontSize = "18px";
		btnAddTitle.onclick = function() { btnAddTitleClick() };
		if (atChapter || atManga)
			btnAddTitle.disabled = false;
		else
			btnAddTitle.disabled = true;
		divButtons.appendChild(btnAddTitle);

		btnCancel.innerHTML = "Cancel";
		btnCancel.style.margin = "5px";
		btnCancel.style.marginRight = "10px";
		btnCancel.style.marginBottom = "10px";
		btnCancel.style.fontSize = "18px";
		btnCancel.style.cssFloat = "right";
		btnCancel.onclick = function() { btnCancelClick() };
		divButtons.appendChild(btnCancel);

		btnSave.innerHTML = "Save";
		btnSave.style.margin = "5px";
		btnSave.style.marginBottom = "10px";
		btnSave.style.fontSize = "18px";
		btnSave.style.cssFloat = "right";
		btnSave.onclick = function() { btnSaveClick() };
		divButtons.appendChild(btnSave);

		divButtons.style.textAlign = "center";
		configWindow.appendChild(divButtons);

		configWindow.style.position = "fixed";
		configWindow.style.top = "50%";
		configWindow.style.left = "50%";
		configWindow.style.textAlign = "center";
		configWindow.style.width = "700px";
		configWindow.style.transform = "translate(-50%, -50%)";
		configWindow.style.backgroundColor = "darkviolet";
		configWindow.style.color = "whitesmoke";
		window.top.document.body.appendChild(configWindow);

		uiInitialized = true;
	}

 	 // Displays configuration UI
 	function openConfig()
 	{
 		configOpen = true;

 		if (!uiInitialized) {
 			initConfigUI();
 		}
 		else {
 			taTitleList.value = titleList.join("\r\n");
 			configWindow.style.display = "block";
 		}
 	}

 	// Remove margins between images on specified titles
 	function removeMargins() 
 	{
 		let titleMatch = false;

 		for (let i = 0; i < titleList.length; i++) 
 		{
 			if (titleList[i].trim().toLowerCase() == currentTitle.toLowerCase())
 			{
 				titleMatch = true;
 				curInList = true;
 				break;
 			}
 		}

 		if (!titleMatch && !curInList)
 			return;

 		if (atMangakakalot && titleMatch) {
 			$("#vungdoc img", window.top.document).css("margin", "0 auto 0");
 			$("#vungdoc > div", window.top.document).hide();
 		}
 		else if (titleMatch) {
 			$(".container-chapter-reader img", window.top.document).css("margin", "0 auto 0");
 			$(".container-chapter-reader > div", window.top.document).hide();
 		}
 		else if (atMangakakalot) { // It was originally in the list, but is now removed.
 			$("#vungdoc img", window.top.document).css("margin", "0 auto 5px");
 			curInList = false;
 		}
 		else { // It was originally in the list, but is now removed.
 			$(".container-chapter-reader img", window.top.document).css("margin", "5px auto 0");
 			curInList = false;
 		}
 	}

 	// Find URLs for Next and Prev and sets the current title of the manga
 	function findUrls()
 	{
 		var nextPage, prevPage, curTitleLink;

 		// Find title page link
 		if (atMangakakalot) {
 			curTitleLink = $("div.breadcrumb:nth-child(2) > p:nth-child(1) > span:nth-child(3) > a:nth-child(1)", window.top.document);
 			currentTitle = curTitleLink.attr("title").trim();
 		}
 		else {
 			curTitleLink = $("div.container:nth-child(1) > div.panel-breadcrumb:nth-child(2) > a:nth-child(3)", window.top.document);
 			currentTitle = curTitleLink.text().trim();
 		}

 		// Find next chapter link
 		if (atMangakakalot && $("a.back", window.top.document).length) {
 			nextPage = $("a.back:first", window.top.document);  // This is not an error. Mangakakalot has their 'next/back' buttons named backwards
 		}
 		else if ($("a.navi-change-chapter-btn-next.a-h", window.top.document).length) {
 			nextPage = $("a.navi-change-chapter-btn-next.a-h:first", window.top.document);
 		}
 		else
 			nextPage = curTitleLink; // We're at the last chapter, so set the next page to the title page

 		// Find previous chapter link
 		if (atMangakakalot && $("a.next", window.top.document).length) {
 			prevPage = $("a.next:first", window.top.document);
 		}
 		else if ($("a.navi-change-chapter-btn-prev.a-h", window.top.document).length) {
 			prevPage = $("a.navi-change-chapter-btn-prev.a-h:first", window.top.document);
 		} 
 		else {
 			prevPage = curTitleLink; // We're at the first chapter, so set the prev page to the title page
 		}

    	nextUrl = nextPage.attr("href");
    	prevUrl = prevPage.attr("href");
 	}

 	// Checks if this is the first run, and displays a message if so
 	function checkFirstRun()
 	{
 		var firstRun = GM_getValue("firstRun", true);

 		if (firstRun)
 		{
 			GM_setValue("firstRun", false);
 			alert("Manganelo Helper 1.10\n\n" +
 				'Hello! Manganelo seems to be in the process of changing to "Manganato", which has changed\n' +
 				"the format of their URLs. I believe that I have accounted for it with this update, but they\n" +
 				"don't seem to be doing all of their URLs in a consistent manner now, so it's possible that I\n" +
 				"have missed something. If you notice any situations where this script isn't working, please\n" +
 				"let me know at my greasyfork page at:\n\n" +
 				"https://greasyfork.org/en/scripts/412420-manganelo-helper");
 		}
 	}

 	// Loads title list from storage if it exists, otherwise it uses the default
 	function loadTitleList()
 	{
 		var jTitleList = GM_getValue("titleList");

 		if (!jTitleList)
 			titleList = titleListDefault;
 		else
 			titleList = JSON.parse(jTitleList);
 	}

 	// Handle arrow key events
 	function attachArrowKeyEvent()
 	{
 		document.onkeydown = function(evt) {
			switch (evt.keyCode) {
				case 37: // Left Arrow
					if (!configOpen)
						window.top.location = prevUrl;
					break;
				case 39: // Right Arrow
					if (!configOpen)
						window.top.location = nextUrl;
					break;
				case 65: // a
 					if (!configOpen)
						window.top.location = prevUrl;
 					break;
 				case 68: // d
 					if (!configOpen)
						window.top.location = nextUrl;
 					break;
 				case 87: // w
 					if (!configOpen)
 						window.top.scrollBy({top: -50, behavior: 'auto'});
 					break;
 				case 83: // s
 					if (!configOpen)
 						window.top.scrollBy({top: 50, behavior: 'auto'});
 					break;
			}
		};
 	}

 	$(document).ready(function() 
 	{
 		atMangakakalot = /https:\/\/mangakakalot\.com\S*/.test(window.top.location.href);
 		atManganelo = /https:\/\/manganelo\.com\S*/.test(window.top.location.href);
 		atManganato = /https:\/\/(?:read|chap)?manganato\.(?:com|to)\S*/.test(window.top.location.href);

 		if (atMangakakalot || atManganelo) {
	 		atChapter = /https:\/\/(?:manganelo\.com|mangakakalot\.com)\/chapter\/[\w\.\-~%]+\/[\w\.\-~%]+/.test(window.top.location.href);
	 		atManga = /https:\/\/(?:manganelo\.com|mangakakalot\.com)\/(?:manga\/[\w\.\-~%]+|read-[\w\.\-~%]+)/.test(window.top.location.href);
 		}
 		else {     // atManganato
 			atChapter = /https:\/\/(?:read|chap)?manganato.(?:com|to)\/manga-[\w\.\-~%]+\/chapter-[\d\.\-]+/.test(window.top.location.href);
	 		atManga = /https:\/\/(?:read|chap)?manganato.(?:com|to)\/manga-[\w\.\-~%]+$/.test(window.top.location.href);
 		}

 		if (atChapter)
 			findUrls();

 		loadTitleList();

 		if (atChapter) {
 			removeMargins();
 			attachArrowKeyEvent();
 		}

 		GM_registerMenuCommand("Configure Titles", function () { openConfig() }, "t");
 		checkFirstRun();
	});

})();