CSSBuy Suite

Automatically upload QC images from CSSBuy to Imgur

目前为 2020-06-11 提交的版本。查看 最新版本

// ==UserScript==
// @name         CSSBuy Suite
// @namespace    https://www.reddit.com/user/DeliciousLysergic/
// @version      0.64
// @description  Automatically upload QC images from CSSBuy to Imgur
// @author       https://www.reddit.com/user/DeliciousLysergic/
// @match        https://www.cssbuy.com/?go=m&name=orderlist*
// @match        https://www.cssbuy.com/m.php?name=orderlist
// @connect      self
// @connect      imgur.com
// @connect      fashionreps.tools
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/build/alertify.min.js
// @require      https://gf.qytechs.cn/scripts/401399-gm-xhr/code/GM%20XHR.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/spark-md5/3.0.0/spark-md5.min.js
// @grant        GM_xmlhttpRequest
// @run-at       document-end
// ==/UserScript==
'use strict';
/* globals $:false, SparkMD5:false, GM_XHR: false */

let CSSBuySuite = {}

// Stores each order's information
let orderInfo = {}

// Used to store each item's data
var items = {};

// Select random application ID for imgur
const clientIds = ["1ffdbfe5699ecec", "447a420679198a0", "956dd191d8320c9", "efb0b998924ef3c", "6f8eb75873d5f89", "9af4f2c84a12716"];
const clientId = clientIds[Math.floor(Math.random()*clientIds.length)]
// Time it takes for the image URLs to load in the iFrame in milliseconds
const imageLoadingTime = 5000; 

// Stores the MD5 of the user's username (used for fashiontools)
let usernameMD5 = "";

/*
    Imgur uploads are all stored within localStorage, in the form:
    cssbuy_suite_uploads: {
        "version": 1,
        "orders": {
            "528320": {
                "imageHashes": [],
                "imageIds": [],
                "albumHash": "",
                "albumId": ""
            }
        }
    }

    If version is different from what is currently expected, the object should be updated to the new format
*/
// Setup easy functions for writing/reading from local storage
Storage.prototype.setObject = function(key, value) {
    this.setItem(key, JSON.stringify(value));
}

Storage.prototype.getObject = function(key) {
    var value = this.getItem(key);
    return value && JSON.parse(value);
}
// Check whether local storage is currently initialised
if(localStorage.getObject("cssbuy_suite_uploads") == null)
{
    localStorage.setObject("cssbuy_suite_uploads", {
        "version": 1,
        "orders": {}
    })
}

const shipPromptHTML = `<div style="
z-index: 1000000;
position: fixed;
bottom: 0;
width: 60%;
left: 20%;
right: 20%;
height: 45px;
background-color: white;
border: 2px solid #72c02c;
border-bottom: 0;
display: flex;
justify-content: space-around;
font-size: 18px;
align-items: center;
visibility: hidden;
" id="ship-prompt"><div style="
">Items Selected: <span id="ship-prompt-items"></span></div><div>Weight: <span id="ship-prompt-weight"></span>g</div>
<div>Total Price: <span id="ship-prompt-price"></span>¥</div><div style="
background-color: #95a5a5;
color: white;
padding: 8px;
cursor: pointer;
" id="ship-prompt-cost-estimate">Cost Estimate</div><div style="
background-color: #72c02c;
color: white;
padding: 8px;
cursor: pointer;
" id="ship-prompt-submit-to-ship">Submit To Ship</div></div>`;

// Add the prompt to the body
$("body").append(shipPromptHTML);
const shipPrompt = $("#ship-prompt");
const shipPromptItems = $("#ship-prompt-items");
const shipPromptWeight = $("#ship-prompt-weight");
const shipPromptPrice = $("#ship-prompt-price");
const shipPromptCostEstimate = $("#ship-prompt-cost-estimate");
const shipPromptSubmit = $("#ship-prompt-submit-to-ship");

// Setup GM_XHR
$.ajaxSetup({ xhr: function() {return new GM_XHR; } });

