ecsa

为csp的素材商店网页-收藏及下载页面 增加“按素材类型/购买时间排序”按钮和按素材类型筛选快捷菜单 Support sorting and filtering on clip studio assets favourites/download page

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

  1. // ==UserScript==
  2. // @name ecsa
  3. // @namespace boni
  4. // @version 1.01
  5. // @description 为csp的素材商店网页-收藏及下载页面 增加“按素材类型/购买时间排序”按钮和按素材类型筛选快捷菜单 Support sorting and filtering on clip studio assets favourites/download 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 getAllText = ()=>{
  15.  
  16. if (window.location.href.includes("starred")) {
  17.  
  18. // Find the first <a> element inside the .btn-group.selectFilter
  19. const selectFilter = document.querySelector('.btn-group.selectFilter');
  20. if (selectFilter) {
  21. const firstOption = selectFilter.querySelector('a');
  22. if (firstOption) {
  23. const firstOptionText = firstOption.textContent.trim();
  24. console.log(firstOptionText);
  25. return firstOptionText
  26. }
  27. }
  28. } else {
  29.  
  30. // Find the <ul> element inside the .dropdown.selectFilter
  31. const dropdown = document.querySelector('.dropdown.selectFilter');
  32. if (dropdown) {
  33. const ul = dropdown.querySelector('ul.dropdown-menu');
  34. if (ul) {
  35. const firstOption = ul.querySelector('li:first-child a');
  36. if (firstOption) {
  37. const firstOptionText = firstOption.textContent.trim();
  38. console.log(firstOptionText);
  39. return firstOptionText
  40. }
  41. }
  42. }
  43.  
  44. }
  45.  
  46. }
  47.  
  48. // Define liElementsByType in the global scope
  49. const liElementsByType = {};
  50. let container = document.querySelector("ul.layput__cardPanel");
  51. let sortAsset = false;
  52. let orig = container.innerHTML;
  53. let types = []
  54. let allText = getAllText()
  55. const toggleSort = (sort) => {
  56. if (sort) {
  57. // Clear the existing content on the page
  58. container.innerHTML = '';
  59. // Sort the <li> elements by type value (custom sorting logic)
  60. const sortedTypes = Object.keys(liElementsByType).sort();
  61. // Reconstruct the sorted list of <li> elements
  62. const sortedLiElements = [];
  63. sortedTypes.forEach((type) => {
  64. sortedLiElements.push(...liElementsByType[type]);
  65. });
  66. // Append the sorted <li> elements back to the container
  67. sortedLiElements.forEach((li) => {
  68. container.appendChild(li);
  69. });
  70. } else {
  71. container.innerHTML = orig;
  72. }
  73. }
  74. // Function to sort the <li> elements by type
  75. const sortAssets = () => {
  76. const liElements = document.querySelectorAll("li.materialCard");
  77. liElements.forEach((li) => {
  78. const materialTypeLink = li.querySelector("a[href*='/search?type=']");
  79. if (materialTypeLink) {
  80. const type = materialTypeLink.textContent.trim(); // Get the text content of the <a> tag
  81. if (!types.includes(type)) {
  82. types.push(type)
  83. }
  84. if (type) {
  85. if (!liElementsByType[type]) {
  86. liElementsByType[type] = [];
  87. }
  88. liElementsByType[type].push(li);
  89. }
  90. }
  91. });
  92. // Find the existing button element
  93. const existingButton = document.querySelector(".btn.btn-default.operationButton.favoriteButton");
  94. if (existingButton) {
  95. // Create a new button element
  96. const newButton = document.createElement("button");
  97. newButton.type = "button";
  98. newButton.className = "btn btn-primary "; // You can adjust the class as needed
  99. newButton.id = "sortButton";
  100. newButton.textContent = "按素材类型排序";
  101. newButton.style.marginLeft = '10px'
  102. //fa fa-filter
  103.  
  104. // Add an event listener to the new button if needed
  105. newButton.addEventListener("click", function() {
  106. // Handle button click event
  107. sortAsset = !sortAsset
  108. newButton.textContent = sortAsset ? "按购买时间排序" : "按素材类型排序";
  109. toggleSort(sortAsset)
  110. });
  111. // Insert the new button after the existing button
  112. existingButton.parentNode.insertBefore(newButton, existingButton.nextSibling);
  113. // Example usage:
  114. const options = [...types];
  115. options.unshift(allText)
  116. const dropdown = createDropdown(options);
  117. existingButton.parentNode.insertBefore(dropdown, newButton.nextSibling);
  118. }
  119. };
  120. // Create a function to generate the dropdown HTML
  121. function createDropdown(types) {
  122. const dropdown = document.createElement("div");
  123. dropdown.className = "dropdown selectFilter ";
  124. dropdown.style.display = 'inline-block'
  125. dropdown.style.marginLeft = '10px'
  126. dropdown.style.marginTop = '0px'
  127.  
  128. const button = document.createElement("button");
  129. button.className = "btn btn-default dropdown-toggle filterButton";
  130. button.type = "button";
  131. button.setAttribute("data-toggle", "dropdown");
  132. button.setAttribute("aria-haspopup", "true");
  133. button.setAttribute("aria-expanded", "true");
  134. button.textContent = types[0]; // Set the default text
  135. button.style.borderRadius = '0px'
  136. button.style.textAlign = 'left'
  137. const caret = document.createElement("span");
  138. caret.className = "caret";
  139. caret.style.position = "absolute";
  140.  
  141. if (window.location.href.includes("starred")) {
  142. // The URL contains "starred"
  143. caret.style.top = "15px"
  144. } else {
  145. // The URL does not contain "starred"
  146.  
  147. }
  148.  
  149.  
  150.  
  151. caret.style.right = "10px";
  152. const ul = document.createElement("ul");
  153. ul.className = "dropdown-menu";
  154. // Create options from the 'types' array
  155. types.forEach((type) => {
  156. const li = document.createElement("li");
  157. const a = document.createElement("a");
  158. a.textContent = type;
  159. li.appendChild(a);
  160. ul.appendChild(li);
  161. li.addEventListener("click", function(event) {
  162. // Prevent the default behavior of following the link (if it's an anchor)
  163. event.preventDefault();
  164. container.innerHTML = '';
  165. // Enable or disable the new button based on the selected option
  166. const sortButton = document.getElementById("sortButton");
  167. sortButton.disabled = type !== allText;
  168. button.firstChild.textContent = type;
  169. if (sortAsset) {
  170. sortAsset = !sortAsset
  171. sortButton.textContent = sortAsset ? "按购买时间排序" : "按素材类型排序";
  172. }
  173. if (type !== allText) {
  174. liElementsByType[type].forEach((li) => {
  175. container.appendChild(li);
  176. });
  177. } else {
  178. container.innerHTML = orig;
  179. }
  180. });
  181. });
  182. // Append elements to the dropdown
  183. button.appendChild(caret);
  184. dropdown.appendChild(button);
  185. dropdown.appendChild(ul);
  186. return dropdown;
  187. }
  188.  
  189. // Wait for the page to fully load before executing the sorting function
  190. window.onload = function() {
  191. sortAssets();
  192. };
  193. })();