Display items in Cardtrader Zero orders grouped by processing/shipment status
当前为
// ==UserScript==
// @name CardtraderZero Detailed Displayer
// @namespace https://www.cardtrader.com
// @version 2025-09-16
// @description Display items in Cardtrader Zero orders grouped by processing/shipment status
// @author Sibbob
// @match https://www.cardtrader.com/*
// @icon https://www.cardtrader.com/assets/favicon/favicon-32x32-a5e0283790f269dc65e3d5d886d9ec2ac290bf407249b2c124e7baff5c10080d.png
// @grant window.onurlchange
// @license MIT
// ==/UserScript==
const TEXT_HEADER_CLASS = "bg-tertiary";
const TEXT_INFO_CLASS = "text-info";
// Event listener to URL changes, to allow the script to be run if you land to the page navigating throug CT.
if (window.onurlchange === null) {
window.addEventListener('urlchange', (info) => {if(info.url.includes("orders/buyer_future_order")) main()});
}
// Run the script if landing directly to the page.
if (window.location.href.indexOf("orders/buyer_future_order") > -1) main();
function main() {
const trs = document.getElementsByTagName('tr');
let futureOrderLineIds = [];
let textInfo;
let textInfoIndex = 0;
let textHeader;
//get the list of all cards ordered, and the template for headers
for (let tr of trs) {
if (tr.classList.length > 0 ){
if (tr.classList.contains(TEXT_HEADER_CLASS)) {
textHeader = tr;
} else if(tr.classList.contains(TEXT_INFO_CLASS)){
if (textInfoIndex == 0) {
textInfo = tr;
}
textInfoIndex ++ ;
}
} else {
if (tr.dataset.testId.endsWith("pending")){
futureOrderLineIds.push(tr.dataset.futureOrderLineId);
}
}
}
console.debug('OriginalTextHeader',textHeader);
console.debug('OriginalTextInfo',textInfo);
// creating new sections of the table
const tbody = document.getElementsByTagName('tbody')[0];
const sec_ids = ["arrived-final","shipped-final","arrived-local","shipped-local","processed","purchased"];
const sec_descs = ["arrived in main warehouse", "shipped to main warehouse", "arrived in local hub","shipped to local hub","processed", "purchased"];
const sec_icon_classes = ["fa-truck-loading","fa-truck","fa-truck-loading","fa-truck","fa-cogs","fa-shopping-cart"]
for (let i = 0; i < sec_ids.length; i++){
//modify the header, including id to the text box to ease changing its text
let textHeaderModified = textHeader.cloneNode(true);
let textBox = textHeaderModified.children[0].children[0];
let textIcon = textBox.children[0];
setNewText(textBox,`0 cards ${sec_descs[i]}`);
textBox.id = `header-${sec_ids[i]}`;
// change icon
textIcon.classList.remove("fa-truck");
textIcon.classList.add(sec_icon_classes[i]);
//add id to info - to ease append after it
let textInfoModified = textInfo.cloneNode(true);
textInfoModified.id = `info-${sec_ids[i]}`
console.debug('ModifiedTextHeader',textHeaderModified);
console.debug('ModifiedTextInfo',textInfoModified);
tbody.insertAdjacentElement('beforeend', textHeaderModified);
tbody.insertAdjacentElement('beforeend', textInfoModified);
}
// fetch status and move the line accordingly
for (let lineId of futureOrderLineIds){
fetch(`https://www.cardtrader.com/orders/${lineId}/where_is_my_card.json?state=pending`)
.then(res => res.json())
.then(data => {
console.debug('FetchedData',lineId,data);
let orderInfo = data[0].data;
if (orderInfo.repurchase){
orderInfo = orderInfo.repurchase;
}
console.debug('ProcessedData',lineId,orderInfo);
let orderStatus = determineStatus(orderInfo);
// Purchased
insertRowInSection(lineId,orderStatus);
})
};
//delete the original header and info
textInfo.remove();
textHeader.remove();
};
function setNewText(node, newText) {
const children = Array.from(node.childNodes);
children.forEach(child => {
if (child.nodeType === Node.TEXT_NODE) {
child.textContent = newText;
return;
}
});
}
function determineStatus(orderInfo) {
if (orderInfo.has_mini_hub){
if (orderInfo.last_delivered_at){
// Arrived to final
return "arrived-final";
}
if (orderInfo.mini_hub_shipped_at ){
// Shipped to final
return "shipped-final";
}
if (orderInfo.mini_hub_accepted_at){
// Arrived to local
return "arrived-local";
}
if (orderInfo.shipped_at) {
// Shipped to local
return "shipped-local";
}
}else{
if (orderInfo.first_delivered_at){
//Arrived to final
return "arrived-final"
}
if (orderInfo.shipped_at) {
// Shipped to final
return "shipped-final";
}
}
if (orderInfo.closed_at){
// Processed
return "processed";
}
return "purchased"
}
function insertRowInSection(lineId,sectionId){
let info = document.getElementById(`info-${sectionId}`)
let tableRow = document.querySelector(`tr[data-future-order-line-id="${lineId}"]`);
info.parentNode.insertBefore(tableRow,info.nextSibling);
increaseCardCount(document.getElementById(`header-${sectionId}`));
}
function increaseCardCount(node) {
const children = Array.from(node.childNodes);
children.forEach(child => {
if (child.nodeType === Node.TEXT_NODE) {
let n = parseInt(child.textContent.split(" ")[0]);
child.textContent=child.textContent.replace(/\d+/,n+1);
return;
}
});
};