E-Hentai & ExHentai Fade or hide viewed galleries and tag hider

Fade or hide viewed galleries and hide tags on e-hentai and exhentai. Now working with GM4

As of 2020-05-06. See the latest version.

// ==UserScript==
// @name        E-Hentai & ExHentai Fade or hide viewed galleries and tag hider
// @namespace   https://greasyfork.org/users/25356
// @description Fade or hide viewed galleries and hide tags on e-hentai and exhentai. Now working with GM4
// @version     6.7

// @include     https://exhentai.org/*
// @include     https://e-hentai.org/*

// @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @require	https://code.jquery.com/jquery-git.min.js


// @grant		GM.getValue
// @grant		GM.setValue
// @grant		GM_getValue
// @grant		GM_setValue
// @author      CoLdAsIcE
// ==/UserScript==

(async () => {
	'use strict';

	let $hideGal = await GM.getValue("EHXFade_hidevisited", false);

	async function isGalVisited(gid) {
		let $md = await GM.getValue("g_" + gid, 0);
		if ($md == 1) {
			return true;
		}

		return false;
	}

	async function visitGal(gid) {
		if (!await isGalVisited(gid)) {
			GM.setValue("g_" + gid, 1);
		}
	}

	function saveViewedGal() {
		if (document.URL.match(/^https?:\/\/(e-|e[^-])hentai\.org\/g\/.*$/)) { //gallery case
			//record visited galleries to local DB
			const $gal_idx = document.URL.match(/^https?:\/\/(?:e-|e[^-])hentai\.org\/g\/(\d*)\/.*$/);
			console.log("should match 2 items:", $gal_idx, "Should match gal nr:", $gal_idx[1])

			if (!isNaN($gal_idx[1])) {
				const gal_id = parseInt($gal_idx[1])

				visitGal(gal_id);
			}
		}
	}

	function fadeThumb($tag, tr = false) {
		let $p
		const $alpha = parseFloat(0.2);
		
		if (tr) {
			$p = $tag.closest('tr');
		} else {
			$p = $tag.closest('.gl1t');
		}

		if (isNaN($alpha))
			$alpha = '0.2';

		$p.css('opacity', $alpha);

		$p.hover(
			function () {
				$(this).stop().fadeTo('fast', 1);
			},
			function () {
				$(this).stop().fadeTo('fast', $alpha);
			}
		);
	}


	//fades thumbnails that is divs
	async function fadeViewedGalThumb() {
		console.log("should contain many elements:", $('.itg.gld > div.gl1t'), "GalThumb")
		$('.itg.gld > div.gl1t').each(async function () {
			if (document.URL.match(/^https?:\/\/(e-|e[^-])hentai\.org\/(?!s).*$/) && self == top) { //search / index case, exclude iframe
				const $tagContainer = $(this);
				const $gallery = $(this).closest('.gl1t');
				const $gal_href = $tagContainer.closest('.gl1t').find('div.gl3t a').first().attr('href');
				const $gal_idx = $gal_href.match(/^https?:\/\/(?:e-|e[^-])hentai\.org\/g\/(\d*)\/.*$/);

				if (!isNaN($gal_idx[1])) {
					const gal_id = parseInt($gal_idx[1], 10);

					if (await isGalVisited(gal_id)) {
						if (!$hideGal) {
							fadeThumb($tagContainer);
							$gallery.show();

							//apply visited color to a tag
							$('<style type="text/css">' +
								'.gl1t > a:visited > div {font-weight:normal; color:#4b90eb !important; }' +
								'</style>')
								.appendTo("head");

						} else {
							$gallery.hide();
						}
					}
				}
			}
		});
	}

	//fades anything with table
	async function fadeViewedGalTable(compact = null) {
		console.log("should contain many elements:", $('table.itg > tbody > tr'), "GalTable")

		const className = compact ? 'gl1c' : 'gl1m'
		const title = compact ? '.gl3c' : '.gl3m'

		$('table.itg > tbody > tr').each(async function () {
			const isAGallery = this.firstElementChild.classList[0] === className

			if (document.URL.match(/^https?:\/\/(e-|e[^-])hentai\.org\/(?!s).*$/) && self == top && isAGallery) { //search / index case, exclude iframe
				const $tagContainer = $(this);
				const $gallery = $(this).closest('tr');
				const $gal_href = $tagContainer.closest('tr').find(title + ' a').first().attr('href');
				const $gal_idx = $gal_href.match(/^https?:\/\/(?:e-|e[^-])hentai\.org\/g\/(\d*)\/.*$/);

				if (!isNaN($gal_idx[1])) {
					const gal_id = parseInt($gal_idx[1], 10);

					if (await isGalVisited(gal_id)) {
						if (!$hideGal) {
							fadeThumb($tagContainer, true);
							$gallery.show();
							if (compact) {
								//apply visited color to compact a tag
								$('<style type="text/css">' +
									title + ' > a:visited > div {font-weight:normal; color:#4b90eb !important; }' +
									'</style>')
									.appendTo("head");
							} else {
								//apply visited color to minimal and minimal+ a tag
								$('<style type="text/css">' +
									title + ' > a:visited > div {font-weight:normal; color:#4b90eb !important; }' +
									'</style>')
									.appendTo("head");
							}
						} else {
							$gallery.hide();
						}
					}
				}

			}
		});
	}

	//fades extended
	async function fadeViewedGalExt() {
		console.log("should contain many elements:", $('table.itg > tbody > tr'), "fadeGalExt")

		$('table.itg > tbody > tr').each(async function () {
			if (document.URL.match(/^https?:\/\/(e-|e[^-])hentai\.org\/(?!s).*$/) && self == top) { //search / index case, exclude iframe
				const $tagContainer = $(this);
				const $gallery = $(this).closest('tr');
				const $gal_href = $tagContainer.closest('tr').find('.gl2e a').last().attr('href');
				const $gal_idx = $gal_href.match(/^https?:\/\/(?:e-|e[^-])hentai\.org\/g\/(\d*)\/.*$/);

				if (!isNaN($gal_idx[1])) {
					const gal_id = parseInt($gal_idx[1], 10);

					if (await isGalVisited(gal_id)) {
						if (!$hideGal) {
							fadeThumb($tagContainer, true);
							$gallery.show();

							//apply visited color to minimal and minimal+ a tag
							$('<style type="text/css">' +
								'.gl2e div a:visited div > div {font-weight:normal; color:#4b90eb !important; }' +
								'</style>')
								.appendTo("head");
						} else {
							$gallery.hide();
						}
					}
				}
			}
		});
	}

    async function removeBadTags() {
        switch ($select.val()) {
            case 'p':
            case 'm':
                hideTags('.gl3m.glname', '.gltm')
                break;
            case 'l':
                hideTagsCompact('tr > .gl3c.glname > a > div > .gt[style*="color"]')
                break;
            case 'e':
                hideTagsExtended('.gl2e table tbody tr .gt[style*="color"]:first-child')
                break;
            case 't':
                hideTags('.itg.gld > div.gl1t', '.gl6t')
                break;
        }

        async function hideTags(classSelector, TagName) {
            $(classSelector).each(function () {
                const $blankGif = $(this).find(TagName)
                const $image = $(this);
                console.log('found tags to hide', "minimal or thumbnail")

                if ($blankGif.length > 0) {
                    $image.hide();
                }
            });
        }

        async function hideTagsCompact(classSelector) {
            console.log('hide tags compact')
            $(classSelector).each(function () {
                const $blankGif = $(this)
                console.log('found tags to hide', "compact")

                if ($blankGif.length > 0) {
                    $blankGif.closest('tr').hide()
                }
            });
        }

        async function hideTagsExtended(classSelector) {
            console.log('hide tags Extended')
            $(classSelector).each(function () {
                const $blankGif = $(this)
                console.log('found tags to hide', "extended")

                if ($blankGif.length > 0) {
                    $blankGif.closest('.itg.glte > tbody > tr').hide()
                }
            });
        }
    }

    function css() {
        if (document.URL.match(/^https?:\/\/(e-)hentai\.org/)) {
            $('<style type="text/css">' +
              'div.hideGal {width:65px; height:auto; position:fixed; margin-left:-76px; background-color:#EDEBDF; color:#5C0D11; border: 1px solid #5C0D11; z-index: 10; cursor:pointer; }' +
              'div.hideGal div.tab { margin:6px; text-align: center;}' +
              'div.hideGalWide {width:65px; height:auto; color:#5C0D11; border: 1px solid #5C0D11; z-index: 10; cursor:pointer; }' +
              'div.hideGalWide div.tab { margin:6px; text-align: center;}' +
              '</style>').appendTo("head");
        } else {
            $('<style type="text/css">' +
              'div.hideGal {width:65px; height:auto; position:fixed; margin-left:-76px; background-color:#4F535B; color:skyblue; border: 1px solid #000000; z-index: 10; cursor:pointer; }' +
              'div.hideGal div.tab { margin:6px; text-align: center;}' +
              'div.hideGalWide {width:65px; height:auto; color:skyblue; border: 1px solid #000000; z-index: 10; cursor:pointer; }' +
              'div.hideGalWide div.tab { margin:6px; text-align: center;}' +
              '</style>').appendTo("head");
        }
    }

    function hideVisitedGal() {
        //add a hide gallery tab
        const ele = document.getElementsByClassName("ido")
        const width = ele.length > 0 && document.getElementsByClassName("ido")[0].clientWidth
        if(width > 1380){
            if (!$hideGal) {
                $('div#toppane').prepend('<div class="hideGalWide"><div class="tab" id="toggleseen">Hide viewed galleries</div></div>');
            } else {
                $('div#toppane').prepend('<div class="hideGalWide"><div class="tab" id="toggleseen">Show viewed galleries</div></div>');
            }
        } else {
            if (!$hideGal) {
                $('div.ido').prepend('<div class="hideGal"><div class="tab" id="toggleseen">Hide viewed galleries</div></div>');
            } else {
                $('div.ido').prepend('<div class="hideGal"><div class="tab" id="toggleseen">Show viewed galleries</div></div>');
            }
        }

		//hide or show gallery
		$('#toggleseen').parent().click(function (e) {
			$hideGal = !$hideGal;

			GM.setValue("EHXFade_hidevisited", $hideGal);

			if ($hideGal) {
				$("#toggleseen").text("Show viewed galleries");
			} else {
				$("#toggleseen").text("Hide viewed galleries");
			}

			applyChanges();

		});
	}

	function applyChanges() {
		//make sure FadeGalleries are not run everytime we open a gallery
		const openedGal = document.URL.match(/^https?:\/\/(?:e-|e[^-])hentai\.org\/g\/(\d*)\/.*$/) || false

		if (!openedGal) {
			FadeGalleries();
		}
	}

	function FadeGalleries() {
		//fade based on what viewing style is used
		console.log("should be a html element", document.querySelector("#toggleseen"), "FadeGalleries")

		switch ($select.val()) {
			case 'p':
			case 'm':
				fadeViewedGalTable();
				break;
			case 'l':
				fadeViewedGalTable(true);
				break;
			case 'e':
				fadeViewedGalExt();
				break;
			case 't':
				fadeViewedGalThumb();
				break;
		}
	}

	const $select = $('#dms div select')

	css();
	hideVisitedGal();
	saveViewedGal();
	applyChanges();
	removeBadTags();
})();