Sleazy Fork is available in English.

EhxVisited

E-H Visited, combined with ExVisited, and then better.

As of 2019-12-24. See the latest version.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         EhxVisited
// @namespace    https://sleazyfork.org/en/users/285675-hauffen
// @version      2.45.39
// @description  E-H Visited, combined with ExVisited, and then better.
// @author       Hauffen
// @require      https://code.jquery.com/jquery-3.3.1.min.js
// @include      /https?:\/\/(e-|ex)hentai\.org\/.*/
// ==/UserScript==

(function() {
    window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
    window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE: "readwrite"};
    window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;

    if (!window.indexedDB) {
        console.warn("Your browser doesn't support a stable version of IndexedDB. Such and such feature will not be available.");
        return;
    }

    /*═════════════════════════════╗
    ║    Configuration Defaults    ║
    ╚═════════════════════════════*/
    var setStore = JSON.parse(localStorage.getItem("ehx-settings")) ? JSON.parse(localStorage.getItem("ehx-settings")) : JSON.parse('{"softHide":false, "minAdd":true, "minShow":false, "cssTT":false, "repPub":false, "visHide":false, "hidShow":false, "pFilter":false, "pLimit":0, "stFilter":false, "stLimit":0, "titleShow":true}');
    var filters = localStorage.getItem("ehx-filters") ? localStorage.getItem("ehx-filters") : "#\\[Erocolor\\]";
    var cssA = JSON.parse(localStorage.getItem("ehx-css")) ? JSON.parse(localStorage.getItem("ehx-css")) : JSON.parse('{"visible":"box-shadow: inset 0 0 0 500px rgba(2, 129, 255, .2) !important;", "hidden":"box-shadow: inset 0 0 0 500px rgba(255, 40, 0, .2) !important;", "filter":"box-shadow: inset 0 0 0 500px rgba(200, 0, 100, .2) !important;", "page":"box-shadow: inset 0 0 0 500px rgba(0, 0, 180, .2) !important;", "rating":"box-shadow: inset 0 0 0 500px rgba(180, 80, 60, .2) !important;"}');
    var cssV = localStorage.getItem("ehx-cssv") ? localStorage.getItem("ehx-cssv") : "box-shadow: inset 0 0 0 500px rgba(2, 129, 255, .2) !important;";
    var cssH = localStorage.getItem("ehx-cssh") ? localStorage.getItem("ehx-cssh") : "box-shadow: inset 0 0 0 500px rgba(255, 40, 0, .2) !important;";
    var cssD = (setStore.softHide) ? "opacity:0.2; -webkit-opacity: 0.2;" : "display: none;";
    /*════════════════════════════*/

    let db = null;
    var filterArr = [];
    var pIS = 0; // Post Infinite Scroll
    var observer = new MutationObserver(e => {
        pIS = true; // Triggered on mutation, should never be false at this point though
        addCSS();
    });

    var spl = document.URL.split("/");
    var d1 = spl[3];
    var galleries = JSON.parse('{"data":{}}');
    var hidden = JSON.parse('{"data":{}}');
    var ehxClearConfirm = 0, ehxhClearConfirm = 0;

    if (d1 == "g") addGallery(); // Add the current page to galleries
    if (d1.substr(0, 1) == "?" || d1.substr(0, 1) == "w" || d1.substr(0, 1) == "#" || d1.substr(0, 1) == "f" || d1.substr(0, 1) == "t" || !d1) {
        populateFilter();
        populate();
    }

    /**
     * Populate the custom filter array with user input converted into regular expressions
	 */
    function populateFilter() {
        if (filters != "") {
            var tempArr = filters.split("\n");
            for(var i = 0; i < tempArr.length; i++) {
                if (tempArr[i].startsWith("#")) continue;
                filterArr.push(new RegExp(tempArr[i], "i"));
            }
        }
    }

    /**
     * Add a gallery to our IndexedDB
	 */
    function addGallery() {
        const request = indexedDB.open("ehxvisited", 1);

        request.onupgradeneeded = e => { // Generate our database if it's not there
            db = e.target.result;

            if (!db.objectStoreNames.contains('galleries')) {
                db.createObjectStore('galleries', {keyPath: 'id'});
            }
            if (!db.objectStoreNames.contains('hidden')) {
                db.createObjectStore('hidden', {keyPath: 'id'});
            }
        };

        request.onsuccess = e => {
            db = e.target.result;

            var objStore = db.transaction('galleries', 'readwrite').objectStore('galleries');
            var openRequest = objStore.openCursor(spl[4] + "." + spl[5]);

            openRequest.onsuccess = e => {
                var cursor = openRequest.result;
                if (cursor) { // Update entry if key exists
                    cursor.update({id: spl[4] + "." + spl[5], visited: Date.now()});
                    console.log("EhxVisited: Updated " + spl[4] + "." + spl[5]);
                } else { // Otherwise, add entry
                    objStore.add({id: spl[4] + "." + spl[5], visited: Date.now()});
                    console.log("EhxVisited: Added " + spl[4] + "." + spl[5]);
                }
            };

            openRequest.onerror = e => {
                console.log(`EhxVisited: Something bad happened with gallery ${spl[4]}.${spl[5]}: ${e.target.error}`);
            };
        };
    };

    /**
     * Updates the hidden gallery count in the header object
	 */
    function updateGListing() {
        // There's probably a better way to do this portion rather than iterate through all current objects, but runtime is negligible
        var list = $(".itg .gl1t").length > 0 ? $(".itg .gl1t") : $("table.itg>tbody>tr").has('.glhide, .gldown, th'); // Get the proper elements depending on our view mode
        var hAmount, vAmount, fAmount, pAmount, rAmount, hCount;
        hAmount = vAmount = fAmount = pAmount = rAmount = hCount = 0;
        for (var i = 0; i < list.length; i++) {
            if ($(list[i]).hasClass("ehx-hidden")) { // Count generic Hidden galleries
                if ($(list[i]).hasClass("ehx-visited")) vAmount++;
                hCount++;
            }
            if ($(list[i]).attr("data-jqstyle") != undefined) { // Count elements via JQ Style tags
                if ($(list[i]).attr("data-jqstyle").match('h')) hAmount++;
                if ($(list[i]).attr("data-jqstyle").match('f')) fAmount++;
                if ($(list[i]).attr("data-jqstyle").match('p')) pAmount++;
                if ($(list[i]).attr("data-jqstyle").match('r')) rAmount++;
            }
            if($(".ehx-show").text() === "Show") { // If Visited Galleries are hidden, count those as well
                if ($(list[i]).hasClass("ehx-visited")) {
                    vAmount++;
                    hCount++;
                }
            }
        }
        if(!setStore.softHide) {
            $("#hideCount").html("There " + (hCount > 1 || hCount == 0 ? 'are ' : 'is ') + "<span>" + hCount + " hidden " + (hCount > 1 || hCount == 0 ? 'galleries' : 'gallery') + "</span> on this page.");
        } else {
            $("#hideCount").html("There are <span>0 hidden galleries</span> on this page.");
        }
        $("#hideCount > span").prop("title", "Hidden: " + hAmount + " | Visited: " + vAmount + " | Filtered: " + fAmount + " | Page Limit: " + pAmount + " | Rating Limit: " + rAmount);
    }

    /**
     * Convert the star count of a specified element to a double
	 * @param {Object} el - A specific element within the DOM
	 */
    function getStarNumber(el) {
        var stars = $(el).find(".ir").css("background-position");
        switch(stars) {
            case "0px -1px":
                return 5;
            case "0px -21px":
                return 4.5;
            case "-16px -1px":
                return 4;
            case "-16px -21px":
                return 3.5;
            case "-32px -1px":
                return 3;
            case "-32px -21px":
                return 2.5;
            case "-48px -1px":
                return 2;
            case "-48px -21px":
                return 1.5;
            case "-64px -1px":
                return 1;
            case "-64px -21px":
                return 0.5;
            default:
                return 0;
        }
    }

    /**
	 * Check a specified element through the filters individually, then apply jqstyle tags for CSS
	 * @param {Object} el - A specific element within the DOM
	 */
    function filterCheck(el) {
        if (filterArr.length > 0) {
            if(filterArr.some(rx => rx.test($(el).find('.glink').text()))) { // Test our gallery name through our regex filters
                if(!$(el).hasClass('ehx-hidden')) {
                    $(el).addClass("ehx-hidden");
                }
                addStyle($(el), "f");
            }
        }

        // Filter our galleries through the star limit filter
        if (setStore.stFilter && setStore.stLimit > 0) {
            if (getStarNumber(el) < setStore.stLimit) {
                if(!$(el).hasClass('ehx-hidden')) {
                    $(el).addClass("ehx-hidden");
                }
                addStyle($(el), "r");
            }
        }
        var pages = 0; // Page Count is stored in a lot of different random elements throughout, there are probably better selectors for this
        if ($(".gl1e").length) { pages = $(el).find('.gl3e > div:nth-child(5)').text().split(" ")[0]; }
        else if ($(".gl1c").length) { pages = $(el).find('.gl4c > div:nth-child(2)').text().split(" ")[0]; }
        else if ($(".gl1t").length) { pages = $(el).find('.gl5t > div:nth-child(2) > div:nth-child(2)').text().split(" ")[0]; }
        else { pages = $(el).find('.gl2m > div:nth-child(2) > div:nth-child(2) > div:nth-child(2) > div:nth-child(2)').text().split(" ")[0]; }
        if (setStore.pFilter && setStore.pLimit > 0) {
            if(parseInt(pages) < parseInt(setStore.pLimit)) {
                if(!$(el).hasClass('ehx-hidden')) {
                    $(el).addClass("ehx-hidden");
                }
                addStyle($(el), "p");
            }
        }
    }

    /**
     * Adds the specified style flag to a specified element
	 * @param {Object} el - A specific element within the DOM
	 * @param {String} flag - A character to mark an element for JQ Styling CSS rules
	 */
    function addStyle(el, flag) {
        if ($(el).attr("data-jqstyle") != undefined) {
            $(el).attr("data-jqstyle", $(el).attr("data-jqstyle") + flag);
        } else {
            $(el).attr("data-jqstyle", flag);
        }
    }

    /**
     * Removes the specified style flag from a specified element
	 * @param {Object} el - A specific element within the DOM
	 * @param {string} flag - A JQ Style flag to remove from an element
	 */
    function removeStyle(el, flag) {
        if ($(el).attr("data-jqstyle") != undefined) {
            $(el).attr("data-jqstyle", $(el).attr("data-jqstyle").replace(flag, ''));
        } else {
            $(el).attr("data-jqstyle", "");
        }
    }

    /**
     * Toggles a specified element's hidden status
	 * @param {String} tga - Full gallery URL
	 * @param {Object} el - A specific element within the DOM
	 */
    function toggleElement(tga, el) {
        const request = indexedDB.open("ehxvisited", 1);
        var tgid = tga.split('/')[4] + "." + tga.split('/')[5];

        request.onsuccess = e => {
            db = e.target.result;
            var objStore = db.transaction("hidden", "readwrite").objectStore("hidden");
            var openReq = objStore.openCursor(tgid);
            openReq.onsuccess = e => {
                var cursor = e.target.result;
                if (cursor) { // Gallery already exists within our hidden table
                    cursor.delete();
                    console.log("EhxVisited: Removed " + tgid + " from hidden list.");
                    $(el).removeClass("ehx-hidden");
                    removeStyle($(el), "h");
                    delete hidden.data[tgid]; // Remove gallery listing from our local store of hidden galleries
                } else {
                    objStore.put({id: tgid}); // Put the gallery into our hidden table
                    console.log("EhxVisited: Added " + tgid + " to hidden list.");
                    $(el).addClass("ehx-hidden");
                    addStyle($(el), "h");
                    hidden.data[tgid] = 1; // Add gallery listing to our local store of hidden galleries
                }
                updateGListing();
                $("#hLength").text(Object.keys(hidden.data).length);
            }
        }
    }

    /**
	 * Fill our local gallery listings so we can preform easier operations on the data.
	 * Also set up the majority of our global HTML elements and their functions.
	 */
    function populate() {
        const request = indexedDB.open("ehxvisited", 1);

        request.onupgradeneeded = e => {
            db = e.target.result;

            if (!db.objectStoreNames.contains('galleries')) {
                db.createObjectStore('galleries', {keyPath: 'id'});
            }
            if (!db.objectStoreNames.contains('hidden')) {
                db.createObjectStore('hidden', {keyPath: 'id'});
            }
        };

        request.onsuccess = e => {
            db = e.target.result;
            var objStore = db.transaction("galleries", "readonly").objectStore("galleries");
            var openReq = objStore.getAll();
            openReq.onsuccess = f => {
                console.log("EhxVisited: Populated global variables.");
                var transform = f.target.result;
                for (var i = 0; i < transform.length; i++) {
                    galleries.data[transform[i].id] = transform[i].visited; // Force matrix data into array data
                }
                var gLength = Object.keys(galleries.data).length
                var objStore2 = db.transaction("hidden", "readonly").objectStore("hidden");
                var openReq2 = objStore2.getAll();
                openReq2.onsuccess = g => {
                    var transform2 = g.target.result;
                    for (i = 0; i < transform2.length; i++) {
                        hidden.data[transform2[i].id] = 1; // Force matrix data into array data
                    }
                    var hLength = Object.keys(hidden.data).length
                    $("#toppane").append("<ehx class='ehx-controls'>Galleries visited: <span id='gLength'>" + gLength + "</span> ( <span id='ehx-menu-control'></span><a href='javascript:;' class='ehx-settings'>Settings</a> )<br/>Hidden Galleries: <span id='hLength'>" + hLength + "</span><span id='ehxh-menu-control'></span></ehx>");
                    if (!setStore.softHide) {
                        $("#ehx-menu-control").append("<a href='javascript:;' class='ehx-show'>Hide</a> / ");
                        $("#ehxh-menu-control").append(" ( <a href='javascript:;' class='ehxh-show'>Show</a> )");
                    }
                    $(".ehx-settings").click(e => {
                        e.preventDefault();
                        settings();
                        return false;
                    });
                    $(".ehx-show").click(e => {
                        var disp =  $(".ehx-visited.ehx-hidden").css("display");
                        if ($(".ehx-show").text() === "Show") {
                            $(".ehx-visited").css({display: ""});
                            $(".ehx-visited.ehx-hidden").css({display: disp});
                        } else {
                            $(".ehx-visited").css({display: "none"});
                            $(".ehx-visited.ehx-hidden").css({display: disp});
                        }
                        $(".ehx-show").text((i, t) => {
                            return t === "Show" ? "Hide" : "Show";
                        });
                        updateGListing();
                        setStore.visHide = $(".ehx-show")[0].innerText === "Show" ? true : false;
                        localStorage.setItem("ehx-settings", JSON.stringify(setStore)); // Update our stored settings
                    });
                    $(".ehxh-show").click(e => {
                        if ($(".ehxh-show").text() === "Show") {
                            if ($(".gl1t").length == 0) { // For table view modes
                                $(".ehx-hidden").css({display: $(".ehx-hidden").parent().find("tr").not(".ehx-hidden").css("display")}); // Copy the display CSS of our closest element
                                $(".ehx-visited.ehx-hidden").css({display: $(".ehx-hidden").parent().find("tr").not(".ehx-hidden").css("display")});
                            } else { // Default display CSS for thumbnail
                                $(".ehx-hidden").css({display: 'flex'});
                                $(".ehx-visited.ehx-hidden").css({display: 'flex'});
                            }
                        } else {
                            $(".ehx-hidden").css({display: ""});
                            $(".ehx-visited.ehx-hidden").css({display: ""});
                        }
                        $(".ehxh-show").text((i, t) => { // Toggle text
                            return t === "Show" ? "Hide" : "Show";
                        });
                        updateGListing();
                        setStore.hidShow = $(".ehxh-show")[0].innerText === "Hide" ? true : false;
                        localStorage.setItem("ehx-settings", JSON.stringify(setStore));
                    });
                    addCSS();
                    $(".ehx-controls").append("<br /><span id='hideCount'><span></span></span>");
                    updateGListing();
                }
            }
        }
    }

    /**
	 * Our main function that does basically everything that we see.
	 * Appends our custom HTML objects to the main page.
	 * Adds CSS to elements based on whether they can be found in the populated local gallery listing.
	 */
    function addCSS() {
        observer.disconnect(); // Disconnect the observer, or else all the CSS changes will trigger the mutation observer
        var img_hide = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIhSURBVDjLlZPrThNRFIWJicmJz6BWiYbIkYDEG0JbBiitDQgm0PuFXqSAtKXtpE2hNuoPTXwSnwtExd6w0pl2OtPlrphKLSXhx07OZM769qy19wwAGLhM1ddC184+d18QMzoq3lfsD3LZ7Y3XbE5DL6Atzuyilc5Ciyd7IHVfgNcDYTQ2tvDr5crn6uLSvX+Av2Lk36FFpSVENDe3OxDZu8apO5rROJDLo30+Nlvj5RnTlVNAKs1aCVFr7b4BPn6Cls21AWgEQlz2+Dl1h7IdA+i97A/geP65WhbmrnZZ0GIJpr6OqZqYAd5/gJpKox4Mg7pD2YoC2b0/54rJQuJZdm6Izcgma4TW1WZ0h+y8BfbyJMwBmSxkjw+VObNanp5h/adwGhaTXF4NWbLj9gEONyCmUZmd10pGgf1/vwcgOT3tUQE0DdicwIod2EmSbwsKE1P8QoDkcHPJ5YESjgBJkYQpIEZ2KEB51Y6y3ojvY+P8XEDN7uKS0w0ltA7QGCWHCxSWWpwyaCeLy0BkA7UXyyg8fIzDoWHeBaDN4tQdSvAVdU1Aok+nsNTipIEVnkywo/FHatVkBoIhnFisOBoZxcGtQd4B0GYJNZsDSiAEadUBCkstPtN3Avs2Msa+Dt9XfxoFSNYF/Bh9gP0bOqHLAm2WUF1YQskwrVFYPWkf3h1iXwbvqGfFPSGW9Eah8HSS9fuZDnS32f71m8KFY7xs/QZyu6TH2+2+FAAAAABJRU5ErkJggg==";
        var list = $("table.itg>tbody>tr").has('.glhide, .gldown, th'); // Present only in list views
        var thumb = $(".itg .gl1t"); // Present only in thumbnail view
        var gid, galleryId, onFavs, d;

        if (list.length > 0) {
            if ($('.gl1e').length) { // Extended
                if ($('h1').text() === "Favorites") {
                    onFavs = 1;
                }
                for (var i = 0; i < list.length; i++) {
                    gid = $(list[i]).find(".gl1e a").attr("href").split("/");
                    galleryId = gid[4] + "." + gid[5];
                    if ($(list[i])[0].children.length === 2 && onFavs) {
                        $(list[i]).append('<td></td>');
                    }
                    if(galleries.data[galleryId] != undefined) {
                        if (!$(list[i]).hasClass('ehx-visited')) {
                            d = new Date(galleries.data[galleryId]);
                            $(list[i]).addClass("ehx-visited");
                            if (setStore.cssTT) $(list[i]).find('.glname').attr("title", 'EhxVisited: ' + timeDifference(galleries.data[galleryId]) + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ") " + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate());
                            // Check for fav pages
                            if ($(list[i]).find('.gl3e').children('div').length >= 7) { // Date favourited div is present
                                $(list[i]).find('.gl3e > div:last-child').append("<br><ehx class='ehx-extended-favs'>\uD83D\uDC41" + timeDifference(galleries.data[galleryId]) + "<br>" + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ")</ehx>");
                            } else {
                                $(list[i]).find('.gl3e').append("<ehx class='ehx-extended'>\uD83D\uDC41" + timeDifference(galleries.data[galleryId]) + "<br>" + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ")</ehx>");
                            }
                        }
                    } else {
                        if (setStore.cssTT) $(list[i]).find('.glname').attr("title", "Never Visited");
                    }
                    if(hidden.data[galleryId] != undefined) {
                        if(!$(list[i]).hasClass('ehx-hidden')) {
                            $(list[i]).addClass("ehx-hidden");
                        }
                        addStyle($(list[i]), "h");
                    }
                    if($(list[i])[0].childElementCount < 3) { // Don't append anything if it's already been appended
                        $("<img class='imgHide' src='" + img_hide + "' style='cursor:pointer !important; padding:4px 0px 0px 4px;' title='Show/Hide gallery'>").prependTo($(list[i]).find("a").first().parent().parent().parent()).on('click', e => {
                            var el = $(e.currentTarget).parent();
                            toggleElement($(el).find("a").attr("href"), $(el));
                        })
                    }
                    filterCheck($(list[i]));
                }
                updateGListing();
            } else if ($('.gl1c').length) { // Compact
                var borderColour = $('.gl1c').first().css('border-top-color'); // Border colour is different between domains
                if (!pIS && $('table.itg tbody>tr:first-child')[0].children.length < 5) { // Apend our table columns to the table head
                    $('table.itg tbody>tr:first-child th:nth-child(4)').after('<th style="text-align:center;" title="EhxVisited: Click to Show/Hide">&#x2716</th>');
                    $('table.itg tbody>tr:first-child th:nth-child(2)').after('<th>Visited</th>');
                    pIS = true;
                }
                if ($('h1').text() === "Favorites") {
                    onFavs = 1;
                }
                for (i = 1; i < list.length; i++) {
                    gid = $(list[i]).find(".glname a").attr("href").split("/");
                    galleryId = gid[4] + "." + gid[5];
                    if ($(list[i])[0].children.length === 4 || $(list[i])[0].children.length === 5 && onFavs) {
                        if ($(list[i])[0].children.length === 4 && onFavs) {
                            $(list[i]).append('<td></td>');
                        }
                        if(galleries.data[galleryId] != undefined) {
                            d = new Date(galleries.data[galleryId]);
                            $(list[i]).addClass("ehx-visited");
                            if (setStore.cssTT) $(list[i]).find('.glname').attr("title", 'EhxVisited: ' + timeDifference(galleries.data[galleryId]) + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ") " + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate());
                            $(list[i]).children('.gl2c').after('<td class="ehx-compact" style="border-color:' + borderColour + ';"><ehx>' + timeDifference(galleries.data[galleryId], true) + "<br>(" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ')<br>' + d.getFullYear().toString().substr(2) + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + '</ehx></td>');
                        } else {
                            if (setStore.cssTT) $(list[i]).find('.glname').attr("title", "Never Visited");
                            $(list[i]).children('.gl2c').after('<td class="ehx-compact" style="border-color:' + borderColour + ';"></td>');
                        }
                    }
                    if(hidden.data[galleryId] != undefined) {
                        if(!$(list[i]).hasClass('ehx-hidden')) {
                            $(list[i]).addClass("ehx-hidden");
                        }
                        addStyle($(list[i]), "h");
                    }
                    if($(list[i])[0].childElementCount < 6) { // Don't append anything if it's already been appended
                        $("<td class='hideContainer' style='border-bottom: 1px solid #6f6f6f4d; border-top: 1px solid #6f6f6f4d;'><img class='imgHide' src='" + img_hide + "' style='cursor:pointer !important; vertical-align:center;' title='Show/Hide gallery'></td>").appendTo($(list[i]).find("a").first().closest("tr")).on('click', e => {
                            var el = $(e.currentTarget).closest("tr");
                            toggleElement($(el).find($(".gl3c > a")).attr("href"), $(el));
                        })
                    }
                    filterCheck($(list[i]));
                }
                updateGListing();
            } else { // Minimal
                if(!pIS) { // Append our table columns to the table head
                    $('table.itg tbody>tr:first-child th:nth-child(6)').after('<th style="text-align:center;" title="EhxVisited: Click to Show/Hide">&#x2716</th>');
                    if (setStore.minAdd) {
                        $('table.itg tbody>tr:first-child th:nth-child(2)').after('<th title="EhxVisited: Hover for timestamps">\uD83D\uDC41</th>');
                    }
                    pIS = true;
                }
                if (setStore.repPub) {
                    $('table.itg tbody>tr:first-child')[0].children[1].innerText = "Visited"
                }
                if ($('h1').text() === "Favorites") {
                    onFavs = 1;
                }
                for (i = 1; i < list.length; i++) {
                    gid = $(list[i]).find(".glname a").attr("href").split("/");
                    galleryId = gid[4] + "." + gid[5];
                    if(hidden.data[galleryId] != undefined) {
                        if(!$(list[i]).hasClass('ehx-hidden')) {
                            $(list[i]).addClass("ehx-hidden");
                        }
                        addStyle($(list[i]), "h");
                    }
                    if ($(list[i])[0].children.length === 6 || $(list[i])[0].children.length === 7 && onFavs) {
                        if ($(list[i])[0].children.length === 6 && onFavs) {
                            $(list[i]).append('<td></td>');
                        }
                        if (setStore.minAdd) { // Append viewed column
                            if (galleries.data[galleryId] != undefined) {
                                d = new Date(galleries.data[galleryId]);
                                $(list[i]).addClass("ehx-visited");
                                if (setStore.cssTT) $(list[i]).find('.glname').attr("title", 'EhxVisited: ' + timeDifference(galleries.data[galleryId]) + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ") " + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate());
                                if (setStore.minShow) { // Show text in appended column
                                    $(list[i]).children('.gl2m').after('<td class="ehx-minimal-text"><ehx>' + timeDifference(galleries.data[galleryId], true) + "<br>(" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ')<br>' + d.getFullYear().toString().substr(2) + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + '</ehx></td>');
                                } else { // Show icon in appended column
                                    $(list[i]).children('.gl2m').after('<td class="ehx-minimal" title="EhxVisited: ' + timeDifference(galleries.data[galleryId]) + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ") " + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + '"><ehx>\uD83D\uDC41</ehx></td>');
                                }
                                if (setStore.repPub) {
                                    $(list[i]).find(".gl2m").text(d.getFullYear().toString() + "\u2011" + ('0' + (d.getMonth() + 1)).slice(-2) + "\u2011" + d.getDate() + " " + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0'));
                                }
                            } else { // Not viewed
                                $(list[i]).children('.gl2m').after('<td class="ehx-minimal"></td>'); // Only append another table cell to the row
                                if (setStore.repPub) $(list[i]).find(".gl2m").text("Never Visited");
                                if (setStore.cssTT) $(list[i]).find('.glname').attr("title", "Never Visited");
                            }
                        } else { // Append nothing, highlight only
                            if (galleries.data[galleryId] != undefined) {
                                d = new Date(galleries.data[galleryId]);
                                $(list[i]).addClass("ehx-visited");
                                $(list[i]).children('.glname')[0].setAttribute("title", 'EhxVisited: ' + timeDifference(galleries.data[galleryId]) + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ") " + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate());
                            }
                        }
                        if($(list[i])[0].childElementCount < 8 || ($(list[i])[0].childElementCount < 8 && !setStore.minAdd)) { // Don't append anything if it's already been appended // I'll have to look at this conditional again, seems redundant
                            $("<td class='hideContainer'><img class='imgHide' src='" + img_hide + "' style='cursor:pointer !important; vertical-align:middle;' title='Show/Hide gallery'></td>").appendTo($(list[i]).find("a").first().closest("tr")).on('click', e => {
                                var el = $(e.currentTarget).closest("tr");
                                toggleElement($(el).find($(".gl3m > a")).attr("href"), $(el));
                            })
                        }
                        filterCheck($(list[i]));
                    }
                }
                updateGListing();
            }
        } else if (thumb.length > 0) { // Thumbnail
            for (i = 0; i < thumb.length; i++) {
                gid = $(thumb[i]).find(".gl3t a").attr("href").split("/");
                galleryId = gid[4] + "." + gid[5];
                if(galleries.data[galleryId] != undefined) {
                    if (!$(thumb[i]).hasClass('ehx-visited')) {
                        d = new Date(galleries.data[galleryId]);
                        $(thumb[i]).addClass("ehx-visited");
                        if (setStore.cssTT) {
                            $(thumb[i]).find('.glname').attr("title", 'EhxVisited: ' + timeDifference(galleries.data[galleryId]) + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ") " + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate());
                        }
                        $(thumb[i]).children('.gl5t').after("<ehx class='ehx-thumbnail'>\uD83D\uDC41" + timeDifference(galleries.data[galleryId]) + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ") " + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + "</ehx>");
                    }
                } else {
                    if (setStore.cssTT) {
                        $(thumb[i]).find('.glname').attr("title", "Never Visited");
                    }
                }
                if(hidden.data[galleryId] != undefined) {
                    if(!$(thumb[i]).hasClass('ehx-hidden')) {
                        $(thumb[i]).addClass("ehx-hidden");
                    }
                    addStyle($(thumb[i]), "h");
                }
                if($(thumb[i]).find(".gl5t").children().length < 3) { // Don't append anything if it's already been appended
                    $("<div class='hideContainer'><img class='imgHide' src='" + img_hide + "' style='cursor:pointer !important; position:absolute; bottom:3px; left:2px;' title='Show/Hide gallery'></div>").appendTo($(thumb[i]).find(".gl5t")).on('click', e => {
                        var el = $(e.currentTarget).parent().parent();
                        toggleElement($(el).find("a").attr("href"), $(el));
                    })
                }
                filterCheck($(thumb[i]));
            }
            updateGListing();
        } else {
            console.log("EhxVisited: Something went wrong or an invalid view"); // This happens when you use empty() on itg, which can happen with other scripts
        }

        if (setStore.visHide) {
            $(".ehx-visited").css({display: "none"});
            $(".ehx-show").text("Show");
        }
        if (setStore.hidShow) {
            if ($(".ehx-hidden").length < 25) { $(".ehx-hidden").css({display: $(".ehx-hidden").siblings().not(".ehx-hidden").css("display")}) } // Make sure there are elements on the page
            else { // Unless you're an idiot and hid everything on the page
                if ($(".gl1t").length) { $(".ehx-hidden").css({display: "flex"}); } // Use the default values
                else { $(".ehx-hidden").css({display: "table-row"}); }
            }
            $(".ehxh-show").text("Hide");
        }
        observer.observe($('.itg').get(0), { // Reconnect the observer for changes
            childList: true,
            subtree: true
        });
    }

    /**
	 * Get time difference in words
	 * @param {Date} previous - Previous date to compare against Date.now()
	 * @param {Boolean} abbreviate - Should the text string have abbreviatated text
	 */
    function timeDifference(previous, abbreviate) {
        var msPerMinute = 60 * 1000;
        var msPerHour = msPerMinute * 60;
        var msPerDay = msPerHour * 24;
        var msPerMonth = msPerDay * 30;
        var msPerYear = msPerDay * 365;
        var elapsed = Date.now() - previous;

        if (elapsed < msPerMinute) {
            return Math.round(elapsed / 1000) + ((typeof abbreviate !== 'undefined') ? '&nbsp;sec' : ' seconds ago');
        } else if (elapsed < msPerHour) {
            return Math.round(elapsed / msPerMinute) + ((typeof abbreviate !== 'undefined') ? '&nbsp;min' : ' minutes ago');
        } else if (elapsed < msPerDay) {
            return Math.round(elapsed / msPerHour) + ((typeof abbreviate !== 'undefined') ? '&nbsp;hrs' : ' hours ago');
        } else if (elapsed < msPerMonth) {
            return Math.round(elapsed / msPerDay) + ((typeof abbreviate !== 'undefined') ? '&nbsp;days' : ' days ago');
        } else if (elapsed < msPerYear) {
            return Math.round(elapsed / msPerMonth) + ((typeof abbreviate !== 'undefined') ? '&nbsp;mos' : ' months ago');
        } else {
            return Math.round(elapsed / msPerYear) + ((typeof abbreviate !== 'undefined') ? '&nbsp;yrs' : ' years ago');
        }
    }

    /**
	 * Generates a text area with formatted gallery data for export
	 * @param {String} message - A message to display as the legend or title of the text area
	 * @param {IndexedDB Matrix} items - Raw IndexedDB getAll output
	 */
    function ehxExport(message, items) {
        var data = "";
        for (var i in items) {
            data += items[i].id + ":" + items[i].visited + ";";
        }
        if ($('.ehx-exported-data').length) { // Remove any data if it exists for whatever reason
            $('.ehx-exported-data').remove();
        }
        $('.section-container').prepend('<section class="ehx-exported-data"><fieldset><legend>' + message + '</legend><div><textarea class="ehx-exported-data-text">' + data + '</textarea></div></fieldset></section>');
    }

    $(".itg").on("mousedown", "a", e => {
        if (e.which === 3) return; // Ignore right-clicks
        if (e.currentTarget.href.split('/')[3] === "g") {
            galleries.data[e.currentTarget.href.split('/')[4] + "." + e.currentTarget.href.split('/')[5]] = Date.now();
            $("#gLength").text(Object.keys(galleries.data).length);
            addCSS();
        }
    });

    /**
	 * Import user data into our indexedDB
	 * @param {String} store - An object store within the indexedDB
	 * @param {JSON Array} items - String of exported data to import
	 */
    function ehxImport(store, items) {
        var objStore2 = db.transaction(store, 'readwrite').objectStore(store);
        var count = 0, sp = "";

        /**
		 * Push entries into the specified indexedDB store
		 */
        function insertNext() {
            if (count < sp.length) {
                var str = sp[count].split(":");
                objStore2.put({id: str[0], visited: parseInt(str[1])}).onsuccess = insertNext; // Update the record if it's there, or add it if it's not, then continue
                ++count;
            } else {
                console.log("EhxVisited: Merge Completed");
            }
        }

        if (typeof items == "undefined") {
            var c = prompt("EhxVisited:\nPaste here to import " + (store == 'hidden' ? 'hidden ' : '') + "galleries.");
            if (c) {
                sp = c.split(";");
                sp = sp.filter(Boolean); // Filter out any null ("") entries
                insertNext();

                alert("EhxVisited:\nImported " + sp.length + " entries.");
                location.reload();
            }
        } else {
            sp = items.split(";");
            sp = sp.filter(Boolean); // Filter out any null ("") entries
            insertNext();

            alert("EhxVisited:\nImported " + sp.length + " entries."); // Change this probably
        }
    }

    /**
	 * Open the Settings menu and set up all necessary menu functions
	 */
    function settings() {
        const req = indexedDB.open("ehxvisited", 1);

        req.onsuccess = e => {
            if (db == null) db = e.target.result;
            var objStore = db.transaction('galleries', 'readwrite').objectStore('galleries');
            var openReq = objStore.getAll();
            openReq.onsuccess = e => {
                var len = e.target.result;
                // There's probably a much easier way to do this, or at least a nicer looking, more technical way
                var container = $(`
                <div class="overlay">
					<div class="settings">
						<nav class="topNav">
							<span style="float:left;margin-left:3px;font-weight:lighter;opacity:0.5;-webkit-opacity:0.5;">All Settings Will Be Applied On Close</span>
							<div>
								<div class="mencon">
									<button class="menu">Export</button>
									<div class="dropdown">
										<a id="ehx-export" href="javascript:;">Export Galleries</a>
										<a id="ehxh-export" href="javascript:;">Export Hidden Galleries</a>
									</div>
								</div>
								<div class="mencon">
									<button class="menu">Import</button>
									<div class="dropdown">
										<a id="ehx-import" href="javascript:;">Import Galleries</a>
										<a id="ehxh-import" href="javascript:;">Import Hidden Galleries</a>
									</div>
								</div>
								<a id="settings-close" href="javascript:;">🞫</a>
							</div>
						</nav>
						<div class="section-container">
							<section>
								<fieldset>
									<legend>Settings</legend>
									<div>
										<label>
											<input type="checkbox" id="softHide" ` + (setStore.softHide ? `checked` : ``) + `>Soft Hide Galleries
										</label>
										<span>: Darken hidden galleries instead of removing them from view</span>
									</div>
									<div>
										<label>
											<input type="checkbox" id="minAdd" ` + (setStore.minAdd ? `checked` : ``) + `>Minimal Add Column
										</label>
										<span>: Show visits in an additional column in Minimal/Minimal+ view modes</span>
										<div class="suboptions">
											<div>
												<span class="branch">&#8735</span>
												<label>
													<input type="checkbox" id="minShow" ` + (setStore.minShow ? `checked` : ``) + `>Minimal Show Text
												</label>
												<span>: Show visits as text instead of hovering tooltip in Minimal/Minimal+ view modes</span>
											</div>
										</div>
									</div>
									<div>
										<label>
											<input type="checkbox" id="cssTT" ` + (setStore.cssTT ? `checked` : ``) + `>CSS Tooltips
										</label>
										<span>: Replace gallery link tooltips with visited information in all view modes</span>
									</div>
									<div>
										<label>
											<input type="checkbox" id="repPub" ` + (setStore.repPub ? `checked` : ``) + `>Replace Published
										</label>
										<span>: Replace date published with date visited in Minimal/Minimal+ view modes</span>
									</div>
									<div>
										<label>
											<input type="checkbox" id="titleShow" ` + (setStore.titleShow ? `checked`: ``) + `>Show Full Title
										</label>
										<span>: Show the full title of a gallery on hover in Thumbnail view</span>
									</div>
								</fieldset>
								<fieldset>
									<legend>Custom CSS</legend>
									<h3>Visited Galleries
										<div class="control" id="visControls">
											<button id="resV">Reset CSS</button>
											<button class="ehx-clear">Clear Data</button>
										</div>
									</h3>
									<textarea id="visited" class="field" spellcheck="false" placeholder="Insert CSS">` + cssA.visible + `</textarea>
									<h3>Hidden Galleries
										<div class="control sControls" id="hideControls">
											<button id="resH">Reset CSS</button>
											<button class="ehxh-clear">Clear Data</button>
										</div>
									</h3>
									<textarea id="hidden" class="field" spellcheck="false" placeholder="Insert CSS">` + cssA.hidden + `</textarea>
									<div class="suboptions2">
										<button class="collapsible">Filtered Galleries</button>
										<div class="content">
											<textarea id="filtered" class="field" spellcheck="false">` + cssA.filter + `</textarea>
											<div class="control sControls">
												<button id="resF">Reset CSS</button>
											</div>
										</div>
										<button class="collapsible">Page Filtered</button>
										<div class="content">
											<textarea id="page" class="field" spellcheck="false"placeholder="Insert CSS">` + cssA.page + `</textarea>
											<div class="control sControls">
												<button id="resP">Reset CSS</button>
											</div>
										</div>
										<button class="collapsible">Rating Filtered</button>
										<div class="content">
											<textarea id="rating" class="field" spellcheck="false" placeholder="Insert CSS">` + cssA.rating + `</textarea>
											<div class="control sControls">
												<button id="resR">Reset CSS</button>
											</div>
										</div>
									</div>
								</fieldset>
								<fieldset>
									<legend>Filters</legend>
									Use one <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">regular expression</a> per line to filter out matching galleries.
									<ul style="margin: 3px 0px; padding-left: 30px;">
										<li>E.G. <code>Ongoing</code> will filter out every gallery with <code>ongoing</code>, case-insensitive, in the title. <code>\\[Digital\\]</code> will filter out every gallery with <code>[Digital]</code>, case-insensitive, in the title.</li>
										<li>Lines starting with <code>#</code> will be ignored.</li>
									</ul>
									<textarea id="galFilter">` + filters + `</textarea>
									<div>
										<label>
											<input type="checkbox" id="pFilt" ` + (setStore.pFilter ? `checked` : ``) + `>Page Limit
										</label>
										<span>: Filter out any gallery with pages less than:
											<input id="pLim" type="number" min="1" value="` + setStore.pLimit + `" ` + (setStore.pFilter ? `` : `disabled`) + `/>
										</span>
									</div>
									<div>
										<label>
											<input type="checkbox" id="stFilt" ` + (setStore.stFilter ? `checked` : ``) + `>Minimum Rating
										</label>
										<span>: Filter out any gallery with a rating less than:
											<select id="stLim" ` + (setStore.stFilter ? `` : `disabled`) + `>
												<option>5</option>
												<option>4.5</option>
												<option>4</option>
												<option>3.5</option>
												<option>3</option>
												<option>2.5</option>
												<option>2</option>
												<option>1.5</option>
												<option>1</option>
											</select>
										</span>
									</div>
								</fieldset>
							</section>
						</div>
					</div>
				</div>`);
                $("body").append(container);
                if (!$("#minAdd").prop("checked")) { $("#minShow").prop("disabled", true); }
                $("#resV").click(e => { $("#visited").val("box-shadow: inset 0 0 0 500px rgba(2, 129, 255, .2) !important;"); }); // Default Values
                $("#resH").click(e => { $("#hidden").val("box-shadow: inset 0 0 0 500px rgba(255, 40, 0, .2) !important;"); });
                $("#resF").click(e => { $("#filtered").val("box-shadow: inset 0 0 0 500px rgba(200, 0, 100, .2) !important;"); });
                $("#resP").click(e => { $("#page").val("box-shadow: inset 0 0 0 500px rgba(0, 0, 180, .2) !important;"); });
                $("#resR").click(e => { $("#rating").val("box-shadow: inset 0 0 0 500px rgba(180, 80, 60, .2) !important;"); });
                $("#stLim").val(setStore.stLimit);
                $(document).on("change", "input", e => { // Put the change listener on document since I suck at event propogation and bubbling
                    if ($("#minAdd").prop('checked')) {
                        $("#minShow").prop("disabled", false);
                    } else {
                        $("#minShow").prop("disabled", true);
                    }
                    if ($("#pFilt").prop('checked')) {
                        $("#pLim").prop("disabled", false);
                    } else {
                        $("#pLim").prop("disabled", true);
                    }
                    if ($("#stFilt").prop('checked')) {
                        $("#stLim").prop("disabled", false);
                    } else {
                        $("#stLim").prop("disabled", true);
                    }
                });
                $("#settings-close").click(e => applySettings());
                $("body").click(e => {
                    if (e.target.className == "overlay") { // Exit if settings menu isn't clicked
                        applySettings();
                    } else if (e.target.className != "show" && e.target.className != "menu") {
                        $(".show").removeClass("show");
                    }
                });

                /**
				 * Parse our HTML options into a temporary JSON array and then stringify it into localStorage
				 */
                function applySettings() {
                    var tempSto = {
                        "softHide": $("#softHide").prop('checked'),
                        "minAdd": $("#minAdd").prop('checked'),
                        "minShow": $("#minShow").prop('checked'),
                        "cssTT": $("#cssTT").prop('checked'),
                        "repPub": $("#repPub").prop('checked'),
                        "visHide": $(".ehx-show").text() === "Show" ? true : false,
                        "hidShow": $(".ehxh-show").text() === "Hide" ? true : false,
                        "pFilter": $("#pFilt").prop('checked'),
                        "pLimit": $("#pFilt").prop('checked') ? $("#pLim").val() : "0",
                        "stFilter": $("#stFilt").prop('checked'),
                        "stLimit": $("#stFilt").prop('checked') ? $("#stLim option:selected").text() : "0",
                        "titleShow": $("#titleShow").prop('checked')
                    }
                    localStorage.setItem("ehx-settings", JSON.stringify(tempSto)); // Write settings to localStorage
                    var tempCss = {
                        "visible": $("#visited").val(),
                        "hidden": $("#hidden").val(),
                        "filter":  $("#filtered").val(),
                        "page": $("#page").val(),
                        "rating": $("#rating").val()
                    }
                    localStorage.setItem("ehx-css", JSON.stringify(tempCss));
                    localStorage.setItem("ehx-filters", $("#galFilter").val().replace(/^\s*[\r\n]/gm, '')); // Remove null entries because bad things happen if they're there
                    $(".overlay").remove(); // Not entirely necessary, but slightly cosmetic
                    location.reload(); // Force reload to apply settings, I'll probably change this into just a button and not force reload
                }

                $(".collapsible").click(e => { // Expand our custom filtering CSS boxes
                    if ($(".active").length && !$(".active").is(e.target)) { // If a menu is open and it isn't the one we're clicking, close it
                        $(".active").next().css("max-height", "");
                        $(".active").toggleClass("active");
                    }
                    e.target.classList.toggle("active");
                    var content = e.target.nextElementSibling;
                    if (content.style.maxHeight){
                        content.style.maxHeight = null;
                    } else {
                        content.style.maxHeight = "500px";
                    }
                });

                $("#ehx-import").click(e => ehxImport('galleries'));
                $("#ehxh-import").click(e => ehxImport('hidden'));

                $("#ehx-export").click(e => {
                    ehxExport('Exported Entries:', len);
                });

                $("#ehxh-export").click(e => {
                    var objStore2 = db.transaction('hidden', 'readwrite').objectStore('hidden');
                    var openReq = objStore2.getAll();
                    openReq.onsuccess = e => {
                        ehxExport('Exported Entries:', e.target.result);
                    }
                });

                $(".ehx-clear").click(e => {
                    if (!ehxClearConfirm) { // Make sure to double check before deleting
                        ehxClearConfirm = 1;
                        $('.ehx-clear').append(': Are you sure?');
                        ehxExport('Backup your current data:', len);
                    } else {
                        var objStore2 = db.transaction('galleries', 'readwrite').objectStore('galleries');
                        var openReq = objStore2.clear();
                        openReq.onsuccess = e => {
                            alert("EhxVisited:\nCleared all entries.");
                            location.reload();
                        }
                    }
                });

                $(".ehxh-clear").click(e => {
                    var objStore2 = db.transaction('hidden', 'readwrite').objectStore('hidden');
                    var openReq = objStore2.getAll();
                    openReq.onsuccess = e => {
                        if (!ehxhClearConfirm) { // Make sure to double check before deleting
                            ehxhClearConfirm = 1;
                            $('.ehxh-clear').append(': Are you sure?');
                            ehxExport('Backup your current data:', e.target.result);
                        } else {
                            var objStore3 = db.transaction('hidden', 'readwrite').objectStore('hidden');
                            var openReq = objStore3.clear();
                            openReq.onsuccess = e => {
                                alert("EhxVisited:\nCleared all entries.");
                                location.reload();
                            }
                        }
                    }
                });

                // Fancy function to make sure there's not more than one top menu item open
                $(".menu").click(e => {
                    if ($(".show").length) {
                        if ($(".show").prev().is(e.target)) { $(e.target).next().toggleClass("show"); }
                        else {
                            $(".show").removeClass("show");
                            $(e.target).next().toggleClass("show");
                        }
                    } else {
                        $(e.target).next().toggleClass("show");
                    }
                });
            }
        }
    }
    // The giant CSS block
    $(`<style data-jqstyle='ehxVisited'>
#hideCount > span { border-bottom: 1px dotted currentColor; }
#settings-close {
	text-decoration: none;
	position: absolute;
	top: -2px;
	right: 1.5px;
	font-size: 1.4em;
}
#visControls { top: -6px; } `
+ (setStore.titleShow ? `div.gl4t:hover { overflow: visible; z-index: 3; position: relative; background: rgba(0, 0, 0, 0.5); height: auto; }` : ``) + `
ehx { font-family:` + $('body').css('font-family') + `, arial, symbola;  }
table.itg > tbody > tr.ehx-visited, .gl1t.ehx-visited { ` + cssA.visible + ` }
input[type="checkbox"] {
	-webkit-appearance: none;
	border: 1px solid #F1F1F1BB;
	padding: 5px;
	top: 4px;
	background-color: transparent;
}
input[type="checkbox"]:checked:after {
	content: '\\2714';
	position: absolute;
	top: -8px;
	left: 1px;
	font-size: 1.1em;
}
input[type="checkbox"]:focus { outline: none; }
input[type="checkbox"]:hover { cursor: pointer; }
nav > div {
	text-align: right;
	margin-right: 30px;
}
nav > div button {
	border: none !important;
	padding: 1px 20px 1px 10px !important;
	position: relative;
}
table.itg > tbody > tr.ehx-visited.ehx-hidden, .gl1t.ehx-visited.ehx-hidden { ` + cssA.hidden + ` }
.active:after { content: '\\2212' !important; }
.branch {
	position: absolute;
	left: 10px;
	top: 1px;
	margin-left: -3px;
}
.collapsible {
	cursor: pointer;
	width: 100%;
	border: 0;
	outline: none;
	text-align: left;
	font-size: 1.25em;
	background-color: rgba(0, 0, 0, 0);
	color: inherit;
	font-weight: bold;
	padding:5px 3px;
	position: relative;
}
.collapsible:after {
	content: '\\002B';
	font-weight:bold;
	float:right;
	margin-right:5px;
}
.collapsible:before {
	content: '';
	position: absolute;
	padding: 4px;
	border-bottom: 1px solid threedface;
	border-left: 1px solid threedface;
	top: 5px;
	left: -11px;
}
.collapsible:hover { background-color: rgba(255, 255, 255, 0.1); }
.content {
	max-height: 0;
	overflow: hidden;
	transition: all .2s ease-in-out;
	border-bottom: 1px solid threedface;
}
.content button {
	margin-top: 3px;
	margin-right: 10px;
}
.control {
	position: relative;
	float: right;
	right: -5px;
}
.dropdown {
	display: none;
	position: absolute;
	z-index: 999;
	min-width: 150px;
	padding: 2px;
	border-radius: 1px;
	box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
	right: 0px;
	border: 1px solid threedface;
	background: ` + $(".ido").css("background") + `
}
.dropdown a {
	display: block;
	text-decoration: none;
	padding-right:2px;
}
.dropdown a:hover { background: rgba(255,255,255,0.2); }
.ehx-compact {
	border-style: solid;
	border-width: 1px 0;
	text-align: center;
}
.ehx-controls {
	padding: 3px 1px;
	text-align: center;
	display: block;
}
.ehx-exported-data { display: block; }
.ehx-extended {
	width: 120px;
	position: absolute;
	left: 3px;
	top: 172px;
	text-align: center;
	font-size: 8pt;
	line-height: 1.5;
}
.ehx-extended-favs {
	padding: 3px 1px;
	display: block;
	line-height: 1.5;
}
.ehx-hidden { ` + cssD + cssA.hidden + ` }
.ehx-hidden[data-jqstyle*="f"] {` + cssA.filter + `}
.ehx-hidden[data-jqstyle*="p"] {` + cssA.page + `}
.ehx-hidden[data-jqstyle*="r"] {` + cssA.rating + `}
.ehx-minimal {
	border-left: 1px solid #6f6f6f4d;
}
.ehx-minimal-text {
	text-align: center;
	display: block;
}
.ehx-thumbnail {
	display: block;
	text-align: center;
	margin: 3px 0 5px;
	line-height: 12px;
}
.ehx-visited .gl3e { min-height: 206px; }
.ehx-visited .gl4e { min-height: 264px !important; }
.gl2c { width: 115px; }
.mencon {
	display: inline-block;
	position: relative;
}
.menu:after {
	content: '\\2335';
	position: absolute;
	right: 5px;
	bottom: 1px;
}
.overlay {
	background: rgba(0,0,0,0.5);
	display: -webkit-flex;
	display: flex;
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 100;
	font-size: 9pt;
}
.overlay button:not(.collapsible) {
	background-color: transparent;
	border-radius: 6px;
	border: 1px solid threedface;
	cursor: pointer;
	font-weight: bold;
	padding: 3px 20px;
	text-decoration: none;
	color: inherit;
	margin-left: 5px;
}
.overlay button:not(.collapsible):hover { background-color: rgba(255, 255, 255, 0.1); }
.overlay button:not(.collapsible):focus { outline: none; }
.sControls { top: -3px; }
.section-container {
	text-align: left;
	overflow: auto;
}
.section-container textarea:disabled, .section-container input:disabled, .section-container select:disabled {
	opacity: 0.6;
	-webkit-opacity: 0.6;
}
.section-container input[type="number"] {
	border: 1px solid #8d8d8d;
	margin-left:0px;
	text-align: center;
	width: 50px;
}
.section-container select { margin-left: 0px; }
.section-container code {
	color: #000;
	background-color: #FFF;
}
.section-container fieldset { padding-right: 18px; }
.settings {
	background: ` + $(".ido").css("background") + `;
	box-sizing: border-box;
	height: 555px;
	max-height: 100%;
	width: 900px;
	max-width: 100%;
	margin: auto;
	padding: 5px;
	display: -webkit-flex;
	display: flex;
	-webkit-flex-direction: column;
	flex-direction: column;
	box-shadow: 0px 0px 20px 0px rgba(0,0,0,0.5);
}
.settings nav {
	text-align: right;
	padding-bottom: 5px;
	font-weight: bold;
	position: relative;
}
.settings legend {
	font-size: 10pt;
	font-weight: bold;
}
.settings label {
	font-weight: bold;
	text-decoration: underline;
	cursor: pointer;
}
.settings h3 {
	margin: 3px;
	position: relative;
}
.settings input { vertical-align: -1px; }
.settings textarea {
	width: 100%;
	height: 50px;
	resize: vertical;
}
.show { display:block }
.suboptions { position: relative; }
.suboptions > div {
	position: relative;
	padding-left: 1.4em;
}
.suboptions2 {
	margin-left: 4px;
	padding-left: 10px;
	margin-right: -9px;
}
</style>`).appendTo("head");
})();