ecsa

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

目前為 2023-11-20 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         ecsa
// @namespace    boni
// @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
// @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();
    };
})();