ecsa

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

当前为 2023-10-16 提交的版本,查看 最新版本

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