Carousell++

Makes Carousell search less annoying and more useful

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Carousell++
// @namespace    http://tampermonkey.net/
// @version      1.1
// @license      GPL-3.0
// @description  Makes Carousell search less annoying and more useful
// @author       oopsitsdeleted
// @match        https://www.carousell.sg/search/*
// @match        https://www.carousell.com.my/search/*
// @match        https://www.carousell.ph/search/*
// @match        https://www.carousell.com.hk/search/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    // Log removal events only if you want to debug.
    const DEBUG = true;

    /**
     * removes all the annoying bs from carousell search (boosted/sponsored) hehe 99.999% vibecoded
     */
    function removeSponsoredPosts() {
        let removedCount = 0;

        // --- boosted/spotlight ads ---

        // find boosted
        const boostedIndicators = document.querySelectorAll('svg[fill="#00816D"]');

        // find spotlight indicators
        const spotlightIndicators = document.querySelectorAll('div[style*="background: rgb(169, 80, 168)"]');

        // Combine all listing indicators into one NodeList
        const allListingIndicators = [...boostedIndicators, ...spotlightIndicators];

        allListingIndicators.forEach(indicatorElement => {
            let cardElement = indicatorElement;
            let depth = 0;
            const MAX_DEPTH = 10;

            // main card wrapper
            while (cardElement && depth < MAX_DEPTH) {
                // rabs
                if (cardElement.hasAttribute('data-testid') && cardElement.getAttribute('data-testid').startsWith('listing-card')) {

                    // remove parents
                    const removalTarget = cardElement.parentElement;

                    if (removalTarget && removalTarget.parentElement) {
                        if (DEBUG) console.log(`[Carousell++] Removing Boosted/Spotlight Listing:`, removalTarget);
                        removalTarget.parentElement.removeChild(removalTarget);
                        removedCount++;
                        return;
                    }
                }
                cardElement = cardElement.parentElement;
                depth++;
            }
        });

        // --- banner ads ---

        // target shoutout banner
        const shoutoutSelector = '.D_bNr';
        const shoutoutBanners = document.querySelectorAll(shoutoutSelector);

        shoutoutBanners.forEach(banner => {
            // remove grid item and collapse space so it doesnt leave blank space
            // Shoutout Banner (.D_bNr) -> Parent DIV (1st level) -> Grid Item Container (2nd level, what we want to remove)
            const parent = banner.parentElement;
            const removalTarget = parent ? parent.parentElement : null;

            if (removalTarget && removalTarget.parentElement) {
                if (DEBUG) console.log(`[Carousell++] Removing Shoutout Banner Grid Container:`, removalTarget);
                removalTarget.parentElement.removeChild(removalTarget);
                removedCount++;
            }
        });

        // --- big ass carousell ads ---

        // target banner
        const smartRenderSelector = '.D_aEW';
        const smartRenderBanners = document.querySelectorAll(smartRenderSelector);

        smartRenderBanners.forEach(banner => {
            // remove grid item
            // .D_aEW -> Parent DIV (.D_ZP) -> Grid Item Container (what we want to remove)
            const removalTarget = banner.parentElement;

            if (removalTarget && removalTarget.parentElement) {
                if (DEBUG) console.log(`[Carousell++] Removing Smart Render/Carousell Ad Grid Container:`, removalTarget);
                removalTarget.parentElement.removeChild(removalTarget);
                removedCount++;
            }
        });

        // --- big big big banner ---

        // target banner
        const promotedContentSelector = '.D_ais';
        const promotedContentBanners = document.querySelectorAll(promotedContentSelector);

        promotedContentBanners.forEach(banner => {
            // hmmm
            const removalTarget = banner;

            if (removalTarget && removalTarget.parentElement) {
                if (DEBUG) console.log(`[Carousell++] Removing Promoted Content Banner:`, removalTarget);
                removalTarget.parentElement.removeChild(removalTarget);
                removedCount++;
            }
        });


        if (DEBUG && removedCount > 0) {
            console.log(`[Carousell++] Successfully removed ${removedCount} annoying bs.`);
        }
    }

    /**
     * Use MutationObserver to watch for new content being loaded (e.g., infinite scroll)
     * and run the removal function again.
     */
    function observeDOM() {
        // Observe the main content area (document.body) for new elements.
        const targetNode = document.body;

        const config = { childList: true, subtree: true };

        const observer = new MutationObserver((mutationsList, observer) => {
            // Run the removal logic every time the DOM changes.
            removeSponsoredPosts();
        });

        // Start observing the target node for configured mutations
        observer.observe(targetNode, config);

        // Run the function immediately on page load, as the observer might miss initial content
        removeSponsoredPosts();
    }

    // Start the whole process
    observeDOM();

})();