// We only need to display the reddit review button on the confirmed page
if(window.location.href.includes("confirmed"))
{
    const tabContainer = $("#submit_form").parent().parent();
    // Create reddit review button
    const redditReviewButton = $("<button>", {
        id: "createRedditReview",
        type: "button",
        class: "btn-u btn-u-xs",
        style: "background-color: red; margin-left: 4px;",
        text: "Create Reddit Review"
    });
    tabContainer.prepend(redditReviewButton);

    // Now go through all the checkboxes and re-enable them
    $("input.products").each(function() { 
        $(this).removeAttr("disabled");
        $(this).parent().removeClass("state-disabled");
    });
    redditReviewButton.on("click", function() {
        // Get all the ticked orders
        let tickedOrderIDs = [];

        $(".products:checked").each(function() {
            // "value" contains the order ID
            tickedOrderIDs.push(parseInt($(this).attr("value")));
        });

        if(!tickedOrderIDs.length)
        {
            alertify.error("Please select some items!");
            return;
        }
        
        let redditReview = "";

        tickedOrderIDs.forEach(orderId => {
            redditReview += `
    **${orderInfo[orderId].name}**

    * ${orderInfo[orderId].price} Yuan - ${orderInfo[orderId].weight}g
    * W2C: ${orderInfo[orderId].url}
    * 10/10: Insert a comment about this item here!
    ${orderInfo[orderId].albumId == "" ? "" : "* QC: https://imgur.com/a/" + orderInfo[orderId].albumId}
    `;
        });

        redditReview += "\n\nReview format made by CSSBuySuite - read more here: " + redditLink;
        
        // Copy to clipboard
        copyToClipboard(redditReview);
        alertify.success("Copied the review to your clipboard!");
    });
}

// Setup combining multiple albums
const multipleOrderUploadHTML = `
<div class="overflow-h" style="padding: 5px 0 5px 8px;">
    <button id="multipleOrderUpload" class="btn-u btn-u-default btn-u-xs" style="background-color: #1bb76e;" type="button">Combine Imgur Albums</button>
    <span style="margin-left: 4px;" id="multipleOrderUploadLabel">Select multiple items to combine their QC pictures into one album.</span>
    <a style="padding: 3px; font-size: 1em; cursor: pointer; display: none;" id="multipleOrderUploadCopy">Copy to Clipboard</a>
</div>
`;

if($("#createRedditReview"))
{
    $("#createRedditReview").after(multipleOrderUploadHTML);
}
else
{
    $("#submit_form > div").after(multipleOrderUploadHTML);
}
const multipleOrderUpload = $("#multipleOrderUpload");
const multipleOrderUploadLabel = $("#multipleOrderUploadLabel");
const multipleOrderUploadCopy = $("#multipleOrderUploadCopy");
let multipleOrderUploading = false;

multipleOrderUploadCopy.on("click", () => {
    copyToClipboard(multipleOrderUploadCopy.attr("data-album-link"));
    alertify.success("Copied the album to your clipboard!")
});

// Configure alertify
alertify.set('notifier', 'position', 'bottom-left');
// Add styling for alertify
$("head").append(`
<!-- CSS -->
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/[email protected]/build/css/alertify.min.css"/>
<!-- Bootstrap theme -->
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/[email protected]/build/css/themes/bootstrap.min.css"/>
`);

const redditLink = "https://www.reddit.com/r/FashionReps/comments/gx5xdg/";

// Used for setting buttons as disabled
CSSBuySuite.setDisabledButton = function(button, disabled) {
    if (disabled) 
    {
        button.attr("disabled", "disabled");
        button.text("Uploading...");
    }
    else
    {
        button.attr("disabled", null);
        // Ugly fix
        if(button == multipleOrderUpload)
        {
            button.text("Combine Imgur Albums");
        }
        else
        {
            button.text("Upload to Imgur");
        }
    }
}

