您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
View items you are searching for in bazaars!
当前为
// ==UserScript== // @name Bazaar Item Search powered by IronNerd // @namespace [email protected] // @version 0.4.0 // @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 = '×'; 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'] }); } })();