Greasy Fork 还支持 简体中文。

Add non-MFC figure

Track preordered non-MFC items on collection screen

目前為 2023-04-07 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Add non-MFC figure
  3. // @namespace https://tharglet.me.uk
  4. // @version 1.10
  5. // @description Track preordered non-MFC items on collection screen
  6. // @author Tharglet
  7. // @match https://myfigurecollection.net/users.v4.php?*mode=view&*tab=collection&*
  8. // @grant GM_addStyle
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // ==/UserScript==
  12.  
  13. //Polyfill for GM_addStyle for Greasemonkey...
  14. if(typeof GM_addStyle == 'undefined') {
  15. GM_addStyle = (aCss) => {
  16. 'use strict';
  17. let head = document.getElementsByTagName('head')[0];
  18. if (head) {
  19. let style = document.createElement('style');
  20. style.setAttribute('type', 'text/css');
  21. style.textContent = aCss;
  22. head.appendChild(style);
  23. return style;
  24. }
  25. return null;
  26. };
  27. }
  28.  
  29. GM_addStyle(`
  30. .non-mfc-item__tray-icon {
  31. border: green 1px solid;
  32. display: block;
  33. margin: 8px;
  34. padding: 1px;
  35. }
  36. .non-mfc-item__icon-container {
  37. float: left;
  38. margin-bottom: 20px;
  39. }
  40. .non-mfc-item__tray-icon img {
  41. width: 60px;
  42. height: 60px;
  43. border-radius: 2px;
  44. }
  45. .non-mfc-item__edit, .non-mfc-item__delete {
  46. display: inline-block;
  47. }
  48.  
  49. .non-mfc-item__edit span, .non-mfc-item__delete span {
  50. font-size: 16px;
  51. margin: 0 4px;
  52. }
  53. `);
  54.  
  55. (function() {
  56. 'use strict';
  57. let BASE_COUNT = 0;
  58. var isUsersPreorderPage = () => {
  59. const urlParams = new URLSearchParams(window.location.search);
  60. const status = urlParams.get("status");
  61. if(status == 1) {
  62. let loggedInUser = $(".user-menu .handle");
  63. if(loggedInUser) {
  64. let userLink = loggedInUser.attr("href");
  65. if(userLink === "/session/signup") {
  66. return false;
  67. } else {
  68. let userParam;
  69. const windowLocation = window.location.href;
  70. if(windowLocation.startsWith("https://myfigurecollection.net/profile/")) {
  71. userParam = windowLocation.match(/https:\/\/myfigurecollection\.net\/profile\/([^\/]*)/)[1];
  72. } else {
  73. const urlParams = new URLSearchParams(window.location.search);
  74. userParam = urlParams.get("username");
  75. }
  76. return userParam === userLink.substring("9");
  77. }
  78. } else {
  79. return false;
  80. }
  81. } else {
  82. return false;
  83. }
  84. };
  85.  
  86. var additionalFigures = JSON.parse(GM_getValue("additionalFigures", "[]"));
  87. var resetNonMfcItemForm = () => {
  88. $("#non-mfc-item__form-title").text('Add non-MFC figure');
  89. $("#addNonMfcItem").text("Add");
  90. $("#nonMfcItemEditId").val("");
  91. $("#nonMfcItemName").val("");
  92. $("#nonMfcItemImage").val("");
  93. $("#nonMfcItemLink").val("");
  94. $("#nonMfcItemReleaseDate").val("");
  95. }
  96.  
  97. var drawAdditionalFigures = () => {
  98. const urlParams = new URLSearchParams(window.location.search);
  99. const groupBy = urlParams.get("groupBy");
  100. const output = urlParams.get("output");
  101. //Clear all additions before redo
  102. $("#nonMfcAdditions").remove();
  103. $(".non-mfc-item__icon").remove();
  104. $(".non-mfc-item__edit").remove();
  105. $(".non-mfc-item__delete").remove();
  106. $(".non-mfc-item__year-header").remove();
  107. if(additionalFigures.length > 0) {
  108. //update item count
  109. let totalFigureCount = BASE_COUNT + additionalFigures.length;
  110. $('.result-link-toggle.on .count').text(totalFigureCount);
  111. $('.results-count-value').get(0).lastChild.nodeValue = `${totalFigureCount} items`;
  112. //Pre-add setup
  113. const addList = $("#nonMfcFigureList");
  114. let dateHeadings;
  115. if(groupBy == "releaseDates") {
  116. if(output === "0") {
  117. dateHeadings = $("div.results-title");
  118. } else {
  119. dateHeadings = $(".item-group-by h3");
  120.  
  121. }
  122. } else if(!!groupBy) {
  123. if(output === "0") {
  124. $(".results-toggles:last").after('<li id="nonMfcAdditions" class="results-title">Non-MFC</li>');
  125. } else {
  126. $(".result .item-icons").prepend('<div class="item-group-by" id="nonMfcAdditions"><h3>Non-MFC</h3></div>');
  127. }
  128.  
  129. }
  130. //Add icons to page and delete box
  131. additionalFigures.forEach((fig, idx) => {
  132. let linkLine;
  133. const figYear = fig.date.substring(0, 4);
  134. const figMonth = fig.date.substring(5);
  135. const figureThumb = `<span class="non-mfc-item__icon item-icon">
  136. <a href="${fig.link}" class="tbx-tooltip item-root-0 item-category-1">
  137. <img src="${fig.image}">
  138. </a>
  139. </span>`;
  140. if(output === "0") {
  141. linkLine = `<div class='result non-mfc-item__icon'><div class="stamp item-stamp">
  142. <a href="/item/872779" class="tbx-tooltip">
  143. <img class="stamp-icon" src="${fig.image}"</a><div class="stamp-anchor"><a class="tbx-tooltip item-category-1" href="${fig.link}">${fig.name}</a>
  144. </div></div></div>`
  145. }
  146. addList.append(`<span class='non-mfc-item__icon-container'>
  147. ${figureThumb.replace('item-icon', 'non-mfc-item__tray-icon')}
  148. <a href="#" class='non-mfc-item__edit' title="Edit" data-index="${idx}"><span class="tiny-icon-only icon-pencil-square-o" data-index="${idx}"></span></a>
  149. <a href="#" class='non-mfc-item__delete' title="Delete" data-index="${idx}"><span class="tiny-icon-only icon-trash-o" data-index="${idx}"></span></a>
  150. </span>`);
  151. let toAppend = true;
  152. if(groupBy == "releaseDates") {
  153. dateHeadings.each((idx, heading) => {
  154. if(toAppend) {
  155. const headingYear = $(heading).text().substring(0,4);
  156. const headingMonth = $(heading).text().substring(5);
  157. if(figYear == headingYear && figMonth == headingMonth) {
  158. if(output === "0") {
  159. $(heading).after(linkLine);
  160. } else {
  161. $(heading).after(figureThumb);
  162. }
  163. toAppend = false;
  164. } else if(new Date(figYear, figMonth, 1) > new Date(headingYear, headingMonth, 1)) {
  165. if(output === "0") {
  166. const newHeading = `<li class="results-title non-mfc-item__year-header" id='nhi_${idx}'>${figYear}-${figMonth}</li></h3>`
  167. $(heading).before(newHeading + linkLine);
  168. } else {
  169. const newHeading = `<h3 class="non-mfc-item__year-header" id='nhi_${idx}'>${figYear}-${figMonth}</h3>`
  170. $(heading).before(newHeading + figureThumb);
  171. }
  172. dateHeadings.splice(idx, 0, $(`#nhi_${idx}`));
  173. toAppend = false;
  174. }
  175. }
  176. });
  177. //Append if trailing
  178. if(toAppend) {
  179. const newHeading = `<h3 class="non-mfc-item__year-header" id='nhi_${idx}'>${figYear}-${figMonth}</h3>`
  180. $('.item-group-by:last').after('<div class="item-group-by">' + newHeading + figureThumb + '</div>');
  181. dateHeadings.push($(`#nhi_${idx}`));
  182. }
  183. } else if(!!groupBy) {
  184. if(output === "0") {
  185. console.log("moop");
  186. $("#nonMfcAdditions").after(linkLine)
  187. } else {
  188. $("#nonMfcAdditions h3").after(figureThumb);
  189. }
  190. } else {
  191. if(output === "0") {
  192. console.log("moop2");
  193. $(".results-toggles:last").after(linkLine);
  194. } else {
  195. $(".result .item-icons").prepend(figureThumb);
  196. }
  197. }
  198. });
  199. $('.non-mfc-item__delete').click((evt) => {
  200. evt.preventDefault();
  201. if(confirm("Delete this figure?")) {
  202. additionalFigures.splice($(evt.target).attr("data-index"), 1);
  203. additionalFigures.sort((a, b) => (a.date < b.date) ? 1 : -1);
  204. GM_setValue("additionalFigures", JSON.stringify(additionalFigures));
  205. drawAdditionalFigures();
  206. resetNonMfcItemForm();
  207. }
  208. });
  209. $('.non-mfc-item__edit').click((evt) => {
  210. evt.preventDefault();
  211. var figToEdit = additionalFigures[$(evt.target).attr("data-index")];
  212. $("#non-mfc-item__form-title").text(`Editing ${figToEdit.name}`);
  213. $("#addNonMfcItem").text("Edit");
  214. $("#nonMfcItemEditId").val($(evt.target).attr("data-index"));
  215. $("#nonMfcItemName").val(figToEdit.name);
  216. $("#nonMfcItemImage").val(figToEdit.image);
  217. $("#nonMfcItemLink").val(figToEdit.link);
  218. $("#nonMfcItemReleaseDate").val(figToEdit.date);
  219. $([document.documentElement, document.body]).animate({
  220. scrollTop: $("#non-mfc-item__section").offset().top - 100
  221. }, 200);
  222. });
  223. $("#cancelNonMfcItem").click((evt) => {
  224. evt.preventDefault();
  225. if(confirm("Are you sure you want to cancel?")) {
  226. resetNonMfcItemForm();
  227. }
  228. });
  229. }
  230. }
  231.  
  232. $().ready(() => {
  233. BASE_COUNT = parseInt($('.result-link-toggle.on .count').text());
  234. if(isUsersPreorderPage()) {
  235. const addSection = `<section id='non-mfc-item__section'>
  236. <h2 id='non-mfc-item__form-title'>Add non-MFC figure</h2>
  237. <div class='form'>
  238. <input type='hidden' id='nonMfcItemEditId' value=''/>
  239. <div class='bigchar form-field'>
  240. <div class='form-label'>Figure name</div>
  241. <div class='form-input'><input type='text' id='nonMfcItemName'/></div>
  242. </div>
  243. <div class='bigchar form-field'>
  244. <div class='form-label'>Image URL *</div>
  245. <div class='form-input'><input type='text' id='nonMfcItemImage'/></div>
  246. </div>
  247. <div class='bigchar form-field'>
  248. <div class='form-label'>Item link *</div>
  249. <div class='form-input'><input type='text' id='nonMfcItemLink'/></div>
  250. </div>
  251. <div class='bigchar form-field'>
  252. <div class='form-label'>Release date (YYYY-MM) *</div>
  253. <div class='form-input'><input type='text' id='nonMfcItemReleaseDate'/></div>
  254. </div>
  255. <div class='form-field'>
  256. <div class='form-input'>
  257. <button id='addNonMfcItem'>Add</button>
  258. <button id='cancelNonMfcItem'>Cancel</button>
  259. </div>
  260. </div>
  261. </div>
  262. </section>
  263. <section>
  264. <h2>Added non-MFC figures</h2>
  265. <div class='form'>
  266. <div id='nonMfcFigureList' class='item-icons'>
  267. </div>
  268. </div>
  269. </section>`
  270. $("#side section:last").after(addSection);
  271. drawAdditionalFigures();
  272. $("#addNonMfcItem").click((e) => {
  273. e.preventDefault();
  274. const name = $("#nonMfcItemName").val() || "Non-MFC figure";
  275. const image = $("#nonMfcItemImage").val();
  276. const link = $("#nonMfcItemLink").val();
  277. const date = $("#nonMfcItemReleaseDate").val();
  278. const editId = $("#nonMfcItemEditId").val();
  279. if(image && link && date && name) {
  280. if(date.match(/^\d{4}-0[1-9]|1[0-2]$/)) {
  281. if(editId) {
  282. additionalFigures[editId] = {
  283. name: name,
  284. image: image,
  285. link: link,
  286. date: date
  287. }
  288. } else {
  289. additionalFigures.push({
  290. name: name,
  291. image: image,
  292. link: link,
  293. date: date
  294. });
  295. }
  296. additionalFigures.sort((a, b) => (a.date < b.date) ? 1 : -1);
  297. GM_setValue("additionalFigures", JSON.stringify(additionalFigures));
  298. drawAdditionalFigures();
  299. resetNonMfcItemForm();
  300. } else {
  301. alert("Please enter a valid date in YYYY-MM format");
  302. }
  303. } else {
  304. alert("Please fill in all mandatory fields");
  305. }
  306. });
  307. }
  308. });
  309.  
  310. })();