Filter Items by Price on Dead Frontier

Filter items on the Dead Frontier market page by user-defined price range and category

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Filter Items by Price on Dead Frontier
// @namespace    http://tampermonkey.net/
// @version      0.9.1
// @description  Filter items on the Dead Frontier market page by user-defined price range and category
// @author       Diabetus
// @match        https://fairview.deadfrontier.com/onlinezombiemmo/index.php?page=35
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Function to validate price input
    function validatePriceInput(price) {
        const priceRegex = /^\$\d{1,3}(,\d{3})*$/; // Matches $ and commas in the correct format
        return priceRegex.test(price);
    }

    // Function to parse price string into a number
    function parsePrice(priceString) {
        return parseInt(priceString.replace(/[^0-9]/g, ''), 10);
    }

    // Function to filter items by price range
    function filterByPriceRange(minPrice, maxPrice) {
        const items = document.querySelectorAll('.fakeItem');

        items.forEach(item => {
            const salePriceElement = item.querySelector('.salePrice');

            if (salePriceElement) {
                const priceText = salePriceElement.textContent.trim();

                if (validatePriceInput(priceText)) {
                    const price = parsePrice(priceText);

                    if (price < minPrice || price > maxPrice) {
                        item.style.display = 'none';
                    } else {
                        item.style.display = '';
                    }
                }
            }
        });
    }

    // Function to filter items by food type
    function filterByFoodType(type) {
        const items = document.querySelectorAll('.fakeItem');

        items.forEach(item => {
            const itemType = item.getAttribute('data-type');

            if (itemType) {
                if (type === 'cooked' && !itemType.includes('_cooked')) {
                    item.style.display = 'none';
                } else if (type === 'uncooked' && itemType.includes('_cooked')) {
                    item.style.display = 'none';
                } else {
                    item.style.display = '';
                }
            }
        });
    }

    // Function to reset visibility for all food items
    function resetAllFoodItems() {
        const items = document.querySelectorAll('.fakeItem');

        items.forEach(item => {
            const itemType = item.getAttribute('data-type');

            if (itemType && itemType.includes('food')) {
                item.style.display = '';
            }
        });
    }

 // Function to filter items by affordability
    function filterByAffordability() {
        const cashElement = document.querySelector('.heldCash');
        const heldCash = parsePrice(cashElement.getAttribute('data-cash'));

        const items = document.querySelectorAll('.fakeItem');
        items.forEach(item => {
            const salePriceElement = item.querySelector('.salePrice');

            if (salePriceElement) {
                const priceText = salePriceElement.textContent.trim();
                const price = validatePriceInput(priceText) ? parsePrice(priceText) : Infinity;

                if (price > heldCash) {
                    item.style.display = 'none';
                } else {
                    item.style.display = '';
                }
            }
        });
    }

    // Function to toggle food options visibility based on category
    function toggleFoodOptionsVisibility() {
        const foodOptions = document.querySelectorAll('[name="foodType"], label[for="cookedFood"], label[for="uncookedFood"], label[for="bothFood"]');
        const currentCategory = document.querySelector('#categoryChoice')?.getAttribute('data-catname');

        if (currentCategory === 'food') {
            foodOptions.forEach(option => {
                option.style.display = '';
            });
        } else {
            foodOptions.forEach(option => {
                option.style.display = 'none';
            });
        }
    }

 // Function to create and display the UI
    function createFilterUI() {
        const uiContainer = document.createElement('div');
        uiContainer.style.position = 'fixed';
        uiContainer.style.top = '10px';
        uiContainer.style.right = '10px';
        uiContainer.style.backgroundColor = 'grey';
        uiContainer.style.border = '1px solid #ccc';
        uiContainer.style.padding = '10px';
        uiContainer.style.zIndex = '9999';

        uiContainer.innerHTML = `
            <label for="minPrice" style="color: red;">Min Price:</label>
            <input id="minPrice" type="text" placeholder="$0">
            <br>
            <label for="maxPrice" style="color: red;">Max Price:</label>
            <input id="maxPrice" type="text" placeholder="$1,000,000">
            <br>
            <input type="checkbox" id="hideUnaffordable" name="hideUnaffordable"> <label for="hideUnaffordable" style="color: red;">Hide Items You Can't Afford</label>
            <button id="applyFilter">Apply Filter</button>
            <p id="errorMessage" style="color: red; display: none;">Invalid price format. Use "$1,000" format.</p>
            <br>
            <label name="foodType" style="color: red;">Food Type:</label><br>
            <input type="radio" id="cookedFood" name="foodType" value="cooked"> <label for="cookedFood">Cooked Food</label><br>
            <input type="radio" id="uncookedFood" name="foodType" value="uncooked"> <label for="uncookedFood">Uncooked Food</label><br>
            <input type="radio" id="bothFood" name="foodType" value="both" checked> <label for="bothFood">Both</label><br>
        `;

        document.body.appendChild(uiContainer);

        const minPriceInput = document.getElementById('minPrice');
        const maxPriceInput = document.getElementById('maxPrice');
        const applyFilterButton = document.getElementById('applyFilter');
        const errorMessage = document.getElementById('errorMessage');
        const cookedFoodRadio = document.getElementById('cookedFood');
        const uncookedFoodRadio = document.getElementById('uncookedFood');
        const bothFoodRadio = document.getElementById('bothFood');
        const hideUnaffordableCheckbox = document.getElementById('hideUnaffordable');

        // Automatically filter food type when radio buttons are clicked
        cookedFoodRadio.addEventListener('change', () => {
            if (cookedFoodRadio.checked) filterByFoodType('cooked');
        });

        uncookedFoodRadio.addEventListener('change', () => {
            if (uncookedFoodRadio.checked) filterByFoodType('uncooked');
        });

        bothFoodRadio.addEventListener('change', () => {
            if (bothFoodRadio.checked) resetAllFoodItems();
        });


        applyFilterButton.addEventListener('click', () => {
            const minPriceText = minPriceInput.value.trim();
            const maxPriceText = maxPriceInput.value.trim();

            if ((minPriceText && validatePriceInput(minPriceText)) || (maxPriceText && validatePriceInput(maxPriceText)) || hideUnaffordableCheckbox.checked) {
                errorMessage.style.display = 'none';

                const minPrice = minPriceText && validatePriceInput(minPriceText) ? parsePrice(minPriceText) : 0;
                const maxPrice = maxPriceText && validatePriceInput(maxPriceText) ? parsePrice(maxPriceText) : Infinity;

                filterByPriceRange(minPrice, maxPrice);

            } else {
                errorMessage.style.display = 'block';
            }
        });

        hideUnaffordableCheckbox.addEventListener('change', () => {
            if (hideUnaffordableCheckbox.checked) {
                filterByAffordability();
            } else {
                filterByPriceRange(0, Infinity); // Reset to show all items within the current range
            }
        });

        // Toggle food options visibility based on category
        toggleFoodOptionsVisibility();

        // Observe category changes
        const observer = new MutationObserver(toggleFoodOptionsVisibility);
        observer.observe(document.querySelector('#categoryChoice'), { attributes: true });
    }

    // Initialize the script
    window.addEventListener('load', () => {
        createFilterUI();
    });
})();