CSSBuySuite.createAlbumForOrder = function(orderId)
{
    let albumHash = "";
    let albumId = "";

    orderInfo[orderId].infoLabel.text("Creating Imgur album...");

    $.ajax({
        url: "https://api.imgur.com/3/album",
        method: "POST",
        headers: {"Authorization": "Client-ID " + clientId},
        data: {
            description: "Auto uploaded using CSSBuySuite. More info here: " + redditLink,
            privacy: "hidden"
        },
        success: function(response) {
            // Retrieve the delete hash and the ID of the album from the response
            albumHash = response.data.deletehash;
            albumId = response.data.id;
            orderInfo[orderId].albumHash = albumHash;
            orderInfo[orderId].albumId = albumId;
            
            // An album has been created for this, now we can upload the images
            console.log("Album has been created for " + orderId + ". Now uploading images...");
            CSSBuySuite.uploadImagesToAlbum(orderId);
        },
        error: function(response) {
            result = $.parseJSON(result.responseText)
            // Update text
            orderInfo[orderId].infoLabel.text("Failed to create album! Imgur Error: " + result.data.error.message);
            orderInfo[orderId].uploading = false;
            // Display alert
            alertify.error("Failed to create an album for order " + orderId + ". Error: " + result.data.error.message);
            // Re-enable the upload button
            setDisabled(orderInfo[orderId].uploadButton, false)
            console.log("Failed to create album:");
            console.log(result.data.error)
        }
    });
}

CSSBuySuite.uploadMultipleOrders = function() 
{
    if(multipleOrderUploading)
    {
        return;
    }

    let orderIds = [];
    let invalidIds = [];

    // Check whether they've selected multiple orders 
    $(".products:checked").each(function() {
        let orderId = $(this).attr("value");
        if(orderId in orderInfo)
        {
            if(orderInfo[orderId]["albumId"] == "")
            {
                invalidIds.push(orderId);
            }
            else
            {
                orderIds.push(orderId);
            }
        }
    });

    // Check they have no invalid orders
    if(invalidIds.length != 0)
    {
        alertify.error("Please upload orders " + invalidIds.join(", ") + " before trying to combine them.");
        return;
    }
    // Check they've selected some valid orders
    if(orderIds.length == 0 || orderIds.length == 1)
    {
        alertify.error("Please select at least 2 orders to combine into one album!");
        return;
    }
    
    // Create album
    CSSBuySuite.createMultipleOrderAlbum(orderIds);
}

CSSBuySuite.createMultipleOrderAlbum = function(orderIds)
{
    multipleOrderUploadLabel.text("Creating Imgur album...");

    multipleOrderUploading = true;
    
    // Get all the image IDs
    let imageIds = [];

    orderIds.forEach(orderId => {
        imageIds = imageIds.concat(orderInfo[orderId].imageIds);
    });

    $.ajax({
        url: "https://api.imgur.com/3/album",
        method: "POST",
        headers: {"Authorization": "Client-ID " + clientId},
        data: {
            description: "Auto uploaded using CSSBuySuite. More info here: " + redditLink,
            privacy: "hidden",
            // We can submit IDs with the album creation, making this easy!
            ids: imageIds
        },
        success: function(response) {
            // Retrieve the delete hash and the ID of the album from the response
            let albumLink = "https://imgur.com/a/" + response.data.id;
            
            // An album has been created for this, now we can upload the images
            console.log("Album has been created for multi-order.");
            multipleOrderUploadLabel.html(`<strong>Uploaded to</strong> <a href="${albumLink}" target="_blank">${albumLink}</a>`);
            // Show Copy to clipboard
            multipleOrderUploadCopy.attr("data-album-link", albumLink);
            multipleOrderUploadCopy.css("display", "unset");
        },
        error: function(response) {
            result = $.parseJSON(result.responseText)
            // Update text
            multipleOrderUploadLabel.text("Failed to create album! Imgur Error: " + result.data.error.message);
            multipleOrderUploading = false;
            // Display alert
            alertify.error("Failed to create an album. Error: " + result.data.error.message);
            // Re-enable the upload button
            setDisabled(multipleOrderUpload, false)
            console.log("Failed to create album:");
            console.log(result.data.error)
        }
    });
}

