NHentai Improved

Partially fade/remove non-english, HQ thumbnails, mark as read, subs, version grouping etc.

As of 2020-11-22. See the latest version.

// ==UserScript==
// @name         NHentai Improved
// @namespace    Hentiedup
// @version      1.7.9
// @description  Partially fade/remove non-english, HQ thumbnails, mark as read, subs, version grouping etc.
// @author       Hentiedup
// @match        https://nhentai.net/*
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// @icon         https://i.imgur.com/1lihxY2.png
// @noframes
// ==/UserScript==

(function() {
    'use strict';

    //YOU SHOULD NOT TOUCH THE SETTINGS HERE. THEY ARE NOW AVAILABLE ON THE SITE IN THE PROFILE SETTINGS

	//== non-english settings ==//
	var remove_non_english = GM_getValue("remove_non_english", false);
	var partially_fade_all_non_english = GM_getValue("partially_fade_all_non_english", true);
	var non_english_fade_opacity = GM_getValue("non_english_fade_opacity", 0.3);

	//== browse sections ==//
	var browse_thumbnail_width = GM_getValue("browse_thumbnail_width", 250);
	var browse_thumnail_container_width = GM_getValue("browse_thumnail_container_width", 1350);
	var load_high_quality_browse_thumbnails = GM_getValue("load_high_quality_browse_thumbnails", true);

	//== comic pages view ==//
	var pages_thumbnail_width = GM_getValue("pages_thumbnail_width", 300);
	var pages_thumnail_container_width = GM_getValue("pages_thumnail_container_width", 1350);
	var load_high_quality_pages_thumbnails = GM_getValue("load_high_quality_pages_thumbnails", true);

    var max_image_reload_attempts = 20;

	//== mark as read system ==//
	var mark_as_read_system_enabled = GM_getValue("mark_as_read_system_enabled", true);
	var marked_as_read_fade_opacity = GM_getValue("marked_as_read_fade_opacity", 0.3);
	var read_tag_font_size = GM_getValue("read_tag_font_size", 15);

	//== subscription system ==//
	var subscription_system_enabled = GM_getValue("subscription_system_enabled", true);

    //== version grouping system ==//
    var version_grouping_enabled = GM_getValue("version_grouping_enabled", true);
    var version_grouping_filter_brackets = GM_getValue("version_grouping_filter_brackets", false);
    var auto_group_on_page_comics = GM_getValue("auto_group_on_page_comics", true);
    var flagEn = "https://i.imgur.com/vSnHmmi.gif";
    var flagJp = "https://i.imgur.com/GlArpuS.gif";
    var flagCh = "https://i.imgur.com/7B55DYm.gif";

    //== comic reader system ==//
    var comic_reader_improved_zoom = GM_getValue("comic_reader_improved_zoom", true);
    var remember_zoom_level = GM_getValue("remember_zoom_level", true);
    var zoom_level = Number(GM_getValue("zoom_level", 1.0));

    //== tag blocking system ==//
    var tag_blocking_enabled = GM_getValue("tag_blocking_enabled", true);

    var banIcon = `<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="ban" class="svg-inline--fa fa-ban fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 8C119.034 8 8 119.033 8 256s111.034 248 248 248 248-111.034 248-248S392.967 8 256 8zm130.108 117.892c65.448 65.448 70 165.481 20.677 235.637L150.47 105.216c70.204-49.356 170.226-44.735 235.638 20.676zM125.892 386.108c-65.448-65.448-70-165.481-20.677-235.637L361.53 406.784c-70.203 49.356-170.226 44.736-235.638-20.676z"></path></svg>`;

	//================= Getting arrays ready =================//
	if(true) {
        var SubArray = [];
        var SubArrayString = GM_getValue("SubArrayString", null);
        if(SubArrayString == "null")
            SubArrayString = "[]";
        if(SubArrayString) { SubArray = JSON.parse(SubArrayString); }

        var MARArray = [];
        var MARArrayString = GM_getValue("MARArrayString", null);
        if(MARArrayString == "null")
            MARArrayString = "[]";
        if(MARArrayString) { MARArray = JSON.parse(MARArrayString); }

        var unreadImg = '<svg style="vertical-align: middle;" width="15" height="15" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="book-open" class="svg-inline--fa fa-book-open fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M542.22 32.05c-54.8 3.11-163.72 14.43-230.96 55.59-4.64 2.84-7.27 7.89-7.27 13.17v363.87c0 11.55 12.63 18.85 23.28 13.49 69.18-34.82 169.23-44.32 218.7-46.92 16.89-.89 30.02-14.43 30.02-30.66V62.75c.01-17.71-15.35-31.74-33.77-30.7zM264.73 87.64C197.5 46.48 88.58 35.17 33.78 32.05 15.36 31.01 0 45.04 0 62.75V400.6c0 16.24 13.13 29.78 30.02 30.66 49.49 2.6 149.59 12.11 218.77 46.95 10.62 5.35 23.21-1.94 23.21-13.46V100.63c0-5.29-2.62-10.14-7.27-12.99z"></path></svg>';
        var readImg = '<svg style="vertical-align: middle;" width="15" height="15" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="book" class="svg-inline--fa fa-book fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z"></path></svg>';

        var BlockTagArray = [];
        var BlockTagArrayString = GM_getValue("BlockTagArrayString", null);
        if(BlockTagArrayString == "null")
            BlockTagArrayString = "[]";
        if(BlockTagArrayString) { BlockTagArray = JSON.parse(BlockTagArrayString); }
	}
	//========================================================//

	//================== Adding stylesheets ==================//
	if(true) {
		if(remove_non_english) {
			addGlobalStyle(`
				.gallery:not([data-tags~='12227']) {
					display: none;
				}
			`);
		}
		else if(!remove_non_english && partially_fade_all_non_english) {
			addGlobalStyle(`
				.gallery:not([data-tags~='12227']) > .cover > img, .gallery:not([data-tags~='12227']) > .cover > .caption{
					opacity: ` + non_english_fade_opacity + `;
				}
			`);
		}

        if(mark_as_read_system_enabled)
        {
            let MARArraySelector = "";
            for(let i = 0; i < MARArray.length; i++)
                MARArraySelector += `.cover[href="`+MARArray[i]+`"] > img, .cover[href="`+MARArray[i]+`"] > .caption, `;
            MARArraySelector = MARArraySelector.substr(0, MARArraySelector.length-2);

            addGlobalStyle(`
				`+MARArraySelector+`
				{
					opacity: `+marked_as_read_fade_opacity+`;
				}
			`);
        }

        if(tag_blocking_enabled) {
            let blockedTagsStylingString = "";
            for(let i = 0; i < BlockTagArray.length; i++)
            {
                blockedTagsStylingString += "html.theme-black a.tag.tag-" + BlockTagArray[i][0] + " > span" +
                    ", html.theme-black a.tag.tag-" + BlockTagArray[i][0] + ":hover" + " > span" +
                    ", html.theme-black a.tag.tag-" + BlockTagArray[i][0] + ":active" + " > span" +
                    ", html.theme-black a.tag.tag-" + BlockTagArray[i][0] + ":focus" + " > span" +
                    ", a.tag.tag-" + BlockTagArray[i][0] + " > span" +
                    ", a.tag.tag-" + BlockTagArray[i][0] + ":hover" + " > span" +
                    ", a.tag.tag-" + BlockTagArray[i][0] + ":active" + " > span" +
                    ", a.tag.tag-" + BlockTagArray[i][0] + ":focus" + " > span";

                if(i < BlockTagArray.length-1)
                    blockedTagsStylingString += ", ";
            }
            //console.log(BlockTagArray);
            //console.log(blockedTagsStylingString);

			addGlobalStyle(`
				`+blockedTagsStylingString+` {
					background-color: #500;
				}

				.blockTagButton
				{
					display: inline-block;
					width: 13px;
					height: 13px;
					vertical-align: middle;
					cursor: pointer;
					margin-left: 2px;
				}
				.blockTagButton > svg
				{
					vertical-align: top;
					color: #ff5454;
					width: 13px;
					height: 13px;
				}
				.blockTagButton:active > svg, .blockTagButton:hover > svg, .blockTagButton:focus > svg
				{
					color: #822B2B;
				}
			`);
        }

        //fixing too long cover images
        addGlobalStyle(`
			.gallery, .gallery > .cover {
				max-height: `+(browse_thumbnail_width*1.42)+`px;
			}
			.gallery > .cover {
				overflow: hidden;
				padding: 0 !important;
			}
			.gallery > .cover > img {
				position: relative;
				min-height: 100%;
			}
		`);

		addGlobalStyle(`
			/*browsing comics*/
			.container.index-container, #favcontainer {
				text-align: center;
				max-width: 100%;
				width: ` + browse_thumnail_container_width + `px;
			}
			.gallery > .cover > img {
				width: 100%;
			}
			.container.index-container > div.gallery, #favcontainer > .gallery-favorite {
				width: ` + browse_thumbnail_width + `px;
			}

			/*view comic pages*/
			div.thumb-container {
				width: auto;
			}
			#thumbnail-container {
				text-align: center;
				max-width: 100%;
				width: ` + pages_thumnail_container_width + `px;
			}
				div.thumb-container img {
				width: ` + pages_thumbnail_width + `px;
			}
		`);

        if(version_grouping_enabled)
        {
            addGlobalStyle(`
				.overlayFlag
				{
					position: absolute;
					display: inline-block;
					top: 3px;
					left: 3px;
					z-index: 3;
					width: 18px;
					height: 12px;
				}
				.numOfVersions {
					border-radius: 10px;
					padding: 5px 10px;
					position: absolute;
					background-color: rgba(0,0,0,.7);
					color: rgba(255,255,255,.8);
					top: 7.5px;
					left: 105px;
					font-size: 12px;
					font-weight: 900;
					opacity: 1;
					width: 40px;
					z-index: 2;
					display: none;
				}
				.findVersionButton {
					border-radius: 10px;
					padding: 5px 10px;
					position: absolute;
					background-color: rgba(0,0,0,.4);
					color: rgba(255,255,255,.8);
					bottom: 7.5px;
					left: 7.5px;
					font-size: 12px;
					font-weight: 900;
					opacity: 1;
					width: 125px;
					z-index: 2;
					cursor: pointer;
				}
				.versionNextButton {
					border-radius: 10px;
					padding: 5px 10px;
					position: absolute;
					background-color: rgba(0,0,0,.7);
					color: rgba(255,255,255,.8);
					top: 7.5px;
					right: 7.5px;
					font-size: 12px;
					font-weight: 900;
					opacity: 1;
					display: none;
					z-index: 2;
					cursor: pointer;
				}
				.versionPrevButton {
					border-radius: 10px;
					padding: 5px 10px;
					position: absolute;
					background-color: rgba(0,0,0,.7);
					color: rgba(255,255,255,.8);
					top: 7.5px;
					left: 7.5px;
					font-size: 12px;
					font-weight: 900;
					opacity: 1;
					z-index: 2;
					display: none;
					cursor: pointer;
				}

				.findVersionButton:focus, .findVersionButton:hover, .findVersionButton:active,
				.versionNextButton:focus, .versionNextButton:hover, .versionNextButton:active,
				.versionPrevButton:focus, .versionPrevButton:hover, .versionPrevButton:active
				{
					background-color: rgba(50,50,50,1);
				}
			`);
        }

		if(mark_as_read_system_enabled)
		{
			addGlobalStyle(`
				.readTag {
					border-radius: 10px;
					padding: 5px 10px;
					position: absolute;
					background-color: rgba(0,0,0,.7);
					color: rgba(255,255,255,.8);
					bottom: 7.5px;
					right: 7.5px;
					font-size: `+read_tag_font_size+`px;
					font-weight: 900;
					opacity: 1;
				}

				#markAsRead, #markAsRead:visited {
					background-color: #3d9e48;
				}
				#markAsRead:active, #markAsRead:hover {
					background-color: #52bc5e;
				}

				#markAsUnRead, #markAsUnRead:visited {
					background-color: rgb(218, 53, 53);
				}
				#markAsUnRead:active, #markAsUnRead:hover {
					background-color: #e26060;
				}

				.gallery {
					position: relative;
				}
			`);
		}

		if(subscription_system_enabled) {
			addGlobalStyle(`
				#tags .subbedTag, #tags .subbedTag:visited {
					background-color: #2c5030;
				}
				#tags .subbedTag:active, #tags .subbedTag:hover {
					background-color: #416144;
				}

				#subTo, #subTo:visited {
					background-color: #3d9e48;
				}
				#subTo:active, #subTo:hover {
					background-color: #52bc5e;
				}

				#unsubTo, #unsubTo:visited {
					background-color: rgb(218, 53, 53);
				}
				#unsubTo:active, #unsubTo:hover {
					background-color: #e26060;
				}

				#sub-content ul {
					text-align: left;
				}
				#sub-content li {
					box-sizing: border-box;
					display: inline-block;
					width: 25%;
					text-align: center;
					padding: 5px 20px;
				}

				#subTo, #unsubTo {
					height: auto;
					line-height: initial;
					cursor: pointer;
					font-size: 0.5em;
					padding: 6px 12px;
				}
			`);
		}
	}
	//========================================================//


	//================== On Comic info page ==================//
	if(window.location.href.match(/^https:\/\/nhentai\.net\/g\/\d+?\/(\?.*|\#.*|)$/g)) //if on the comic info page
	{
		//=== Mark as read system ===//
		if(mark_as_read_system_enabled) {
			var item = window.location.href.split("nhentai.net")[1].split("?")[0].split("#")[0]; //get item from url

			if(MARArray.includes(item)) //if item is marked as read
				$(".buttons").append('<a href="#" id="markAsUnRead" class="btn btn-secondary">'+unreadImg+' <span style="vertical-align: middle;">Mark as unread</span></a>'); //..add unmark button
			else
				$(".buttons").append('<a href="#" id="markAsRead" class="btn btn-secondary">'+readImg+' <span style="vertical-align: middle;">Mark as read</span></a>'); //...add mark button

			AddMARClickListeners();
		}
		//===========================//

		//==== Subscribe system =====//
		if(subscription_system_enabled) {
			let SubArraySelector = SubArray.join("'], .tag[href='");
			$(".tag[href='" + SubArraySelector + "']").addClass("subbedTag");
		}
		//===========================//

		//=== HQ thumbnail system ===//
		if(load_high_quality_pages_thumbnails && $("#thumbnail-container").length !== 0) {
			$("#thumbnail-container .thumb-container > .gallerythumb > img").on("load", function(){
                if($(this).attr("src").startsWith("http"))
                {
                    $(this).attr("src", $(this).attr("data-src").replace(/\/\/t\d*?\./g, "//i.").replace("t.jpg", ".jpg").replace("t.png", ".png"));

                    //retry loading image
                    $(this).on("error", function(){
                        //count reload attempts
                        let attempts = parseInt($(this).attr("img-reloads"));
                        if(!attempts)
                            attempts = 0;
                        else if(attempts >= max_image_reload_attempts) //after x attempts, give up
                        {
                            $(this).off("error");
                            console.log("gave up on: " + $(this).attr("src"));
                            return;
                        }

                        $(this).attr("src", $(this).attr("src")); //reload
                        attempts++;
                        $(this).attr("img-reloads", attempts);
                        console.log("image reload attempt " + attempts + " for: " + $(this).attr("src"));
                    });
                    $(this).off("load");
                }
			});
		}
		//===========================//
	}
	//========================================================//

	//============== On Artist/group info page ===============//
	else if(subscription_system_enabled && (window.location.href.match(/^.+?\/artist\/.+?\/(popular)?(\?.*?|\#.*?|)$/g) || window.location.href.match(/^.+?\/group\/.+?\/(popular)?(\?.*?|\#.*?|)$/g))) //in artist or group page
	{
		var subItem = window.location.href.split("nhentai.net")[1].split("popular")[0].split("?")[0].split("#")[0]; //get item from url
		if(SubArray.includes(subItem)) //if subscribed
			$("h1").append('<a href="#" id="unsubTo" class="btn btn-secondary"><span style="vertical-align: middle;">Unsubscribe</span></a>'); //...add unsub button
		else
			$("h1").append('<a href="#" id="subTo" class="btn btn-secondary"><span style="vertical-align: middle;">Subscribe</span></a>'); //...add sub button

		AddSubClickListeners();
	}
	//========================================================//

	//====================== Subs page =======================//
	else if(subscription_system_enabled && window.location.href.match(/^.+?\/subscriptions\/(\?.*|\#.*|)$/g)) //in subs page
	{
		$("head title").html('Subscriptions').prop("style", "font-size: 3.5em;");
		$("#content").prepend('<h1>Subscriptions</h1>');
		$("#content > .container").removeClass("error").addClass("artists-section").prop("id", "tag-container");
        $(".artists-section").before("<h2 style='font-size: 2em;'>Artists</h2>");
        $(".artists-section").after('<div class="container groups-section" id="tag-container"></div>');
        $(".groups-section").before("<h2 style='font-size: 2em; margin-top: 50px;'>Groups</h2>");

		var artistsHTML = "";
        var groupsHTML = "";
		for(let i = 0; i < SubArray.length; i++) {
            if(SubArray[i].split("/")[1].split("/")[0] == "artist")
                artistsHTML += '<a class="tag" href="'+SubArray[i]+'">'+(SubArray[i].split("/")[2].split("/")[0].replace(/\-/g, " "))+'</a>';
            else
                groupsHTML += '<a class="tag" href="'+SubArray[i]+'">'+(SubArray[i].split("/")[2].split("/")[0].replace(/\-/g, " "))+'</a>';
		}
		$(".artists-section").html(artistsHTML);
        $(".groups-section").html(groupsHTML);
	}
	//========================================================//

    //====================== Reader Page =====================//
    else if(window.location.href.match(/^.+?\/g\/\d+?\/\d+\/$/g))
    {
        if(comic_reader_improved_zoom)
        {
            let prevVal = 1.0;
            if(remember_zoom_level)
                prevVal = zoom_level;
            let curVal = prevVal;
            SetReaderImageScale(curVal);

            $('body').on('keydown', function(e) {
                if(e.key == '+')
                {
                    curVal = prevVal+0.1;
                    if(curVal > 3)
                        curVal = 3;

                    SetReaderImageScale(curVal);
                    prevVal = curVal;
                }
                else if(e.key == '-')
                {
                    curVal = prevVal-0.1;
                    if(curVal < 0.1)
                        curVal = 0.1;

                    SetReaderImageScale(curVal);
                    prevVal = curVal;
                }
            });

            //make sure the current zoom-level stays between pages
            var observer = new MutationObserver(function( mutations ) {
                for(let i = 0; i < mutations.length; i++)
                    if(mutations[i].type == 'attributes')
                        SetReaderImageScale(curVal);
            });
            observer.observe($("#image-container > a")[0], {attributes: true, childList: false, characterData: false});

            $("section.reader-bar button.reader-zoom-out").click(function(e){
                e.preventDefault();
                e.stopPropagation();
                curVal = prevVal-0.1;
                if(curVal < 0.1)
                    curVal = 0.1;

                SetReaderImageScale(curVal);
                prevVal = curVal;
            });
            $("section.reader-bar button.reader-zoom-in").click(function(e){
                e.preventDefault();
                e.stopPropagation();
                curVal = prevVal+0.1;
                if(curVal > 3)
                    curVal = 3;

                SetReaderImageScale(curVal);
                prevVal = curVal;
            });
        }
    }
    //========================================================//

	//====================== all pages with lists of comics ====================//
	if($(".container.index-container, #favcontainer.container, #recent-favorites-container").length !== 0)
	{
        //=== Tag blocking system ===//
        if(tag_blocking_enabled && BlockTagArray.length > 0)
        {
            let selector = "";
            for(let i = 0; i < BlockTagArray.length; i++)
            {
                selector += ".gallery[data-tags*=" + BlockTagArray[i][0] + "]";
                if(i < BlockTagArray.length-1)
                    selector += ", ";
            }
            $(selector).remove();
        }
        //===========================//

		//=== HQ thumbnail system ===//
		if(load_high_quality_browse_thumbnails) {
			$(".container.index-container > .gallery > .cover > img, #favcontainer.container > .gallery-favorite > .gallery > .cover > img").on("load", function(){
                if($(this).attr("src").startsWith("http"))
                {
                    $(this).attr("src", $(this).attr("data-src").replace(/\/\/t\d*?\./g, "//i.").replace("thumb.jpg", "1.jpg").replace("thumb.png", "1.png"));
                    //console.log("image load for: " + $(this).attr("src"));

                    //retry loading image
                    $(this).on("error", function(){
                        //count reload attempts
                        let attempts = parseInt($(this).attr("img-reloads"));
                        if(!attempts)
                            attempts = 0;
                        else if(attempts >= max_image_reload_attempts) //after x attempts, give up
                        {
                            $(this).off("error");
                            console.log("gave up on: " + $(this).attr("src"));
                            return;
                        }

                        $(this).attr("src", $(this).attr("src")); //reload
                        attempts++;
                        $(this).attr("img-reloads", attempts);
                        console.log("image reload attempt " + attempts + " for: " + $(this).attr("src"));
                    });

                    $(this).off("load");
                }
			});
		}
		//===========================//

		//=== Mark as read system ===//
		if(mark_as_read_system_enabled) {
			let MARArraySelector = MARArray.join("'], .cover[href='");
			$(".cover[href='" + MARArraySelector + "']").append("<div class='readTag'>READ</div>");
		}
		//===========================//

        //=== Version Grouping system ===//
		if(version_grouping_enabled) {
			$(".cover").parent().append("<div class='findVersionButton'>Find Alt Versions</div>");
            $(".cover").parent().append("<div class='numOfVersions'>1/1</div>");
            $(".cover").parent().append("<div class='versionNextButton'>►</div>");
            $(".cover").parent().append("<div class='versionPrevButton'>◄</div>");

            $(".findVersionButton").click(function(e){
                e.preventDefault();
                AddAltVersionsToThis($(this));
            });

            if(auto_group_on_page_comics && !remove_non_english)
                GroupAltVersionsOnPage();

            $(".versionPrevButton").click(function(e){
                e.preventDefault();
                let toHide = $(this).parent().find(".cover").filter(":visible");
                let toShow = toHide.prev();
                if(!toShow || toShow.length <= 0)
                    return;
                if(!toShow.is(".cover"))
                    toShow = toHide.prevUntil(".cover", ":last").prev();
                if(!toShow || toShow.length <= 0)
                    return;
                toHide.hide(100);
                toShow.show(100);
                let n = $(this).parent().find(".numOfVersions");
                n.text( (Number(n.text().split("/")[0])-1) + "/" + n.text().split("/")[1] );
            });
            $(".versionNextButton").click(function(e){
                e.preventDefault();
                let toHide = $(this).parent().find(".cover").filter(":visible");
                let toShow = toHide.next();
                if(!toShow || toShow.length <= 0)
                    return;
                if(!toShow.is(".cover"))
                    toShow = toHide.nextUntil(".cover", ":last").next();
                if(!toShow || toShow.length <= 0)
                    return;
                toHide.hide(100);
                toShow.show(100);
                let n = $(this).parent().find(".numOfVersions");
                n.text( (Number(n.text().split("/")[0])+1) + "/" + n.text().split("/")[1] );
            });
		}
		//===========================//
	}
	//==========================================================================//

	//====================== Settings page ===================//
	if($("#settings-container").length !== 0)
	{

        //this is actually needed here even if tag blocking is disabled (so that you can still remove tags properly). If it is enabled, then there is no need to add it again, thus: add it if it's NOT on
        if(!tag_blocking_enabled) {
            let blockedTagsStylingString = "";
            for(let i = 0; i < BlockTagArray.length; i++)
            {
                blockedTagsStylingString += "html.theme-black a.tag.tag-" + BlockTagArray[i][0] + " > span" +
                    ", html.theme-black a.tag.tag-" + BlockTagArray[i][0] + ":hover" + " > span" +
                    ", html.theme-black a.tag.tag-" + BlockTagArray[i][0] + ":active" + " > span" +
                    ", html.theme-black a.tag.tag-" + BlockTagArray[i][0] + ":focus" + " > span" +
                    ", a.tag.tag-" + BlockTagArray[i][0] + " > span" +
                    ", a.tag.tag-" + BlockTagArray[i][0] + ":hover" + " > span" +
                    ", a.tag.tag-" + BlockTagArray[i][0] + ":active" + " > span" +
                    ", a.tag.tag-" + BlockTagArray[i][0] + ":focus" + " > span";

                if(i < BlockTagArray.length-1)
                    blockedTagsStylingString += ", ";
            }
            //console.log(BlockTagArray);
            //console.log(blockedTagsStylingString);

			addGlobalStyle(`
				`+blockedTagsStylingString+` {
					background-color: #500;
				}

				.blockTagButton
				{
					display: inline-block;
					width: 13px;
					height: 13px;
					vertical-align: middle;
					cursor: pointer;
					margin-left: 2px;
				}
				.blockTagButton > svg
				{
					vertical-align: top;
					color: #ff5454;
					width: 13px;
					height: 13px;
				}
				.blockTagButton:active > svg, .blockTagButton:hover > svg, .blockTagButton:focus > svg
				{
					color: #822B2B;
				}
			`);
        }

		addGlobalStyle(`
			#settings-container .custom-settings {
				margin: 5px 5px 5px 20px;
			}

			#settings-container .custom-settings input[type="text"],
			#settings-container .custom-settings input[type="number"]{
				width: 70px;
				height: 25px;
				border-radius: 3px;
				text-align: center;
				padding: 0;
			}

			#settings-container .custom-settings.disabled-setting {
				color: RGBA(153, 153, 153, 1);
				opacity: 0.3;
			}

			#settings-container h2 {position: relative;}
			#settings-container #settings-saved-mark {
				color: green;
				font-size: 15px;
				position: absolute;
				right: 0;
				top: 10px;
				display: none;
			}

			#importexportdiv {
				position: fixed;
				top: 10%;
				left: 10%;
				width: 80%;
				height: 80%;
				background-color: #393939;
				padding: 3%;
				border-radius: 15px;
			}
			#importexportdiv > textarea {
				width: 100%;
				height: 90%;
			}
		`);

        let blockedTagsHTML = "";
        for(let i = 0; i < BlockTagArray.length; i++)
            blockedTagsHTML += "<a class='tag tag-"+BlockTagArray[i][0]+" href='#'><span class='name'>"+BlockTagArray[i][1]+"</span><span class='count'></span></a>";

		let settingsHTML = `<br><div id="customSettingsContainer"><form class="form-horizontal" role="form">
			<h2>NHentai Improved Settings <span id="settings-saved-mark">Saved 🗸</span></h2>

			<h3>Non-English Settings</h3>
			<div class="custom-settings"><div class="form-control">
			<label><input id="remove_non_english" type="checkbox">
			Remove Non-English</label>
			</div></div>

			<div class="custom-settings"><div class="form-control">
			<label><input id="partially_fade_all_non_english" type="checkbox">
			Partially Fade Non-English</label>
			</div></div>

			<div class="custom-settings">
			<label>Non-English Fade Opacity
			<input id="non_english_fade_opacity" type="text" placeholder="0.0 - 1.0" autocomplete="off"></label>
			</div>


			<h3>Browse Section Settings</h3>
			<div class="custom-settings" title="height scales automatically">
			<label>Thumbnail Width
			<input id="browse_thumbnail_width" type="number" placeholder="250"> px</label>
			</div>

			<div class="custom-settings" title="max-width = 100% of available space, meaning no need to worry about going too big">
			<label>Thumbnail Container Width
			<input id="browse_thumnail_container_width" type="number" placeholder="1350"> px</label>
			</div>

			<div class="custom-settings"><div class="form-control">
			<label><input id="load_high_quality_browse_thumbnails" type="checkbox">
			HQ Thumbnails</label>
			</div></div>


			<h3>Comic Pages Section Settings</h3>
			<div class="custom-settings" title="height scales automatically">
			<label>Thumbnail Width
			<input id="pages_thumbnail_width" type="number" placeholder="250"> px</label>
			</div>

			<div class="custom-settings" title="max-width = 100% of available space, meaning no need to worry about going too big">
			<label>Thumbnail Container Width
			<input id="pages_thumnail_container_width" type="number" placeholder="1350"> px</label>
			</div>

			<div class="custom-settings"><div class="form-control">
			<label><input id="load_high_quality_pages_thumbnails" type="checkbox">
			HQ Thumbnails</label>
			</div></div>


			<h3>Comic Reader Settings</h3>
			<div class="custom-settings"><div class="form-control">
			<label><input id="comic_reader_improved_zoom" type="checkbox">
			Improved Zoom</label>
			</div></div>
<div class="custom-settings"><div class="form-control">
			<label><input id="remember_zoom_level" type="checkbox">
			Remember Zoom Level</label>
			</div></div>


			<h3>Mark As Read Settings</h3>
			<div class="custom-settings"><div class="form-control">
			<label><input id="mark_as_read_system_enabled" type="checkbox">
			Enabled</label>
			</div></div>

			<div class="custom-settings">
			<label>Fade Opacity
			<input id="marked_as_read_fade_opacity" type="text" placeholder="0.0 - 1.0" autocomplete="off"></label>
			</div>

			<div class="custom-settings">
			<label>Read Tag Font Size
			<input id="read_tag_font_size" type="number" placeholder="15"> px</label>
			</div>


			<h3>Subscription Settings</h3>
			<div class="custom-settings"><div class="form-control">
			<label><input id="subscription_system_enabled" type="checkbox">
			Enabled</label>
			</div></div>

			<h3>Version Grouping Settings</h3>
			<div class="custom-settings"><div class="form-control">
			<label><input id="version_grouping_enabled" type="checkbox">
			Enabled</label>
			</div></div>

			<div class="custom-settings"><div class="form-control">
			<label><input id="version_grouping_filter_brackets" type="checkbox">
			Filter out normal brackets for version searches<br><sup>(square brackets are always filtered out regardless of this setting)</sup></label>
			</div></div>

            <div class="custom-settings"><div class="form-control">
			<label><input id="auto_group_on_page_comics" type="checkbox">
			Automatically group on-page comics<br><sup>(doesn't search the site, just current page)</sup><br><sup style="top: -1em;">(Currently does not properly work with "Remove Non-English")</sup></label>
			</div></div>

			<h3>Tag Blocking Settings</h3>
			<div class="custom-settings"><div class="form-control">
			<label><input id="tag_blocking_enabled" type="checkbox">
			Enabled</label>
			</div></div>

			<p>Currently Blocked Tags:</p>
			`+(BlockTagArray.length > 0 ? `
			<span class="tags">`+blockedTagsHTML+`</span>
			` : "none")+`

<h3>Import/Export Data</h3>
<button id="exportButt" style="line-height: 30px; height: 30px;" type="submit" class="btn btn-primary">Export</button>
<button id="importButt" style="line-height: 30px; height: 30px;" type="submit" class="btn btn-primary">Import</button> <input id="NHIImportFile" type="file" style="display: none;">
			<br><br>
			</form>
			<br><br>
			</div>`;
		$("#settings-container").append(settingsHTML);
		InitialValuesForSettings();
		$("#settings-container form:last").change(function(){
			UpdateSettingsValues();
		});

        $("#importButt").click((e) => {
            e.preventDefault();
            e.stopPropagation();
            $("#NHIImportFile").animate({width:'toggle'},200);
        });

        $("#NHIImportFile").change((event) => {
            if (typeof window.FileReader !== 'function')
                throw ("The file API isn't supported on this browser.");
            let input = event.target;
            if (!input)
                throw ("The browser does not properly implement the event object");
            if (!input.files)
                throw ("This browser does not support the `files` property of the file input.");

            let file = input.files[0];
            let fr = new FileReader();
            fr.onload = (ev) => {
                let importedData = ev.target.result;
                if(importedData != null && confirm("File received. Import this file?"))
                {
                    let dataString = importedData;
                    dataString = dataString.replace(/(\r?\n|\r)/g, ""); //remove newlines
                    dataString.trim(); //remove whitespace around the string

					if(dataString.indexOf("|||||") < 0) {
						alert("invalid data");
						return;
					}

                    let dataArr = dataString.split("|||||");

                    if(dataArr.length > 0)
                    {
                        GM_setValue("SubArrayString", dataArr[0]);
                        console.log("NHI - SubArrayString imported");
                    }
                    if(dataArr.length > 1)
                    {
                        GM_setValue("MARArrayString", dataArr[1]);
                        console.log("NHI - MARArrayString imported");
                    }
                    if(dataArr.length > 2)
                    {
                        GM_setValue("BlockTagArrayString", dataArr[2]);
                        console.log("NHI - BlockTagArrayString imported");
                    }

                    if(dataArr.length > 3)
                    {
                        GM_setValue("remove_non_english", (String(dataArr[3]) == "true"));
                        console.log("NHI - remove_non_english imported");
                    }
                    if(dataArr.length > 4)
                    {
                        GM_setValue("partially_fade_all_non_english", (String(dataArr[4]) == "true"));
                        console.log("NHI - partially_fade_all_non_english imported");
                    }
                    if(dataArr.length > 5)
                    {
                        GM_setValue("non_english_fade_opacity", dataArr[5]);
                        console.log("NHI - non_english_fade_opacity imported");
                    }

                    if(dataArr.length > 6)
                    {
                        GM_setValue("load_high_quality_browse_thumbnails", (String(dataArr[6]) == "true"));
                        console.log("NHI - load_high_quality_browse_thumbnails imported");
                    }
                    if(dataArr.length > 7)
                    {
                        GM_setValue("browse_thumbnail_width", dataArr[7]);
                        console.log("NHI - browse_thumbnail_width imported");
                    }
                    if(dataArr.length > 8)
                    {
                        GM_setValue("browse_thumnail_container_width", dataArr[8]);
                        console.log("NHI - browse_thumnail_container_width imported");
                    }

                    if(dataArr.length > 9)
                    {
                        GM_setValue("load_high_quality_pages_thumbnails", (String(dataArr[9]) == "true"));
                        console.log("NHI - load_high_quality_pages_thumbnails imported");
                    }
                    if(dataArr.length > 10)
                    {
                        GM_setValue("pages_thumbnail_width", dataArr[10]);
                        console.log("NHI - pages_thumbnail_width imported");
                    }
                    if(dataArr.length > 11)
                    {
                        GM_setValue("pages_thumnail_container_width", dataArr[11]);
                        console.log("NHI - pages_thumnail_container_width imported");
                    }

                    if(dataArr.length > 12)
                    {
                        GM_setValue("max_image_reload_attempts", dataArr[12]);
                        console.log("NHI - max_image_reload_attempts imported");
                    }

                    if(dataArr.length > 13)
                    {
                        GM_setValue("mark_as_read_system_enabled", (String(dataArr[13]) == "true"));
                        console.log("NHI - mark_as_read_system_enabled imported");
                    }
                    if(dataArr.length > 14)
                    {
                        GM_setValue("marked_as_read_fade_opacity", dataArr[14]);
                        console.log("NHI - marked_as_read_fade_opacity imported");
                    }
                    if(dataArr.length > 15)
                    {
                        GM_setValue("read_tag_font_size", dataArr[15]);
                        console.log("NHI - read_tag_font_size imported");
                    }

                    if(dataArr.length > 16)
                    {
                        GM_setValue("subscription_system_enabled", (String(dataArr[16]) == "true"));
                        console.log("NHI - subscription_system_enabled imported");
                    }

                    if(dataArr.length > 17)
                    {
                        GM_setValue("version_grouping_enabled", (String(dataArr[17]) == "true"));
                        console.log("NHI - version_grouping_enabled imported");
                    }
                    if(dataArr.length > 18)
                    {
                        GM_setValue("version_grouping_filter_brackets", (String(dataArr[18]) == "true"));
                        console.log("NHI - version_grouping_filter_brackets imported");
                    }
                    if(dataArr.length > 19)
                    {
                        GM_setValue("auto_group_on_page_comics", (String(dataArr[19]) == "true"));
                        console.log("NHI - auto_group_on_page_comics imported");
                    }

                    if(dataArr.length > 20)
                    {
                        GM_setValue("comic_reader_improved_zoom", (String(dataArr[20]) == "true"));
                        console.log("NHI - comic_reader_improved_zoom imported");
                    }
                    if(dataArr.length > 21)
                    {
                        GM_setValue("remember_zoom_level", (String(dataArr[21]) == "true"));
                        console.log("NHI - remember_zoom_level imported");
                    }
                    if(dataArr.length > 22)
                    {
                        GM_setValue("zoom_level", Number(dataArr[22]));
                        console.log("NHI - zoom_level imported");
                    }
                    if(dataArr.length > 23)
                    {
                        GM_setValue("tag_blocking_enabled", (String(dataArr[23]) == "true"));
                        console.log("NHI - tag_blocking_enabled imported");
                    }
					location.reload();
                }
                else
                    $("#NHIImportFile").val('');
            };
            fr.readAsText(file);
        });

        $("#exportButt").click((e) => {
            e.preventDefault();
            e.stopPropagation();

            let data = SubArrayString + "|||||" +
                MARArrayString + "|||||" +
                BlockTagArrayString + "|||||" +

                remove_non_english + "|||||" +
                partially_fade_all_non_english + "|||||" +
                non_english_fade_opacity + "|||||" +

                load_high_quality_browse_thumbnails + "|||||" +
                browse_thumbnail_width + "|||||" +
                browse_thumnail_container_width + "|||||" +

                load_high_quality_pages_thumbnails + "|||||" +
                pages_thumbnail_width + "|||||" +
                pages_thumnail_container_width + "|||||" +

                max_image_reload_attempts + "|||||" +

                mark_as_read_system_enabled + "|||||" +
                marked_as_read_fade_opacity + "|||||" +
                read_tag_font_size + "|||||" +

                subscription_system_enabled + "|||||" +

                version_grouping_enabled + "|||||" +
                version_grouping_filter_brackets + "|||||" +
                auto_group_on_page_comics + "|||||" +

                comic_reader_improved_zoom + "|||||" +
                remember_zoom_level + "|||||" +
                zoom_level + "|||||" +
                tag_blocking_enabled;

            SaveToFile("NHI-Backup_" + new Date().toISOString().replace(/:/g, "-") + ".nhi", data);
        });

	}
    //========================================================//

    //====================== Own User Page ===================//
    if($("#user-container").length !== 0 && $(".user-info > h1").text().trim() == $("nav ul.menu.right a[href^='/users/']").text().replace(/<.+?>/g, "").trim())
    {
        $(".user-info > div").before(`<p><b>Comics marked as read: </b>`+MARArray.length+`</p>`); //add number of comics read to page
    }
	//========================================================//

	//====================== All pages =======================//
    if(true)
    {
        if(subscription_system_enabled) {
            $(".menu.right").prepend('<li><a href="/subscriptions/"><i class="fa fa-heartbeat"></i> Subscriptions</a></li>');
        }

        //even if the system is disabled, we should have it on in the settings so we can remove tags from there
        if(tag_blocking_enabled || $("#settings-container").length !== 0)
        {
            if($("a.tag > .count").length > 0)
            {
                $("a.tag > .count").each(function(){
                    //console.log($(this).css("background-color"));
                    $(this).append(`<div class="blockTagButton" alt="block-tag" title="` +
                                   ($(this).css("background-color") == "rgb(85, 0, 0)" ||
                                    $(this).css("background-color") == "rgb(85,0,0)" ||
                                    $(this).css("background-color") == "#500" ||
                                    $(this).css("background-color") == "#550000"
                                    ? `un` : ``)+`block tag">`+banIcon+`</div>`);
                });

                $(".blockTagButton").click(function(e){
                    e.preventDefault();
                    e.stopPropagation();
                    ToggleTagFromBlockArray($(this).parent().parent().attr("class").split("tag-")[1].split(" ")[0], $(this).parent().parent().find(".name").text().trim()); //$(this).parent().clone().children().remove().end().text().trim()
                });
            }
        }
    }
	//========================================================//



    //====================== FUNCTIONS =======================//
    function SetReaderImageScale(scale)
    {
        $("section.reader-bar .zoom-level > .value").html(scale.toFixed(1));
        $("#image-container img").css("width", 1280 * scale);
        GM_setValue("zoom_level", scale);
    }

    function ToggleTagFromBlockArray(tag, tagname)
    {
        //get the array again to make sure we have an up to date array (since other tabs could have modified it since loading this page)
        BlockTagArrayString = GM_getValue("BlockTagArrayString", null);
        if(BlockTagArrayString) { BlockTagArray = JSON.parse(BlockTagArrayString); }

        //console.log("operating on: " + tag + " - " + tagname);
        let tagObj = [tag, tagname];
        let tagObjString = JSON.stringify(tagObj);

        if(BlockTagArrayString.indexOf(tagObjString) >= 0) //remove from blocked
        {
            //console.log(BlockTagArrayString);
            BlockTagArrayString = BlockTagArrayString.replace(tagObjString+",", "").replace(","+tagObjString, "").replace(tagObjString, "");
            //console.log(BlockTagArrayString);
            BlockTagArray = JSON.parse(BlockTagArrayString);

            if($("#settings-container").length !== 0) //if on settings page, remove the tag from the list when unblocking
                $("a.tag.tag-"+tag).remove();
            else
            {
                $("a.tag.tag-"+tag+" .blockTagButton").attr("title", "block tag");
                $("a.tag.tag-"+tag+" > .name").css("background-color", "#4d4d4d");
                $("a.tag.tag-"+tag+" > .count").css("background-color", "#333");
                $("a.tag.tag-"+tag).hover(function(){
                    $("a.tag.tag-"+tag+" > .name").css("background-color", "#595959");
                    $("a.tag.tag-"+tag+" > .count").css("background-color", "#404040");
                }, function(){
                    $("a.tag.tag-"+tag+" > .name").css("background-color", "#4d4d4d");
                    $("a.tag.tag-"+tag+" > .count").css("background-color", "#333");
                });
            }
        }
        else //add to blocked
        {
            BlockTagArray.push(tagObj);
            $("a.tag.tag-"+tag+" .blockTagButton").attr("title", "unblock tag");
            $("a.tag.tag-"+tag+" > .name, a.tag.tag-"+tag+" > .count").css("background-color", "#500");
            $("a.tag.tag-"+tag).off();
        }

        BlockTagArrayString = JSON.stringify(BlockTagArray); //covert array to string
        GM_setValue("BlockTagArrayString", BlockTagArrayString); //save string
    }

    function GroupAltVersionsOnPage()
    {
        let i = 0;
        let found = $(".container > .gallery");
        while(!!found && i < found.length)
        {
            AddAltVersionsToThisFromPage(found[i]);
            i++;
            found = $(".container > .gallery");
        }
    }

    function AddAltVersionsToThisFromPage(target)
    {
        let place = $(target);
        place.addClass("ignoreThis");
        let title = place.find(".cover > .caption").text();
        if(!title || title.length <= 0)
            return;
        let found = $(".container > .gallery:not(.ignoreThis)");
        let numOfValid = 0;
        for(let i = 0; i < found.length; i++) //loop through galleries
        {
            let cap = $(found[i]).find(".caption");
            if(cap.length == 1) //if the gallery includes just one item
            {
                if(IncludesAll(cap.text(), title)) //valid target
                {
                    if(partially_fade_all_non_english)
                        $(found[i]).find(".cover > img, .cover > .caption").css("opacity", non_english_fade_opacity);

                    if($(found[i]).attr("data-tags").includes("12227")) //en
                    {
                        $(found[i]).find(".caption").append(`<img class="overlayFlag" src="`+flagEn+`">`);
                        $(found[i]).find(".cover > img, .cover > .caption").css("opacity", "1");
                    }
                    else
                    {
                        if($(found[i]).attr("data-tags").includes("6346")) //jp
                            $(found[i]).find(".caption").append(`<img class="overlayFlag" src="`+flagJp+`">`);
                        else if($(found[i]).attr("data-tags").includes("29963")) //ch
                            $(found[i]).find(".caption").append(`<img class="overlayFlag" src="`+flagCh+`">`);

                        if(!partially_fade_all_non_english)
                           $(found[i]).find(".cover > img, .cover > .caption").css("opacity", "1");
                    }

                    if(mark_as_read_system_enabled) {
                        let MARArraySelector = MARArray.join("'], .cover[href='");
                        $(found[i]).find(".cover[href='" + MARArraySelector + "']").append("<div class='readTag'>READ</div>");
                        let readTag = $(found[i]).find(".readTag");
                        if(!!readTag && readTag.length > 0)
                            readTag.parent().parent().find(".cover > img, .cover > .caption").css("opacity", marked_as_read_fade_opacity);
                    }

                    place.append($(found[i]).find(".cover"));
                    $(found[i]).addClass("deleteThis");
                    numOfValid++;
                }
            }
            else //the gallery incvludes multiple items
            {
                let addThese = false;
                for(let j = 0; j < cap.length; j++) //loop through items in the gallery
                {
                    if(IncludesAll($(cap[j]).text(), title))
                    {
                        addThese = true; //if any of them match
                        break;
                    }
                }

                if(addThese) //if any matched
                {
                    for(let j = 0; j < cap.length; j++)
                        place.append($(cap[j]).parent()); //add all
                    $(found[i]).addClass("deleteThis");
                    numOfValid += cap.length;
                }
            }
        }
        numOfValid++;
        place.removeClass("deleteThis");
        place.removeClass("ignoreThis");
        $(".deleteThis").remove();
        if(numOfValid > 1)
        {
            place.find(".cover:not(:first)").css("display", "none");
            place.find(".versionPrevButton, .versionNextButton, .numOfVersions").show(200);
            place.find(".numOfVersions").text("1/" + numOfValid);
            //place.find(".findVersionButton").hide();
        }
    }

    function IncludesAll(string, search)
    {
        string = CleanupSearchString(string);
        search = CleanupSearchString(search);
        let yes = true;
        let searches = search.split(" ");
        //console.log(string + " ::: includes all::: " + searches);
        for(let i = 0; i < searches.length; i++)
            if(!!searches[i] && searches[i].length > 0 && !string.includes(searches[i]))
                yes = false;
        //console.log(yes);
        return yes;
    }

    function AddAltVersionsToThis(target)
    {
        let place = target;
        let title = place.parent().find(".cover:visible > .caption").text();
        $.get(BuildUrl(title), function(data){
            let found = $(data).find(".container > .gallery");
            if(!found || found.length <= 0)
            {
                alert("error reading data");
                return;
            }
            place.parent().find(".cover").remove();
            try
            {
                for(let i = 0; i < found.length; i++)
                {
                    if(partially_fade_all_non_english)
                            $(found[i]).find(".cover > img, .cover > .caption").css("opacity", non_english_fade_opacity);

                    if($(found[i]).attr("data-tags").includes("12227")) //en
                    {
                        $(found[i]).find(".caption").append(`<img class="overlayFlag" src="`+flagEn+`">`);
                        $(found[i]).find(".cover > img, .cover > .caption").css("opacity", "1");
                    }
                    else
                    {
                        if($(found[i]).attr("data-tags").includes("6346")) //jp
                            $(found[i]).find(".caption").append(`<img class="overlayFlag" src="`+flagJp+`">`);
                        else if($(found[i]).attr("data-tags").includes("29963")) //ch
                            $(found[i]).find(".caption").append(`<img class="overlayFlag" src="`+flagCh+`">`);

                        if(!partially_fade_all_non_english)
                           $(found[i]).find(".cover > img, .cover > .caption").css("opacity", "1");
                    }

                    if(mark_as_read_system_enabled) {
                        let MARArraySelector = MARArray.join("'], .cover[href='");
                        $(found[i]).find(".cover[href='" + MARArraySelector + "']").append("<div class='readTag'>READ</div>");
                        let readTag = $(found[i]).find(".readTag");
                        if(!!readTag && readTag.length > 0)
                            readTag.parent().parent().find(".cover > img, .cover > .caption").css("opacity", marked_as_read_fade_opacity);
                    }

                    let thumbnailReplacement;
                    if(!!$(found[i]).find(".cover > img").attr("data-src"))
                        thumbnailReplacement = $(found[i]).find(".cover > img").attr("data-src").replace("//t.", "//i.").replace("thumb.jpg", "1.jpg").replace("thumb.png", "1.png");
                    else
                        thumbnailReplacement = $(found[i]).find(".cover > img").attr("src").replace("//t.", "//i.").replace("thumb.jpg", "1.jpg").replace("thumb.png", "1.png");

                    $(found[i]).find(".cover > img").attr("src", thumbnailReplacement);
                    place.parent().append($(found[i]).find(".cover"));
                }
            }
            catch(er)
            {
                alert("error modifying data: " + er);
                return;
            }
            place.parent().find(".cover:not(:first)").css("display", "none");
            place.parent().find(".versionPrevButton, .versionNextButton, .numOfVersions").show(200);
            place.parent().find(".numOfVersions").text("1/" + (found.length));
            place.hide(200);
        }).fail(function(e){
            alert("error getting data: " + e);
        });
    }

    function CleanupSearchString(title)
    {
        title = title.replace(/\[.*?\]/g, "");
        title = title.replace(/\【.*?\】/g, "");
        if(version_grouping_filter_brackets)
            title = title.replace(/\(.*?\)/g, "");
        return title;
    }

    function BuildUrl(title)
    {
        let url = CleanupSearchString(title);
        url = url.replace(/\s+?-/g, " ");
        url = url.replace(/\s\S+?:\S+?(\s|$)/g, " "); //remove two part words with ":" in the middle e.g. "Re:Dive", because the site search can't handle that and just removing the ":" breaks the word again ruining the search
        url = url.replace(/[,|♡|♂|♀|;|:|…]/g, " "); //some symbols do not get handled by encodeURIComponent and break search.
        //Currently not sure how to go about creating a whitelist because of all the japanese/chinese etc. so I guess I'll just filter out some specific problem symbols as I run into them
        //though "," is filtered out for another reason, mainly because it's used so inconsistently in titles

        url = url.trim();
        url = encodeURIComponent(url);
        //alert(url);
        url = "https://nhentai.net/search/?q=" + url;
        return url;
    }

	function InitialValuesForSettings() {
		$("#remove_non_english").prop("checked", remove_non_english);
		$("#partially_fade_all_non_english").prop("checked", partially_fade_all_non_english);
		$("#non_english_fade_opacity").val(non_english_fade_opacity);
		$("#browse_thumbnail_width").val(browse_thumbnail_width);
		$("#browse_thumnail_container_width").val(browse_thumnail_container_width);
		$("#load_high_quality_browse_thumbnails").prop("checked", load_high_quality_browse_thumbnails);
		$("#pages_thumbnail_width").val(pages_thumbnail_width);
		$("#pages_thumnail_container_width").val(pages_thumnail_container_width);
		$("#load_high_quality_pages_thumbnails").prop("checked", load_high_quality_pages_thumbnails);
		$("#mark_as_read_system_enabled").prop("checked", mark_as_read_system_enabled);
		$("#marked_as_read_fade_opacity").val(marked_as_read_fade_opacity);
		$("#read_tag_font_size").val(read_tag_font_size);
		$("#subscription_system_enabled").prop("checked", subscription_system_enabled);
        $("#version_grouping_enabled").prop("checked", version_grouping_enabled);
        $("#version_grouping_filter_brackets").prop("checked", version_grouping_filter_brackets);
        $("#auto_group_on_page_comics").prop("checked", auto_group_on_page_comics);
        $("#tag_blocking_enabled").prop("checked", tag_blocking_enabled);
        $("#comic_reader_improved_zoom").prop("checked", comic_reader_improved_zoom);
        $("#remember_zoom_level").prop("checked", remember_zoom_level);

        DisableEnableSettingsByValue();
	}

	function UpdateSettingsValues() {
		remove_non_english = $("#remove_non_english").is(':checked');
		partially_fade_all_non_english = $("#partially_fade_all_non_english").is(':checked');
		non_english_fade_opacity = $("#non_english_fade_opacity").val();
		browse_thumbnail_width = $("#browse_thumbnail_width").val();
		browse_thumnail_container_width = $("#browse_thumnail_container_width").val();
		load_high_quality_browse_thumbnails = $("#load_high_quality_browse_thumbnails").is(':checked');
		pages_thumbnail_width = $("#pages_thumbnail_width").val();
		pages_thumnail_container_width = $("#pages_thumnail_container_width").val();
		load_high_quality_pages_thumbnails = $("#load_high_quality_pages_thumbnails").is(':checked');
		mark_as_read_system_enabled = $("#mark_as_read_system_enabled").is(':checked');
		marked_as_read_fade_opacity = $("#marked_as_read_fade_opacity").val();
		read_tag_font_size = $("#read_tag_font_size").val();
		subscription_system_enabled = $("#subscription_system_enabled").is(':checked');
        version_grouping_enabled = $("#version_grouping_enabled").is(':checked');
        version_grouping_filter_brackets = $("#version_grouping_filter_brackets").is(':checked');
        auto_group_on_page_comics = $("#auto_group_on_page_comics").is(':checked');
        tag_blocking_enabled = $("#tag_blocking_enabled").is(':checked');
        comic_reader_improved_zoom = $("#comic_reader_improved_zoom").is(':checked');
        remember_zoom_level = $("#remember_zoom_level").is(':checked');

		GM_setValue("remove_non_english", remove_non_english);
		GM_setValue("partially_fade_all_non_english", partially_fade_all_non_english);
		GM_setValue("non_english_fade_opacity", non_english_fade_opacity);
		GM_setValue("browse_thumbnail_width", browse_thumbnail_width);
		GM_setValue("browse_thumnail_container_width", browse_thumnail_container_width);
		GM_setValue("load_high_quality_browse_thumbnails", load_high_quality_browse_thumbnails);
		GM_setValue("pages_thumbnail_width", pages_thumbnail_width);
		GM_setValue("pages_thumnail_container_width", pages_thumnail_container_width);
		GM_setValue("load_high_quality_pages_thumbnails", load_high_quality_pages_thumbnails);
		GM_setValue("mark_as_read_system_enabled", mark_as_read_system_enabled);
		GM_setValue("marked_as_read_fade_opacity", marked_as_read_fade_opacity);
		GM_setValue("read_tag_font_size", read_tag_font_size);
		GM_setValue("subscription_system_enabled", subscription_system_enabled);
        GM_setValue("version_grouping_enabled", version_grouping_enabled);
        GM_setValue("version_grouping_filter_brackets", version_grouping_filter_brackets);
        GM_setValue("auto_group_on_page_comics", auto_group_on_page_comics);
        GM_setValue("tag_blocking_enabled", tag_blocking_enabled);
        GM_setValue("comic_reader_improved_zoom", comic_reader_improved_zoom);
        GM_setValue("remember_zoom_level", remember_zoom_level);

		$("#settings-saved-mark").fadeIn(500, function() {
			setTimeout(function() {
				$("#settings-saved-mark").fadeOut(500);
			}, 1000);
		});

        DisableEnableSettingsByValue();
	}

    function DisableEnableSettingsByValue()
    {
        if(remove_non_english) {
			$("#partially_fade_all_non_english").prop("disabled", true);
			$("#non_english_fade_opacity").prop("disabled", true);
			$("#partially_fade_all_non_english").parentsUntil(".custom-settings").parent().addClass("disabled-setting");
			$("#non_english_fade_opacity").parentsUntil(".custom-settings").parent().addClass("disabled-setting");
		}
		else {
			$("#partially_fade_all_non_english").prop("disabled", false);
			$("#non_english_fade_opacity").prop("disabled", false);
			$("#partially_fade_all_non_english").parentsUntil(".custom-settings").parent().removeClass("disabled-setting");
			$("#non_english_fade_opacity").parentsUntil(".custom-settings").parent().removeClass("disabled-setting");
            $("#auto_group_on_page_comics").prop("disabled", false);
			$("#auto_group_on_page_comics").parentsUntil(".custom-settings").parent().removeClass("disabled-setting");

			if(!partially_fade_all_non_english) {
				$("#non_english_fade_opacity").prop("disabled", true);
				$("#non_english_fade_opacity").parentsUntil(".custom-settings").parent().addClass("disabled-setting");
			}
			else {
				$("#non_english_fade_opacity").prop("disabled", false);
				$("#non_english_fade_opacity").parentsUntil(".custom-settings").parent().removeClass("disabled-setting");
			}
		}

		if(mark_as_read_system_enabled) {
			$("#marked_as_read_fade_opacity, #read_tag_font_size").prop("disabled", false);
			$("#marked_as_read_fade_opacity, #read_tag_font_size").parentsUntil(".custom-settings").parent().removeClass("disabled-setting");
		}
		else {
			$("#marked_as_read_fade_opacity, #read_tag_font_size").prop("disabled", true);
			$("#marked_as_read_fade_opacity, #read_tag_font_size").parentsUntil(".custom-settings").parent().addClass("disabled-setting");
		}

        if(version_grouping_enabled) {
			$("#version_grouping_filter_brackets").prop("disabled", false);
			$("#version_grouping_filter_brackets").parentsUntil(".custom-settings").parent().removeClass("disabled-setting");

            if(remove_non_english)
            {
                $("#auto_group_on_page_comics").prop("disabled", true);
                $("#auto_group_on_page_comics").parentsUntil(".custom-settings").parent().addClass("disabled-setting");
            }
            else
            {
                $("#auto_group_on_page_comics").prop("disabled", false);
                $("#auto_group_on_page_comics").parentsUntil(".custom-settings").parent().removeClass("disabled-setting");
            }
		}
		else {
			$("#version_grouping_filter_brackets").prop("disabled", true);
			$("#version_grouping_filter_brackets").parentsUntil(".custom-settings").parent().addClass("disabled-setting");

            $("#auto_group_on_page_comics").prop("disabled", true);
			$("#auto_group_on_page_comics").parentsUntil(".custom-settings").parent().addClass("disabled-setting");
		}

        if(tag_blocking_enabled)
        {
            $("#tag_blocking_enabled").parent().parent().parent().next().show();
            $("#tag_blocking_enabled").parent().parent().parent().next().next().show();
        }
        else
        {
            $("#tag_blocking_enabled").parent().parent().parent().next().hide();
            $("#tag_blocking_enabled").parent().parent().parent().next().next().hide();
        }

        if(comic_reader_improved_zoom)
        {
            $("#remember_zoom_level").prop("disabled", false);
            $("#remember_zoom_level").parentsUntil(".custom-settings").parent().removeClass("disabled-setting");
        }
        else
        {
            $("#remember_zoom_level").prop("disabled", true);
            $("#remember_zoom_level").parentsUntil(".custom-settings").parent().addClass("disabled-setting");
        }
    }

	function AddSubClickListeners() {
		$("#subTo").click(function(){

			//get the array again to make sure we have an up to date array (since other tabs could have modified it since loading this page)
			SubArrayString = GM_getValue("SubArrayString", null);
			if(SubArrayString) { SubArray = JSON.parse(SubArrayString); }

			SubArray.push(subItem); //add to array
			SubArrayString = JSON.stringify(SubArray); //convert array to string
			GM_setValue("SubArrayString", SubArrayString); //save string
			$(this).html('<span style="vertical-align: middle;">Unsubscribe</span>').prop("id", "unsubTo");
			$(this).off();
			AddSubClickListeners();
		});
		$("#unsubTo").click(function(){

			//get the array again to make sure we have an up to date array (since other tabs could have modified it since loading this page)
			SubArrayString = GM_getValue("SubArrayString", null);
			if(SubArrayString) { SubArray = JSON.parse(SubArrayString); }

			//do it mutiple times if needed (due to multiple tab fuckery)
			while(SubArray.indexOf(subItem) >= 0)
				SubArray.splice(SubArray.indexOf(subItem), 1); //remove from array

			SubArrayString = JSON.stringify(SubArray); //convert array to string
			GM_setValue("SubArrayString", SubArrayString); //save string
			$(this).html('<span style="vertical-align: middle;">Subscribe</span>').prop("id", "subTo");
			$(this).off();
			AddSubClickListeners();
		});
	}

	function AddMARClickListeners() {
		$("#markAsRead").click(function(){

			//get the array again to make sure we have an up to date array (since other tabs could have modified it since loading this page)
			MARArrayString = GM_getValue("MARArrayString", null);
			if(MARArrayString) { MARArray = JSON.parse(MARArrayString); }

			MARArray.push(item); //add to array
			MARArrayString = JSON.stringify(MARArray); //covert array to string
			GM_setValue("MARArrayString", MARArrayString); //save string
			$(this).html(unreadImg+' <span style="vertical-align: middle;">Mark as unread</span>').prop("id", "markAsUnRead");
			$(this).off();
			AddMARClickListeners();
		});

		$("#markAsUnRead").click(function(){

			//get the array again to make sure we have an up to date array (since other tabs could have modified it since loading this page)
			MARArrayString = GM_getValue("MARArrayString", null);
			if(MARArrayString) { MARArray = JSON.parse(MARArrayString); }

			//do it mutiple times if needed (due to multiple tab fuckery)
			while(MARArray.indexOf(item) >= 0)
				MARArray.splice(MARArray.indexOf(item), 1); //remove from array

			MARArrayString = JSON.stringify(MARArray); //covert array to string
			GM_setValue("MARArrayString", MARArrayString); //save string
			$(this).html(readImg+' <span style="vertical-align: middle;">Mark as read</span>').prop("id", "markAsRead");
			$(this).off();
			AddMARClickListeners();
		});
	}

	function addGlobalStyle(css) {
		var head, style;
		head = document.getElementsByTagName('head')[0];
		if (!head) { return; }
		style = document.createElement('style');
		style.type = 'text/css';
		style.innerHTML = css;
		head.appendChild(style);
	}

    function SaveToFile(filename, data) {
        var blob = new Blob([data], {type: 'text/plain'});
        if(window.navigator.msSaveOrOpenBlob) {
            window.navigator.msSaveBlob(blob, filename);
        }
        else{
            var elem = window.document.createElement('a');
            elem.href = window.URL.createObjectURL(blob);
            elem.download = filename;
            document.body.appendChild(elem);
            elem.click();
            document.body.removeChild(elem);
        }
    }
    //========================================================//
})();