Nookies Gallery Auto Loader (Full Width Responsive Grid - 4 per row, Full Vertical Images)

Load gallery images on nookies.com by replacing thumbnail URLs with full‑size ones and displaying them in a full‑width responsive grid (4 per row). Vertical images won’t be cropped.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Nookies Gallery Auto Loader (Full Width Responsive Grid - 4 per row, Full Vertical Images)
// @namespace    http://tampermonkey.net/
// @version      0.27
// @description  Load gallery images on nookies.com by replacing thumbnail URLs with full‑size ones and displaying them in a full‑width responsive grid (4 per row). Vertical images won’t be cropped.
// @match        https://www.nookies.com/membersarea/gallery/*
// @grant        none
// @license      GPL-3.0
// ==/UserScript==

(function() {
    'use strict';

    // Inject custom CSS to override container width and create a responsive flex grid.
    const style = document.createElement('style');
    style.innerHTML = `
        /* Use full width for the page content container */
        .page-content .container {
            max-width: 100% !important;
            padding-left: 20px !important;
            padding-right: 20px !important;
        }
        /* Responsive flex grid for the gallery: 4 images per row */
        .flexy-gallery {
          display: flex !important;
          flex-wrap: wrap !important;
          gap: 10px !important;
          justify-content: center;
          padding: 10px;
        }
        /* Each gallery item takes roughly 25% of the width (minus gap adjustments) */
        .flexy-gallery .gallery-item {
          flex: 1 1 calc(25% - 20px) !important;
          max-width: calc(25% - 20px) !important;
          box-sizing: border-box;
        }
        /* Ensure images fill their container and display fully (no cropping for vertical images) */
        .flexy-gallery .gallery-item img {
          width: 100% !important;
          height: auto !important;
          max-height: none !important;
          object-fit: contain !important;
          display: block !important;
        }
        /* Fixed load button styling */
        #nookiesLoadButton {
          position: fixed !important;
          top: 10px !important;
          right: 10px !important;
          z-index: 100000 !important;
          padding: 10px !important;
          background-color: #007bff !important;
          color: #fff !important;
          border: none !important;
          border-radius: 5px !important;
          cursor: pointer !important;
        }
    `;
    document.head.appendChild(style);

    // When the page loads, update the initial images and add the load button.
    if (document.readyState === 'complete') {
        addLoadButton();
        updateInitialImages();
    } else {
        window.addEventListener('load', () => {
            addLoadButton();
            updateInitialImages();
        });
    }

    function logDebug(msg) {
        console.log("[NookiesGalleryAutoLoader] " + msg);
    }

    // Update a gallery item's image: remove restrictions and swap thumbnail URL for the full‑size image.
    function updateGalleryImage(item) {
        const img = item.querySelector('img');
        if (img) {
            img.classList.remove('img-fluid');
            img.removeAttribute('width');
            img.removeAttribute('height');
            img.removeAttribute('srcset');
            if (img.src.includes('/thumbs/')) {
                const oldSrc = img.src;
                img.src = img.src.replace('/thumbs/', '/');
                logDebug("Replaced image URL: from " + oldSrc + " to " + img.src);
            }
            // Force image styles to fill the container.
            img.style.width = "100%";
            img.style.height = "auto";
        }
    }

    // Update all gallery items already on the first page.
    function updateInitialImages() {
        const items = document.querySelectorAll('.flexy-gallery .gallery-item');
        items.forEach(updateGalleryImage);
    }

    // Determine the total number of pages from pagination.
    function getTotalPages() {
        let maxPage = 1;
        const pages = document.querySelectorAll('ul.pagination li.page-item');
        pages.forEach(li => {
            const num = parseInt(li.textContent.trim(), 10);
            if (!isNaN(num) && num > maxPage) {
                maxPage = num;
            }
        });
        logDebug("Total pages: " + maxPage);
        return maxPage;
    }

    // Fetch the HTML content of a gallery page.
    async function fetchGalleryPage(url) {
        try {
            logDebug("Fetching gallery page: " + url);
            const res = await fetch(url, { credentials: 'same-origin' });
            if (!res.ok) {
                logDebug("Error fetching " + url + ": " + res.status);
                return null;
            }
            const html = await res.text();
            const parser = new DOMParser();
            const doc = parser.parseFromString(html, "text/html");
            const container = doc.querySelector('.flexy-gallery');
            if (!container) {
                logDebug("No gallery container found on " + url);
                return null;
            }
            return container.innerHTML;
        } catch (e) {
            logDebug("Fetch error: " + e);
            return null;
        }
    }

    // Load additional gallery pages.
    async function loadAllGalleryPages() {
        const totalPages = getTotalPages();
        if (totalPages <= 1) {
            logDebug("Only one page available.");
            return;
        }
        const gallery = document.querySelector('.flexy-gallery');
        if (!gallery) {
            logDebug("No gallery container found.");
            return;
        }
        const loader = document.createElement('div');
        loader.style.textAlign = "center";
        loader.style.padding = "10px";
        loader.textContent = "Loading all images...";
        gallery.parentNode.insertBefore(loader, gallery.nextSibling);

        const baseUrl = window.location.href.split('?')[0];
        for (let page = 2; page <= totalPages; page++) {
            const pageUrl = `${baseUrl}?page=${page}`;
            const content = await fetchGalleryPage(pageUrl);
            if (content) {
                const tempDiv = document.createElement('div');
                tempDiv.innerHTML = content;
                const items = tempDiv.querySelectorAll('.gallery-item');
                items.forEach(item => {
                    updateGalleryImage(item);
                    gallery.appendChild(item);
                });
                logDebug("Appended " + items.length + " items from page " + page);
            }
        }
        loader.textContent = "All images loaded.";
        document.querySelectorAll('ul.pagination').forEach(el => el.remove());
    }

    // Add a floating load button.
    function addLoadButton() {
        const oldBtn = document.getElementById('nookiesLoadButton');
        if (oldBtn) {
            oldBtn.remove();
        }
        const btn = document.createElement('button');
        btn.id = 'nookiesLoadButton';
        btn.textContent = 'Load All Images';
        btn.addEventListener('click', () => {
            btn.disabled = true;
            logDebug("Load button clicked.");
            loadAllGalleryPages();
        });
        document.body.appendChild(btn);
        logDebug("Load button added.");
    }
})();