CSSBuySuite.uploadImagesToAlbum = function(orderId)
{
    // Stores how many images have been uploaded
    let imageCount = 0;
    // Stores total amount of images we have to upload
    let totalImages = orderInfo[orderId].qcImages.length;

    // Update label
    orderInfo[orderId].infoLabel.text("Uploading images to Imgur... (0/" + totalImages + ")");

    // Create the description for the item (inserted into each image)
    let description = "";
    description = description + (orderInfo[orderId].itemUrl != "" ? "W2C: " + orderInfo[orderId].url + "\n": "");
    description = description + (orderInfo[orderId].weight != "" ? "Weight: " + orderInfo[orderId].weight + " grams\n": "");
    description = description + (orderInfo[orderId].price != "" ? "Price: ¥" + toFixed(orderInfo[orderId].price, 2) + "\n": "");
    description = description + (orderInfo[orderId].sizing != "" ? "Item Info: " + orderInfo[orderId].sizing + "\n": "");

    // Form data for the uploading of each image
    let imageFormData = {
        album: orderInfo[orderId].albumHash,
        description: description
    }

    // For each image ID
    orderInfo[orderId].qcImages.forEach(function(image) {
        // Update the form data with this image's URL
        // While we can't access another user's CSSBuy QC page, the images themselves have no access control
        // That's why we can use the image URLs
        imageFormData.image = image;
        
        // Now we can upload the image
        $.ajax({
            url: "https://api.imgur.com/3/image",
            method: "POST",
            headers: {"Authorization": "Client-ID " + clientId},
            data: imageFormData,
            success: function(result) {
                // Add the image's delete hash to imageHashes
                orderInfo[orderId].imageHashes.push(result.data.deletehash);
                orderInfo[orderId].imageIds.push(result.data.id);
                imageCount += 1;

                // Update the label
                orderInfo[orderId].infoLabel.text("Uploading images to Imgur... (" + imageCount + "/" + totalImages + ")");
                
                // Now check whether we've uploaded everything
                if(imageCount == totalImages)
                {
                    // We have, so call uploadFinished
                    CSSBuySuite.uploadFinished(orderId);
                }
            },
            error: function(result) {
                result = $.parseJSON(result.responseText)
                // Update text
                orderInfo[orderId].infoLabel.text("Failed to create album! Imgur Error: " + result.data.error.message);
                orderInfo[orderId].uploading = false;
                // Display alert
                alertify.error("Failed to create an album for order " + orderId + ". Error: " + result.data.error.message);
                // Re-enable the upload button
                CSSBuySuite.setDisabledButton(orderInfo[orderId].uploadButton, false);
            }
        });
    });
}

CSSBuySuite.uploadFinished = function(orderId)
{
    const albumUrl = "https://imgur.com/a/" + orderInfo[orderId].albumId;

    console.log("All images uploaded for " + orderId + ": " + albumUrl);

    // Save the URL
    try
    {
        window.localStorage.setItem("orderalbum_" + orderId, orderInfo[orderId].albumId);
    }
    catch(error)
    {
        console.log("Failed to save order album into local storage.");
        console.log(error);
    }
    
    orderInfo[orderId].uploading = false;
    CSSBuySuite.setDisabledButton(orderInfo[orderId].uploadButton, false);

    // Update local storage
    let uploadObject = localStorage.getObject("cssbuy_suite_uploads");
    uploadObject["orders"][orderId] = {
        "imageHashes": orderInfo[orderId].imageHashes,
        "imageIds": orderInfo[orderId].imageIds,
        "albumId": orderInfo[orderId].albumId,
        "albumHash": orderInfo[orderId].albumHash
    };
    localStorage.setObject("cssbuy_suite_uploads", uploadObject)

    // Show the new album ID
    CSSBuySuite.updateOrderAlbumDisplay(orderId);

    // Now attempt to upload to Fashiontools
    CSSBuySuite.checkForFashiontoolsUpload(orderId);
}

