Sorts items by value and adds a check box to select items with 1 click. Optimized edition.
// ==UserScript==
// @name Rostoll's Trade Helper
// @namespace https://greatest.deepsurf.us/en/users/1594626-rostoll-3936240
// @version 1.4
// @description Sorts items by value and adds a check box to select items with 1 click. Optimized edition.
// @author Rostoll [3936240]
// @license MIT
// @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @match https://www.torn.com/trade.php*
// @match https://www.torn.com/profiles.php*
// @grant GM_xmlhttpRequest
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addStyle
// @connect api.torn.com
// ==/UserScript==
/* jshint esversion: 11 */
(function () {
'use strict';
if (window.self !== window.top) return;
// --- 1. CONFIGURATION & STATE ---
const SCRIPT_NAME = "Rostoll's Trade Helper";
const API_STORAGE_KEY = 'rst_trade_api_key';
const PDA_API_KEY = "###PDA-APIKEY###";
const isPDA = PDA_API_KEY.indexOf("#") !== 0 && PDA_API_KEY.length === 16;
let priceCache = {};
let activeApiKey = null;
window.rstTrdHasAutoLoaded = false;
const autoCheckHitList = new Set();
// --- 2. GLOBAL STYLES ---
GM_addStyle(`
/* Desktop Weapon/Gear Stat Adjustments */
.rst-trd-flex-list [class*="bonuses"],
.rst-trd-flex-list ul.icons,
.rst-trd-flex-list [class*="info-wrap"],
.rst-trd-flex-list [class*="armour-info"],
.rst-trd-flex-list [class*="weapon-info"] {
transform: translateX(-90px) !important;
transition: transform 0.2s ease;
}
/* Third-Party UI Suppression (Trade Screen Only) */
.rst-trd-flex-list .name-wrap > span[style*="color"], .rst-trd-flex-list .title-wrap .tt-price { display: none !important; }
/* Trade UI Structural Styles */
.rst-trd-ghost-hidden { display: none !important; }
ul.rst-trd-flex-list:not([style*="none"]):not(.hide) {
display: flex !important;
flex-direction: column !important;
}
.rst-name-wrap-flex { flex-grow: 1; min-width: 0; padding-right: 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rst-input-wrapper-flex { display: flex !important; align-items: center !important; justify-content: flex-end !important; flex-shrink: 0 !important; }
/* Custom UI Elements */
.rst-qty-input { box-sizing: border-box; width: 60px !important; min-width: 60px !important; height: 24px !important; margin: 0 !important; padding: 2px 4px !important; text-align: center; }
.rst-trd-price-tag { font-size: 13px; color: #4caf50; font-weight: bold; text-shadow: 1px 1px 2px rgba(0,0,0,0.8); margin-right: 8px; white-space: nowrap; pointer-events: none; }
.rst-trd-custom-cb, .rst-trd-master-cb { width: 16px; height: 16px; cursor: pointer; margin: 0 6px 0 0; flex-shrink: 0; accent-color: #28a745; }
.rst-trd-phantom-box { box-sizing: border-box; width: 60px; min-width: 60px; height: 24px; display: flex; align-items: center; justify-content: center; background: rgba(25, 25, 25, 0.6); color: #777; border: 1px solid #333; border-radius: 4px; font-size: 13px; margin: 0; }
.rst-trd-phantom-box.interactive { cursor: pointer; }
.rst-trd-phantom-box.disabled { cursor: not-allowed; }
.rst-trd-overlay { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); display: flex; align-items: center; justify-content: flex-end; z-index: 10; pointer-events: auto; background: #242424; padding-left: 10px; }
/* Profile Accordion Styles */
#rst-trade-settings-box { margin: 10px 0; background: #242424; border-radius: 5px; border: 1px solid #333; color: #ccc; font-family: Arial, sans-serif; overflow: hidden; box-shadow: 0px 2px 4px rgba(0,0,0,0.5); }
#rst-trade-header { background: #333; padding: 10px 15px; cursor: pointer; font-weight: bold; display: flex; align-items: center; color: #ddd; transition: background 0.2s; }
#rst-trade-header:hover { background: #3d3d3d; }
#rst-trade-icon { margin-right: 8px; font-size: 12px; transition: transform 0.2s; }
#rst-trade-body { display: none; padding: 15px; border-top: 1px solid #444; }
.rst-trade-row { display: flex; align-items: center; margin-bottom: 15px; gap: 15px; }
.rst-trade-label { min-width: 130px; font-size: 13px; color: #aaa; }
.rst-trade-input { flex: 1; max-width: 250px; background: #111; border: 1px solid #555; color: #4caf50; padding: 8px 10px; border-radius: 4px; font-family: monospace; font-size: 14px; letter-spacing: 1px; transition: filter 0.3s, border-color 0.3s; }
.rst-trade-input:focus { outline: none; border-color: #4caf50; filter: blur(0px) !important; }
.rst-blur { filter: blur(4px); }
.rst-btn { padding: 8px 16px; border: none; border-radius: 4px; font-weight: bold; cursor: pointer; font-size: 12px; transition: background 0.2s; }
.rst-btn-verify { background: #333; color: #fff; border: 1px solid #555; }
.rst-btn-verify:hover { background: #444; }
.rst-btn-clear { background: #5a1e1e; color: #fff; border: 1px solid #7a2828; }
.rst-btn-clear:hover { background: #7a2828; }
.rst-status { font-size: 12px; font-weight: bold; margin-top: 5px; }
.rst-status-bad { color: #ff6600; }
.rst-status-good { color: #4caf50; }
.rst-status-wait { color: #88beff; }
`);
// --- 3. UI GENERATOR ---
const UI = {
createPriceTag: (html) => {
const el = document.createElement('div');
el.className = 'rst-trd-price-tag';
el.innerHTML = html;
return el;
},
createCheckbox: (className) => {
const el = document.createElement('input');
el.type = 'checkbox';
el.className = className;
return el;
},
createPhantomBox: (qtyText, interactive) => {
const el = document.createElement('div');
el.className = `rst-trd-phantom-box ${interactive ? 'interactive' : 'disabled'}`;
el.innerHTML = qtyText;
return el;
}
};
// --- 4. SETTINGS INJECTION ---
function checkGlobalKey() {
if (isPDA) return;
const key = GM_getValue(API_STORAGE_KEY, '');
if (key.length !== 16 && !window.location.href.includes('profiles.php') && !document.getElementById('rst-trade-banner')) {
const myIdMatch = document.cookie.match(/uid=(\d+)/);
const myId = myIdMatch ? myIdMatch[1] : '';
const profileUrl = myId ? `/profiles.php?XID=${myId}&rstFocus=true` : `/profiles.php?rstFocus=true`;
const banner = document.createElement('div');
banner.id = 'rst-trade-banner';
banner.style.cssText = "position: relative; display: block; width: 100%; background: #2a0808; border-bottom: 2px solid #ff4444; color: #fff; text-align: center; padding: 10px 5px; font-family: sans-serif; font-size: 13px; z-index: 9999999;";
banner.innerHTML = `⚠️ <b>${SCRIPT_NAME}</b> requires an API Key. <a href="${profileUrl}" style="color: #ffaa00; font-weight:bold; text-decoration:none;">Tap here to set it up ➔</a>`;
document.body.prepend(banner);
}
}
function injectProfileSettings() {
if (!window.location.href.includes('profiles.php')) return;
const myIdMatch = document.cookie.match(/uid=(\d+)/);
const myId = myIdMatch ? myIdMatch[1] : null;
const urlParams = new URLSearchParams(window.location.search);
const pageXid = urlParams.get('XID');
const shouldFocus = urlParams.get('rstFocus') === 'true';
if (pageXid && pageXid !== myId) return;
let attempts = 0;
const waitInterval = setInterval(() => {
if (++attempts >= 20) return clearInterval(waitInterval);
const allHeaders = Array.from(document.querySelectorAll('div[class*="title"]'));
const medalsHeader = allHeaders.find(h => h.textContent.trim() === 'Medals' || h.textContent.includes('Medals'));
let targetAnchor = medalsHeader ? medalsHeader.closest('div[class*="box-info"], div[class*="profile-wrapper"], div[class*="mt-"]') : null;
if (!targetAnchor) {
const basicInfoHeader = allHeaders.find(h => h.textContent.includes('Basic Information'));
targetAnchor = basicInfoHeader ? basicInfoHeader.closest('div[class*="box-info"], div[class*="profile-wrapper"], div[class*="mt-"]') : null;
}
if (!targetAnchor) return;
clearInterval(waitInterval);
if (document.getElementById('rst-trade-settings-box')) return;
const savedKey = GM_getValue(API_STORAGE_KEY, '');
const hasKey = savedKey.length === 16;
const accordion = document.createElement('div');
accordion.id = 'rst-trade-settings-box';
let uiContent = isPDA ? `
<div class="rst-trade-row">
<span class="rst-trade-label">API Key:</span>
<span style="color: #888; font-family: monospace;">Managed securely by Torn PDA</span>
</div>
<div class="rst-trade-row" style="margin-bottom: 0;">
<span class="rst-trade-label"></span>
<div id="rst-trade-status" class="rst-status rst-status-good">🟢 Status: Active via Torn PDA</div>
</div>
` : `
<div class="rst-trade-row">
<span class="rst-trade-label">API Key:</span>
<input type="text" id="rst-trade-api-input" placeholder="Paste 16-char key here..." spellcheck="false" autocomplete="off" maxlength="16" value="${savedKey}" class="rst-trade-input ${hasKey ? 'rst-blur' : ''}">
</div>
<div class="rst-trade-row" style="margin-bottom: 5px;">
<span class="rst-trade-label"></span>
<button class="rst-btn rst-btn-verify" id="rst-trade-btn-verify">VERIFY & SAVE</button>
<button class="rst-btn rst-btn-clear" id="rst-trade-btn-clear">CLEAR</button>
</div>
<div class="rst-trade-row" style="margin-bottom: 0;">
<span class="rst-trade-label"></span>
<div id="rst-trade-status" class="rst-status ${hasKey ? 'rst-status-good' : 'rst-status-bad'}">
${hasKey ? '🟢 Status: Key Verified & Active' : '🔴 Status: No Key Found'}
</div>
</div>
`;
accordion.innerHTML = `
<div id="rst-trade-header">
<span id="rst-trade-icon">▶</span>
<span>⚙️ ${SCRIPT_NAME} Settings</span>
</div>
<div id="rst-trade-body">
<p style="font-size: 12px; margin-bottom: 15px; color: #888;">Manage your API Key for this specific script. It is stored securely in your browser.</p>
${uiContent}
</div>
`;
targetAnchor.parentNode.insertBefore(accordion, targetAnchor);
const header = document.getElementById('rst-trade-header');
const body = document.getElementById('rst-trade-body');
const icon = document.getElementById('rst-trade-icon');
if (!hasKey && !isPDA) {
body.style.display = 'block';
icon.innerHTML = '▼';
}
header.addEventListener('click', () => {
const isOpen = body.style.display === 'block';
body.style.display = isOpen ? 'none' : 'block';
icon.innerHTML = isOpen ? '▶' : '▼';
});
if (shouldFocus || (!hasKey && !isPDA)) {
setTimeout(() => {
accordion.scrollIntoView({ behavior: 'smooth', block: 'center' });
accordion.style.transition = 'box-shadow 0.5s ease';
accordion.style.boxShadow = '0px 0px 15px rgba(255, 170, 0, 0.5)';
setTimeout(() => accordion.style.boxShadow = '0px 2px 4px rgba(0,0,0,0.5)', 2000);
}, 300);
}
if (!isPDA) {
const input = document.getElementById('rst-trade-api-input');
const verifyBtn = document.getElementById('rst-trade-btn-verify');
const clearBtn = document.getElementById('rst-trade-btn-clear');
const statusBox = document.getElementById('rst-trade-status');
input.addEventListener('blur', () => { if (input.value.length > 0) input.classList.add('rst-blur'); });
verifyBtn.addEventListener('click', () => {
const val = input.value.trim();
if (val.length === 16) {
statusBox.className = 'rst-status rst-status-wait';
statusBox.innerHTML = '⏳ Verifying with Torn API...';
verifyBtn.disabled = true;
GM_xmlhttpRequest({
method: "GET",
url: `https://api.torn.com/user/?selections=profile&key=${val}`,
onload: function(response) {
verifyBtn.disabled = false;
try {
const data = JSON.parse(response.responseText);
if (data.error) {
statusBox.className = 'rst-status rst-status-bad';
statusBox.innerHTML = `⚠️ Error: ${data.error.error}`;
} else {
GM_setValue(API_STORAGE_KEY, val);
input.classList.add('rst-blur');
statusBox.className = 'rst-status rst-status-good';
statusBox.innerHTML = `🟢 Welcome, ${data.name}! Key Saved.`;
const banner = document.getElementById('rst-trade-banner');
if (banner) banner.remove();
}
} catch (e) {
statusBox.className = 'rst-status rst-status-bad';
statusBox.innerHTML = '⚠️ Error parsing response.';
}
},
onerror: function() {
verifyBtn.disabled = false;
statusBox.className = 'rst-status rst-status-bad';
statusBox.innerHTML = '⚠️ Network error.';
}
});
} else {
statusBox.className = 'rst-status rst-status-bad';
statusBox.innerHTML = '⚠️ Key must be 16 chars!';
}
});
clearBtn.addEventListener('click', () => {
GM_setValue(API_STORAGE_KEY, '');
input.value = '';
input.classList.remove('rst-blur');
statusBox.className = 'rst-status rst-status-bad';
statusBox.innerHTML = '🔴 Key Cleared.';
});
}
}, 500);
}
// --- 5. DATA & LOGIC ---
function loadPrices() {
const cached = localStorage.getItem('rst_trade_prices_v36');
const cacheTime = localStorage.getItem('rst_trade_prices_time_v36');
const now = Date.now();
if (cached && cacheTime && (now - parseInt(cacheTime) < 24 * 60 * 60 * 1000)) {
priceCache = JSON.parse(cached);
return;
}
GM_xmlhttpRequest({
method: "GET",
url: `https://api.torn.com/torn/?selections=items&key=${activeApiKey}`,
onload: function(response) {
if (response.status === 200) {
try {
const data = JSON.parse(response.responseText);
if (data.error) return console.error("Torn API Error:", data.error.error);
const newPrices = {};
for (let id in data.items) {
newPrices[id] = data.items[id].market_value;
newPrices[data.items[id].name.toLowerCase()] = data.items[id].market_value;
}
priceCache = newPrices;
localStorage.setItem('rst_trade_prices_v36', JSON.stringify(newPrices));
localStorage.setItem('rst_trade_prices_time_v36', now.toString());
} catch (e) { console.error("Error parsing Torn API prices", e); }
}
}
});
}
function autoLoadAllItems() {
if (window.rstTrdHasAutoLoaded) return;
window.rstTrdHasAutoLoaded = true;
const startY = window.scrollY;
const curtain = document.createElement('div');
curtain.id = "rst-trd-curtain";
curtain.style.cssText = "position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(20, 20, 20, 0.95); z-index: 9999999; display: flex; flex-direction: column; align-items: center; justify-content: center; color: #4caf50; font-family: sans-serif; backdrop-filter: blur(5px);";
curtain.innerHTML = `
<div style="font-size: 24px; font-weight: bold; margin-bottom: 8px; text-shadow: 1px 1px 2px #000;">*Sorting by value...</div>
<div style="font-size: 14px; color: #ccc;">It's just a second✨</div>
`;
document.body.appendChild(curtain);
let lastItemCount = 0;
let unchangedCycles = 0;
const scrollInterval = setInterval(() => {
const items = document.querySelectorAll('li[data-item], li.clearfix');
const currentItems = items.length;
window.scrollTo(0, document.body.scrollHeight);
if (currentItems === lastItemCount) {
unchangedCycles++;
} else {
unchangedCycles = 0;
lastItemCount = currentItems;
}
if (unchangedCycles >= 3) {
clearInterval(scrollInterval);
window.scrollTo(0, startY);
curtain.innerHTML = `<div style="font-size: 24px; font-weight: bold; color: #fff; text-shadow: 1px 1px 2px #000;">Sorted!</div>`;
setTimeout(() => {
curtain.style.transition = "opacity 0.2s ease";
curtain.style.opacity = "0";
setTimeout(() => curtain.remove(), 200);
}, 150);
}
}, 250);
}
function setReactValue(el, val) {
const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
if (setter) {
setter.call(el, val);
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
}
}
function getItemId(row) {
const img = row.querySelector('img[src*="/items/"]');
if (img) {
const match = img.src.match(/\/items\/(?:[a-zA-Z0-9_-]+\/)*(\d+)(?:\/|\.)/i);
if (match) return match[1];
}
return null;
}
function getItemName(row) {
const img = row.querySelector('img[alt]');
if (img && img.alt) return img.alt.trim();
let rawText = row.textContent.split(/\$\d+/)[0].split(/N\/A/)[0].split(/Qty/i)[0];
rawText = rawText.replace(/(?:Equipped|Loaned|Unavailable)/ig, '').replace(/[\n\r\t\u00a0]/g, ' ').trim();
const match = rawText.match(/^[^a-zA-Z0-9]*x\s*([\d,]+)\s*(.*)$/i);
return match ? match[2].trim() : rawText;
}
function getMaxQty(row) {
const titleWrap = row.querySelector('.title-wrap') || row;
const textMatch = titleWrap.textContent.match(/x\s*([\d,]+)/i);
if (textMatch) {
const parsed = parseInt(textMatch[1].replace(/,/g, ''), 10);
if (parsed > 0) return parsed;
}
const qtyDiv = row.querySelector('.qty');
if (qtyDiv && qtyDiv.textContent.trim().length > 0) {
const parsed = parseInt(qtyDiv.textContent.replace(/,/g, ''), 10);
if (!isNaN(parsed) && parsed > 0) return parsed;
}
return 1;
}
function processInputs() {
if (Object.keys(priceCache).length === 0) return;
const allRows = document.querySelectorAll('li[data-item], li.clearfix');
allRows.forEach(row => {
if (/Equipped/i.test(row.textContent)) {
row.style.display = 'none';
return;
}
const nameWrap = row.querySelector('.name-wrap');
if (!row.querySelector('.title-wrap') && !nameWrap) {
row.style.order = 9999;
return;
}
if (nameWrap) nameWrap.classList.add('rst-name-wrap-flex');
const itemId = getItemId(row);
const itemName = getItemName(row);
const maxQty = getMaxQty(row);
const suspects = row.querySelectorAll('span, font, div, p');
suspects.forEach(node => {
if (node.className && typeof node.className === 'string') {
if (node.className.includes('rst-') || node.className.includes('name') || node.className.includes('title-wrap') || node.className.includes('amount')) return;
}
if (node.children.length === 0 && node.textContent) {
if (/^\s*\$[\d,]+/.test(node.textContent) || /[\d,]+x\s*=/.test(node.textContent)) {
node.classList.add('rst-trd-ghost-hidden');
node.style.display = "none !important";
}
}
});
const hasQtyInput = row.querySelector('input[placeholder="Qty" i], input[aria-label="Quantity" i]');
const lookupName = itemName.toLowerCase();
let matchPrice = priceCache[itemId] || priceCache[lookupName] || null;
let displayVal = matchPrice !== null ? (matchPrice * maxQty) : -1;
let sortOrder = -Math.round(displayVal / 100);
const parentList = row.parentElement;
if (parentList && !parentList.classList.contains('rst-trd-flex-list')) {
parentList.classList.add('rst-trd-flex-list');
}
row.style.order = sortOrder;
row.dataset.rstTrdSortOrder = sortOrder;
const priceHTML = matchPrice !== null ? `$${displayVal.toLocaleString()}` : `N/A`;
if (hasQtyInput && hasQtyInput.type !== 'hidden') {
let priceSpan = row.querySelector('.rst-trd-price-tag');
if (!row.dataset.rstTrdCbInjected) {
row.dataset.rstTrdCbInjected = "true";
const cb = UI.createCheckbox('rst-trd-custom-cb');
cb.addEventListener('change', (e) => {
if (e.target.checked) {
setReactValue(hasQtyInput, maxQty.toString());
hasQtyInput.style.border = "1px solid #28a745";
hasQtyInput.style.backgroundColor = "rgba(40, 167, 69, 0.1)";
} else {
setReactValue(hasQtyInput, "");
hasQtyInput.style.border = "";
hasQtyInput.style.backgroundColor = "";
}
});
hasQtyInput.addEventListener('input', () => {
const cleanValue = hasQtyInput.value.replace(/,/g, '');
if (cleanValue !== maxQty.toString()) {
cb.checked = false;
hasQtyInput.style.border = "";
hasQtyInput.style.backgroundColor = "";
} else {
cb.checked = true;
hasQtyInput.style.border = "1px solid #28a745";
hasQtyInput.style.backgroundColor = "rgba(40, 167, 69, 0.1)";
}
});
hasQtyInput.classList.add('rst-qty-input');
const inputWrapper = hasQtyInput.parentElement;
inputWrapper.classList.add('rst-input-wrapper-flex');
priceSpan = UI.createPriceTag(priceHTML);
inputWrapper.insertBefore(cb, hasQtyInput);
inputWrapper.insertBefore(priceSpan, cb);
}
if (priceSpan && priceSpan.innerHTML !== priceHTML) priceSpan.innerHTML = priceHTML;
}
else if (maxQty === 1) {
const titleWrap = row.querySelector('.title-wrap') || row;
const oldOverlay = titleWrap.querySelector('.rst-trd-overlay');
if (oldOverlay) oldOverlay.remove();
const amountDiv = row.querySelector('.amount');
const nativeCb = amountDiv ? amountDiv.querySelector('input[type="checkbox"]') : null;
const nativeLabel = amountDiv ? amountDiv.querySelector('label.marker-css') : null;
if (amountDiv && nativeCb) {
let priceSpan = amountDiv.querySelector('.rst-trd-price-tag');
if (!amountDiv.dataset.rstTrdSingleInjected) {
amountDiv.dataset.rstTrdSingleInjected = "true";
nativeCb.style.display = "none";
if (nativeLabel) nativeLabel.style.display = "none";
amountDiv.classList.add('rst-input-wrapper-flex');
const customCb = UI.createCheckbox('rst-trd-custom-cb');
customCb.checked = nativeCb.checked;
customCb.addEventListener('change', () => nativeCb.click());
const phantomBox = UI.createPhantomBox("1", false);
priceSpan = UI.createPriceTag(priceHTML);
amountDiv.appendChild(priceSpan);
amountDiv.appendChild(customCb);
amountDiv.appendChild(phantomBox);
} else {
if (nativeCb.style.display !== "none") nativeCb.style.display = "none";
if (nativeLabel && nativeLabel.style.display !== "none") nativeLabel.style.display = "none";
if (priceSpan && priceSpan.innerHTML !== priceHTML) priceSpan.innerHTML = priceHTML;
const customCb = amountDiv.querySelector('.rst-trd-custom-cb');
if (customCb && customCb.checked !== nativeCb.checked) customCb.checked = nativeCb.checked;
}
if (autoCheckHitList.has(lookupName) && !row.dataset.rstAutoChecked) {
row.dataset.rstAutoChecked = "true";
setTimeout(() => {
const freshNativeCb = row.querySelector('.amount input[type="checkbox"]');
if (freshNativeCb && !freshNativeCb.checked) freshNativeCb.click();
}, 200);
}
}
}
else if (maxQty > 1) {
const titleWrap = row.querySelector('.title-wrap') || row;
const nativeArrow = titleWrap.querySelector('svg, i[class*="icon"], [class*="arrow"]');
if (nativeArrow) nativeArrow.style.display = 'none';
let overlay = titleWrap.querySelector('.rst-trd-overlay');
if (overlay && overlay.dataset.rstTrdQty !== maxQty.toString()) {
overlay.remove();
overlay = null;
}
if (!overlay) {
titleWrap.style.position = "relative";
overlay = document.createElement('div');
overlay.className = "rst-trd-overlay";
overlay.dataset.rstTrdQty = maxQty.toString();
const priceSpan = UI.createPriceTag(priceHTML);
const phantomBox = UI.createPhantomBox(maxQty.toString(), true);
phantomBox.addEventListener('click', () => titleWrap.click());
const masterCb = UI.createCheckbox('rst-trd-master-cb');
masterCb.title = "Open stack and select all";
masterCb.addEventListener('click', (e) => {
e.stopPropagation();
if (masterCb.checked) {
autoCheckHitList.add(lookupName);
titleWrap.click();
}
});
overlay.appendChild(priceSpan);
overlay.appendChild(masterCb);
overlay.appendChild(phantomBox);
titleWrap.appendChild(overlay);
} else {
const existingPriceSpan = overlay.querySelector('.rst-trd-price-tag');
if (existingPriceSpan && existingPriceSpan.innerHTML !== priceHTML) {
existingPriceSpan.innerHTML = priceHTML;
}
}
}
});
}
// --- 6. INITIALIZATION SEQUENCE ---
async function init() {
injectProfileSettings();
checkGlobalKey();
activeApiKey = isPDA ? PDA_API_KEY : await GM_getValue(API_STORAGE_KEY, '');
if (activeApiKey && activeApiKey.length === 16 && window.location.href.includes('trade.php')) {
loadPrices();
document.addEventListener('click', (e) => {
const clickedTab = e.target.closest('a.ui-tabs-anchor');
if (!clickedTab) return;
if (clickedTab.classList.contains('all-category-icon') || clickedTab.getAttribute('href') === '#All') {
window.rstTrdHasAutoLoaded = false;
setTimeout(() => {
if (!window.rstTrdHasAutoLoaded && document.querySelector('ul.items-cont, ul.items-list')) {
autoLoadAllItems();
}
}, 100);
}
}, true);
const observer = new MutationObserver(() => {
observer.disconnect();
if (document.querySelector('ul.items-cont, ul.items-list') && !window.rstTrdHasAutoLoaded) {
autoLoadAllItems();
}
processInputs();
document.querySelectorAll('li[data-rst-trd-sort-order]').forEach(row => {
if (row.style.order !== row.dataset.rstTrdSortOrder) {
row.style.order = row.dataset.rstTrdSortOrder;
}
});
observer.observe(document.body, { childList: true, subtree: true });
});
observer.observe(document.body, { childList: true, subtree: true });
}
}
init();
})();