Greasy Fork is available in English.

ecsa

为csp的素材商店网页-我的下载和收藏页面 增加“按素材类型排序”和按素材类型筛选快捷按钮

// ==UserScript==
// @author	 Boni
// @name         ecsa
// @name:ko      ecsa
// @name:en      ecsa
// @namespace    https://greasyfork.org/en/scripts/476919-ecsa
// @version      1.10
// @description  为csp的素材商店网页-我的下载和收藏页面 增加“按素材类型排序”和按素材类型筛选快捷按钮
// @match        https://assets.clip-studio.com/*/download-list
// @match        https://assets.clip-studio.com/*/download-list?*
// @match        https://assets.clip-studio.com/*/starred*
// @grant        none
// @license      GPL-3.0-only
// @icon         https://www.google.com/s2/favicons?sz=64&domain=clip-studio.com
// @description:zh 为csp的素材商店网页-我的下载和收藏页面 增加“按素材类型排序”和按素材类型筛选快捷按钮
// @description:en Support sorting and filtering on Clip Studio Assets favorites and downloads page
// @description:ja Clip Studio Assetsのマイリストとマイダウンロードページでのソートとフィルタリングをサポート
// @description:de Für die Favoriten und Downloads Seite von Clip Studio Assets Unterstützung für das Sortieren und Filtern hinzufügen
// @description:es Agregar soporte para ordenar y filtrar en la página de favoritos y descargas de Clip Studio Assets
// @description:fr Ajouter la prise en charge du tri et du filtrage sur la page des favoris et des téléchargements de Clip Studio Assets
// @description:ko Clip Studio Assets의 즐겨찾기 및 다운로드 페이지에서 정렬 및 필터링 지원
// ==/UserScript==