// This updates a order with the new link for their album
CSSBuySuite.updateOrderAlbumDisplay = function(orderId)
{
    const albumUrl = "https://imgur.com/a/" + orderInfo[orderId].albumId;
    orderInfo[orderId].infoLabel.text("Uploaded to ");
    orderInfo[orderId].infoLink.text(albumUrl);
    orderInfo[orderId].infoLink.attr("href", albumUrl);
    orderInfo[orderId].copyButton.show();
    // orderInfo[orderId].copyButton.attr("onclick", "copyToClipboard('" + albumUrl + "')");
}

CSSBuySuite.clearLink = function(orderId)
{
    orderInfo[orderId].copyButton.hide()
    orderInfo[orderId].infoLink.text("")
}

// This checks whether the URL + sizing is valid and that we have a username to upload with
CSSBuySuite.checkForFashiontoolsUpload = function(orderId)
{
    // Firstly check whether we have a sizing parameter for this order
    if(orderInfo[orderId].sizing == "")
        return;
    
    // Check whether our url is from taobao
    if(orderInfo[orderId].url.indexOf('item.taobao.com') == -1)
        return;
    
    // Check whether we have a username stored, if not, retrieve it then upload
    if(usernameMD5 == "")
    {
        // Go to the cssbuy homepage and get the username
        usernameiFrame = $("<iframe>", {
            style: "display: none;",
            src: "https://www.cssbuy.com/?go=m&"
        });
        usernameiFrame.on("load", () => CSSBuySuite.collectUsername());
        usernameiFrame.insertAfter($("form[name='search-form']"));
        setTimeout(function() {
            CSSBuySuite.uploadToFashiontools(orderId);
        }, 3500);
    }
    else
    {
        // We already have a username, let's upload!
        CSSBuySuite.uploadToFashiontools(orderId);
    }
}

CSSBuySuite.uploadToFashiontools = function(orderId)
{
    console.log("Attemping to upload to fashiontools.");
    // Get the search query parameters
    const urlParams = new URLSearchParams(orderInfo[orderId].url.split("?").pop());
    const itemID = urlParams.get('id');

    $.post('https://fashionreps.tools/qcdb/qcdb.php', {
            'userhash': usernameMD5,
            'imgur': orderInfo[orderId].albumId,
            'w2c': 'https://item.taobao.com/item.htm?id=' + itemID,
            'sizing': orderInfo[orderId].sizing,
            'source': "cssbuyUploader"
    });
}

// iFrame helpers
CSSBuySuite.collectUsername = function()
{
    // Get the username from the homepage
    const username = $("a[href='https://www.cssbuy.com/?go=m&name=edituserinfo']", usernameiFrame.contents()).parent().find("span").text()
    console.log("Found username: " + username);
    usernameMD5 = SparkMD5.hash(username);
    console.log("Username MD5: " + usernameMD5);
}

CSSBuySuite.collectPictures = function(orderId) {
    // Check that we are uploading this order atm
    // onload is called when iFrame is initialised
    if(!(orderId in orderInfo) || !orderInfo[orderId].uploading)
        return;

    // Wait a few seconds to ensure all the images have loaded...
    setTimeout(function() {
        // Check iFrame for all images
        // Add images to a list in form [url, base64]
        let urls = [];
        
        // Retrieve all the images
        orderInfo[orderId].iFrame.contents().find("#photolist").find("img").each(function() {
            let url = $(this).attr("src");

            urls.push(url);
        });

        orderInfo[orderId].qcImages = urls

        if(!urls.length)
        {
            orderInfo[orderId].infoLabel.text("Found no QC images!")
        }
        else
        {
            orderInfo[orderId].infoLabel.text("Found " + urls.length + " QC pictures...")

            CSSBuySuite.createAlbumForOrder(orderId);
        }
    }, imageLoadingTime);
};

