您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
为csp的素材商店网页-我的下载和收藏页面 增加“按素材类型排序”和按素材类型筛选快捷按钮
当前为
// ==UserScript== // @author Boni // @name 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 // @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(); }; })();