Bazaar Item Search powered by IronNerd

View items you are searching for in bazaars!

Versión del día 23/11/2024. Echa un vistazo a la versión más reciente.

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         Bazaar Item Search powered by IronNerd
// @namespace    [email protected]
// @version      0.3.7
// @description  View items you are searching for in bazaars!
// @author       Nurv [669537]
// @match        https://www.torn.com/page.php?sid=ItemMarket*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-end
// @license Copyright IronNerd.me
// @connect      ironnerd.me
// ==/UserScript==

(function () {
    'use strict';

    console.log('IronNerd Bazaar Enhancements script started.');

    // ------------------ Configuration ------------------
    const BACKEND_URL = 'https://www.ironnerd.me';
    const ongoingRequests = new Set();
    let currentPage = 1;
    const itemsPerPage = 15;
    let allBazaarItems = [];

    // ------------------ Initialization ------------------
    init();

    function init() {
        injectAdditionalStyles();
        ensureBazaarEnhancerContainer();
        addBazaarButtons();
        observeDOMChanges();
        detectSearch();
        observeDarkMode();
        initializeTopCheapestItems();
        adjustBazaarEnhancerContainerTheme();
    }

    // ------------------ Utility Functions ------------------

    function debounce(func, wait) {
        let timeout;
        return function (...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }

    function getItemInfoFromURL() {
        const url = new URL(window.location.href);
        let itemID = null;
        let itemName = '';

        let hash = url.hash.startsWith('#/') ? url.hash.substring(2) : url.hash.substring(1);
        const hashParts = hash.split('/');
        const paramsString = hashParts[hashParts.length - 1];
        const hashParams = new URLSearchParams(paramsString);
        itemID = hashParams.get('itemID');
        itemName = hashParams.get('itemName') ? decodeURIComponent(hashParams.get('itemName')) : '';

        console.log('IronNerd Bazaar Enhancements: Extracted itemID from hash:', itemID);
        console.log('IronNerd Bazaar Enhancements: Extracted itemName from hash:', itemName);

        if (!itemID) {
            const searchParams = url.searchParams;
            itemID = searchParams.get('itemID');
            itemName = searchParams.get('itemName') ? decodeURIComponent(searchParams.get('itemName')) : '';
            console.log('IronNerd Bazaar Enhancements: Extracted itemID from search:', itemID);
            console.log('IronNerd Bazaar Enhancements: Extracted itemName from search:', itemName);
        }

        if (itemID) {
            return { itemID: parseInt(itemID), itemName };
        }

        return { itemID: null, itemName: '' };
    }

    function ensureBazaarEnhancerContainer() {
        let container = document.getElementById('bazaar-enhancer-container');
        if (!container) {
            container = document.createElement('div');
            container.id = 'bazaar-enhancer-container';

            const delimiter = document.querySelector('.delimiter___zFh2E');
            if (delimiter && delimiter.parentNode) {
                delimiter.parentNode.insertBefore(container, delimiter.nextSibling);
            } else {
                document.body.appendChild(container);
            }

            console.log('IronNerd Bazaar Enhancements: `bazaar-enhancer-container` created and appended to the DOM.');
        } else {
            console.log('IronNerd Bazaar Enhancements: `bazaar-enhancer-container` already exists.');
        }
    }

    function addBazaarButtons() {
        const addListingsLink = document.querySelector('a[href="#/addListing"]');
        if (addListingsLink) {
            const linksContainer = addListingsLink.parentElement;
            if (linksContainer && !document.getElementById('bazaarButton')) {
                const bazaarLink = addListingsLink.cloneNode(true);
                bazaarLink.id = 'bazaarButton';
                bazaarLink.setAttribute('aria-labelledby', 'Bazaar');
                bazaarLink.href = '#';

                const linkTitle = bazaarLink.querySelector('.linkTitle____NPyM');
                if (linkTitle) {
                    linkTitle.innerText = 'Bazaar';
                }

                const svgIcon = bazaarLink.querySelector('svg');
                if (svgIcon) {
                    svgIcon.innerHTML = '<svg fill="#000000" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 902.86 902.86" xml:space="preserve"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g> <g> <path d="M671.504,577.829l110.485-432.609H902.86v-68H729.174L703.128,179.2L0,178.697l74.753,399.129h596.751V577.829z M685.766,247.188l-67.077,262.64H131.199L81.928,246.756L685.766,247.188z"></path> <path d="M578.418,825.641c59.961,0,108.743-48.783,108.743-108.744s-48.782-108.742-108.743-108.742H168.717 c-59.961,0-108.744,48.781-108.744,108.742s48.782,108.744,108.744,108.744c59.962,0,108.743-48.783,108.743-108.744 c0-14.4-2.821-28.152-7.927-40.742h208.069c-5.107,12.59-7.928,26.342-7.928,40.742 C469.675,776.858,518.457,825.641,578.418,825.641z M209.46,716.897c0,22.467-18.277,40.744-40.743,40.744 c-22.466,0-40.744-18.277-40.744-40.744c0-22.465,18.277-40.742,40.744-40.742C191.183,676.155,209.46,694.432,209.46,716.897z M619.162,716.897c0,22.467-18.277,40.744-40.743,40.744s-40.743-18.277-40.743-40.744c0-22.465,18.277-40.742,40.743-40.742 S619.162,694.432,619.162,716.897z"></path> </g> </g> </g></svg>';
                }

                bazaarLink.addEventListener('click', (e) => {
                    e.preventDefault();
                    openShowBazaarModal();
                });

                linksContainer.appendChild(bazaarLink);

                console.log('Bazaar button added to layout.');
            }
        }
    }

    function createBazaarButton(id, text) {
        const button = document.createElement('button');
        button.id = id;
        button.innerText = text;
        button.style.cursor = 'pointer';
        button.style.padding = '6px 10px';
        button.style.margin = '5px';
        button.style.backgroundColor = '#4caf50';
        button.style.color = '#fff';
        button.style.border = 'none';
        button.style.borderRadius = '4px';
        button.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.2)';
        button.style.fontSize = '12px';

        button.type = 'button';

        button.addEventListener('click', () => {
            console.log(`${text} button clicked!`);
            openShowBazaarModal();
        });

        return button;
    }

    function observeDOMChanges() {
        const targetNode = document.body;
        const config = { childList: true, subtree: true };

        const debouncedAddButtons = debounce(() => {
            addBazaarButtons();
        }, 500);

        const callback = function (mutationsList, observer) {
            for (let mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    debouncedAddButtons();
                }
            }
        };

        const observer = new MutationObserver(callback);
        observer.observe(targetNode, config);
    }

    function openShowBazaarModal() {
        console.log('IronNerd Bazaar Enhancements: "Show Bazaar" button clicked.');

        createShowBazaarModal();

        const modal = document.getElementById('showBazaarModal');
        if (modal) {
            modal.style.display = 'flex';
            console.log('IronNerd Bazaar Enhancements: Show Bazaar modal displayed.');

            const { itemID, itemName } = getItemInfoFromURL();
            const itemNameDisplay = modal.querySelector('#itemNameDisplay');
            const resultsContainer = modal.querySelector('#showBazaarResults');

            currentPage = 1;
            allBazaarItems = [];

            if (itemName && itemNameDisplay) {
                itemNameDisplay.innerText = `Showing Bazaar Listings for: ${itemName}`;
            } else {
                itemNameDisplay.innerText = 'No item selected.';
            }

            if (itemID) {
                console.log(`IronNerd Bazaar Enhancements: Fetching all bazaar items for item_id ${itemID}.`);
                fetchBazaarItems(itemID);
            } else {
                resultsContainer.innerHTML = '<p>No item selected for display.</p>';
            }

            trapFocus(modal);
        } else {
            console.error('IronNerd Bazaar Enhancements: showBazaarModal element not found.');
        }
    }

    function createShowBazaarModal() {
        if (document.getElementById('showBazaarModal')) {
            console.log('IronNerd Bazaar Enhancements: Show Bazaar modal already exists.');
            return;
        }

        console.log('IronNerd Bazaar Enhancements: Creating Show Bazaar modal.');

        const overlay = document.createElement('div');
        overlay.id = 'showBazaarModal';
        overlay.setAttribute('role', 'dialog');
        overlay.setAttribute('aria-labelledby', 'modal-title');
        overlay.setAttribute('aria-modal', 'true');
        overlay.style.position = 'fixed';
        overlay.style.top = '0';
        overlay.style.left = '0';
        overlay.style.width = '100%';
        overlay.style.height = '100%';
        overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
        overlay.style.display = 'none';
        overlay.style.zIndex = '10000';
        overlay.style.overflowY = 'auto';
        overlay.style.alignItems = 'center';
        overlay.style.justifyContent = 'center';

        const modalContent = document.createElement('div');
        modalContent.id = 'modal-content';
        modalContent.style.backgroundColor = '#9e9b9b';
        modalContent.style.padding = '20px';
        modalContent.style.borderRadius = '8px';
        modalContent.style.width = '90%';
        modalContent.style.maxWidth = '800px';
        modalContent.style.position = 'relative';
        modalContent.style.boxShadow = '0 5px 15px rgba(0,0,0,0.3)';
        modalContent.style.maxHeight = '90%';
        modalContent.style.overflowY = 'auto';

        const closeBtn = document.createElement('span');
        closeBtn.innerHTML = '&times;';
        closeBtn.style.position = 'absolute';
        closeBtn.style.top = '10px';
        closeBtn.style.right = '20px';
        closeBtn.style.fontSize = '30px';
        closeBtn.style.fontWeight = 'bold';
        closeBtn.style.cursor = 'pointer';
        closeBtn.style.color = '#aaa';
        closeBtn.addEventListener('mouseover', () => {
            closeBtn.style.color = '#000';
        });
        closeBtn.addEventListener('mouseout', () => {
            closeBtn.style.color = '#aaa';
        });
        closeBtn.addEventListener('click', closeShowBazaarModal);

        const title = document.createElement('h2');
        title.id = 'modal-title';
        title.style.textAlign = 'center';
        title.style.marginBottom = '20px';

        const itemNameDisplay = document.createElement('h3');
        itemNameDisplay.id = 'itemNameDisplay';
        itemNameDisplay.style.textAlign = 'center';
        itemNameDisplay.style.marginBottom = '10px';
        itemNameDisplay.style.color = '#333';
        modalContent.appendChild(itemNameDisplay);

        const resultsContainer = document.createElement('div');
        resultsContainer.id = 'showBazaarResults';
        resultsContainer.style.marginTop = '20px';

        const statusDiv = document.createElement('div');
        statusDiv.id = 'showBazaarStatusMessage';
        statusDiv.style.marginTop = '10px';
        statusDiv.style.fontWeight = 'bold';

        modalContent.appendChild(closeBtn);
        modalContent.appendChild(title);
        modalContent.appendChild(resultsContainer);
        modalContent.appendChild(statusDiv);

        overlay.appendChild(modalContent);

        document.body.appendChild(overlay);

        overlay.addEventListener('click', function (event) {
            if (event.target === overlay) {
                closeShowBazaarModal();
            }
        });

        document.addEventListener('keydown', function (event) {
            if (event.key === 'Escape') {
                closeShowBazaarModal();
            }
        });

        console.log('IronNerd Bazaar Enhancements: Show Bazaar modal created and appended to the DOM.');
    }

    function closeShowBazaarModal() {
        const modal = document.getElementById('showBazaarModal');
        if (modal) {
            modal.style.display = 'none';
            console.log('IronNerd Bazaar Enhancements: Show Bazaar modal closed.');
        }
    }

    function fetchBazaarItems(itemID) {
        const modal = document.getElementById('showBazaarModal');
        const resultsContainer = modal.querySelector('#showBazaarResults');
        const statusDiv = modal.querySelector('#showBazaarStatusMessage');

        if (ongoingRequests.has(`bazaar_items_${itemID}`)) {
            console.log('IronNerd Bazaar Enhancements: Skipping duplicate request for bazaar items.');
            return;
        }

        ongoingRequests.add(`bazaar_items_${itemID}`);

        resultsContainer.innerHTML = `
            <p>Loading...</p>
            <div class="loading-spinner"></div>
        `;
        statusDiv.innerHTML = '';

        GM_xmlhttpRequest({
            method: 'GET',
            url: `${BACKEND_URL}/get_bazaar_items/${itemID}`,
            headers: {
                'Accept': 'application/json'
            },
            onload: function (response) {
                ongoingRequests.delete(`bazaar_items_${itemID}`);

                if (response.status === 200) {
                    try {
                        const data = JSON.parse(response.responseText);
                        if (data.bazaar_items) {
                            allBazaarItems = data.bazaar_items;
                            displayBazaarItems(allBazaarItems);
                            console.log('IronNerd Bazaar Enhancements: All Bazaar Items fetched successfully.');
                        } else {
                            resultsContainer.innerHTML = '<p>No items found.</p>';
                            console.error('IronNerd Bazaar Enhancements: Invalid data format:', data);
                        }
                    } catch (e) {
                        resultsContainer.innerHTML = '<p>Error parsing server response.</p>';
                        console.error('IronNerd Bazaar Enhancements: Parsing Error:', e);
                    }
                } else {
                    resultsContainer.innerHTML = `<p>Error: ${response.status} - ${response.statusText}</p>`;
                    console.error('IronNerd Bazaar Enhancements: Fetch All Bazaar Items Error:', response.responseText);
                }
            },
            onerror: function (error) {
                ongoingRequests.delete(`bazaar_items_${itemID}`);

                resultsContainer.innerHTML = '<p>Network error occurred. Please try again later.</p>';
                console.error('IronNerd Bazaar Enhancements: Network Error:', error);
            }
        });
    }

    function displayBazaarItems(items) {
        const modal = document.getElementById('showBazaarModal');
        const resultsContainer = modal.querySelector('#showBazaarResults');
        resultsContainer.innerHTML = '';

        if (items.length === 0) {
            resultsContainer.innerHTML = '<p>No items found in registered bazaars.</p>';
            return;
        }

        const totalPages = Math.ceil(items.length / itemsPerPage);
        if (currentPage > totalPages) currentPage = totalPages;

        const startIndex = (currentPage - 1) * itemsPerPage;
        const endIndex = Math.min(startIndex + itemsPerPage, items.length);
        const paginatedItems = items.slice(startIndex, endIndex);

        const tableContainer = document.createElement('div');
        tableContainer.style.overflowX = 'table-responsive';
        tableContainer.style.width = '100%';

        const table = document.createElement('table');
        table.className = 'bazaar-table';
        table.style.width = '100%';
        table.style.borderCollapse = 'collapse';

        const thead = document.createElement('thead');
        const headerRow = document.createElement('tr');

        const headers = ['Image', 'Owner', 'Price ($)', 'Quantity', 'Visit Bazaar'];
        headers.forEach(header => {
            const th = document.createElement('th');
            th.innerText = header;
            th.style.border = '1px solid #ccc';
            th.style.padding = '8px';
            th.style.backgroundColor = '#f2f2f2';
            th.style.textAlign = 'center';
            th.style.fontSize = '14px';
            headerRow.appendChild(th);
        });
        thead.appendChild(headerRow);
        table.appendChild(thead);

        const tbody = document.createElement('tbody');

        paginatedItems.forEach(item => {
            const tr = document.createElement('tr');

            const imgCell = document.createElement('td');
            imgCell.style.border = '1px solid #ccc';
            imgCell.style.padding = '4px';
            imgCell.style.textAlign = 'center';
            const img = document.createElement('img');
            img.src = `/images/items/${item.item_id}/small.png`;
            img.alt = item.name;
            img.style.height = '30px';
            imgCell.appendChild(img);
            tr.appendChild(imgCell);

            const ownerCell = document.createElement('td');
            ownerCell.setAttribute('data-label', 'Owner');
            ownerCell.style.border = '1px solid #ccc';
            ownerCell.style.padding = '6px';
            ownerCell.style.textAlign = 'center';
            ownerCell.style.fontSize = '14px';
            const ownerLink = document.createElement('a');
            ownerLink.href = `https://www.torn.com/profiles.php?XID=${item.user_id}`;
            ownerLink.textContent = item.owner;
            ownerLink.target = '_blank';
            ownerLink.style.color = 'inherit';
            ownerLink.style.textDecoration = 'none';
            ownerLink.addEventListener('mouseover', () => {
                ownerLink.style.textDecoration = 'underline';
            });
            ownerLink.addEventListener('mouseout', () => {
                ownerLink.style.textDecoration = 'none';
            });
            ownerCell.appendChild(ownerLink);
            tr.appendChild(ownerCell);

            const priceTd = document.createElement('td');
            priceTd.innerText = `$${item.price.toLocaleString()}`;
            priceTd.setAttribute('data-label', 'Price ($)');
            priceTd.style.border = '1px solid #ccc';
            priceTd.style.padding = '6px';
            priceTd.style.textAlign = 'center';
            priceTd.style.fontSize = '14px';
            tr.appendChild(priceTd);

            const quantityTd = document.createElement('td');
            quantityTd.innerText = item.quantity;
            quantityTd.setAttribute('data-label', 'Quantity');
            quantityTd.style.border = '1px solid #ccc';
            quantityTd.style.padding = '6px';
            quantityTd.style.textAlign = 'center';
            quantityTd.style.fontSize = '14px';
            tr.appendChild(quantityTd);

            const bazaarTd = document.createElement('td');
            bazaarTd.style.border = '1px solid #ccc';
            bazaarTd.style.padding = '6px';
            bazaarTd.style.textAlign = 'center';
            bazaarTd.style.fontSize = '14px';
            const bazaarLink = document.createElement('a');
            bazaarLink.href = `https://www.torn.com/bazaar.php?userID=${item.user_id}`;
            bazaarLink.textContent = 'Visit';
            bazaarLink.target = '_blank';
            bazaarLink.style.color = '#007bff';
            bazaarLink.style.textDecoration = 'none';
            bazaarLink.addEventListener('mouseover', () => {
                bazaarLink.style.textDecoration = 'underline';
            });
            bazaarLink.addEventListener('mouseout', () => {
                bazaarLink.style.textDecoration = 'none';
            });
            bazaarTd.appendChild(bazaarLink);
            bazaarTd.setAttribute('data-label', 'Visit Bazaar');
            tr.appendChild(bazaarTd);

            tbody.appendChild(tr);
        });

        table.appendChild(tbody);
        tableContainer.appendChild(table);
        resultsContainer.appendChild(tableContainer);

        addPaginationControls(resultsContainer, allBazaarItems.length, totalPages);

        adjustBazaarTableTheme();
    }

    function addPaginationControls(container, totalItems, totalPages) {
        const existingPagination = container.querySelector('.pagination-controls');
        if (existingPagination) {
            existingPagination.remove();
        }

        if (totalPages <= 1) return;

        const paginationContainer = document.createElement('div');
        paginationContainer.className = 'pagination-controls';
        paginationContainer.style.display = 'flex';
        paginationContainer.style.justifyContent = 'center';
        paginationContainer.style.alignItems = 'center';
        paginationContainer.style.marginTop = '15px';
        paginationContainer.style.flexWrap = 'wrap';

        const prevButton = document.createElement('button');
        prevButton.innerText = 'Previous';
        prevButton.disabled = currentPage === 1;
        prevButton.className = 'pagination-button';
        prevButton.addEventListener('click', () => {
            if (currentPage > 1) {
                currentPage--;
                displayBazaarItems(allBazaarItems);
            }
        });
        paginationContainer.appendChild(prevButton);

        const pageIndicator = document.createElement('span');
        pageIndicator.innerText = `Page ${currentPage} of ${totalPages}`;
        pageIndicator.style.margin = '0 10px';
        pageIndicator.style.fontSize = '14px';
        paginationContainer.appendChild(pageIndicator);

        const nextButton = document.createElement('button');
        nextButton.innerText = 'Next';
        nextButton.disabled = currentPage === totalPages;
        nextButton.className = 'pagination-button';
        nextButton.addEventListener('click', () => {
            if (currentPage < totalPages) {
                currentPage++;
                displayBazaarItems(allBazaarItems);
            }
        });
        paginationContainer.appendChild(nextButton);

        container.appendChild(paginationContainer);
    }

    function fetchTopCheapestItems(itemID) {
        const { itemName } = getItemInfoFromURL();
        const container = document.getElementById('bazaar-enhancer-container');
        if (!container) {
            console.error('IronNerd Bazaar Enhancements: Container for top 3 items not found.');
            return;
        }

        if (ongoingRequests.has(`top_cheapest_${itemID}`)) {
            console.log('IronNerd Bazaar Enhancements: Skipping duplicate request for top 3 cheapest items.');
            return;
        }

        ongoingRequests.add(`top_cheapest_${itemID}`);
        container.innerHTML = `
            <p>Loading top 3 cheapest items...</p>
            <div class="loading-spinner"></div>
        `;

        GM_xmlhttpRequest({
            method: 'GET',
            url: `${BACKEND_URL}/get_top_cheapest_items/${itemID}`,
            headers: {
                'Accept': 'application/json'
            },
            onload: function (response) {
                ongoingRequests.delete(`top_cheapest_${itemID}`);

                if (response.status === 200) {
                    try {
                        const data = JSON.parse(response.responseText);
                        if (data.top_cheapest_items && Array.isArray(data.top_cheapest_items)) {
                            displayTopCheapestItems(data.top_cheapest_items, itemName);
                            console.log('IronNerd Bazaar Enhancements: Top 3 Cheapest Items fetched successfully.');
                        } else {
                            displayShowBazaarStatusMessage('error', 'Invalid data format received.');
                            console.error('IronNerd Bazaar Enhancements: Invalid data format:', data);
                        }
                    } catch (e) {
                        container.innerHTML = '<p>Error parsing server response.</p>';
                        console.error('IronNerd Bazaar Enhancements: Parsing Error:', e);
                    }
                } else {
                    container.innerHTML = `<p>Error: ${response.status} - ${response.statusText}</p>`;
                    console.error('IronNerd Bazaar Enhancements: Fetch Top 3 Cheapest Items Error:', response.responseText);
                }
            },
            onerror: function (error) {
                ongoingRequests.delete(`top_cheapest_${itemID}`);

                container.innerHTML = '<p>Network error occurred. Please try again later.</p>';
                console.error('IronNerd Bazaar Enhancements: Network Error:', error);
            }
        });
    }

    function displayTopCheapestItems(items, itemName = 'Item') {
        const container = document.getElementById('bazaar-enhancer-container');
        container.innerHTML = '';

        if (!items || items.length === 0) {
            container.innerHTML = '<p>No items found.</p>';
            return;
        }

        const title = document.createElement('h3');
        title.innerText = `Top 3 Cheapest ${itemName} Bazaar Items`;
        title.style.textAlign = 'center';
        title.style.marginTop = '2px';
        title.style.marginBottom = '10px';
        container.appendChild(title);

        const tableContainer = document.createElement('div');
        tableContainer.style.overflowX = 'table-responsive';
        tableContainer.style.width = '100%';

        const table = document.createElement('table');
        table.className = 'top-cheapest-table';
        table.style.width = '100%';
        table.style.borderCollapse = 'collapse';

        const thead = document.createElement('thead');
        const headerRow = document.createElement('tr');

        const headers = ['Rank', 'Price ($)', 'Quantity', 'Seller', 'Visit Bazaar'];
        headers.forEach(headerText => {
            const th = document.createElement('th');
            th.innerText = headerText;
            th.style.border = '1px solid #ccc';
            th.style.padding = '8px';
            th.style.backgroundColor = '#e0e0e0';
            th.style.textAlign = 'center';
            th.style.fontSize = '14px';
            headerRow.appendChild(th);
        });
        thead.appendChild(headerRow);
        table.appendChild(thead);

        const tbody = document.createElement('tbody');

        items.forEach((item, index) => {
            const tr = document.createElement('tr');

            const rankTd = document.createElement('td');
            rankTd.innerText = index + 1;
            rankTd.style.border = '1px solid #ccc';
            rankTd.style.padding = '6px';
            rankTd.style.textAlign = 'center';
            rankTd.style.fontSize = '14px';
            tr.appendChild(rankTd);

            const priceTd = document.createElement('td');
            priceTd.innerText = `$${item.price.toLocaleString()}`;
            priceTd.setAttribute('data-label', 'Price ($)');
            priceTd.style.border = '1px solid #ccc';
            priceTd.style.padding = '6px';
            priceTd.style.textAlign = 'center';
            priceTd.style.fontSize = '14px';
            tr.appendChild(priceTd);

            const quantityTd = document.createElement('td');
            quantityTd.innerText = item.quantity;
            quantityTd.setAttribute('data-label', 'Quantity');
            quantityTd.style.border = '1px solid #ccc';
            quantityTd.style.padding = '6px';
            quantityTd.style.textAlign = 'center';
            quantityTd.style.fontSize = '14px';
            tr.appendChild(quantityTd);

            const sellerTd = document.createElement('td');
            sellerTd.setAttribute('data-label', 'Seller');
            sellerTd.style.border = '1px solid #ccc';
            sellerTd.style.padding = '6px';
            sellerTd.style.textAlign = 'center';
            sellerTd.style.fontSize = '14px';
            const sellerLink = document.createElement('a');
            sellerLink.href = `https://www.torn.com/profiles.php?XID=${item.user_id}`;
            sellerLink.textContent = item.owner;
            sellerLink.target = '_blank';
            sellerLink.style.color = 'inherit';
            sellerLink.style.textDecoration = 'none';
            sellerLink.addEventListener('mouseover', () => {
                sellerLink.style.textDecoration = 'underline';
            });
            sellerLink.addEventListener('mouseout', () => {
                sellerLink.style.textDecoration = 'none';
            });
            sellerTd.appendChild(sellerLink);
            tr.appendChild(sellerTd);

            const bazaarTd = document.createElement('td');
            bazaarTd.style.border = '1px solid #ccc';
            bazaarTd.style.padding = '6px';
            bazaarTd.style.textAlign = 'center';
            bazaarTd.style.fontSize = '14px';
            const bazaarLink = document.createElement('a');
            bazaarLink.href = `https://www.torn.com/bazaar.php?userID=${item.user_id}`;
            bazaarLink.textContent = 'Visit';
            bazaarLink.target = '_blank';
            bazaarLink.style.color = '#007bff';
            bazaarLink.style.textDecoration = 'none';
            bazaarLink.addEventListener('mouseover', () => {
                bazaarLink.style.textDecoration = 'underline';
            });
            bazaarLink.addEventListener('mouseout', () => {
                bazaarLink.style.textDecoration = 'none';
            });
            bazaarTd.appendChild(bazaarLink);
            bazaarTd.setAttribute('data-label', 'Visit Bazaar');
            tr.appendChild(bazaarTd);

            tbody.appendChild(tr);
        });

        table.appendChild(tbody);
        tableContainer.appendChild(table);
        container.appendChild(tableContainer);

        adjustTopCheapestTableTheme();
    }

    function detectSearch() {
        window.addEventListener('hashchange', onHashChange, false);
        window.addEventListener('popstate', onHashChange, false);
        onHashChange();
    }

    function onHashChange() {
        const { itemID, itemName } = getItemInfoFromURL();
        if (itemID) {
            console.log(`IronNerd Bazaar Enhancements: Detected itemID change to ${itemID}. Fetching top 3 cheapest items.`);
            fetchTopCheapestItems(itemID);
        }
    }

    function initializeTopCheapestItems() {
        const { itemID, itemName } = getItemInfoFromURL();
        if (itemID) {
            fetchTopCheapestItems(itemID);
        } else {
            console.warn('IronNerd Bazaar Enhancements: Item ID not found in URL. Top 3 Cheapest Items will not be displayed.');
        }
    }


    function displayShowBazaarStatusMessage(status, message) {
        const statusDiv = document.getElementById('showBazaarStatusMessage');
        if (!statusDiv) return;

        statusDiv.innerHTML = '';

        const icon = document.createElement('span');
        icon.style.marginRight = '8px';
        if (status === 'success') {
            icon.textContent = '✅';
            statusDiv.style.color = '#155724';
            statusDiv.style.backgroundColor = '#d4edda';
        } else if (status === 'error') {
            icon.textContent = '❌';
            statusDiv.style.color = '#721c24';
            statusDiv.style.backgroundColor = '#f8d7da';
        } else if (status === 'info') {
            icon.textContent = 'ℹ️';
            statusDiv.style.color = '#004085';
            statusDiv.style.backgroundColor = '#cce5ff';
        }

        const messageSpan = document.createElement('span');
        messageSpan.textContent = message;

        statusDiv.appendChild(icon);
        statusDiv.appendChild(messageSpan);

        statusDiv.style.padding = '5px';
        statusDiv.style.borderRadius = '3px';
        statusDiv.style.display = 'flex';
        statusDiv.style.alignItems = 'center';
        statusDiv.style.transition = 'background-color 0.3s, color 0.3s';

        setTimeout(() => {
            statusDiv.textContent = '';
            statusDiv.style.display = 'none';
        }, 5000);
    }

    function trapFocus(modal) {
        const focusableElements = modal.querySelectorAll('a[href], button, textarea, input, select');
        if (focusableElements.length === 0) return;
        const firstFocusable = focusableElements[0];
        const lastFocusable = focusableElements[focusableElements.length - 1];

        modal.addEventListener('keydown', function (e) {
            const isTabPressed = (e.key === 'Tab' || e.keyCode === 9);

            if (!isTabPressed) return;

            if (e.shiftKey) {
                if (document.activeElement === firstFocusable) {
                    lastFocusable.focus();
                    e.preventDefault();
                }
            } else {
                if (document.activeElement === lastFocusable) {
                    firstFocusable.focus();
                    e.preventDefault();
                }
            }
        });
    }


    function injectAdditionalStyles() {
        const style = document.createElement('style');
        style.type = 'text/css';
        style.innerHTML = `
    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }

    #showBazaarModal {
        background-color: rgba(0, 0, 0, 0.7);
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 10000; /* Ensure it's above other elements */
        padding: 20px;
    }

    #showBazaarModal #modal-content {
        background-color: #fff;
        color: #000;
        padding: 20px;
        border-radius: 12px;
        max-width: 800px; /* Adjust modal width */
        width: 100%; /* Changed from 85% to 100% */
        box-sizing: border-box; /* Include padding and border in width */
        box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
        overflow-y: auto;
        max-height: 80vh; /* Limit height to 80% of the viewport */
        margin: 0 10px; /* Add horizontal margin for small screens */
    }

    #showBazaarModal h2 {
        text-align: center;
        font-size: 1.5em;
        margin-bottom: 15px;
        color: #333;
    }

    #itemNameDisplay {
        text-align: center;
        margin-bottom: 15px;
        color: #333;
        font-size: 1.3em;
        font-weight: bold;
    }

    #bazaar-enhancer-container {
        background-color: #ffffff;
        color: #000000;
        border: 1px solid #ddd;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        border-radius: 8px;
        padding: 10px;
        margin: 10px 0;
        transition: background-color 0.3s, color 0.3s;
    }

    .dark-mode #bazaar-enhancer-container {
        background-color: rgba(0, 0, 0, 0.6);
        color: #f0f0f0;
        border: 1px solid rgba(255, 255, 255, 0.1);
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
    }

    #showBazaarModal table.bazaar-table,
    #bazaar-enhancer-container table.top-cheapest-table {
        color: black;
        width: 100%;
        border-collapse: collapse;
        margin-top: 10px;
        table-layout: auto;
    }

    #showBazaarModal table.bazaar-table th,
    #showBazaarModal table.bazaar-table td,
    #bazaar-enhancer-container table.top-cheapest-table th,
    #bazaar-enhancer-container table.top-cheapest-table td {
        text-align: center;
        padding: 8px;
        border: 1px solid #ccc;
    }

    #showBazaarModal table.bazaar-table th,
    #bazaar-enhancer-container table.top-cheapest-table th {
        background-color: #f2f2f2;
    }

    .dark-mode #showBazaarModal table.bazaar-table th,
    .dark-mode #showBazaarModal table.bazaar-table td,
    .dark-mode #bazaar-enhancer-container table.top-cheapest-table th,
    .dark-mode #bazaar-enhancer-container table.top-cheapest-table td {
        background-color: #2a2a2a;
        color: #f0f0f0;
    }

    .dark-mode #showBazaarModal table.bazaar-table th,
    .dark-mode #bazaar-enhancer-container table.top-cheapest-table th {
        background-color: #333;
    }

        #mobileBazaarButton,
        #desktopBazaarButton {
            padding: 6px 10px;
            font-size: 12px;
            border-radius: 4px;
            margin: 5px;
            background-color: #4caf50;
            color: white;
            border: none;
            cursor: pointer;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
            transition: background-color 0.3s, opacity 0.3s;
        }

        #mobileBazaarButton:hover,
        #desktopBazaarButton:hover {
            background-color: #45a049;
            opacity: 0.9;
        }

    #showBazaarModal .pagination-button,
    #bazaar-enhancer-container .pagination-button {
        padding: 6px 10px;
        font-size: 12px;
        margin: 5px;
        border: 1px solid #ccc;
        background-color: #4caf50;
        color: white;
        border-radius: 4px;
        cursor: pointer;
        transition: background-color 0.3s, opacity 0.3s;
    }

    #showBazaarModal .pagination-button:disabled,
    #bazaar-enhancer-container .pagination-button:disabled {
        background-color: #ccc;
        cursor: not-allowed;
    }

    #showBazaarModal .pagination-button:hover:not(:disabled),
    #bazaar-enhancer-container .pagination-button:hover:not(:disabled) {
        background-color: #45a049;
    }

    @media screen and (max-width: 768px) {
        #showBazaarModal #modal-content {
            padding: 15px;
        }

        #bazaarButton {
            padding: 5px 8px;
            font-size: 12px;
        }

        #showBazaarModal table.bazaar-table th,
        #bazaar-enhancer-container table.top-cheapest-table th,
        #showBazaarModal table.bazaar-table td,
        #bazaar-enhancer-container table.top-cheapest-table td {
            padding: 6px;
        }
    }


    #showBazaarModal .loading-spinner,
    #bazaar-enhancer-container .loading-spinner {
        border: 4px solid #f3f3f3;
        border-top: 4px solid #3498db;
        border-radius: 50%;
        width: 24px;
        height: 24px;
        animation: spin 2s linear infinite;
        display: inline-block;
        margin-left: 10px;
    }
    `;
        document.head.appendChild(style);
        console.log('IronNerd Bazaar Enhancements: Additional styles injected.');
    }

    function adjustBazaarTableTheme() {
        const isDarkMode = document.body.classList.contains('dark-mode');
        const bazaarTable = document.querySelector('.bazaar-table');

        if (isDarkMode && bazaarTable) {
            bazaarTable.style.backgroundColor = '#1c1c1c';
            bazaarTable.style.color = '#f0f0f0';
            bazaarTable.querySelectorAll('th').forEach(th => {
                th.style.backgroundColor = '#444';
                th.style.color = '#ffffff';
            });
            bazaarTable.querySelectorAll('tr:nth-child(even)').forEach(tr => {
                tr.style.backgroundColor = '#2a2a2a';
            });
            bazaarTable.querySelectorAll('tr:nth-child(odd)').forEach(tr => {
                tr.style.backgroundColor = '#1e1e1e';
            });
            bazaarTable.querySelectorAll('td a').forEach(a => {
                a.style.color = '#4ea8de';
            });
        } else if (bazaarTable) {
            bazaarTable.style.backgroundColor = '#fff';
            bazaarTable.style.color = '#000';
            bazaarTable.querySelectorAll('th').forEach(th => {
                th.style.backgroundColor = '#f2f2f2';
                th.style.color = '#000';
            });
            bazaarTable.querySelectorAll('tr:nth-child(even)').forEach(tr => {
                tr.style.backgroundColor = '#f9f9f9';
            });
            bazaarTable.querySelectorAll('tr:nth-child(odd)').forEach(tr => {
                tr.style.backgroundColor = '#fff';
            });
            bazaarTable.querySelectorAll('td a').forEach(a => {
                a.style.color = '#007bff';
            });
        }
    }

    function adjustTopCheapestTableTheme() {
        const isDarkMode = document.body.classList.contains('dark-mode');
        const topCheapestTable = document.querySelector('.top-cheapest-table');

        if (isDarkMode && topCheapestTable) {
            topCheapestTable.style.backgroundColor = '#1c1c1c';
            topCheapestTable.style.color = '#f0f0f0';
            topCheapestTable.querySelectorAll('th').forEach(th => {
                th.style.backgroundColor = '#444';
                th.style.color = '#ffffff';
            });
            topCheapestTable.querySelectorAll('tr:nth-child(even)').forEach(tr => {
                tr.style.backgroundColor = '#2a2a2a';
            });
            topCheapestTable.querySelectorAll('tr:nth-child(odd)').forEach(tr => {
                tr.style.backgroundColor = '#1e1e1e';
            });
            topCheapestTable.querySelectorAll('td a').forEach(a => {
                a.style.color = '#4ea8de';
            });
        } else if (topCheapestTable) {
            topCheapestTable.style.backgroundColor = '#fff';
            topCheapestTable.style.color = '#000';
            topCheapestTable.querySelectorAll('th').forEach(th => {
                th.style.backgroundColor = '#f2f2f2';
                th.style.color = '#000';
            });
            topCheapestTable.querySelectorAll('tr:nth-child(even)').forEach(tr => {
                tr.style.backgroundColor = '#f9f9f9';
            });
            topCheapestTable.querySelectorAll('tr:nth-child(odd)').forEach(tr => {
                tr.style.backgroundColor = '#fff';
            });
            topCheapestTable.querySelectorAll('td a').forEach(a => {
                a.style.color = '#007bff';
            });
        }
    }

    function adjustBazaarEnhancerContainerTheme() {
        const container = document.getElementById('bazaar-enhancer-container');
        const isDarkMode = document.body.classList.contains('dark-mode');

        if (container) {
            if (isDarkMode) {
                container.style.backgroundColor = 'rgba(0, 0, 0, 0.6)';
                container.style.color = '#f0f0f0';
                container.style.border = '1px solid rgba(255, 255, 255, 0.1)';
                container.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.4)';
            } else {
                container.style.backgroundColor = '#ffffff';
                container.style.color = '#000000';
                container.style.border = '1px solid #ddd';
                container.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.1)';
            }
        }
    }


    function observeDarkMode() {
        const observer = new MutationObserver(() => {
            adjustBazaarTableTheme();
            adjustTopCheapestTableTheme();
            adjustBazaarEnhancerContainerTheme();
        });

        observer.observe(document.body, { attributes: true, attributeFilter: ['class'] });
    }

})();