ecsa

为csp的素材商店网页-收藏及下载页面增加“按素材类型排序”和按素材类型筛选快捷按钮 Support sorting and filtering on clip studio assets downloads & favorites page

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

  1. // ==UserScript==
  2. // @name ecsa
  3. // @namespace boni
  4. // @version 1.02
  5. // @description 为csp的素材商店网页-收藏及下载页面增加“按素材类型排序”和按素材类型筛选快捷按钮 Support sorting and filtering on clip studio assets downloads & favorites page
  6. // @match https://assets.clip-studio.com/*/download-list*
  7. // @match https://assets.clip-studio.com/*/starred*
  8. // @grant none
  9. // @license GPL-3.0-only
  10. // ==/UserScript==
  11. (function() {
  12. 'use strict';
  13.  
  14. const getButtonText = ()=>{
  15.  
  16. // Get the current URL
  17. const currentURL = window.location.href;
  18.  
  19. const withoutProtocol = currentURL.replace("https://", "");
  20.  
  21. // Split by "/"
  22. const urlSegments = withoutProtocol.split("/");
  23.  
  24. // Get the first part
  25. const lang = urlSegments[1];
  26.  
  27. const translations = {
  28. "zh-tw":{
  29. category: "按素材类别排序",
  30. time: "按下载时间排序",
  31. },
  32. "ja-jp": {
  33. category: "素材タイプ別に並べ替え",
  34. time: "ダウンロード時間別に並べ替え",
  35. },
  36. "en-us": {
  37. category: "Sort by Category",
  38. time: "Sort by Download Time"
  39. },
  40. "de-de": {
  41. category: "Nach Kategorie sortieren",
  42. time: "Nach Download-Zeit sortieren"
  43. },
  44. "es-es": {
  45. category: "Ordenar por categoría",
  46. time: "Ordenar por tiempo de descarga"
  47. },
  48. "fr-fr": {
  49. category: "Trier par catégorie",
  50. time: "Trier par heure de téléchargement"
  51. },
  52. "ko-kr": {
  53. category: "카테고리별 정렬",
  54. time: "다운로드 시간별 정렬"
  55. }
  56. };
  57.  
  58. return translations[lang]
  59. }
  60.  
  61. const getAllText = ()=>{
  62.  
  63. if (window.location.href.includes("starred")) {
  64.  
  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.  
  76. // Find the <ul> element inside the .dropdown.selectFilter
  77. const dropdown = document.querySelector('.dropdown.selectFilter');
  78. if (dropdown) {
  79. const ul = dropdown.querySelector('ul.dropdown-menu');
  80. if (ul) {
  81. const firstOption = ul.querySelector('li:first-child a');
  82. if (firstOption) {
  83. const firstOptionText = firstOption.textContent.trim();
  84. return firstOptionText
  85. }
  86. }
  87. }
  88.  
  89. }
  90.  
  91. }
  92.  
  93. // Define liElementsByType in the global scope
  94. const liElementsByType = {};
  95. let container = document.querySelector("ul.layput__cardPanel");
  96. let sortAsset = false;
  97. let orig = container.innerHTML;
  98. let types = []
  99. let allText = getAllText()
  100. let sortBtnText = getButtonText()
  101.  
  102. const toggleSort = (sort) => {
  103. if (sort) {
  104. // Clear the existing content on the page
  105. container.innerHTML = '';
  106. // Sort the <li> elements by type value (custom sorting logic)
  107. const sortedTypes = Object.keys(liElementsByType).sort();
  108. // Reconstruct the sorted list of <li> elements
  109. const sortedLiElements = [];
  110. sortedTypes.forEach((type) => {
  111. sortedLiElements.push(...liElementsByType[type]);
  112. });
  113. // Append the sorted <li> elements back to the container
  114. sortedLiElements.forEach((li) => {
  115. container.appendChild(li);
  116. });
  117. } else {
  118. container.innerHTML = orig;
  119. }
  120. }
  121. // Function to sort the <li> elements by type
  122. const sortAssets = () => {
  123. const liElements = document.querySelectorAll("li.materialCard");
  124. liElements.forEach((li) => {
  125. const materialTypeLink = li.querySelector("a[href*='/search?type=']");
  126. if (materialTypeLink) {
  127. const type = materialTypeLink.textContent.trim(); // Get the text content of the <a> tag
  128. if (!types.includes(type)) {
  129. types.push(type)
  130. }
  131. if (type) {
  132. if (!liElementsByType[type]) {
  133. liElementsByType[type] = [];
  134. }
  135. liElementsByType[type].push(li);
  136. }
  137. }
  138. });
  139. // Find the existing button element
  140. const existingButton = document.querySelector(".btn.btn-default.operationButton.favoriteButton");
  141. if (existingButton) {
  142. // Create a new button element
  143. const sortButton = document.createElement("button");
  144. sortButton.type = "button";
  145. sortButton.className = "btn btn-primary "; // You can adjust the class as needed
  146. sortButton.id = "sortButton";
  147. sortButton.textContent = sortBtnText.category;
  148. sortButton.style.marginLeft = '10px'
  149. //fa fa-filter
  150.  
  151. // Add an event listener to the new button if needed
  152. sortButton.addEventListener("click", function() {
  153. // Handle button click event
  154. sortAsset = !sortAsset
  155. sortButton.textContent = sortAsset ? sortBtnText.time : sortBtnText.category;
  156. toggleSort(sortAsset)
  157. });
  158. // Insert the new button after the existing button
  159. existingButton.parentNode.insertBefore(sortButton, existingButton.nextSibling);
  160. // Example usage:
  161. const options = [...types];
  162. options.unshift(allText)
  163. const dropdown = createDropdown(options);
  164. existingButton.parentNode.insertBefore(dropdown, sortButton.nextSibling);
  165. }
  166. };
  167. // Create a function to generate the dropdown HTML
  168. function createDropdown(types) {
  169. const dropdown = document.createElement("div");
  170. dropdown.className = "dropdown selectFilter ";
  171. dropdown.style.display = 'inline-block'
  172. dropdown.style.marginLeft = '10px'
  173. dropdown.style.marginTop = '0px'
  174.  
  175. const button = document.createElement("button");
  176. button.className = "btn btn-default dropdown-toggle filterButton";
  177. button.type = "button";
  178. button.setAttribute("data-toggle", "dropdown");
  179. button.setAttribute("aria-haspopup", "true");
  180. button.setAttribute("aria-expanded", "true");
  181. button.textContent = types[0]; // Set the default text
  182. button.style.borderRadius = '0px'
  183. button.style.textAlign = 'left'
  184. const caret = document.createElement("span");
  185. caret.className = "caret";
  186. caret.style.position = "absolute";
  187.  
  188. if (window.location.href.includes("starred")) {
  189. // The URL contains "starred"
  190. caret.style.top = "15px"
  191. } else {
  192. // The URL does not contain "starred"
  193.  
  194. }
  195.  
  196.  
  197.  
  198. caret.style.right = "10px";
  199. const ul = document.createElement("ul");
  200. ul.className = "dropdown-menu";
  201. // Create options from the 'types' array
  202. types.forEach((type) => {
  203. const li = document.createElement("li");
  204. const a = document.createElement("a");
  205. a.textContent = type;
  206. li.appendChild(a);
  207. ul.appendChild(li);
  208. li.addEventListener("click", function(event) {
  209. // Prevent the default behavior of following the link (if it's an anchor)
  210. event.preventDefault();
  211. container.innerHTML = '';
  212. // Enable or disable the new button based on the selected option
  213. const sortButton = document.getElementById("sortButton");
  214. sortButton.disabled = type !== allText;
  215. button.firstChild.textContent = type;
  216. if (sortAsset) {
  217. sortAsset = !sortAsset
  218. sortButton.textContent = sortAsset ? sortBtnText.time : sortBtnText.category;
  219. }
  220. if (type !== allText) {
  221. liElementsByType[type].forEach((li) => {
  222. container.appendChild(li);
  223. });
  224. } else {
  225. container.innerHTML = orig;
  226. }
  227. });
  228. });
  229. // Append elements to the dropdown
  230. button.appendChild(caret);
  231. dropdown.appendChild(button);
  232. dropdown.appendChild(ul);
  233. return dropdown;
  234. }
  235.  
  236. // Wait for the page to fully load before executing the sorting function
  237. window.onload = function() {
  238. sortAssets();
  239. };
  240. })();