(function() {
    'use strict';
    const getSortBtnLabel = () => {
        // Get the current URL
        const currentURL = window.location.href;
        const withoutProtocol = currentURL.replace("https://", "");
        // Split by "/"
        const urlSegments = withoutProtocol.split("/");
        // Get the first part
        const lang = urlSegments[1];
        const translations = {
            "zh-tw": {
                category: "按素材类别排序",
                time: "按默认顺序排序",
            },
            "ja-jp": {
                category: "素材タイプ別に並べ替え",
                time: "デフォルトの順序別に並べ替え",
            },
            "en-us": {
                category: "Sort by Category",
                time: "Sort in Default Order",
            },
            "de-de": {
                category: "Nach Kategorie sortieren",
                time: "In der Standardreihenfolge sortieren",
            },
            "es-es": {
                category: "Ordenar por categoría",
                time: "Ordenar en el orden predeterminado",
            },
            "fr-fr": {
                category: "Trier par catégorie",
                time: "Trier dans l'ordre par défaut"
            },
            "ko-kr": {
                category: "카테고리별 정렬",
                time: "기본 순서로 정렬"
            }
        };
        return translations[lang]
    }
    // text for "all" option
    const getAllText = () => {
        if (window.location.href.includes("starred")) {
            // Find the first <a> element inside the .btn-group.selectFilter
            const selectFilter = document.querySelector('.btn-group.selectFilter');
            if (selectFilter) {
                const firstOption = selectFilter.querySelector('a');
                if (firstOption) {
                    const firstOptionText = firstOption.textContent.trim();
                    return firstOptionText
                }
            }
        } else {
            // Find the <ul> element inside the .dropdown.selectFilter
            const dropdown = document.querySelector('.dropdown.selectFilter');
            if (dropdown) {
                const ul = dropdown.querySelector('ul.dropdown-menu');
                if (ul) {
                    const firstOption = ul.querySelector('li:first-child a');
                    if (firstOption) {
                        const firstOptionText = firstOption.textContent.trim();
                        return firstOptionText
                    }
                }
            }
        }
    }
    // Define liElementsByType in the global scope
    const liElementsByType = {};
    let container = document.querySelector("ul.layput__cardPanel");
    let sortAsset = false;
    let orig = container.innerHTML;
    let types = []
    let allText = getAllText()
    let sortBtnText = getSortBtnLabel()
    let currentLocation = ''
    if (window.location.href.includes("starred")) {
        currentLocation = 's'
    } else {
        currentLocation = 'd'
    }


    const toggleSort = (sort) => {
        // Set a value in localStorage
        localStorage.setItem( currentLocation +'sorted', sort === true ? 1 : 0);
        sortAsset = sort
        const sortButton = document.getElementById("sortButton");
        sortButton.textContent = sortAsset ? sortBtnText.time : sortBtnText.category;
        // sortButton.disabled = type !== allText;
        if (sort) {
            // Clear the existing content on the page
            container.innerHTML = '';
            // Sort the <li> elements by type value (custom sorting logic)
            const sortedTypes = Object.keys(liElementsByType).sort();
            // Reconstruct the sorted list of <li> elements
            const sortedLiElements = [];
            sortedTypes.forEach((type) => {
                sortedLiElements.push(...liElementsByType[type]);
            });
            // Append the sorted <li> elements back to the container
            sortedLiElements.forEach((li) => {
                container.appendChild(li);
            });
        } else {
            container.innerHTML = orig;
        }
    }
    // Function to sort the <li> elements by type
    const preprocessAssets = () => {
        const liElements = document.querySelectorAll("li.materialCard");
        liElements.forEach((li) => {
            const materialTypeLink = li.querySelector("a[href*='/search?type=']");
            if (materialTypeLink) {
                const type = materialTypeLink.textContent.trim(); // Get the text content of the <a> tag
                if (!types.includes(type)) {
                    types.push(type)
                }
                if (type) {
                    if (!liElementsByType[type]) {
                        liElementsByType[type] = [];
                    }
                    liElementsByType[type].push(li);
                }
            }
        });
        // Find the existing button element
        const existingButton = document.querySelector(".btn.btn-default.operationButton.favoriteButton");
        if (existingButton) {
            // Create a new button element
            const sortButton = document.createElement("button");
            sortButton.type = "button";
            sortButton.className = "btn btn-primary ";
            sortButton.id = "sortButton";
            sortButton.textContent = sortBtnText.category;
            sortButton.style.marginLeft = '10px'
            // Add an event listener to the new button if needed
            sortButton.addEventListener("click", function() {
                // Handle button click event
                sortAsset = !sortAsset
                sortButton.textContent = sortAsset ? sortBtnText.time : sortBtnText.category;
                toggleSort(sortAsset)
            });
            // Insert the new button after the existing button
            existingButton.parentNode.insertBefore(sortButton, existingButton.nextSibling);
            const options = [...types];
            options.unshift(allText)
            const dropdown = createDropdown(options);
            existingButton.parentNode.insertBefore(dropdown, sortButton.nextSibling);
        }
        const filterBtn = document.getElementById("filterButton");
        if(filterBtn.textContent === getAllText()) {
            // Read a value from localStorage
            const sorted = localStorage.getItem(currentLocation + 'sorted');
            // Check if the value exists
            if (sorted == 1) {
                // Use the value
                toggleSort(true)
            } else {
            }
        }
    };
    // Create a function to generate the dropdown HTML
    function createDropdown(types) {
        const dropdown = document.createElement("div");
        dropdown.className = "dropdown selectFilter ";
        dropdown.style.display = 'inline-block'
        dropdown.style.marginLeft = '10px'
        dropdown.style.marginTop = '0px'
        const button = document.createElement("button");
        button.className = "btn btn-default dropdown-toggle filterButton";
        button.id = "filterButton"
        button.type = "button";
        button.style.width = 'auto';
        button.style.minWidth = 'fit-content';
        button.style.paddingRight = '20px';

        button.setAttribute("data-toggle", "dropdown");
        button.setAttribute("aria-haspopup", "true");
        button.setAttribute("aria-expanded", "true");
        const filterOption = localStorage.getItem(currentLocation + 'filtered');

        //  set sort button text but only allow change when 'all' option is selected
        const sorted = localStorage.getItem(currentLocation +'sorted');
        //sortButton.textContent = sorted ? sortBtnText.time : sortBtnText.category;
        // toggleSort()

        if(types.includes(filterOption) && filterOption !== getAllText()){
            const sortButton = document.getElementById("sortButton");

            // sortButton.textContent = sorted ? sortBtnText.time : sortBtnText.category;
            sortButton.disabled = true
            button.textContent =filterOption
            container.innerHTML = '';
            liElementsByType[filterOption].forEach((li) => {
                container.appendChild(li);
            });
        } else {

            button.textContent = types[0]; // Set the default text

        }
        button.style.borderRadius = '0px'
        button.style.textAlign = 'left'
        const caret = document.createElement("span");
        caret.className = "caret";
        caret.style.position = "absolute";
        if (window.location.href.includes("starred")) {
            // The URL contains "starred"
            caret.style.top = "15px"
        } else {
            // The URL does not contain "starred"
        }
        caret.style.right = "10px";
        const ul = document.createElement("ul");
        ul.className = "dropdown-menu";
        // Create options from the 'types' array
        types.forEach((type) => {
            const li = document.createElement("li");
            const a = document.createElement("a");
            a.textContent = type;
            li.appendChild(a);
            ul.appendChild(li);
            li.addEventListener("click", function(event) {
                localStorage.setItem(currentLocation + 'filtered', type);
                // Prevent the default behavior of following the link (if it's an anchor)
                event.preventDefault();
                container.innerHTML = '';
                // Enable or disable the new button based on the selected option
                const sortButton = document.getElementById("sortButton");
                sortButton.disabled = type !== allText;
                button.firstChild.textContent = type;
                const h4Element = document.querySelector("h4.text-right");
                if (type !== allText) {
                    liElementsByType[type].forEach((li) => {
                        container.appendChild(li);
                    });
                    localStorage.setItem(currentLocation +'filtered', type);
                } else {
                    container.innerHTML = orig;
                    const sorted = localStorage.getItem(currentLocation + 'sorted');
                    // Check if the value exists
                    if (sorted == 1) {
                        // Use the value
                        toggleSort(true)
                    } else {
                    }
                }
            });
        });
        // Append elements to the dropdown
        button.appendChild(caret);
        dropdown.appendChild(button);
        dropdown.appendChild(ul);
        return dropdown;
    }
    // Wait for the page to fully load before executing the sorting function
    window.onload = function() {
        preprocessAssets();
    };
})();