ERISTA Redump+

Filtrar juegos por letra, corregir títulos mal formateados, añadir checkboxes y copiar url de títulos seleccionados en ERISTA.

// ==UserScript==
// @name         ERISTA Redump+
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Filtrar juegos por letra, corregir títulos mal formateados, añadir checkboxes y copiar url de títulos seleccionados en ERISTA.
// @author       Shu2Ouma
// @match        https://myrient.erista.me/files/Redump/*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Estilos específicos para los checkboxes y la alineación
    const checkboxStyles = `
    input[type="checkbox"] {
        width: 15px;
        height: 15px;
        margin: 0;
        vertical-align: middle;
        margin-right: 10px;
    }
    td.link {
        display: flex;
        align-items: center;
    }
    `;

    // Estilos para centrar el selector y los botones
    const centerStyles = `
    #filter-container {
        text-align: center;
        margin: 20px auto;
    }
    #letter-filter, #copy-button, #uncheck-button, #check-all-button {
        color: #FFFFFF;
        background-color: #262A32;
        border: none;
        padding: 10px;
        font-size: 16px;
        border-radius: 5px;
        margin: 5px;
        cursor: pointer;
        transition: all 300ms ease-in;
    }
    #letter-filter {
        display: inline-block;
    }
    #copy-button, #uncheck-button, #check-all-button {
        display: inline-block;
    }
    .clicked {
        transform: scale(0.95);
        transition: transform 0.1s ease-in-out;
    }
    `;

    // Insertamos los estilos en el head de la página
    const styleElement = document.createElement('style');
    styleElement.textContent = checkboxStyles + centerStyles;
    document.head.appendChild(styleElement);

    // Obtenemos el formulario donde queremos insertar los elementos
    let form = document.querySelector('form');
    if (!form) return;

    // Obtenemos el campo de búsqueda para insertarlo antes
    let searchInput = document.querySelector('#search');
    if (!searchInput) return;

    // Creamos el contenedor para el selector y los botones
    let container = document.createElement('div');
    container.id = 'filter-container';

    // Creamos el selector de letras con estilos
    let select = document.createElement('select');
    select.id = 'letter-filter';
    let options = ['Filtrar por letra', '0-9', ...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'];
    options.forEach(letter => {
        let option = document.createElement('option');
        option.value = letter;
        option.text = letter;
        select.appendChild(option);
    });

    // Cargar la letra seleccionada desde localStorage usando la URL actual
    const urlKey = window.location.href;
    const savedLetter = localStorage.getItem(`${urlKey}-selectedLetter`);
    if (savedLetter) {
        select.value = savedLetter;
    }

    // Creamos los botones
    let copyButton = document.createElement('button');
    copyButton.id = 'copy-button';
    copyButton.textContent = 'Copiar url seleccionados';

    let uncheckButton = document.createElement('button');
    uncheckButton.id = 'uncheck-button';
    uncheckButton.textContent = 'Desmarcar todos';

    let checkAllButton = document.createElement('button');
    checkAllButton.id = 'check-all-button';
    checkAllButton.textContent = 'Marcar todos';

    // Creamos el checkbox para ocultar juegos con "(Japan)" o "(Asia)"
    let hideJapanAsiaCheckbox = document.createElement('input');
    hideJapanAsiaCheckbox.type = 'checkbox';
    hideJapanAsiaCheckbox.id = 'hide-japan-asia';
    hideJapanAsiaCheckbox.style.marginLeft = '10px';

    // Cargar el estado del checkbox desde localStorage usando la URL actual
    const hideJapanAsiaState = localStorage.getItem(`${urlKey}-hideJapanAsia`);
    hideJapanAsiaCheckbox.checked = hideJapanAsiaState === 'true';
    let hideJapanAsiaLabel = document.createElement('label');
    hideJapanAsiaLabel.textContent = 'Ocultar (Asiaticos)';
    hideJapanAsiaLabel.htmlFor = 'hide-japan-asia';

    // Insertamos el contenedor antes del campo de búsqueda
    container.appendChild(select);
    container.appendChild(copyButton);
    container.appendChild(uncheckButton);
    container.appendChild(checkAllButton);
    container.appendChild(hideJapanAsiaCheckbox);
    container.appendChild(hideJapanAsiaLabel);
    form.insertBefore(container, searchInput);

    // Función para agregar checkboxes a cada fila de juego
    function addCheckboxes() {
        let rows = document.querySelectorAll('tr');
        rows.forEach((row, index) => {
            let link = row.querySelector('td.link a');
            if (link && !row.querySelector('input.game-checkbox') && !link.textContent.includes('Parent directory')) {
                let checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkbox.className = 'game-checkbox';
                checkbox.style.verticalAlign = 'middle';

                // Cargar el estado del checkbox desde localStorage usando la URL actual
                const savedCheckedState = localStorage.getItem(`${urlKey}-checked-${index}`);
                checkbox.checked = savedCheckedState === 'true';

                // Agregar un evento para guardar el estado del checkbox al cambiar
                checkbox.addEventListener('change', () => {
                    localStorage.setItem(`${urlKey}-checked-${index}`, checkbox.checked);
                });

                let cell = row.querySelector('td.link');
                if (cell) {
                    cell.insertBefore(checkbox, cell.firstChild);
                }
            }
        });
    }

    // Función para corregir los títulos de los juegos
    function correctTitles() {
        let rows = document.querySelectorAll('tr');
        rows.forEach(row => {
            let link = row.querySelector('td.link a');
            if (link && !link.textContent.includes('Parent directory')) {
                let gameTitle = link.textContent.trim();
                // Corregimos el nombre del juego si contiene ', The'
                if (gameTitle.includes(', The')) {
                    gameTitle = gameTitle.replace(', The', '');
                    gameTitle = 'The ' + gameTitle;
                    link.textContent = gameTitle;
                }
            }
        });
    }

    // Función para actualizar la visibilidad de los checkboxes
    function updateCheckboxes() {
        let selectedLetter = select.value;
        localStorage.setItem(`${urlKey}-selectedLetter`, selectedLetter); // Guardar letra seleccionada
        let rows = document.querySelectorAll('tr');
        let hideJapanAsia = hideJapanAsiaCheckbox.checked;
        localStorage.setItem(`${urlKey}-hideJapanAsia`, hideJapanAsia); // Guardar estado del checkbox
        rows.forEach((row, index) => {
            let link = row.querySelector('td.link a');
            if (!link || link.textContent.includes('Parent directory')) return;
            let gameTitle = link.textContent.trim();
            let firstChar = gameTitle.charAt(0).toUpperCase();

            // Ocultar juegos con "(Japan)" o "(Asia)" si el checkbox está marcado
            if (hideJapanAsia && (gameTitle.includes('(Japan)') || gameTitle.includes('(Asia)'))) {
                row.style.display = 'none';
                return;
            }

            // Filtramos los juegos según la letra seleccionada
            if (selectedLetter === 'Filtrar por letra') {
                row.style.display = '';
            } else if (selectedLetter === '0-9' && !isNaN(firstChar)) {
                row.style.display = '';
            } else if (firstChar === selectedLetter) {
                row.style.display = '';
            } else {
                row.style.display = 'none';
            }
        });
    }

    // Función para copiar los enlaces seleccionados
    copyButton.addEventListener('click', function(event) {
        event.preventDefault(); // Evitar que se envíe el formulario
        this.classList.add('clicked'); // Añadir efecto de clic
        setTimeout(() => this.classList.remove('clicked'), 200); // Quitar efecto después de 200ms

        let selectedLinks = [];
        let rows = document.querySelectorAll('tr');
        rows.forEach(row => {
            let checkbox = row.querySelector('input.game-checkbox');
            let link = row.querySelector('td.link a');
            if (checkbox && checkbox.checked && link) {
                selectedLinks.push(link.href);
            }
        });
        if (selectedLinks.length > 0) {
            navigator.clipboard.writeText(selectedLinks.join('\n')).then(() => {
                alert('Enlaces copiados al portapapeles!');
            }).catch(err => {
                console.error('Error al copiar los enlaces: ', err);
            });
        } else {
            alert('No has seleccionado ningún juego.');
        }
    });

    // Función para desmarcar todos los checkboxes
    uncheckButton.addEventListener('click', function(event) {
        event.preventDefault(); // Evitar que se envíe el formulario
        this.classList.add('clicked'); // Añadir efecto de clic
        setTimeout(() => this.classList.remove('clicked'), 200); // Quitar efecto después de 200ms

        let checkboxes = document.querySelectorAll('input.game-checkbox');
        checkboxes.forEach(checkbox => {
            checkbox.checked = false;
            localStorage.setItem(`${urlKey}-checked-${checkbox.parentNode.parentNode.rowIndex}`, false); // Guardar estado
        });
    });

    // Función para marcar todos los checkboxes
    checkAllButton.addEventListener('click', function(event) {
        event.preventDefault(); // Evitar que se envíe el formulario
        this.classList.add('clicked'); // Añadir efecto de clic
        setTimeout(() => this.classList.remove('clicked'), 200); // Quitar efecto después de 200ms

        let checkboxes = document.querySelectorAll('input.game-checkbox');
        checkboxes.forEach(checkbox => {
            checkbox.checked = true;
            localStorage.setItem(`${urlKey}-checked-${checkbox.parentNode.parentNode.rowIndex}`, true); // Guardar estado
        });
    });

    // Añadimos el evento de cambio para actualizar los checkboxes
    select.addEventListener('change', updateCheckboxes);
    hideJapanAsiaCheckbox.addEventListener('change', updateCheckboxes);

    // Ejecutamos las funciones iniciales
    addCheckboxes();
    correctTitles();
    updateCheckboxes();
})();