GameBanana Toggle Categories

Menu to hide/show Mods, Tutorials, Tools, Sounds, Concepts, WIPs, Sprays, Polls, Threads, Requests, Questions everywhere in gamebanana.com.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         GameBanana Toggle Categories
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Menu to hide/show Mods, Tutorials, Tools, Sounds, Concepts, WIPs, Sprays, Polls, Threads, Requests, Questions everywhere in gamebanana.com.
// @author       ChatGPT
// @match        https://gamebanana.com/*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    const STORAGE_KEY = 'gbToggleCategoriesOptions';

    const categories = [
        { label: 'Mods', className: 'ModRecord', keyword: 'mods', hidden: false },
        { label: 'Tutorials', className: 'TutorialRecord', keyword: 'tutorials', hidden: false },
        { label: 'Tools', className: 'ToolRecord', keyword: 'tools', hidden: false },
        { label: 'Sounds', className: 'SoundRecord', keyword: 'sounds', hidden: false },
        { label: 'Concepts', className: 'ConceptRecord', keyword: 'concepts', hidden: false },
        { label: 'WIPs', className: 'WipRecord', keyword: 'wips', hidden: false },
        { label: 'Sprays', className: 'SprayRecord', keyword: 'sprays', hidden: false },
        { label: 'Polls', className: 'PollRecord', keyword: 'polls', hidden: false },
        { label: 'Threads', className: 'ThreadRecord', keyword: 'threads', hidden: false },
        { label: 'Requests', className: 'RequestRecord', keyword: 'requests', hidden: false },
        { label: 'Questions', className: 'QuestionRecord', keyword: 'questions', hidden: false }
    ];

    // Load preferences
    function loadOptions() {
        const saved = localStorage.getItem(STORAGE_KEY);
        if (saved) {
            try {
                const parsed = JSON.parse(saved);
                categories.forEach(cat => {
                    const savedCat = parsed.find(c => c.className === cat.className);
                    if (savedCat && typeof savedCat.hidden === 'boolean') {
                        cat.hidden = savedCat.hidden;
                    }
                });
            } catch(e) {
                console.warn('Error loading options:', e);
            }
        }
    }

    // Save preferences
    function saveOptions() {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(categories));
    }

    loadOptions();

    // Create foldable menu
    const container = document.createElement('div');
    Object.assign(container.style, {
        position: 'fixed',
        top: '70px',
        left: '8px',
        width: '260px',
        backgroundColor: '#1b1b1b',
        border: '1px solid #444',
        borderRadius: '5px',
        boxShadow: '0 0 12px rgba(0,0,0,0.8)',
        fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif",
        color: '#ccc',
        zIndex: 99999,
        userSelect: 'none',
        overflow: 'hidden',
        transition: 'height 0.25s ease',
    });

    // Foldable button
    const toggleBtn = document.createElement('button');
    toggleBtn.textContent = 'Show / Hide categories';
    Object.assign(toggleBtn.style, {
        width: '100%',
        backgroundColor: '#222',
        border: 'none',
        color: '#ccc',
        fontWeight: '600',
        padding: '10px 0',
        cursor: 'pointer',
        fontSize: '14px',
        outline: 'none',
        userSelect: 'none',
        borderRadius: '5px 5px 0 0',
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        textAlign: 'center',
    });
    toggleBtn.addEventListener('mouseenter', () => toggleBtn.style.backgroundColor = '#333');
    toggleBtn.addEventListener('mouseleave', () => toggleBtn.style.backgroundColor = '#222');

    container.appendChild(toggleBtn);

    // Option container
    const optionsContainer = document.createElement('div');
    Object.assign(optionsContainer.style, {
        backgroundColor: '#181818',
        padding: '12px 16px',
        display: 'none', // folded by default
        maxHeight: '300px',
        overflowY: 'auto',
    });

    // Create checkboxes
    categories.forEach(cat => {
        const label = document.createElement('label');
        Object.assign(label.style, {
            display: 'flex',
            alignItems: 'center',
            marginBottom: '8px',
            fontSize: '13px',
            cursor: 'pointer',
            userSelect: 'none',
            color: '#ccc',
        });

        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.checked = !cat.hidden;
        checkbox.style.marginRight = '10px';
        checkbox.style.cursor = 'pointer';

        checkbox.addEventListener('change', () => {
            cat.hidden = !checkbox.checked;
            saveOptions();
            applyDisplay();
        });

        label.appendChild(checkbox);
        label.appendChild(document.createTextNode(cat.label));
        optionsContainer.appendChild(label);
    });

    container.appendChild(optionsContainer);
    document.body.appendChild(container);

    // Manage folding/unfolding
    let isOpen = false;
    function updateContainer() {
        if (isOpen) {
            optionsContainer.style.display = 'block';
            container.style.height = 'auto';
        } else {
            optionsContainer.style.display = 'none';
            container.style.height = toggleBtn.offsetHeight + 'px';
        }
    }

    toggleBtn.addEventListener('click', () => {
        isOpen = !isOpen;
        updateContainer();
    });

    updateContainer();

    // Display / hide function
    function applyDisplay() {
        categories.forEach(cat => {
            // Per class
            document.querySelectorAll(`.${cat.className}`).forEach(el => {
                el.style.display = cat.hidden ? 'none' : '';
            });

            // By data-cat-url for elements close parent (for game section)
            document.querySelectorAll(`[data-cat-url*="${cat.keyword}"]`).forEach(el => {
                el.style.display = cat.hidden ? 'none' : '';
            });

            // For elements and sections where we identify by href links (ex: game section)
            document.querySelectorAll('a[href*="' + cat.keyword + '"]').forEach(a => {
                let el = a.closest('div.Record');
                if (el) {
                    el.style.display = cat.hidden ? 'none' : '';
                }
            });
        });
    }

    applyDisplay();

    // MutationObserver to detect and add dynamically
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            mutation.addedNodes.forEach(node => {
                if (!(node instanceof HTMLElement)) return;
                categories.forEach(cat => {
                    // By class
                    if (node.classList && node.classList.contains(cat.className)) {
                        node.style.display = cat.hidden ? 'none' : '';
                    }
                    // By data-cat-url
                    if (node.hasAttribute && node.hasAttribute('data-cat-url') && node.getAttribute('data-cat-url').includes(cat.keyword)) {
                        node.style.display = cat.hidden ? 'none' : '';
                    }
                    // By href link
                    node.querySelectorAll && node.querySelectorAll('a[href*="' + cat.keyword + '"]').forEach(a => {
                        let el = a.closest('div.Record');
                        if (el) {
                            el.style.display = cat.hidden ? 'none' : '';
                        }
                    });
                    // Search per class
                    node.querySelectorAll && node.querySelectorAll(`.${cat.className}`).forEach(el => {
                        el.style.display = cat.hidden ? 'none' : '';
                    });
                    // Search per data-cat-url
                    node.querySelectorAll && node.querySelectorAll(`[data-cat-url*="${cat.keyword}"]`).forEach(el => {
                        el.style.display = cat.hidden ? 'none' : '';
                    });
                });
            });
        });
    });

    observer.observe(document.body, { childList: true, subtree: true });

})();