ecsa

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

当前为 2024-12-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @author Boni
  3. // @name ecsa
  4. // @name:ko ecsa
  5. // @namespace https://greasyfork.org/en/scripts/476919-ecsa
  6. // @version 1.10
  7. // @description 为csp的素材商店网页-我的下载和收藏页面 增加“按素材类型排序”和按素材类型筛选快捷按钮
  8. // @match https://assets.clip-studio.com/*/download-list
  9. // @match https://assets.clip-studio.com/*/download-list?*
  10. // @match https://assets.clip-studio.com/*/starred*
  11. // @grant none
  12. // @license GPL-3.0-only
  13. // @description:zh 为csp的素材商店网页-我的下载和收藏页面 增加“按素材类型排序”和按素材类型筛选快捷按钮
  14. // @description:en Support sorting and filtering on Clip Studio Assets favorites and downloads page
  15. // @description:ja Clip Studio Assetsのマイリストとマイダウンロードページでのソートとフィルタリングをサポート
  16. // @description:de Für die Favoriten und Downloads Seite von Clip Studio Assets Unterstützung für das Sortieren und Filtern hinzufügen
  17. // @description:es Agregar soporte para ordenar y filtrar en la página de favoritos y descargas de Clip Studio Assets
  18. // @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
  19. // @description:ko Clip Studio Assets의 즐겨찾기 및 다운로드 페이지에서 정렬 및 필터링 지원
  20. // ==/UserScript==
  21.  
  22. (function() {
  23. 'use strict';
  24. const getSortBtnLabel = () => {
  25. // Get the current URL
  26. const currentURL = window.location.href;
  27. const withoutProtocol = currentURL.replace("https://", "");
  28. // Split by "/"
  29. const urlSegments = withoutProtocol.split("/");
  30. // Get the first part
  31. const lang = urlSegments[1];
  32. const translations = {
  33. "zh-tw": {
  34. category: "按素材类别排序",
  35. time: "按默认顺序排序",
  36. },
  37. "ja-jp": {
  38. category: "素材タイプ別に並べ替え",
  39. time: "デフォルトの順序別に並べ替え",
  40. },
  41. "en-us": {
  42. category: "Sort by Category",
  43. time: "Sort in Default Order",
  44. },
  45. "de-de": {
  46. category: "Nach Kategorie sortieren",
  47. time: "In der Standardreihenfolge sortieren",
  48. },
  49. "es-es": {
  50. category: "Ordenar por categoría",
  51. time: "Ordenar en el orden predeterminado",
  52. },
  53. "fr-fr": {
  54. category: "Trier par catégorie",
  55. time: "Trier dans l'ordre par défaut"
  56. },
  57. "ko-kr": {
  58. category: "카테고리별 정렬",
  59. time: "기본 순서로 정렬"
  60. }
  61. };
  62. return translations[lang]
  63. }
  64. // text for "all" option
  65. const getAllText = () => {
  66. if (window.location.href.includes("starred")) {
  67. // Find the first <a> element inside the .btn-group.selectFilter
  68. const selectFilter = document.querySelector('.btn-group.selectFilter');
  69. if (selectFilter) {
  70. const firstOption = selectFilter.querySelector('a');
  71. if (firstOption) {
  72. const firstOptionText = firstOption.textContent.trim();
  73. return firstOptionText
  74. }
  75. }
  76. } else {
  77. // Find the <ul> element inside the .dropdown.selectFilter
  78. const dropdown = document.querySelector('.dropdown.selectFilter');
  79. if (dropdown) {
  80. const ul = dropdown.querySelector('ul.dropdown-menu');
  81. if (ul) {
  82. const firstOption = ul.querySelector('li:first-child a');
  83. if (firstOption) {
  84. const firstOptionText = firstOption.textContent.trim();
  85. return firstOptionText
  86. }
  87. }
  88. }
  89. }
  90. }
  91. // Define liElementsByType in the global scope
  92. const liElementsByType = {};
  93. let container = document.querySelector("ul.layput__cardPanel");
  94. let sortAsset = false;
  95. let orig = container.innerHTML;
  96. let types = []
  97. let allText = getAllText()
  98. let sortBtnText = getSortBtnLabel()
  99. let currentLocation = ''
  100. if (window.location.href.includes("starred")) {
  101. currentLocation = 's'
  102. } else {
  103. currentLocation = 'd'
  104. }
  105.  
  106.  
  107. const toggleSort = (sort) => {
  108. // Set a value in localStorage
  109. localStorage.setItem( currentLocation +'sorted', sort === true ? 1 : 0);
  110. sortAsset = sort
  111. const sortButton = document.getElementById("sortButton");
  112. sortButton.textContent = sortAsset ? sortBtnText.time : sortBtnText.category;
  113. // sortButton.disabled = type !== allText;
  114. if (sort) {
  115. // Clear the existing content on the page
  116. container.innerHTML = '';
  117. // Sort the <li> elements by type value (custom sorting logic)
  118. const sortedTypes = Object.keys(liElementsByType).sort();
  119. // Reconstruct the sorted list of <li> elements
  120. const sortedLiElements = [];
  121. sortedTypes.forEach((type) => {
  122. sortedLiElements.push(...liElementsByType[type]);
  123. });
  124. // Append the sorted <li> elements back to the container
  125. sortedLiElements.forEach((li) => {
  126. container.appendChild(li);
  127. });
  128. } else {
  129. container.innerHTML = orig;
  130. }
  131. }
  132. // Function to sort the <li> elements by type
  133. const preprocessAssets = () => {
  134. const liElements = document.querySelectorAll("li.materialCard");
  135. liElements.forEach((li) => {
  136. const materialTypeLink = li.querySelector("a[href*='/search?type=']");
  137. if (materialTypeLink) {
  138. const type = materialTypeLink.textContent.trim(); // Get the text content of the <a> tag
  139. if (!types.includes(type)) {
  140. types.push(type)
  141. }
  142. if (type) {
  143. if (!liElementsByType[type]) {
  144. liElementsByType[type] = [];
  145. }
  146. liElementsByType[type].push(li);
  147. }
  148. }
  149. });
  150. // Find the existing button element
  151. const existingButton = document.querySelector(".btn.btn-default.operationButton.favoriteButton");
  152. if (existingButton) {
  153. // Create a new button element
  154. const sortButton = document.createElement("button");
  155. sortButton.type = "button";
  156. sortButton.className = "btn btn-primary ";
  157. sortButton.id = "sortButton";
  158. sortButton.textContent = sortBtnText.category;
  159. sortButton.style.marginLeft = '10px'
  160. // Add an event listener to the new button if needed
  161. sortButton.addEventListener("click", function() {
  162. // Handle button click event
  163. sortAsset = !sortAsset
  164. sortButton.textContent = sortAsset ? sortBtnText.time : sortBtnText.category;
  165. toggleSort(sortAsset)
  166. });
  167. // Insert the new button after the existing button
  168. existingButton.parentNode.insertBefore(sortButton, existingButton.nextSibling);
  169. const options = [...types];
  170. options.unshift(allText)
  171. const dropdown = createDropdown(options);
  172. existingButton.parentNode.insertBefore(dropdown, sortButton.nextSibling);
  173. }
  174. const filterBtn = document.getElementById("filterButton");
  175. if(filterBtn.textContent === getAllText()) {
  176. // Read a value from localStorage
  177. const sorted = localStorage.getItem(currentLocation + 'sorted');
  178. // Check if the value exists
  179. if (sorted == 1) {
  180. // Use the value
  181. toggleSort(true)
  182. } else {
  183. }
  184. }
  185. };
  186. // Create a function to generate the dropdown HTML
  187. function createDropdown(types) {
  188. const dropdown = document.createElement("div");
  189. dropdown.className = "dropdown selectFilter ";
  190. dropdown.style.display = 'inline-block'
  191. dropdown.style.marginLeft = '10px'
  192. dropdown.style.marginTop = '0px'
  193. const button = document.createElement("button");
  194. button.className = "btn btn-default dropdown-toggle filterButton";
  195. button.id = "filterButton"
  196. button.type = "button";
  197. button.style.width = 'auto';
  198. button.style.minWidth = 'fit-content';
  199. button.style.paddingRight = '20px';
  200.  
  201. button.setAttribute("data-toggle", "dropdown");
  202. button.setAttribute("aria-haspopup", "true");
  203. button.setAttribute("aria-expanded", "true");
  204. const filterOption = localStorage.getItem(currentLocation + 'filtered');
  205.  
  206. // set sort button text but only allow change when 'all' option is selected
  207. const sorted = localStorage.getItem(currentLocation +'sorted');
  208. //sortButton.textContent = sorted ? sortBtnText.time : sortBtnText.category;
  209. // toggleSort()
  210.  
  211. if(types.includes(filterOption) && filterOption !== getAllText()){
  212. const sortButton = document.getElementById("sortButton");
  213.  
  214. // sortButton.textContent = sorted ? sortBtnText.time : sortBtnText.category;
  215. sortButton.disabled = true
  216. button.textContent =filterOption
  217. container.innerHTML = '';
  218. liElementsByType[filterOption].forEach((li) => {
  219. container.appendChild(li);
  220. });
  221. } else {
  222.  
  223. button.textContent = types[0]; // Set the default text
  224.  
  225. }
  226. button.style.borderRadius = '0px'
  227. button.style.textAlign = 'left'
  228. const caret = document.createElement("span");
  229. caret.className = "caret";
  230. caret.style.position = "absolute";
  231. if (window.location.href.includes("starred")) {
  232. // The URL contains "starred"
  233. caret.style.top = "15px"
  234. } else {
  235. // The URL does not contain "starred"
  236. }
  237. caret.style.right = "10px";
  238. const ul = document.createElement("ul");
  239. ul.className = "dropdown-menu";
  240. // Create options from the 'types' array
  241. types.forEach((type) => {
  242. const li = document.createElement("li");
  243. const a = document.createElement("a");
  244. a.textContent = type;
  245. li.appendChild(a);
  246. ul.appendChild(li);
  247. li.addEventListener("click", function(event) {
  248. localStorage.setItem(currentLocation + 'filtered', type);
  249. // Prevent the default behavior of following the link (if it's an anchor)
  250. event.preventDefault();
  251. container.innerHTML = '';
  252. // Enable or disable the new button based on the selected option
  253. const sortButton = document.getElementById("sortButton");
  254. sortButton.disabled = type !== allText;
  255. button.firstChild.textContent = type;
  256. const h4Element = document.querySelector("h4.text-right");
  257. if (type !== allText) {
  258. liElementsByType[type].forEach((li) => {
  259. container.appendChild(li);
  260. });
  261. localStorage.setItem(currentLocation +'filtered', type);
  262. } else {
  263. container.innerHTML = orig;
  264. const sorted = localStorage.getItem(currentLocation + 'sorted');
  265. // Check if the value exists
  266. if (sorted == 1) {
  267. // Use the value
  268. toggleSort(true)
  269. } else {
  270. }
  271. }
  272. });
  273. });
  274. // Append elements to the dropdown
  275. button.appendChild(caret);
  276. dropdown.appendChild(button);
  277. dropdown.appendChild(ul);
  278. return dropdown;
  279. }
  280. // Wait for the page to fully load before executing the sorting function
  281. window.onload = function() {
  282. preprocessAssets();
  283. };
  284. })();