Greasy Fork

Greasy Fork is available in English.

Amazon Seller Product Price Loader

Optimized version to load Amazon product prices with customizable settings, minimized RAM usage, and UI.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Amazon Seller Product Price Loader
// @namespace    http://tampermonkey.net/
// @version      4.8
// @description  Optimized version to load Amazon product prices with customizable settings, minimized RAM usage, and UI.
// @license      MIT https://opensource.org/licenses/MIT
// @match        https://sellercentral.amazon.com/*
// @match        https://sellercentral.amazon.co.uk/*
// @match        https://sellercentral.amazon.de/*
// @match        https://sellercentral.amazon.fr/*
// @match        https://sellercentral.amazon.it/*
// @match        https://sellercentral.amazon.es/*
// @match        https://sellercentral.amazon.ca/*
// @match        https://sellercentral.amazon.com.mx/*
// @match        https://sellercentral.amazon.com.br/*
// @match        https://sellercentral.amazon.co.jp/*
// @match        https://sellercentral.Amazon.com.br/*
// @match        https://sellercentral.amazon.com.au/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        GM_xmlhttpRequest
// @resource     IMPORTED_CSS https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css
// @run-at       document-end
// ==/UserScript==

(function () {
    'use strict';
    function applySettings() {
        // Apply font size, font family, and bold settings
        document.body.style.fontSize = `${options.fontSize}px`;
        document.body.style.fontFamily = options.fontFamily;
        document.body.style.fontWeight = options.fontBold ? 'bold' : 'normal';

        // Apply font color
        document.body.style.color = options.fontColor || 'initial';

        // Apply glow settings if enabled
        if (options.glowEnabled) {
            document.body.style.textShadow = `0px 0px 5px ${options.glowColor}`;
        } else {
            document.body.style.textShadow = 'none';
        }
    }

    document.addEventListener('DOMContentLoaded', () => {
        // Load saved options from GM_setValue
        options.fontSize = GM_getValue('fontSize', 14); // Default to 14px if not set
        options.fontFamily = GM_getValue('fontFamily', 'Arial'); // Default to Arial if not set
        options.fontBold = GM_getValue('fontBold', false); // Default to false if not set
        options.fontColor = GM_getValue('fontColor', '#000000'); // Default to black if not set
        options.glowEnabled = GM_getValue('glowEnabled', false); // Default to false if not set
        options.glowColor = GM_getValue('glowColor', '#ffffff'); // Default to white if not set

        // Apply loaded settings
        applySettings();

        // Create font color input and add event listener
        const fontColorInput = document.createElement('input');
        fontColorInput.type = 'color';
        fontColorInput.value = options.fontColor; // Set the current font color
        fontColorInput.addEventListener('change', (e) => {
            options.fontColor = e.target.value;
            GM_setValue('fontColor', options.fontColor);
            applySettings(); // Reapply settings to update font color immediately
        });

        // Add the font color input to the settings UI (for example, adding to a settings container)
        document.body.appendChild(fontColorInput); // Adjust where you want it placed in your UI
    });

    const defaultOptions = {
        fontSize: '12px',
        fontFamily: 'Arial, sans-serif',
        textColor: '#0066c0',
        priceColor: '#0066c0',
        reviewsColor: '#008800',
        sellerColor: '#cc5500',
        glowColor: '#ff00ff',
        showFrame: true,
        frameColor: '#cccccc',
        loadDelay: 10,
        currency: 'default',
        enableNotifications: false
    };

    let options = Object.keys(defaultOptions).reduce((acc, key) => {
        acc[key] = GM_getValue(key, defaultOptions[key]);
        return acc;
    }, {});

    const MAX_RETRIES = 2;
    const RETRY_DELAY = 40;

    // Add Tailwind CSS
    GM_addStyle(GM_getResourceText("IMPORTED_CSS"));

    function addCustomStyle() {
        let styles = [];

        if (options.fontBold) {
            styles.push('font-bold');
        }

        if (options.glowIntensity > 0) {
            styles.push(`text-shadow: 0 0 ${options.glowIntensity * 20}px ${options.glowColor}`);
        }

        styles.push(`color: ${options.priceColor}`);
        styles.push(`font-family: ${options.fontFamily}`);
        styles.push(`font-size: ${options.fontSize}`);

        const glowBlurRadius = options.glowIntensity * 10;
        const glowSpreadRadius = options.glowIntensity * 5;
        styles.push(`text-shadow: 0 0 ${glowBlurRadius}px ${options.glowColor}, 0 0 ${glowSpreadRadius}px ${options.glowColor}`);

        styles.push(`color: ${options.priceColor}`);
        styles.push(`font-family: ${options.fontFamily}`);
        styles.push(`font-size: ${options.fontSize}`);

        const customStyle = styles.join('; ');
        document.documentElement.style.setProperty('--custom-style', customStyle);

        if (options.glowIntensity > 0) {
            styles.push(`text-shadow: 0 0 ${options.glowIntensity * 20}px ${options.glowColor}`);
        }

        styles.push(`color: ${options.priceColor}`);
        styles.push(`font-family: ${options.fontFamily}`);
        styles.push(`font-size: ${options.fontSize}`);
        const isDarkMode = document.body.classList.contains('dark');

        function getInvertedColor(color) {
            // Convert the hex color to RGB
            const r = parseInt(color.slice(1, 3), 16);
            const g = parseInt(color.slice(3, 5), 16);
            const b = parseInt(color.slice(5, 7), 16);

            // Invert the RGB values
            const invR = 255 - r;
            const invG = 255 - g;
            const invB = 255 - b;

            // Convert the inverted RGB values back to hex
            return `#${invR.toString(16).padStart(2, '0')}${invG.toString(16).padStart(2, '0')}${invB.toString(16).padStart(2, '0')}`;
        }

        GM_addStyle(`
        .price-display-container {
            display: block;
            margin-top: 4px;
        }
        .price-display {
            display: block;
            font-size: ${options.fontSize};
            font-family: ${options.fontFamily};
            color: ${isDarkMode ? getInvertedColor(options.priceColor) : options.priceColor};
            text-shadow: 0 0 ${glowBlurRadius}px ${options.glowColor}, 0 0 ${glowSpreadRadius}px ${options.glowColor};
            font-weight: ${options.fontBold ? 'bold' : 'normal'};
            -webkit-text-stroke: 2px var(--glow-color);
        }
        .rating-display {
            display: block;
            font-size: ${options.fontSize};
            font-family: ${options.fontFamily};
            color: ${isDarkMode ? getInvertedColor(options.reviewsColor) : options.reviewsColor};
            text-shadow: 0 0 ${glowBlurRadius}px ${options.glowColor}, 0 0 ${glowSpreadRadius}px ${options.glowColor};
            font-weight: ${options.fontBold ? 'bold' : 'normal'};
            -webkit-text-stroke: 2px var(--glow-color);
        }
        .seller-display {
            display: block;
            font-size: ${options.fontSize};
            font-family: ${options.fontFamily};
            color: ${isDarkMode ? getInvertedColor(options.sellerColor) : options.sellerColor};
            text-shadow: 0 0 ${glowBlurRadius}px ${options.glowColor}, 0 0 ${glowSpreadRadius}px ${options.glowColor};
            font-weight: ${options.fontBold ? 'bold' : 'normal'};
            -webkit-text-stroke: 2px var(--glow-color);
        }
        .loading {
            opacity: 0.9;
            padding: 1px 8px;
            border: 1px solid ${options.frameColor};
            display: inline-block;
        }

        #amazon-price-loader-settings {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 10000;
            background: #f9f9f9;
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
            max-width: 400px;
            width: 90%;
            overflow: hidden;
            border: 1px solid #ccc;
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
        }

        .settings-overlay {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0, 0, 0, 0.5);
            z-index: 9999;
        }

        .tooltip {
            position: absolute;
            background: white;
            border: 1px solid black;
            padding: 10px;
            z-index: 1000;
        }

        .setting-row {
            display: flex;
            flex-direction: column;
            width: 48%;
            margin-bottom: 10px;
        }

        .setting-label {
            font-weight: bold;
            color: #333;
            margin-bottom: 5px;
        }

        .setting-button {
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 5px;
            padding: 5px 10px;
            cursor: pointer;
            transition: background-color 0.3s;
            font-size: 14px;
            width: 100%;
            margin-top: 10px;
        }

        .setting-button:hover {
            background-color: #0056b3;
        }

        .color-picker {
            width: 100%;
            height: 30px;
            border: none;
            padding: 0;
            cursor: pointer;
        }

        .font-picker {
            width: 100%;
            padding: 5px;
            border: 1px solid #ccc;
            border-radius: 5px;
        }

        .font-size-input {
            width: 100%;
            padding: 5px;
            border: 1px solid #ccc;
            border-radius: 5px;
        }
    `);
    }

    function createSettingsUI() {
        // Check if the settings overlay already exists
        if (document.querySelector('.settings-overlay')) {
            return; // Exit the function if the overlay is already present
        }
        const settingsContainer = document.createElement('div');
        settingsContainer.className = 'settings-container bg-white shadow-md rounded-lg p-2 w-48';
        const title = document.createElement('h2');
        title.textContent = 'Settings';
        title.classList.add('text-xs', 'font-bold', 'mb-2');
        settingsContainer.style.position = 'fixed';
        settingsContainer.style.top = '0px'; // Adjust the value to move the menu up or down
        settingsContainer.style.right = '70px'; // Adjust the value to move the menu left or right

        settingsContainer.appendChild(title);

        // Display Settings
        const displaySettings = document.createElement('div');
        displaySettings.classList.add('mb-2');

        const fontSizeRow = document.createElement('div');
        fontSizeRow.classList.add('flex', 'items-center', 'justify-between');

        const fontSizeLabel = document.createElement('label');
        fontSizeLabel.textContent = 'Size';
        fontSizeLabel.classList.add('text-xxs', 'font-medium');

        const fontSizeInput = document.createElement('input');
        fontSizeInput.type = 'number';
        fontSizeInput.value = options.fontSize.replace('px', '');
        fontSizeInput.min = 8;
        fontSizeInput.max = 36;
        fontSizeInput.className = 'w-10 px-1 py-0.5 border rounded text-xxs';
        fontSizeInput.onchange = (e) => {
            options.fontSize = `${e.target.value}px`;
            addCustomStyle();
        };

        fontSizeRow.appendChild(fontSizeLabel);
        fontSizeRow.appendChild(fontSizeInput);
        displaySettings.appendChild(fontSizeRow);

        const fontFamilyRow = document.createElement('div');
        fontFamilyRow.classList.add('flex', 'items-center', 'justify-between');

        const fontFamilyLabel = document.createElement('label');
        fontFamilyLabel.textContent = 'Font';
        fontFamilyLabel.classList.add('text-xxs', 'font-medium');

        const fontFamilyInput = document.createElement('select');
        fontFamilyInput.className = 'w-full px-1 py-0.5 border rounded text-xxs';
        fontFamilyInput.onchange = (e) => {
            options.fontFamily = e.target.value;
            addCustomStyle();
        };

        const fonts = [
            'Arial, sans-serif',
            'Times New Roman, serif',
            'Verdana, sans-serif',
            'Georgia, serif',
            'Courier New, monospace',
            'Roboto, sans-serif',
            'Open Sans, sans-serif',
            'Lato, sans-serif',
            'Montserrat, sans-serif',
            'Poppins, sans-serif'
        ];
        fonts.forEach(font => {
            const option = document.createElement('option');
            option.value = font;
            option.textContent = font;
            option.selected = options.fontFamily === font;
            fontFamilyInput.appendChild(option);
        });

        // Bold functionality
        const fontBoldRow = document.createElement('div');
        fontBoldRow.classList.add('flex', 'items-center', 'justify-between');

        const fontBoldLabel = document.createElement('label');
        fontBoldLabel.textContent = 'Bold';
        fontBoldLabel.classList.add('text-xxs', 'font-medium');

        const fontBoldCheckbox = document.createElement('input');
        fontBoldCheckbox.type = 'checkbox';
        fontBoldCheckbox.checked = options.fontBold;
        fontBoldCheckbox.className = 'w-4 h-4 border rounded';
        fontBoldCheckbox.onchange = (e) => {
            options.fontBold = e.target.checked;
            addCustomStyle();
        };

        fontBoldRow.appendChild(fontBoldLabel);
        fontBoldRow.appendChild(fontBoldCheckbox);
        displaySettings.appendChild(fontBoldRow);

        fontFamilyRow.appendChild(fontFamilyLabel);
        fontFamilyRow.appendChild(fontFamilyInput);
        displaySettings.appendChild(fontFamilyRow);
        displaySettings.appendChild(fontBoldCheckbox);
        displaySettings.appendChild(fontBoldLabel);

        settingsContainer.appendChild(displaySettings);

        // Color Settings
        const colorSettings = document.createElement('div');
        colorSettings.classList.add('mb-2');

        const priceColorRow = document.createElement('div');
        priceColorRow.classList.add('flex', 'items-center', 'justify-between');

        const priceColorLabel = document.createElement('label');
        priceColorLabel.textContent = 'Price';
        priceColorLabel.classList.add('text-xxs', 'font-medium');

        const priceColorInput = document.createElement('input');
        priceColorInput.type = 'color';
        priceColorInput.value = options.priceColor;
        priceColorInput.className = 'w-5 h-5 border rounded-full';
        priceColorInput.onchange = (e) => {
            options.priceColor = e.target.value;
            addCustomStyle();
        };

        priceColorRow.appendChild(priceColorLabel);
        priceColorRow.appendChild(priceColorInput);
        colorSettings.appendChild(priceColorRow);

        const reviewsColorRow = document.createElement('div');
        reviewsColorRow.classList.add('flex', 'items-center', 'justify-between');

        const reviewsColorLabel = document.createElement('label');
        reviewsColorLabel.textContent = 'Reviews';
        reviewsColorLabel.classList.add('text-xxs', 'font-medium');

        const reviewsColorInput = document.createElement('input');
        reviewsColorInput.type = 'color';
        reviewsColorInput.value = options.reviewsColor;
        reviewsColorInput.className = 'w-5 h-5 border rounded-full';
        reviewsColorInput.onchange = (e) => {
            options.reviewsColor = e.target.value;
            addCustomStyle();
        };

        reviewsColorRow.appendChild(reviewsColorLabel);
        reviewsColorRow.appendChild(reviewsColorInput);
        colorSettings.appendChild(reviewsColorRow);

        const sellerColorRow = document.createElement('div');
        sellerColorRow.classList.add('flex', 'items-center', 'justify-between');

        const sellerColorLabel = document.createElement('label');
        sellerColorLabel.textContent = 'Seller';
        sellerColorLabel.classList.add('text-xxs', 'font-medium');

        const sellerColorInput = document.createElement('input');
        sellerColorInput.type = 'color';
        sellerColorInput.value = options.sellerColor;
        sellerColorInput.className = 'w-5 h-5 border rounded-full';
        sellerColorInput.onchange = (e) => {
            options.sellerColor = e.target.value;
            addCustomStyle();
        };

        sellerColorRow.appendChild(sellerColorLabel);
        sellerColorRow.appendChild(sellerColorInput);
        colorSettings.appendChild(sellerColorRow);

        settingsContainer.appendChild(colorSettings);

        // Global Glow Settings
        const glowSettings = document.createElement('div');
        glowSettings.classList.add('mb-2');

        const glowColorRow = document.createElement('div');
        glowColorRow.classList.add('flex', 'items-center', 'justify-between');

        const glowColorLabel = document.createElement('label');
        glowColorLabel.textContent = 'Glow Color';
        glowColorLabel.classList.add('text-xxs', 'font-medium');

        const glowColorInput = document.createElement('input');
        glowColorInput.type = 'color';
        glowColorInput.value = options.glowColor;
        glowColorInput.className = 'w-5 h-5 border rounded-full';
        glowColorInput.onchange = (e) => {
            options.glowColor = e.target.value;
            GM_setValue('glowColor', options.glowColor); // Save to memory
            addCustomStyle();
        };
        const glowColor = options.glowColor || '#ff00ff';
        const glowIntensity = options.glowIntensity || 0.5;
        const isBold = options.isBold ? 'bold' : 'normal';
        const fontColor = options.fontColor || '#000000';

        const style = document.createElement('style');
        style.innerHTML = `
        .price-display, .rating-display, .seller-display {
            text-shadow: 0 0 ${glowIntensity * 10}px ${glowColor}; /* Apply glow */
            color: ${fontColor}; /* Apply font color */
            font-weight: ${isBold}; /* Apply bold if set */
        }
    `;
        document.head.appendChild(style);
        addCustomStyle();

        const glowIntensityInput = document.createElement('input');
        glowIntensityInput.type = 'range';
        glowIntensityInput.min = 0;
        glowIntensityInput.max = 1;
        glowIntensityInput.step = 0.01;
        glowIntensityInput.value = options.glowIntensity;
        glowIntensityInput.className = 'w-full';
        glowIntensityInput.onchange = (e) => {
            options.glowIntensity = parseFloat(e.target.value);
            GM_setValue('glowIntensity', options.glowIntensity); // Save to memory
            addCustomStyle();
        };

        const glowIntensityLabel = document.createElement('label');
        glowIntensityLabel.textContent = 'Glow Intensity';
        glowIntensityLabel.classList.add('text-xxs', 'font-medium');

        glowColorRow.appendChild(glowColorLabel);
        glowColorRow.appendChild(glowColorInput);
        glowSettings.appendChild(glowColorRow);
        glowSettings.appendChild(glowIntensityLabel);
        glowSettings.appendChild(glowIntensityInput);

        settingsContainer.appendChild(glowSettings);

        const buttonsContainer = document.createElement('div');
        buttonsContainer.classList.add('flex', 'justify-end', 'space-x-2');

        const saveButton = document.createElement('button');
        saveButton.className = 'bg-blue-500 hover:bg-blue-600 text-white font-medium py-0.5 px-2 rounded text-xxs';
        saveButton.textContent = 'Close';
        saveButton.onclick = () => {
            options.fontSize = `${fontSizeInput.value}px`;
            options.fontFamily = fontFamilyInput.value;
            options.fontBold = fontBoldCheckbox.checked;
            options.priceColor = priceColorInput.value;
            options.reviewsColor = reviewsColorInput.value;
            options.sellerColor = sellerColorInput.value;
            options.glowColor = GM_getValue('glowColor', '#ff00ff'); // Default glow color
            options.glowIntensity = GM_getValue('glowIntensity', 0.5); // Default glow intensity
            options.isBold = GM_getValue('isBold', false); // Default bold setting (false = not bold)
            options.fontColor = GM_getValue('fontColor', '#000000'); // Default font color


            Object.keys(options).forEach(key => {
                GM_setValue(key, options[key]);
            });

            addCustomStyle();
            document.body.removeChild(settingsOverlay);
        };



        buttonsContainer.appendChild(saveButton);
        settingsContainer.appendChild(buttonsContainer);

        const settingsOverlay = document.createElement('div');
        settingsOverlay.className = 'settings-overlay';
        settingsOverlay.appendChild(settingsContainer);
        settingsOverlay.style.backgroundColor = 'transparent'; // Ensure it's transparent
        document.body.appendChild(settingsOverlay);
    }

    function getCurrencySymbol(currency) {
        const symbols = {
            'USD': '$ ',
            'EUR': '€ ',
            'GBP': '£ ',
            'NIS': '₪ ',
            'JPY': '¥ '
        };
        return symbols[currency] || '';
    }

    async function fetchPriceAndRating(url, retries = 0) {
        try {
            const response = await new Promise((resolve, reject) => {
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: url,
                    timeout: 5000,
                    onload: resolve,
                    onerror: reject,
                    ontimeout: reject
                });
            });

            const parser = new DOMParser();
            const doc = parser.parseFromString(response.responseText, 'text/html');
            const priceElement = doc.querySelector('.a-price .a-offscreen');
            let price = priceElement ? priceElement.textContent.trim() : 'No price found';

            if (options.currency !== 'default') {
                price = `${getCurrencySymbol(options.currency)} ${price.replace(/[^\d.]/g, '')}`;
            }

            const ratingElement = doc.querySelector('.a-icon-alt');
            let rating = ratingElement ? ratingElement.textContent : 'No rating found';
            const numberOfRatingsElement = doc.querySelector('#acrCustomerReviewText');
            let numberOfRatings = numberOfRatingsElement ? numberOfRatingsElement.textContent : '0 ratings';

            return { price, rating, numberOfRatings };
        } catch (error) {
            if (retries < MAX_RETRIES) {
                await new Promise(resolve => setTimeout(resolve, RETRY_DELAY));
                return fetchPriceAndRating(url, retries + 1);
            }
            return { price: 'Error fetching price', rating: 'Error fetching rating', numberOfRatings: 'Error fetching ratings' };
        }
    }

    async function fetchPriceRatingAndSeller(url, retries = 0) {
        try {
            const response = await new Promise((resolve, reject) => {
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: url,
                    timeout: 5000,
                    onload: resolve,
                    onerror: reject,
                    ontimeout: reject
                });
            });

            const parser = new DOMParser();
            const doc = parser.parseFromString(response.responseText, 'text/html');

            const priceElement = doc.querySelector('.a-price .a-offscreen');
            let price = priceElement ? priceElement.textContent.trim() : 'No price found';

            if (options.currency !== 'default') {
                price = `${getCurrencySymbol(options.currency)} ${price.replace(/[^\d.]/g, '')}`;
            }

            const ratingElement = doc.querySelector('.a-icon-alt');
            let rating = ratingElement ? ratingElement.textContent : 'No rating found';

            const numberOfRatingsElement = doc.querySelector('#acrCustomerReviewText');
            let numberOfRatings = numberOfRatingsElement ? numberOfRatingsElement.textContent : '0 ratings';

            const sellerElement = doc.querySelector('#sellerProfileTriggerId');
            let sellerName = sellerElement ? sellerElement.textContent.trim() : 'Seller info not available';

            return { price, rating, numberOfRatings, sellerName };
        } catch (error) {
            if (retries < MAX_RETRIES) {
                await new Promise(resolve => setTimeout(resolve, RETRY_DELAY));
                return fetchPriceRatingAndSeller(url, retries + 1);
            }
            return { price: 'Error fetching price', rating: 'Error fetching rating', numberOfRatings: 'Error fetching ratings', sellerName: 'Error fetching seller' };
        }
    }

    async function displayPriceRatingAndSeller(link) {
        const existingDisplay = link.nextElementSibling;
        if (existingDisplay && existingDisplay.classList.contains('price-display-container')) return;

        const parentContainer = document.createElement('div');
        parentContainer.className = 'price-link-container';
        link.parentNode.insertBefore(parentContainer, link);
        parentContainer.appendChild(link);

        const container = document.createElement('div');
        container.className = 'price-display-container loading';
        container.style.border = options.showFrame ? `0.1px solid ${options.frameColor}` : 'none';
        container.style.padding = '0.1em';

        const priceDisplay = document.createElement('div');
        priceDisplay.className = 'price-display';
        priceDisplay.textContent = 'Loading price...';

        const ratingDisplay = document.createElement('div');
        ratingDisplay.className = 'rating-display';
        ratingDisplay.textContent = 'Loading rating...';

        const sellerDisplay = document.createElement('div');
        sellerDisplay.className = 'seller-display';
        sellerDisplay.textContent = 'Loading seller...';

        container.appendChild(priceDisplay);
        container.appendChild(ratingDisplay);
        container.appendChild(sellerDisplay);
        parentContainer.appendChild(container);

        try {
            await new Promise(resolve => setTimeout(resolve, options.loadDelay));
            const { price, rating, numberOfRatings, sellerName } = await fetchPriceRatingAndSeller(link.href);

            priceDisplay.textContent = price;
            ratingDisplay.textContent = `${rating} (${numberOfRatings})`;
            sellerDisplay.textContent = `Seller: ${sellerName}`;

            priceDisplay.classList.remove('loading');
            ratingDisplay.classList.remove('loading');
            sellerDisplay.classList.remove('loading');

            if (options.enableNotifications && price !== 'No price found' && price !== 'Error fetching price') {
                alert(`Price fetched: ${price}`);
            }
        } catch (error) {
            console.error('Failed to fetch price and rating', error);
        }
    }

    function setupPriceAndRatingDisplay() {
        const productLinks = document.querySelectorAll('a[href*="/dp/"]');
        productLinks.forEach(link => displayPriceRatingAndSeller(link));
    }

    addCustomStyle();
    setupPriceAndRatingDisplay();

    // Register the command for settings
    GM_registerMenuCommand('Amazon Price Loader Settings', createSettingsUI);

    // MutationObserver to monitor changes on the page
    const observer = new MutationObserver(setupPriceAndRatingDisplay);
    observer.observe(document.body, { childList: true, subtree: true });
})();