CSSBuySuite.uploadOrder = function(orderId) {
    // If we are already uploading this order, return
    if(orderInfo[orderId].uploading)
        return;

    // Update label
    CSSBuySuite.clearLink(orderId);
    orderInfo[orderId].infoLabel.text("Getting QC pictures...");
    orderInfo[orderId].uploading = true;

    // Disable button
    orderInfo[orderId].uploading = true;
    CSSBuySuite.setDisabledButton(orderInfo[orderId].uploadButton, true)

    // Update iFrame to get pictures
    orderInfo[orderId].iFrame.attr("src", orderInfo[orderId].qcUrl);
}

// URL = https://item.taobao.com...
// orderContainer =  container to add View other QC button to
CSSBuySuite.checkQCExists = function(itemID, orderContainer)
{
    // Thank you to FR:ES (https://gf.qytechs.cn/en/scripts/387421-fr-es-basetao-extension/code)
    $.getJSON({
        url: "https://fashionreps.tools/qcdb/qcExists.php",
        data: {
            "w2c": 'https://item.taobao.com/item.htm?id=' + itemID,
        },
        method: "GET",
        success: function(data) {
            if(data.exists == "1")
            {
                const compareQC = $("<a>", {
                    class: "btn btn-sm btn-default margin-bottom-5", 
                    text: "View Other QC",
                    style: "background: #1b8bb7; border: 1px solid #1b8bb7; color: white;",
                    href: "https://fashionreps.tools/qcdb/qcview.php?id=" + itemID,
                    target: "_blank"
                });
                compareQC.appendTo(orderContainer);
            }
        }
    })
}

// Add buttons for each of the orders
var buttonSelector = ".oss-photo-view-button > a:contains('QC PIC')";

$(buttonSelector).each(function() {
    const orderId = $(this).parent().attr("data-id");

    // Create the "Upload to Imgur" button
    const qcUrl = $(this).attr("href");
    const uploadButton = $("<a>", {
        class: "btn btn-sm btn-default margin-bottom-5", 
        text: "Upload to Imgur",
        orderId: orderId, 
        style: "background: #1bb76e; border: 1px solid #1bb76e; color: white;"
    });
    uploadButton.appendTo($(this).parent());
    // Add click handler
    uploadButton.on("click", () => CSSBuySuite.uploadOrder(orderId));

    // Get parent TR element to retrieve item name & URL & create progress label
    const parentTableEntry = $(this).parentsUntil("tbody");
    const header = $("td div div:nth-child(2)", parentTableEntry.prev())

    // Create progress label
    const label = $("<span>", {
        text: "", 
        style: "font-weight: bold; margin-left: 40px;"
    });
    label.appendTo(header);

    // Create album link
    const link = $("<a>", {style:"margin-right: 10px;", target: "_blank"});
    link.appendTo(header);

    // Create copy butotn
    const copyButton = $("<a>", {
        text: "Copy to Clipboard", 
        style: "padding: 3px; font-size: 1em; cursor: pointer;",
    })
    copyButton.hide()
    copyButton.appendTo(header)
    copyButton.on("click", () => {
        // Generate the imgur link and copy to clipboard
        copyToClipboard("https://imgur.com/a/" + orderInfo[orderId].albumId);
        alertify.success("Copied the album to your clipboard!")
    });

    // Get item name/URL
    const itemLink = parentTableEntry.find("td:nth-child(2) a");
    const itemURL = itemLink.attr("href");
    const price = parentTableEntry.find("td:nth-child(3) span");
    const weight = parentTableEntry.find("td:nth-child(6) span");
    let sizing = "";

    const innerText = parentTableEntry.find("td:nth-child(2)").find("span:eq(1)").html();
    const splitText = innerText.toString().split("<br>");
    if (splitText.length == 1)
    {
        const colour = splitText[0].split(" : ")[1];
        sizing = "Color Classification:"+colour;
    }
    else if(splitText.length == 2)
    {
        const size = splitText[0].split(" : ")[1];
        const colour = splitText[1].split(" : ")[1];
        sizing = "size:" + size + " Colour:"+colour;
    }
    else
    {
        sizing = "";
    }
        
    // Create iframe
    const iFrame = $("<iframe>", {
        style: "display: none;"
    });
    // Add onload listener
    iFrame.on("load", () => CSSBuySuite.collectPictures(orderId));
    iFrame.insertAfter($("form[name='search-form']"));
    
    // Create new item entry
    orderInfo[orderId] = {
        orderId: orderId,
        name: itemLink.text(),
        url: itemURL,
        price: toFixed(price.text(), 2),
        weight: weight.text(),
        sizing: sizing,
        qcUrl: qcUrl,
        qcImages: [],
        copyButton: copyButton,
        infoLink: link,
        infoLabel: label,
        iFrame: iFrame,
        uploading: false,
        uploadButton: uploadButton,
        albumHash: "",
        albumId: "",
        imageHashes: [],
        imageIds: []
    }

    // Check whether they already have a album saved for this id
    let storage = localStorage.getObject("cssbuy_suite_uploads");
    if(storage !== null)
    {
        if(orderId in storage.orders)
        {
            orderInfo[orderId] = Object.assign(orderInfo[orderId], storage.orders[orderId]);
            CSSBuySuite.updateOrderAlbumDisplay(orderId);
        }
    }

    // Create Compare QC button
    // URL is in form: https://fashionreps.tools/qcdb/qcview.php?id=616820737680
    if(itemURL.indexOf('item.taobao.com') !== -1)
    {
        // Get the search query parameters
        const urlParams = new URLSearchParams(itemURL.split("?").pop());
        const itemID = urlParams.get('id');
        if(itemID !== null)
        {
            CSSBuySuite.checkQCExists(itemID, $(this).parent());
        }
    }
    
});

