Infinite Scroll

Infinite scrolling for March 2019 layout redesign.

As of 2019-08-13. See the latest version.

// ==UserScript==
// @name         Infinite Scroll
// @author       Hauffen
// @description  Infinite scrolling for March 2019 layout redesign.
// @version      2.10
// @include      /https?:\/\/(e-|ex)hentai\.org\/.*/
// @require      https://code.jquery.com/jquery-3.3.1.min.js
// @namespace    https://greasyfork.org/users/285675
// ==/UserScript==

(function() {
    var url = document.URL;
    var page = 0;
    var query, nextUrl;
    var flag;
    var timeout;

    function newUrl() {
        if (window.location.origin + "/" == url || url.substr(window.location.origin.length + 1).startsWith("?") || url.split('/')[3] == "uploader") {
            if (parseInt($(".ptt tr")[0].children[$(".ptt tr")[0].childElementCount - 2].textContent) > 1) {
                if ((page + 2) > $(".ptt tr")[0].children[$(".ptt tr")[0].childElementCount - 2].textContent) { // Return null if our next page is outside of the scope of the results for a tag search
                    nextUrl = null;
                    return;
                }
            } else { // Return null if we only have a single page
                nextUrl = null;
                return;
            }

            // Return null if we're doing a file hash search
            if (url.match(/f_shash/)) {
                return null;
            }

            if (url.split('?').length > 1) { // See if we're beginning from a page other than the base URL
                if ($.isNumeric(url.split('?')[1].substr(5,1)) && page == 0) {
                    page = url.split('?')[1].substr(5,1); // Adjust the page offset if we're starting from a page other than the first page
                }

                if (url.includes("page=")) {
                    query = url.substr(url.indexOf('&')); // Get query if page is already set
                } else {
                    query = url.split('?')[1]; // If page is unset, we just need the whole string
                }
                query = (query.startsWith("&")) ? query : "&" + query; // Make sure that our query begins with an ampersand
                query = (query.includes("from=")) ? query.substr(0, query.lastIndexOf("&")) : query; // Remove the gallery ID offset if it's included in the query

                nextUrl = (query != null) ? "https://" + window.location.hostname + "/?page=" + (parseInt(page) + 1) + query : "https://" + window.location.hostname + "/?page=" + (parseInt(page) + 1);
                if (url.match(/\/favorites\//)) {
                    nextUrl = (query != null) ? "https://" + window.location.hostname + "/favorites.php?page=" + (parseInt(page) + 1) + query : "https://" + window.location.hostname + "/favorites.php?page=" + (parseInt(page) + 1);
                }
            } else if (url.match(/\/tag\//) || url.match(/\/uploader\//)) {
                if ($.isNumeric(url.split('/')[5]) && page == 0) {
                    page = parseInt(url.split('/')[5]);
                }

                nextUrl = $.isNumeric(url.split('/')[5]) ? url.substr(0, url.length - 1) + (parseInt(page) + 1) : url + "/" + (parseInt(page) + 1);
                //nextUrl = url + "/" + (parseInt(page) + 1);
            } else { // Otherwise, just do the next generic page URL
                nextUrl = (url.match(/\/favorites\//)) ? "https://" + window.location.hostname + "/favorites.php?page=" + (parseInt(page) + 1) : "https://" + window.location.hostname + "/?page=" + (parseInt(page) + 1);
            }
        }
    };

    newUrl();

    function loadMore(){
        var index = document.getElementsByTagName("select").length > 1 ? 1 : 0; // Offset the select index if there are more than one
        flag = false;
        clearTimeout(timeout);
        // Don't do anything if we're in a gallery or viewing pages
        if (url.split('/')[3] === "g" || url.split('/')[3] === "s") {
            return;
        }

        // Make sure we're near enough to the bottom of the page
        if ($(window).scrollTop() + $(window).height() >= $(document).height() && nextUrl != null) {
            var $content = $('<div>'); // Create a div container to throw scraped content into

            var offset = "";
            if (!url.match(/\/favorites\//)) {
                offset = "&from=" + document.getElementsByClassName('itg')[0].lastChild.getElementsByTagName("a")[0].href.split("/")[4]; // Append the gallery offset to URL
            }
            $content.load((url.match(/\/tag\//) || url.match(/\/uploader\//)) ? nextUrl :`${nextUrl + offset}`, function() { // Only add the gallery offset if we're not doing a tag search, since tag search uses a different URL scheme
                var divs = null;
                // Error catching
                if (document.getElementsByTagName("select")[index] == null) {
                    index = 0;
                }

                // Different selectors for e-h versus exh
                if (window.location.hostname.substr(1,1) !== "x") {
                    if (document.getElementsByTagName("select")[index].selectedIndex == 4 || url.match(/\/favorites\//)) {
                        divs = this.getElementsByClassName('itg')[0].children;
                    } else {
                        divs = this.getElementsByClassName('itg')[0].children;
                    }
                } else {
                    if (document.getElementsByTagName("select")[index].selectedIndex == 4 || url.match(/\/favorites\//)) {
                        divs = this.getElementsByClassName('itg')[0].children;
                    } else {
                        divs = this.getElementsByClassName('itg')[0].children[0].children;
                    }
                }

                // Remove the first element (table header) if not in thumbnail mode
                if (document.getElementsByTagName("select")[index].selectedIndex !== 3 && document.getElementsByTagName("select")[index].selectedIndex !== 4 && !url.match(/favorites/)) {
                    divs[0].parentNode.removeChild(divs[0]);
                }

                // Add scraped content to our current page
                while (divs.length > 0) {
                    $('.itg').append(divs[0]);
                };
                flag = true;
                timeout = setTimeout(forceLoad());
            });

            page = parseInt(page) + 1;
            newUrl();
        }
    };

    function forceLoad() {
        // Force page load if body height is less than window height
        if ($("body").height() < $(window).height()) {
            loadMore();
            if (!flag) {
                return;
            } else {
                timeout = setTimeout(forceLoad(), 10000);
            }
        }
    }

    forceLoad();

    //Otherwise, do the normal scroll checks
    $(window).on('scroll', function(){
        loadMore();
        if (url.split('/')[3] == "" || url.split('/')[3].startsWith("?")) {
            var offset = (document.getElementById('advdiv').style.display == "none") ? 108 : 291;

            // Delete this block if you don't want the search bar to float
            if(window.pageYOffset > (document.getElementById("searchbox").offsetTop + offset)) {
                $('#searchbox').css({
                    position:'fixed',
                    top:'5px',
                    width:'612px',
                    zIndex:'3',
                    background:'#3a4650', //This line is the background color for the box, edit to your preference
                    //background: window.getComputedStyle($("div.ido")[0]).background, // Use this line if you don't want to think about it
                    left:'50%',
                    marginLeft:'-306px'
                });
                $('.ido')[0].lastChild.style.paddingTop = parseInt(offset) + 6 + 'px';
            } else { // Reset CSS rules
                $('#searchbox').css({
                    position:'',
                    top:'',
                    width:'',
                    zIndex:'',
                    background:'',
                    left:'',
                    marginLeft:''
                });
                $('.ido')[0].lastChild.style.paddingTop = '';
            }
        }
    });
})();