AliExpress Enhanced Listings

Shows full listing titles and highlights Choice, Bundle deals, and Premium Quality tagged listings in a unique way.

// ==UserScript==
// @name         AliExpress Enhanced Listings
// @namespace    https://aliexpress.com/
// @version      1.5
// @description  Shows full listing titles and highlights Choice, Bundle deals, and Premium Quality tagged listings in a unique way.
// @author       ObnubiladO
// @match        https://*.aliexpress.com/*
// @grant        GM_addStyle
// @run-at       document-idle
// @license      GPL-3.0-or-later
// ==/UserScript==

(function() {
    'use strict';

    // ==================== Full Titles Script ====================
    // Apply CSS overrides for all title elements
    GM_addStyle(`
        /* Original container style */
        div.kr_av h3 {
            display: block !important;
            -webkit-line-clamp: initial !important;
            -webkit-box-orient: unset !important;
            white-space: normal !important;
            overflow: visible !important;
            text-overflow: clip !important;
            max-height: none !important;
            height: auto !important;
            line-height: 1.4 !important;
        }

        /* New element style */
        span[numberoflines] {
            display: block !important;
            -webkit-line-clamp: initial !important;
            -webkit-box-orient: unset !important;
            white-space: normal !important;
            overflow: visible !important;
            text-overflow: clip !important;
            max-height: none !important;
            height: auto !important;
            line-height: 1.4 !important;
        }

        /* Container adjustments */
        div.kr_av,
        div.kr_av > div,
        div.kr_av > a,
        div.kr_av > div > div,
        .product-container,
        .product-card {
            height: auto !important;
            min-height: unset !important;
            max-height: none !important;
            display: block !important;
            overflow: visible !important;
            position: static !important;
        }

        /* Spacing adjustments */
        .product-container {
            margin-bottom: 25px !important;
        }
    `);

    // Function to reset container heights
    function resetContainerHeights(container) {
        let current = container;
        while (current && current.nodeName !== 'BODY') {
            if (current.style.height) current.style.height = 'auto';
            if (current.style.minHeight) current.style.minHeight = '0';
            if (current.style.maxHeight) current.style.maxHeight = 'none';
            current.style.overflow = 'visible';
            current = current.parentElement;
        }
    }

    // Process all titles on the page
    function revealFullTitles() {
        // Process original title elements
        document.querySelectorAll('div.kr_av h3').forEach(title => {
            resetContainerHeights(title);
        });

        // Process new span elements with numberoflines attribute
        document.querySelectorAll('span[numberoflines]').forEach(title => {
            // Reset inline styles
            title.style.display = 'block';
            title.style.webkitLineClamp = 'initial';
            title.style.overflow = 'visible';
            title.style.height = 'auto';
            title.style.maxHeight = 'none';

            resetContainerHeights(title);
        });
    }

    // ==================== Highlight Tags Script ====================
    const CHOICE_HIGHLIGHT_STYLE = 'background-color: #fff8c4 !important; border: 2px solid #f5c518 !important;';
    const CHOICE_HIGHLIGHT_CLASS = 'choice-highlight';

    const BUNDLE_HIGHLIGHT_STYLE = 'background-color: #ff3b3b !important; color: white !important; font-weight: bold !important; border-radius: 4px;';
    const BUNDLE_HIGHLIGHT_CLASS = 'bundle-highlight';

    const PREMIUM_HIGHLIGHT_STYLE = 'background-color: #ffc501 !important; color: #666666 !important; font-weight: bold !important; border-radius: 4px; padding: 0 4px;';
    const PREMIUM_HIGHLIGHT_CLASS = 'premium-highlight';

    function clearHighlights() {
        // Clear Choice card highlights
        document.querySelectorAll(`.${CHOICE_HIGHLIGHT_CLASS}`).forEach(card => {
            card.style.removeProperty('background-color');
            card.style.removeProperty('border');
            card.classList.remove(CHOICE_HIGHLIGHT_CLASS);
        });

        // Clear Bundle tag highlights
        document.querySelectorAll(`.${BUNDLE_HIGHLIGHT_CLASS}`).forEach(tag => {
            tag.style.removeProperty('background-color');
            tag.style.removeProperty('color');
            tag.style.removeProperty('font-weight');
            tag.style.removeProperty('border-radius');
            tag.classList.remove(BUNDLE_HIGHLIGHT_CLASS);
        });

        // Clear Premium Quality highlights
        document.querySelectorAll(`.${PREMIUM_HIGHLIGHT_CLASS}`).forEach(tag => {
            tag.style.removeProperty('background-color');
            tag.style.removeProperty('color');
            tag.style.removeProperty('font-weight');
            tag.style.removeProperty('border-radius');
            tag.style.removeProperty('padding');
            tag.classList.remove(PREMIUM_HIGHLIGHT_CLASS);
        });
    }

    function highlightChoiceCards() {
        const choiceImages = document.querySelectorAll('img[src*="154x64.png"], img[src*="S1887a285b60743859ac7bdbfca5e0896Z"]');
        const foundCards = new Set();

        choiceImages.forEach(img => {
            if (img.offsetWidth > 0 && img.offsetHeight > 0) {
                let card = img;
                while (card && !card.classList.contains('search-item-card-wrapper-gallery')) {
                    card = card.parentElement;
                    if (!card) break;
                }

                if (card && !foundCards.has(card)) {
                    card.style.cssText += CHOICE_HIGHLIGHT_STYLE;
                    card.classList.add(CHOICE_HIGHLIGHT_CLASS);
                    foundCards.add(card);
                }
            }
        });
    }

    function highlightBundleTags() {
        const elements = document.querySelectorAll('*');
        elements.forEach(el => {
            if (el.textContent.trim() === 'Bundle deals' &&
                el.offsetWidth > 0 &&
                el.offsetHeight > 0) {

                el.style.cssText += BUNDLE_HIGHLIGHT_STYLE;
                el.classList.add(BUNDLE_HIGHLIGHT_CLASS);
            }
        });
    }

    function highlightPremiumQualityTags() {
        const elements = document.querySelectorAll('*');
        elements.forEach(el => {
            if (el.childNodes.length === 1 && el.childNodes[0].nodeType === Node.TEXT_NODE) {
                const text = el.textContent.trim();
                if (text === 'Premium Quality' && el.offsetWidth > 0 && el.offsetHeight > 0) {
                    const span = document.createElement('span');
                    span.textContent = 'Premium Quality';
                    span.style.cssText = PREMIUM_HIGHLIGHT_STYLE;
                    span.classList.add(PREMIUM_HIGHLIGHT_CLASS);

                    el.textContent = '';
                    el.appendChild(span);
                }
            }
        });
    }

    function applyHighlights() {
        clearHighlights();
        highlightChoiceCards();
        highlightBundleTags();
        highlightPremiumQualityTags();
    }

    // ==================== Combined Functionality ====================
    function updateAll() {
        revealFullTitles();
        applyHighlights();
    }

    // Debounced update function
    let timeout;
    function debouncedUpdateAll() {
        clearTimeout(timeout);
        timeout = setTimeout(updateAll, 300);
    }

    // Set up mutation observer and events
    function setupObserversAndEvents() {
        const observer = new MutationObserver(debouncedUpdateAll);
        observer.observe(document.body, { childList: true, subtree: true });

        window.addEventListener('load', debouncedUpdateAll);
        document.addEventListener('scroll', debouncedUpdateAll);

        // URL change detection
        let lastUrl = location.href;
        setInterval(() => {
            if (location.href !== lastUrl) {
                lastUrl = location.href;
                debouncedUpdateAll();
            }
        }, 1000);
    }

    // ==================== Initialization ====================
    function init() {
        console.log('[AliExpress Enhancer v1.7] Initializing...');
        updateAll();
        setupObserversAndEvents();
    }

    // Start after DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        setTimeout(init, 1000);
    }
})();