// Add combine order button handler
multipleOrderUpload.on("click", CSSBuySuite.uploadMultipleOrders);

function handleCheckboxInputOnArriveTab()
{
    // Count all selected products
    let selectedInputs = $("input.products:checked");
    // Check if we need to hide the prompt
    if(!selectedInputs.length)
    {
        shipPrompt.css("visibility", "hidden");
        return;
    }
    
    // Update labels
    let price = 0;
    let weight = 0;

    selectedInputs.each(function() {
        price += parseInt($(this).attr("data-total-price"));
        weight += parseInt($(this).attr("data-weight"));
    })

    shipPromptItems.text(selectedInputs.length.toString());
    shipPromptPrice.text(price.toString());
    shipPromptWeight.text(weight.toString());
    shipPromptCostEstimate.attr("data-weight", weight);
    shipPromptCostEstimate.attr("data-total-price", price);

    // Show prompt
    shipPrompt.css("visibility", "unset");
}

if(window.location.href.includes("orderlist") && (!window.location.href.includes("type") || window.location.href.includes("arrived")))
{
    $("input.products").on("input", handleCheckboxInputOnArriveTab);
    $(".selectall").on("input", handleCheckboxInputOnArriveTab);
    shipPromptSubmit.on("click", () => $("#submitToShip").click());
    shipPromptCostEstimate.on("click", () => {
        window.open(`https://www.cssbuy.com/?go=page&w=${shipPromptCostEstimate.attr("data-weight")}&m=${shipPromptCostEstimate.attr("data-total-price")}`);
    });
    // If you submit to ship then go back on browser tab, the prompt doesn't display
    // Wait until it's loaded, then check if some are already pressed
    setTimeout(handleCheckboxInputOnArriveTab, 1500);
}

// Helper functions
// https://stackoverflow.com/a/11818658
function toFixed(num, fixed) {
    var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?');
    return num.toString().match(re)[0];
}

window.copyToClipboard = function(text) {
    var $temp = $("<textarea>");
    $("body").append($temp);
    $temp.val(text).select();
    document.execCommand("copy");
    $temp.remove();
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址