// ==UserScript==
// @name Bazaar Item Search powered by IronNerd
// @namespace [email protected]
// @version 0.3.4
// @description View items you are searching for in registered 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.');
init();
async function init() {
injectAdditionalStyles();
observeDOMChanges();
addButtonsIfNeeded();
const apiKey = await GM_getValue('tornApiKey', '');
if (apiKey) {
checkBazaarStatus(apiKey);
}
detectSearch(); // Retain the old auto-fetch functionality
observeDarkMode(); // Ensure UI adapts dynamically to dark mode
}
// ------------------ Observe DOM Changes ------------------
function observeDOMChanges() {
const targetNode = document.body;
const config = { childList: true, subtree: true };
const callback = function(mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
addButtonsIfNeeded();
}
}
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
}
// ------------------ Add Buttons If Needed ------------------
function addButtonsIfNeeded() {
const linksContainer = document.querySelector('.linksContainer___LiOTN');
if (!linksContainer) return;
// Add Settings Button
if (!document.getElementById('bazaarSettingsBtn')) {
addSettingsButton(linksContainer);
}
// Add $1 Items Button
if (!document.getElementById('oneDollarSearchBtn')) {
addOneDollarButton(linksContainer);
}
// Add Show Bazaar Button
if (!document.getElementById('showBazaarSearchBtn')) {
addShowBazaarButton(linksContainer);
}
}
// ------------------ Settings Button ------------------
function addSettingsButton(container) {
const button = document.createElement('button');
button.id = 'bazaarSettingsBtn';
button.setAttribute('type', 'button');
button.className = 'linkContainer___X16y4 inRow___VfDnd greyLineV___up8VP iconActive___oAum9';
button.style.cursor = 'pointer';
button.style.display = 'flex';
button.style.alignItems = 'center';
button.style.justifyContent = 'center';
button.style.padding = '8px';
button.style.marginLeft = '10px'; // Added margin to prevent overlapping
const iconWrapper = document.createElement('span');
iconWrapper.className = 'iconWrapper___x3ZLe iconWrapper___COKJD svgIcon___IwbJV';
iconWrapper.style.display = 'flex';
iconWrapper.style.alignItems = 'center';
iconWrapper.style.justifyContent = 'center';
const gearIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
gearIcon.setAttribute('width', '24');
gearIcon.setAttribute('height', '24');
gearIcon.setAttribute('viewBox', '0 0 24 24');
gearIcon.setAttribute('fill', 'currentColor');
gearIcon.innerHTML = `
<path d="M19.14,12.936l1.843-1.061a0.5,0.5,0,0,0,.11-0.63l-1.741-3.012a0.5,0.5,0,0,0-.61-0.22l-2.169,0.875a7.056,7.056,0,0,0-1.607-0.93l-0.33-2.313A0.5,0.5,0,0,0,13.5,4H10.5a0.5,0.5,0,0,0-.49,0.42l-0.33,2.313a7.056,7.056,0,0,0-1.607,0.93l-2.169-0.875a0.5,0.5,0,0,0-.61,0.22L3.56,11.245a0.5,0.5,0,0,0,.11,0.63l1.843,1.061a7.154,7.154,0,0,0,0,1.872L3.67,16.936a0.5,0.5,0,0,0-.11,0.63l1.741,3.012a0.5,0.5,0,0,0,.61,0.22l2.169-0.875a7.056,7.056,0,0,0,1.607,0.93l0.33,2.313a0.5,0.5,0,0,0,.49,0.42h3a0.5,0.5,0,0,0,.49-0.42l0.33-2.313a7.056,7.056,0,0,0,1.607-0.93l2.169,0.875a0.5,0.5,0,0,0,.61-0.22l1.741-3.012a0.5,0.5,0,0,0-.11-0.63Zm-7.14,2.064A3,3,0,1,1,15,12,3,3,0,0,1,12,15Z"/>
`;
iconWrapper.appendChild(gearIcon);
button.appendChild(iconWrapper);
button.addEventListener('click', openSettingsModal);
container.appendChild(button);
console.log('IronNerd Bazaar Enhancements: Settings button added.');
}
// ------------------ Modal Theme Application ------------------
function applyThemeToModal(modal) {
const isDarkMode = document.body.classList.contains('dark-mode');
const modalContent = modal.querySelector('#modal-content');
if (isDarkMode) {
modalContent.style.backgroundColor = '#1c1c1c';
modalContent.style.color = '#f0f0f0';
modalContent.querySelectorAll('button').forEach(btn => {
btn.style.backgroundColor = '#333';
btn.style.color = '#f0f0f0';
btn.style.border = 'none';
});
modalContent.querySelector('h2').style.color = '#ddd';
} else {
modalContent.style.backgroundColor = '#fff';
modalContent.style.color = '#000';
modalContent.querySelectorAll('button').forEach(btn => {
btn.style.backgroundColor = '#f9f9f9';
btn.style.color = '#000';
btn.style.border = '1px solid #ccc';
});
modalContent.querySelector('h2').style.color = '#333';
}
}
// ------------------ Inject Additional Styles ------------------
function injectAdditionalStyles() {
const style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = `
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Ensure modals and tables are responsive */
@media screen and (max-width: 768px) {
.one-dollar-table, .bazaar-table {
width: 100%;
font-size: 12px;
}
.one-dollar-table td, .bazaar-table td {
padding: 5px;
}
#bazaar-enhancer-modal #modal-content,
#oneDollarModal #modal-content,
#showBazaarModal #modal-content {
width: 90%;
padding: 15px;
}
}
/* General Modal Styling */
#bazaar-enhancer-modal, #oneDollarModal, #showBazaarModal {
background-color: rgba(0, 0, 0, 0.7);
display: flex;
align-items: center;
justify-content: center;
}
#bazaar-enhancer-modal #modal-content,
#oneDollarModal #modal-content,
#showBazaarModal #modal-content {
background-color: #fff;
color: #000;
padding: 20px;
border-radius: 8px;
max-width: 600px;
width: 90%;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
}
/* Title Styling */
#bazaar-enhancer-modal h2,
#oneDollarModal h2,
#showBazaarModal h2 {
text-align: center;
font-size: 1.5em;
margin-bottom: 20px;
color: #333;
}
/* Dark Mode Enhancements */
.dark-mode #bazaar-enhancer-modal #modal-content,
.dark-mode #oneDollarModal #modal-content,
.dark-mode #showBazaarModal #modal-content {
background-color: #1c1c1c;
color: #f0f0f0;
}
.dark-mode #bazaar-enhancer-modal h2,
.dark-mode #oneDollarModal h2,
.dark-mode #showBazaarModal h2 {
color: #ddd;
}
/* Table Styling */
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
table th, table td {
text-align: center;
padding: 10px;
border: 1px solid #ccc;
}
.dark-mode table th, .dark-mode table td {
background-color: #2a2a2a;
color: #f0f0f0;
}
.dark-mode table th {
background-color: #333;
}
/* Responsive table design */
@media screen and (max-width: 600px) {
table {
display: block;
overflow-x: auto;
}
table th, table td {
white-space: nowrap;
}
}
/* Button Enhancements */
button {
padding: 10px 15px;
font-size: 14px;
border-radius: 4px;
margin: 5px;
}
button:hover {
opacity: 0.9;
}
/* Loading Spinner */
.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);
}
// ------------------ Observe Dark Mode Changes ------------------
function observeDarkMode() {
const observer = new MutationObserver(() => {
const modals = document.querySelectorAll('#bazaar-enhancer-modal, #oneDollarModal, #showBazaarModal');
modals.forEach(modal => applyThemeToModal(modal));
});
observer.observe(document.body, { attributes: true, attributeFilter: ['class'] });
}
async function openSettingsModal() {
let existingModal = document.getElementById('bazaar-enhancer-modal');
if (existingModal) {
existingModal.style.display = 'flex';
return;
}
const savedApiKey = await GM_getValue('tornApiKey', '');
const modal = document.createElement('div');
modal.id = 'bazaar-enhancer-modal';
modal.setAttribute('role', 'dialog');
modal.setAttribute('aria-labelledby', 'modal-title');
modal.setAttribute('aria-modal', 'true');
modal.style = 'position: fixed; top: 0; left: 0; width: 100%; height: 100%;' +
'background-color: rgba(0,0,0,0.5); z-index: 1001; display: flex; align-items: center; justify-content: center;';
modal.innerHTML = `
<div id="modal-content" style="background-color: #fff; padding: 20px; border-radius: 5px; width: 400px; position: relative;">
<h2 id="modal-title">Bazaar Enhancer Settings</h2>
<label for="apiKey">Your Torn API Key:</label><br>
<input type="password" id="apiKey" style="width: 100%; border: 1px solid #ccc; border-radius: 5px;" value="${savedApiKey}"><br>
<input type="checkbox" id="toggleVisibility"> <label for="toggleVisibility">Show API Key</label><br><br>
<button id="saveApiKey">Save API Key</button>
<button id="registerBazaar">Register Bazaar</button>
<button id="removeBazaar">Remove Bazaar</button><br><br>
<div id="statusMessage" style="margin-top: 10px; font-weight: bold;"></div>
<button id="closeModal" style="position: absolute; top: 10px; right: 10px;" aria-label="Close Modal">×</button>
</div>
`;
document.body.appendChild(modal);
applyThemeToModal(modal);
trapFocus(modal);
modal.style.display = 'flex'; // Show the modal
const toggleVisibility = modal.querySelector('#toggleVisibility');
const apiKeyInput = modal.querySelector('#apiKey');
toggleVisibility.addEventListener('change', () => {
apiKeyInput.type = toggleVisibility.checked ? 'text' : 'password';
});
modal.querySelector('#saveApiKey').addEventListener('click', async () => {
const apiKey = apiKeyInput.value.trim();
const saveButton = modal.querySelector('#saveApiKey');
if (apiKey) {
if (!isValidApiKey(apiKey)) {
displayStatusMessage('error', 'Invalid API key format. Please check and try again.');
return;
}
saveButton.disabled = true;
const spinner = createLoadingSpinner();
saveButton.parentNode.insertBefore(spinner, saveButton.nextSibling);
try {
await GM_setValue('tornApiKey', apiKey);
displayStatusMessage('success', 'API key saved successfully.');
checkBazaarStatus(apiKey);
} catch (error) {
displayStatusMessage('error', 'Failed to save API key.');
console.error(error);
} finally {
saveButton.disabled = false;
spinner.remove();
}
} else {
displayStatusMessage('error', 'Please enter a valid API key.');
}
});
modal.querySelector('#registerBazaar').addEventListener('click', async () => {
const apiKey = await GM_getValue('tornApiKey', '');
if (apiKey) {
registerApiKey(apiKey);
} else {
displayStatusMessage('error', 'Please save your API key first.');
}
});
modal.querySelector('#removeBazaar').addEventListener('click', async () => {
const apiKey = await GM_getValue('tornApiKey', '');
if (apiKey) {
unregisterApiKey(apiKey);
} else {
displayStatusMessage('error', 'No API key found to remove.');
}
});
modal.querySelector('#closeModal').addEventListener('click', () => {
closeSettingsModal();
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
const modal = document.getElementById('bazaar-enhancer-modal');
if (modal) {
closeSettingsModal();
}
}
});
const observer = new MutationObserver(() => {
applyThemeToModal(modal);
});
observer.observe(document.body, { attributes: true, attributeFilter: ['class'] });
apiKeyInput.focus();
}
function closeSettingsModal() {
const modal = document.getElementById('bazaar-enhancer-modal');
if (modal) {
modal.style.display = 'none';
console.log('IronNerd Bazaar Enhancements: Settings modal closed.');
}
}
function trapFocus(modal) {
const focusableElements = modal.querySelectorAll('a[href], button, textarea, input, select');
if (focusableElements.length === 0) return; // No focusable elements
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) { // shift + tab
if (document.activeElement === firstFocusable) {
lastFocusable.focus();
e.preventDefault();
}
} else { // tab
if (document.activeElement === lastFocusable) {
firstFocusable.focus();
e.preventDefault();
}
}
});
}
function createLoadingSpinner() {
const spinner = document.createElement('div');
spinner.className = 'loading-spinner';
return spinner;
}
// ------------------ $1 Items Button ------------------
function addOneDollarButton(container) {
const button = document.createElement('button');
button.id = 'oneDollarSearchBtn';
button.innerText = '1';
button.style.cursor = 'pointer';
button.style.padding = '8px 12px';
button.style.marginLeft = '10px';
button.style.backgroundColor = '#ff5722';
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 = '14px';
const dollarIcon = document.createElement('span');
dollarIcon.innerHTML = '$';
dollarIcon.style.marginRight = '5px';
button.prepend(dollarIcon);
container.appendChild(button);
button.addEventListener('click', openOneDollarModal);
console.log('IronNerd Bazaar Enhancements: "$1 Items" button added.');
}
// ------------------ Show Bazaar Button ------------------
function addShowBazaarButton(container) {
const button = document.createElement('button');
button.id = 'showBazaarSearchBtn';
button.innerText = 'Bazaar';
button.style.cursor = 'pointer';
button.style.padding = '8px 12px';
button.style.marginLeft = '10px';
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 = '14px';
const bazaarIcon = document.createElement('span');
bazaarIcon.innerHTML = '🛒'; // Shopping cart icon
bazaarIcon.style.marginRight = '5px';
button.prepend(bazaarIcon);
container.appendChild(button);
button.addEventListener('click', openShowBazaarModal);
console.log('IronNerd Bazaar Enhancements: "Show Bazaar" button added.');
}
// ------------------ $1 Items Modal ------------------
function openOneDollarModal() {
console.log('IronNerd Bazaar Enhancements: "$1 Items" button clicked.');
createOneDollarModal();
const modal = document.getElementById('oneDollarModal');
if (modal) {
modal.style.display = 'block';
fetchOneDollarItems();
trapFocus(modal);
} else {
console.error('IronNerd Bazaar Enhancements: oneDollarModal element not found.');
}
}
function createOneDollarModal() {
if (document.getElementById('oneDollarModal')) {
console.log('IronNerd Bazaar Enhancements: $1 Items modal already exists.');
return;
}
console.log('IronNerd Bazaar Enhancements: Creating $1 Items modal.');
const overlay = document.createElement('div');
overlay.id = 'oneDollarModal';
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';
const modalContent = document.createElement('div');
modalContent.style.backgroundColor = '#fff';
modalContent.style.margin = '50px auto';
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)';
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', closeOneDollarModal);
const title = document.createElement('h2');
title.innerText = '$1 Items in Bazaar';
title.style.textAlign = 'center';
title.style.marginBottom = '20px';
const sortContainer = document.createElement('div');
sortContainer.style.textAlign = 'right';
sortContainer.style.marginBottom = '10px';
const sortLabel = document.createElement('label');
sortLabel.innerText = 'Sort by Market Price: ';
sortLabel.setAttribute('for', 'sortSelect');
const sortSelect = document.createElement('select');
sortSelect.id = 'sortSelect';
sortSelect.style.padding = '5px';
sortSelect.style.marginLeft = '10px';
const optionAsc = document.createElement('option');
optionAsc.value = 'market_price_asc';
optionAsc.text = 'Low to High';
const optionDesc = document.createElement('option');
optionDesc.value = 'market_price_desc';
optionDesc.text = 'High to Low';
sortSelect.add(optionAsc);
sortSelect.add(optionDesc);
sortContainer.appendChild(sortLabel);
sortContainer.appendChild(sortSelect);
const resultsContainer = document.createElement('div');
resultsContainer.id = 'oneDollarResults';
resultsContainer.style.marginTop = '20px';
modalContent.appendChild(closeBtn);
modalContent.appendChild(title);
modalContent.appendChild(sortContainer);
modalContent.appendChild(resultsContainer);
overlay.appendChild(modalContent);
document.body.appendChild(overlay);
console.log('IronNerd Bazaar Enhancements: $1 Items modal created and appended to the DOM.');
}
function closeOneDollarModal() {
const modal = document.getElementById('oneDollarModal');
if (modal) {
modal.style.display = 'none';
console.log('IronNerd Bazaar Enhancements: $1 Items modal closed.');
}
}
// ------------------ Show Bazaar Modal ------------------
function openShowBazaarModal() {
console.log('IronNerd Bazaar Enhancements: "Show Bazaar" button clicked.');
createShowBazaarModal();
const modal = document.getElementById('showBazaarModal');
if (modal) {
modal.style.display = 'block';
// Automatically fetch based on current search term
const currentSearchTerm = getCurrentSearchTerm();
const searchInput = modal.querySelector('#showBazaarSearchInput');
if (currentSearchTerm) {
searchInput.value = currentSearchTerm;
fetchShowBazaarItems(currentSearchTerm);
}
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.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';
const modalContent = document.createElement('div');
modalContent.style.backgroundColor = '#fff';
modalContent.style.margin = '50px auto';
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)';
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.innerText = 'Show Bazaar Items';
title.style.textAlign = 'center';
title.style.marginBottom = '20px';
// Add input for search term
const searchContainer = document.createElement('div');
searchContainer.style.textAlign = 'center';
searchContainer.style.marginBottom = '10px';
const searchLabel = document.createElement('label');
searchLabel.innerText = 'Enter Item Name: ';
searchLabel.setAttribute('for', 'showBazaarSearchInput');
const searchInput = document.createElement('input');
searchInput.type = 'text';
searchInput.id = 'showBazaarSearchInput';
searchInput.style.width = '70%';
searchInput.style.padding = '8px';
searchInput.style.border = '1px solid #ccc';
searchInput.style.borderRadius = '4px';
const searchButton = document.createElement('button');
searchButton.innerText = 'Search';
searchButton.style.marginLeft = '10px';
searchButton.style.padding = '8px 12px';
searchButton.style.cursor = 'pointer';
searchButton.style.backgroundColor = '#2196f3';
searchButton.style.color = '#fff';
searchButton.style.border = 'none';
searchButton.style.borderRadius = '4px';
searchButton.addEventListener('click', () => {
const itemName = searchInput.value.trim();
if (itemName) {
fetchShowBazaarItems(itemName);
} else {
displayShowBazaarStatusMessage('error', 'Please enter an item name to search.');
}
});
searchContainer.appendChild(searchLabel);
searchContainer.appendChild(searchInput);
searchContainer.appendChild(searchButton);
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(searchContainer);
modalContent.appendChild(resultsContainer);
modalContent.appendChild(statusDiv);
overlay.appendChild(modalContent);
document.body.appendChild(overlay);
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.');
}
}
// ------------------ Fetch $1 Items ------------------
function fetchOneDollarItems() {
const backendUrl = 'https://www.ironnerd.me/search_one_dollar';
let sortOrder = 'market_price_asc';
getOneDollarItems(sortOrder);
const sortSelect = document.getElementById('sortSelect');
sortSelect.addEventListener('change', () => {
sortOrder = sortSelect.value;
getOneDollarItems(sortOrder);
});
}
function getOneDollarItems(sortOrder) {
const resultsContainer = document.getElementById('oneDollarResults');
resultsContainer.innerHTML = '<p>Loading...</p>';
GM_xmlhttpRequest({
method: 'GET',
url: `https://www.ironnerd.me/search_one_dollar?sort=${sortOrder}`,
headers: {
'Accept': 'application/json'
},
onload: function(response) {
if (response.status === 200) {
try {
const data = JSON.parse(response.responseText);
displayOneDollarItems(data.bazaar_items);
console.log('IronNerd Bazaar Enhancements: $1 Items data fetched successfully.');
} 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 $1 Items Error:', response.responseText);
}
},
onerror: function(error) {
resultsContainer.innerHTML = '<p>Network error occurred. Please try again later.</p>';
console.error('IronNerd Bazaar Enhancements: Network Error:', error);
}
});
}
// ------------------ Display $1 Items ------------------
function displayOneDollarItems(items) {
const resultsContainer = document.getElementById('oneDollarResults');
resultsContainer.innerHTML = '';
if (!items || items.length === 0) {
resultsContainer.innerHTML = '<p>No $1 items found.</p>';
return;
}
// Group items by owner
const groupedItems = items.reduce((acc, itemData) => {
const ownerKey = `${itemData.owner}||${itemData.user_id}`; // Unique key combining owner name and user_id
if (!acc[ownerKey]) {
acc[ownerKey] = {
owner: itemData.owner,
user_id: itemData.user_id,
items: []
};
}
acc[ownerKey].items.push(itemData.item);
return acc;
}, {});
// Create table
const table = document.createElement('table');
table.className = 'one-dollar-table';
table.style.width = '100%';
table.style.borderCollapse = 'collapse';
const thead = document.createElement('thead');
const headerRow = document.createElement('tr');
const headers = ['Owner', 'Total Items', 'Highest Item Value','Actions'];
headers.forEach(headerText => {
const th = document.createElement('th');
th.innerText = headerText;
th.style.border = '1px solid #ddd';
th.style.padding = '8px';
th.style.backgroundColor = '#f2f2f2';
th.style.textAlign = 'center';
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
table.appendChild(thead);
const tbody = document.createElement('tbody');
Object.keys(groupedItems).forEach(ownerKey => {
const group = groupedItems[ownerKey];
const ownerRow = document.createElement('tr');
// Owner Name Cell
const ownerTd = document.createElement('td');
ownerTd.textContent = group.owner;
ownerTd.setAttribute('data-label', 'Owner');
ownerTd.style.border = '1px solid #ddd';
ownerTd.style.padding = '8px';
ownerTd.style.textAlign = 'center';
ownerRow.appendChild(ownerTd);
// Total Items Cell
const totalItemsTd = document.createElement('td');
totalItemsTd.textContent = group.items.length;
totalItemsTd.setAttribute('data-label', 'Total Items');
totalItemsTd.style.border = '1px solid #ddd';
totalItemsTd.style.padding = '8px';
totalItemsTd.style.textAlign = 'center';
ownerRow.appendChild(totalItemsTd);
// Highest Market Price Cell
const highestMarketPriceTd = document.createElement('td');
// Calculate the highest market price among the owner's items
let highestMarketPrice = 0;
if (group.items.length > 0) {
highestMarketPrice = group.items.reduce((max, item) => {
return item.market_price > max ? item.market_price : max;
}, 0);
}
// Set the text content with proper formatting
highestMarketPriceTd.textContent = highestMarketPrice > 0 ? `$${highestMarketPrice.toLocaleString()}` : 'N/A';
highestMarketPriceTd.setAttribute('data-label', 'Highest Market Price');
highestMarketPriceTd.style.border = '1px solid #ddd';
highestMarketPriceTd.style.padding = '8px';
highestMarketPriceTd.style.textAlign = 'center';
ownerRow.appendChild(highestMarketPriceTd);
// Actions Cell with Expand/Collapse Button
const actionsTd = document.createElement('td');
actionsTd.setAttribute('data-label', 'Actions');
actionsTd.style.border = '1px solid #ddd';
actionsTd.style.padding = '8px';
actionsTd.style.textAlign = 'center';
const expandBtn = document.createElement('button');
expandBtn.textContent = 'Expand';
// Toggle Functionality
expandBtn.addEventListener('click', () => {
const isExpanded = expandBtn.textContent === 'Collapse';
expandBtn.textContent = isExpanded ? 'Expand' : 'Collapse';
detailsRow.style.display = isExpanded ? 'none' : 'table-row';
});
actionsTd.appendChild(expandBtn);
ownerRow.appendChild(actionsTd);
tbody.appendChild(ownerRow);
// Details Row containing the list of items
const detailsRow = document.createElement('tr');
detailsRow.style.display = 'none'; // Initially hidden
const detailsTd = document.createElement('td');
detailsTd.colSpan = headers.length;
detailsTd.style.border = '1px solid #ddd';
detailsTd.style.padding = '8px';
// Create a nested table for items
const nestedTable = document.createElement('table');
nestedTable.style.width = '100%';
nestedTable.style.borderCollapse = 'collapse';
const nestedThead = document.createElement('thead');
const nestedHeaderRow = document.createElement('tr');
const nestedHeaders = ['Item Name', 'Type', 'Quantity', 'Price ($)', 'Market Price ($)', 'Visit Bazaar'];
nestedHeaders.forEach(headerText => {
const th = document.createElement('th');
th.innerText = headerText;
th.style.border = '1px solid #ddd';
th.style.padding = '6px';
th.style.backgroundColor = '#f9f9f9';
th.style.textAlign = 'center';
nestedHeaderRow.appendChild(th);
});
nestedThead.appendChild(nestedHeaderRow);
nestedTable.appendChild(nestedThead);
const nestedTbody = document.createElement('tbody');
group.items.forEach(item => {
const tr = document.createElement('tr');
// Item Name
const nameTd = document.createElement('td');
nameTd.innerText = item.name;
nameTd.setAttribute('data-label', 'Item Name');
nameTd.style.border = '1px solid #ddd';
nameTd.style.padding = '6px';
nameTd.style.textAlign = 'center';
tr.appendChild(nameTd);
// Type
const typeTd = document.createElement('td');
typeTd.innerText = item.type || 'N/A';
typeTd.setAttribute('data-label', 'Type');
typeTd.style.border = '1px solid #ddd';
typeTd.style.padding = '6px';
typeTd.style.textAlign = 'center';
tr.appendChild(typeTd);
// Quantity
const quantityTd = document.createElement('td');
quantityTd.innerText = item.quantity;
quantityTd.setAttribute('data-label', 'Quantity');
quantityTd.style.border = '1px solid #ddd';
quantityTd.style.padding = '6px';
quantityTd.style.textAlign = 'center';
tr.appendChild(quantityTd);
// Price ($)
const priceTd = document.createElement('td');
priceTd.innerText = `$${item.price.toLocaleString()}`;
priceTd.setAttribute('data-label', 'Price ($)');
priceTd.style.border = '1px solid #ddd';
priceTd.style.padding = '6px';
priceTd.style.textAlign = 'center';
tr.appendChild(priceTd);
// Market Price ($)
const marketPriceTd = document.createElement('td');
marketPriceTd.innerText = item.market_price ? `$${item.market_price.toLocaleString()}` : 'N/A';
marketPriceTd.setAttribute('data-label', 'Market Price ($)');
marketPriceTd.style.border = '1px solid #ddd';
marketPriceTd.style.padding = '6px';
marketPriceTd.style.textAlign = 'center';
tr.appendChild(marketPriceTd);
// Visit Bazaar
const visitTd = document.createElement('td');
visitTd.style.border = '1px solid #ddd';
visitTd.style.padding = '6px';
visitTd.style.textAlign = 'center';
const visitLink = document.createElement('a');
visitLink.href = `https://www.torn.com/bazaar.php?userID=${group.user_id}`;
visitLink.textContent = 'Visit';
visitLink.target = '_blank';
visitLink.style.color = '#007bff';
visitLink.style.textDecoration = 'none';
visitLink.addEventListener('mouseover', () => {
visitLink.style.textDecoration = 'underline';
});
visitLink.addEventListener('mouseout', () => {
visitLink.style.textDecoration = 'none';
});
visitTd.appendChild(visitLink);
visitTd.setAttribute('data-label', 'Visit Bazaar');
tr.appendChild(visitTd);
nestedTbody.appendChild(tr);
});
nestedTable.appendChild(nestedTbody);
detailsTd.appendChild(nestedTable);
detailsRow.appendChild(detailsTd);
tbody.appendChild(detailsRow);
});
table.appendChild(tbody);
resultsContainer.appendChild(table);
adjustOneDollarTableTheme();
}
// ------------------ Fetch Show Bazaar Items ------------------
function fetchShowBazaarItems(itemName = '') {
const resultsContainer = document.getElementById('showBazaarResults');
const statusDiv = document.getElementById('showBazaarStatusMessage');
if (itemName) {
resultsContainer.innerHTML = '<p>Loading...</p>';
statusDiv.innerHTML = '';
GM_xmlhttpRequest({
method: 'GET',
url: `https://www.ironnerd.me/search_bazaar_items?item_name=${encodeURIComponent(itemName)}`,
headers: {
'Accept': 'application/json'
},
onload: function(response) {
if (response.status === 200) {
try {
const data = JSON.parse(response.responseText);
displayShowBazaarItems(data.bazaar_items, itemName);
console.log('IronNerd Bazaar Enhancements: Show Bazaar Items data fetched successfully.');
} 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 Show Bazaar Items Error:', response.responseText);
}
},
onerror: function(error) {
resultsContainer.innerHTML = '<p>Network error occurred. Please try again later.</p>';
console.error('IronNerd Bazaar Enhancements: Network Error:', error);
}
});
} else {
resultsContainer.innerHTML = '<p>Please enter an item name to search.</p>';
}
}
// ------------------ Display Show Bazaar Items ------------------
function displayShowBazaarItems(items, itemName = '') {
const resultsContainer = document.getElementById('showBazaarResults');
resultsContainer.innerHTML = '';
if (!items || items.length === 0) {
resultsContainer.innerHTML = '<p>No items found in registered bazaars.</p>';
return;
}
// Create table
const table = document.createElement('table');
table.className = 'bazaar-table';
table.style.width = '100%';
table.style.borderCollapse = 'collapse';
table.style.minWidth = '600px'; // Ensures table has a minimum width
const thead = document.createElement('thead');
const headerRow = document.createElement('tr');
const headers = ['Image', 'Item Name', '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';
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
table.appendChild(thead);
const tbody = document.createElement('tbody');
items.forEach(itemData => {
const item = itemData.item;
const tr = document.createElement('tr');
// Image
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.ID}/small.png`;
img.alt = item.name;
img.style.height = '30px';
imgCell.appendChild(img);
tr.appendChild(imgCell);
// Item Name
const nameCell = document.createElement('td');
nameCell.innerText = item.name;
nameCell.setAttribute('data-label', 'Item Name');
nameCell.style.border = '1px solid #ccc';
nameCell.style.padding = '6px';
nameCell.style.textAlign = 'center';
tr.appendChild(nameCell);
// Owner
const ownerCell = document.createElement('td');
ownerCell.innerText = itemData.owner;
ownerCell.setAttribute('data-label', 'Owner');
ownerCell.style.border = '1px solid #ccc';
ownerCell.style.padding = '6px';
ownerCell.style.textAlign = 'center';
tr.appendChild(ownerCell);
// Price ($)
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';
tr.appendChild(priceTd);
// Quantity
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';
tr.appendChild(quantityTd);
// Visit Bazaar
const bazaarTd = document.createElement('td');
bazaarTd.style.border = '1px solid #ccc';
bazaarTd.style.padding = '6px';
bazaarTd.style.textAlign = 'center';
const bazaarLink = document.createElement('a');
bazaarLink.href = `https://www.torn.com/bazaar.php?userID=${itemData.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);
const tableWrapper = document.createElement('div');
tableWrapper.style.overflowX = 'auto';
tableWrapper.style.webkitOverflowScrolling = 'touch'; // Smooth scrolling on iOS
tableWrapper.appendChild(table);
resultsContainer.appendChild(tableWrapper);
adjustOneDollarTableTheme();
}
// ------------------ API Key Management ------------------
function registerApiKey(apiKey) {
console.log('IronNerd Bazaar Enhancements: Registering API Key:', apiKey);
const modal = document.getElementById('bazaar-enhancer-modal');
const registerButton = modal.querySelector('#registerBazaar');
registerButton.disabled = true;
const spinner = createLoadingSpinner();
registerButton.parentNode.insertBefore(spinner, registerButton.nextSibling);
GM_xmlhttpRequest({
method: 'POST',
url: 'https://www.ironnerd.me/add_bazaar_api_key',
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({ api_key: apiKey }),
onload: function(response) {
spinner.remove();
registerButton.disabled = false;
console.log('IronNerd Bazaar Enhancements: Response Status:', response.status);
console.log('IronNerd Bazaar Enhancements: Response Text:', response.responseText);
try {
const data = JSON.parse(response.responseText);
if (response.status === 201) {
displayStatusMessage('success', 'Bazaar registered successfully.');
} else if (response.status === 200) {
if (data.status === 'info') {
displayStatusMessage('info', data.message);
} else {
displayStatusMessage('error', data.message || 'Error registering bazaar.');
}
} else if (response.status === 403) {
displayStatusMessage('error', data.message || 'Registration forbidden.');
} else {
displayStatusMessage('error', 'Error registering bazaar.');
console.error('IronNerd Bazaar Enhancements: Register Bazaar Error:', response.responseText);
}
} catch (e) {
displayStatusMessage('error', 'Unexpected response format.');
console.error('IronNerd Bazaar Enhancements: Parsing Error:', e);
}
},
onerror: function(error) {
spinner.remove();
registerButton.disabled = false;
displayStatusMessage('error', 'Network error occurred. Please try again later.');
console.error('IronNerd Bazaar Enhancements: Network Error:', error);
}
});
}
function unregisterApiKey(apiKey) {
console.log('IronNerd Bazaar Enhancements: Unregistering API Key:', apiKey);
const modal = document.getElementById('bazaar-enhancer-modal');
const removeButton = modal.querySelector('#removeBazaar');
removeButton.disabled = true;
const spinner = createLoadingSpinner();
removeButton.parentNode.insertBefore(spinner, removeButton.nextSibling);
GM_xmlhttpRequest({
method: 'POST',
url: 'https://www.ironnerd.me/remove_bazaar_api_key',
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({ api_key: apiKey }),
onload: function(response) {
spinner.remove();
removeButton.disabled = false;
console.log('IronNerd Bazaar Enhancements: Response Status:', response.status);
console.log('IronNerd Bazaar Enhancements: Response Text:', response.responseText);
try {
const data = JSON.parse(response.responseText);
if (response.status === 200) {
displayStatusMessage('success', 'Bazaar removed successfully.');
GM_setValue('tornApiKey', '');
modal.querySelector('#apiKey').value = '';
} else {
displayStatusMessage('error', data.message || 'Error removing bazaar.');
console.error('IronNerd Bazaar Enhancements: Unregister Bazaar Error:', response.responseText);
}
} catch (e) {
displayStatusMessage('error', 'Unexpected response format.');
console.error('IronNerd Bazaar Enhancements: Parsing Error:', e);
}
},
onerror: function(error) {
spinner.remove();
removeButton.disabled = false;
displayStatusMessage('error', 'Network error occurred. Please try again later.');
console.error('IronNerd Bazaar Enhancements: Network Error:', error);
}
});
}
// ------------------ Check Bazaar Status ------------------
function checkBazaarStatus(apiKey) {
console.log('IronNerd Bazaar Enhancements: Checking Bazaar Status for API Key:', apiKey);
GM_xmlhttpRequest({
method: 'POST',
url: 'https://www.ironnerd.me/check_bazaar_status',
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({ api_key: apiKey }),
onload: function(response) {
console.log('IronNerd Bazaar Enhancements: Check Status Response Status:', response.status);
console.log('IronNerd Bazaar Enhancements: Check Status Response Text:', response.responseText);
try {
const data = JSON.parse(response.responseText);
if (response.status === 200) {
if (data.status === 'info') {
displayStatusMessage('info', data.message);
} else {
displayStatusMessage('error', data.message || 'Error checking bazaar status.');
}
} else {
displayStatusMessage('error', 'Error checking bazaar status.');
console.error('IronNerd Bazaar Enhancements: Check Bazaar Status Error:', response.responseText);
}
} catch (e) {
displayStatusMessage('error', 'Unexpected response format.');
console.error('IronNerd Bazaar Enhancements: Parsing Error:', e);
}
},
onerror: function(error) {
displayStatusMessage('error', 'Network error occurred. Please try again later.');
console.error('IronNerd Bazaar Enhancements: Network Error:', error);
}
});
}
// ------------------ Display Status Messages ------------------
function displayStatusMessage(status, message) {
const modal = document.getElementById('bazaar-enhancer-modal');
const statusDiv = modal.querySelector('#statusMessage');
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 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 displayErrorMessage(message) {
displayStatusMessage('error', message);
}
// ------------------ Detect Search (Old Functionality) ------------------
function detectSearch() {
window.addEventListener('hashchange', onHashChange, false);
window.addEventListener('popstate', onHashChange, false);
onHashChange();
}
function onHashChange() {
const itemName = getItemNameFromUrl();
if (itemName) {
fetchBazaarItems(itemName);
}
}
function getItemNameFromUrl() {
let itemName = null;
const hash = window.location.hash;
if (hash && hash.includes('itemName=')) {
const hashParams = new URLSearchParams(hash.substring(hash.indexOf('?') + 1));
itemName = hashParams.get('itemName');
console.log('IronNerd Bazaar Enhancements: Extracted itemName from hash:', itemName);
}
if (!itemName) {
const searchParams = new URLSearchParams(window.location.search);
itemName = searchParams.get('itemName');
console.log('IronNerd Bazaar Enhancements: Extracted itemName from search:', itemName);
}
if (itemName) {
return decodeURIComponent(itemName.replace(/\+/g, ' '));
}
return null;
}
function fetchBazaarItems(itemName) {
console.log('IronNerd Bazaar Enhancements: Fetching bazaar items for:', itemName);
GM_xmlhttpRequest({
method: 'GET',
url: `https://www.ironnerd.me/search_bazaar_items?item_name=${encodeURIComponent(itemName)}`,
onload: function(response) {
if (response.status === 200) {
try {
const data = JSON.parse(response.responseText);
displayBazaarItems(data.bazaar_items, itemName);
} catch (e) {
displayErrorMessage('Error parsing server response.');
console.error('IronNerd Bazaar Enhancements: Parse Error:', e);
}
} else {
displayErrorMessage('Error fetching bazaar items.');
console.error('IronNerd Bazaar Enhancements: Fetch Bazaar Items Error:', response.responseText);
}
},
onerror: function(error) {
displayErrorMessage('Network error occurred. Please try again later.');
console.error('IronNerd Bazaar Enhancements: Network Error:', error);
}
});
}
// ------------------ Display Bazaar Items (Old Functionality) ------------------
function displayBazaarItems(items, itemName = '') {
console.log('IronNerd Bazaar Enhancements: displayBazaarItems - itemName:', itemName);
let container = document.getElementById('bazaar-enhancer-container');
if (!container) {
container = document.createElement('div');
container.id = 'bazaar-enhancer-container';
container.style.marginTop = '20px';
const delimiter = document.querySelector('.delimiter___zFh2E');
if (delimiter && delimiter.parentNode) {
delimiter.parentNode.insertBefore(container, delimiter.nextSibling);
} else {
document.body.appendChild(container);
}
}
container.innerHTML = '';
const title = document.createElement('h2');
title.textContent = `Bazaar Listings for "${itemName}"`;
title.style.textAlign = 'center';
container.appendChild(title);
if (items.length === 0) {
const noItemsMessage = document.createElement('p');
noItemsMessage.textContent = 'No items found in registered bazaars.';
noItemsMessage.style.textAlign = 'center';
container.appendChild(noItemsMessage);
return;
}
const tableWrapper = document.createElement('div');
tableWrapper.style.overflowX = 'auto';
tableWrapper.style.webkitOverflowScrolling = 'touch';
const table = document.createElement('table');
table.style.width = '100%';
table.style.borderCollapse = 'collapse';
table.style.minWidth = '600px';
const thead = document.createElement('thead');
const headerRow = document.createElement('tr');
const headers = ['Image', 'Item Name', 'Owner', 'Type', 'Quantity', 'Price ($)', 'Market Price ($)', 'Visit Bazaar'];
headers.forEach(headerText => {
const th = document.createElement('th');
th.textContent = headerText;
th.style.color = 'black';
th.style.border = '1px solid #ccc';
th.style.padding = '6px';
th.style.backgroundColor = '#f2f2f2';
th.style.textAlign = 'center';
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
table.appendChild(thead);
const tbody = document.createElement('tbody');
items.forEach(itemData => {
const item = itemData.item;
const tr = document.createElement('tr');
// Image
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.ID}/small.png`;
img.alt = item.name;
img.style.height = '30px';
imgCell.appendChild(img);
tr.appendChild(imgCell);
// Item Name
const nameCell = document.createElement('td');
nameCell.innerText = item.name;
nameCell.setAttribute('data-label', 'Item Name');
nameCell.style.border = '1px solid #ccc';
nameCell.style.padding = '6px';
nameCell.style.textAlign = 'center';
tr.appendChild(nameCell);
// Owner
const ownerCell = document.createElement('td');
ownerCell.setAttribute('data-label', 'Owner');
ownerCell.style.border = '1px solid #ccc';
ownerCell.style.padding = '6px';
ownerCell.style.textAlign = 'center';
const ownerLink = document.createElement('a');
ownerLink.href = `https://www.torn.com/profiles.php?XID=${itemData.user_id}`;
ownerLink.textContent = itemData.owner;
ownerLink.target = '_blank';
ownerLink.style.color = 'inherit';
ownerCell.appendChild(ownerLink);
tr.appendChild(ownerCell);
// Type
const typeCell = document.createElement('td');
typeCell.innerText = item.type || 'N/A';
typeCell.setAttribute('data-label', 'Type');
typeCell.style.border = '1px solid #ccc';
typeCell.style.padding = '6px';
typeCell.style.textAlign = 'center';
tr.appendChild(typeCell);
// Quantity
const quantityCell = document.createElement('td');
quantityCell.innerText = item.quantity;
quantityCell.setAttribute('data-label', 'Quantity');
quantityCell.style.border = '1px solid #ccc';
quantityCell.style.padding = '6px';
quantityCell.style.textAlign = 'center';
tr.appendChild(quantityCell);
// Price ($)
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';
tr.appendChild(priceTd);
// Market Price ($)
const marketPriceTd = document.createElement('td');
marketPriceTd.innerText = item.market_price ? `$${item.market_price.toLocaleString()}` : 'N/A';
marketPriceTd.setAttribute('data-label', 'Market Price ($)');
marketPriceTd.style.border = '1px solid #ccc';
marketPriceTd.style.padding = '6px';
marketPriceTd.style.textAlign = 'center';
tr.appendChild(marketPriceTd);
// Visit Bazaar
const bazaarTd = document.createElement('td');
bazaarTd.style.border = '1px solid #ccc';
bazaarTd.style.padding = '6px';
bazaarTd.style.textAlign = 'center';
const bazaarLink = document.createElement('a');
bazaarLink.href = `https://www.torn.com/bazaar.php?userID=${itemData.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);
tableWrapper.appendChild(table);
container.appendChild(tableWrapper);
adjustOneDollarTableTheme();
}
// ------------------ API Key Validation ------------------
function isValidApiKey(apiKey) {
const apiKeyPattern = /^[A-Za-z0-9]{16}$/;
return apiKeyPattern.test(apiKey);
}
// ------------------ Theme Adjustment ------------------
function adjustOneDollarTableTheme() {
const isDarkMode = document.body.classList.contains('darkMode___3kucI');
const oneDollarTable = document.querySelector('.one-dollar-table');
const bazaarTable = document.querySelector('.bazaar-table');
if (isDarkMode) {
if (oneDollarTable) {
oneDollarTable.style.backgroundColor = '#1c1c1c';
oneDollarTable.style.color = '#f0f0f0';
oneDollarTable.querySelectorAll('th').forEach(th => {
th.style.backgroundColor = '#444';
th.style.color = '#ffffff';
});
oneDollarTable.querySelectorAll('tr:nth-child(even)').forEach(tr => {
tr.style.backgroundColor = '#2a2a2a';
});
oneDollarTable.querySelectorAll('tr:nth-child(odd)').forEach(tr => {
tr.style.backgroundColor = '#1e1e1e';
});
oneDollarTable.querySelectorAll('td a').forEach(a => {
a.style.color = '#4ea8de';
});
}
if (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 (oneDollarTable) {
oneDollarTable.style.backgroundColor = '#fff';
oneDollarTable.style.color = '#000';
oneDollarTable.querySelectorAll('th').forEach(th => {
th.style.backgroundColor = '#f2f2f2';
th.style.color = '#000';
});
oneDollarTable.querySelectorAll('tr:nth-child(even)').forEach(tr => {
tr.style.backgroundColor = '#f9f9f9';
});
oneDollarTable.querySelectorAll('tr:nth-child(odd)').forEach(tr => {
tr.style.backgroundColor = '#fff';
});
oneDollarTable.querySelectorAll('td a').forEach(a => {
a.style.color = '#007bff';
});
}
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';
});
}
}
}
// ------------------ Get Current Search Term ------------------
function getCurrentSearchTerm() {
const urlParams = new URLSearchParams(window.location.search);
let itemName = urlParams.get('itemName');
if (!itemName) {
const searchInput = document.querySelector('input[type="text"][name="itemName"], input#itemName');
if (searchInput) {
itemName = searchInput.value.trim();
}
}
console.log('IronNerd Bazaar Enhancements: Current search term:', itemName);
return itemName;
}
})();