Sort items by total value, single value or quantity
// ==UserScript==
// @name Torn Item Sorter
// @namespace torn.item.sorter
// @version 1.1
// @description Sort items by total value, single value or quantity
// @author KOKOT
// @match https://www.torn.com/item.php*
// @grant GM_getValue
// @grant GM_setValue
// @license MIT
// ==/UserScript==
(function () {
'use strict';
const STORAGE_KEY = 'sortMode';
function getVisibleContainer() {
return document.querySelector('ul.itemsList[aria-hidden="false"]');
}
function getAllContainers() {
return [...document.querySelectorAll('ul.itemsList')];
}
function getTotalValue(item) {
const price = item.querySelector('.tt-item-price');
if (!price) return 0;
const spans = price.querySelectorAll('span');
const text = spans.length
? spans[spans.length - 1].textContent
: price.textContent;
return parseInt(text.replace(/[^\d]/g, ''), 10) || 0;
}
function getSingleItemValue(item) {
const price = item.querySelector('.tt-item-price');
if (!price) return 0;
const spans = price.querySelectorAll('span');
if (!spans.length) return 0;
return parseInt(
spans[0].textContent.replace(/[^\d]/g, ''),
10
) || 0;
}
function sortItems(mode) {
if (document.querySelector('[class*="itemInfo"]')) {
return;
}
const containers = getAllContainers();
containers.forEach(container => {
const items = [...container.children];
if (!items.length) return;
if (mode === 'value') {
items.sort((a, b) =>
getTotalValue(b) - getTotalValue(a)
);
} else if (mode === 'singleValue') {
items.sort((a, b) =>
getSingleItemValue(b) - getSingleItemValue(a)
);
} else if (mode === 'qty') {
items.sort((a, b) =>
Number(b.dataset.qty || 0) -
Number(a.dataset.qty || 0)
);
} else {
return;
}
items.forEach(item => container.appendChild(item));
});
}
function createControls() {
if (document.querySelector('#tt-item-sorter')) {
return;
}
const container = getVisibleContainer();
if (!container) return;
const wrapper = document.createElement('div');
wrapper.id = 'tt-item-sorter';
wrapper.innerHTML = `
<select id="tt-sort-select">
<option value="none">Default</option>
<option value="value">Total value ↓</option>
<option value="singleValue">Single value ↓</option>
<option value="qty">Qty ↓</option>
</select>
`;
if (!document.querySelector('#tt-sort-style')) {
const style = document.createElement('style');
style.id = 'tt-sort-style';
style.textContent = `
#tt-sort-select {
height:24px;
width:110px;
background:#2b2b2b;
color:#ddd;
border:1px solid #555;
border-radius:4px;
padding:0 6px;
font-size:11px;
cursor:pointer;
}
#tt-sort-select:hover {
border-color:#777;
}
#tt-sort-select:focus {
outline:none;
border-color:#999;
}
`;
document.head.appendChild(style);
}
const titleBar = document.querySelector(
'.title-black.hospital-dark.top-round.scroll-dark'
);
const searchForm = titleBar?.querySelector('form.isAcSearch');
if (titleBar && searchForm) {
titleBar.style.position = 'relative';
wrapper.style.cssText = `
position:absolute;
right:170px;
top:50%;
transform:translateY(-50%);
z-index:100;
`;
titleBar.appendChild(wrapper);
} else {
container.parentElement.prepend(wrapper);
}
const select = document.querySelector('#tt-sort-select');
const savedMode = GM_getValue(STORAGE_KEY, 'none');
select.value = savedMode;
select.addEventListener('change', () => {
const mode = select.value;
GM_setValue(STORAGE_KEY, mode);
if (mode === 'none') {
location.reload();
return;
}
sortItems(mode);
});
}
let lastMode = '';
setInterval(() => {
createControls();
if (document.querySelector('[class*="itemInfo"]')) {
return;
}
const mode = GM_getValue(STORAGE_KEY, 'none');
if (mode !== 'none') {
sortItems(mode);
}
}, 2000);
})();