Add non-MFC figure

Track preordered non-MFC items on collection screen

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

  1. // ==UserScript==
  2. // @name Add non-MFC figure
  3. // @namespace https://tharglet.me.uk
  4. // @version 1.7
  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 sortType = urlParams.get("sort") || "category";
  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. $('.listing-link-toggle.on .count').text(totalFigureCount);
  111. $('.listing-count-value').get(0).lastChild.nodeValue = `${totalFigureCount} items`;
  112. //Pre-add setup
  113. const addList = $("#nonMfcFigureList");
  114. let dateHeadings;
  115. if(sortType == "groupByReleaseDates") {
  116. if(output === "0") {
  117. dateHeadings = $("li.listing-title");
  118. } else {
  119. dateHeadings = $(".listing-item h3");
  120.  
  121. }
  122. } else if(sortType.startsWith("groupBy")) {
  123. if(output === "0") {
  124. $(".listing-toggles:last").after('<li id="nonMfcAdditions" class="listing-title">Non-MFC</li>');
  125. } else {
  126. $(".listing-item .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='listing-item 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(sortType == "groupByReleaseDates") {
  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="listing-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(sortType.startsWith("groupBy")) {
  184. if(output === "0") {
  185. $("#nonMfcAdditions").after(linkLine)
  186. } else {
  187. $("#nonMfcAdditions h3").after(figureThumb);
  188. }
  189. } else {
  190. if(output === "0") {
  191. $(".listing-toggles:last").after(linkLine);
  192. } else {
  193. $(".listing-item .item-icons").prepend(figureThumb);
  194. }
  195. }
  196. });
  197. $('.non-mfc-item__delete').click((evt) => {
  198. evt.preventDefault();
  199. if(confirm("Delete this figure?")) {
  200. additionalFigures.splice($(evt.target).attr("data-index"), 1);
  201. additionalFigures.sort((a, b) => (a.date < b.date) ? 1 : -1);
  202. GM_setValue("additionalFigures", JSON.stringify(additionalFigures));
  203. drawAdditionalFigures();
  204. resetNonMfcItemForm();
  205. }
  206. });
  207. $('.non-mfc-item__edit').click((evt) => {
  208. evt.preventDefault();
  209. var figToEdit = additionalFigures[$(evt.target).attr("data-index")];
  210. $("#non-mfc-item__form-title").text(`Editing ${figToEdit.name}`);
  211. $("#addNonMfcItem").text("Edit");
  212. $("#nonMfcItemEditId").val($(evt.target).attr("data-index"));
  213. $("#nonMfcItemName").val(figToEdit.name);
  214. $("#nonMfcItemImage").val(figToEdit.image);
  215. $("#nonMfcItemLink").val(figToEdit.link);
  216. $("#nonMfcItemReleaseDate").val(figToEdit.date);
  217. $([document.documentElement, document.body]).animate({
  218. scrollTop: $("#non-mfc-item__section").offset().top - 100
  219. }, 200);
  220. });
  221. $("#cancelNonMfcItem").click((evt) => {
  222. evt.preventDefault();
  223. if(confirm("Are you sure you want to cancel?")) {
  224. resetNonMfcItemForm();
  225. }
  226. });
  227. }
  228. }
  229.  
  230. $().ready(() => {
  231. BASE_COUNT = parseInt($('.listing-link-toggle.on .count').text());
  232. if(isUsersPreorderPage()) {
  233. const addSection = `<section id='non-mfc-item__section'>
  234. <h2 id='non-mfc-item__form-title'>Add non-MFC figure</h2>
  235. <div class='form'>
  236. <input type='hidden' id='nonMfcItemEditId' value=''/>
  237. <div class='bigchar form-field'>
  238. <div class='form-label'>Figure name</div>
  239. <div class='form-input'><input type='text' id='nonMfcItemName'/></div>
  240. </div>
  241. <div class='bigchar form-field'>
  242. <div class='form-label'>Image URL *</div>
  243. <div class='form-input'><input type='text' id='nonMfcItemImage'/></div>
  244. </div>
  245. <div class='bigchar form-field'>
  246. <div class='form-label'>Item link *</div>
  247. <div class='form-input'><input type='text' id='nonMfcItemLink'/></div>
  248. </div>
  249. <div class='bigchar form-field'>
  250. <div class='form-label'>Release date (YYYY-MM) *</div>
  251. <div class='form-input'><input type='text' id='nonMfcItemReleaseDate'/></div>
  252. </div>
  253. <div class='form-field'>
  254. <div class='form-input'>
  255. <button id='addNonMfcItem'>Add</button>
  256. <button id='cancelNonMfcItem'>Cancel</button>
  257. </div>
  258. </div>
  259. </div>
  260. </section>
  261. <section>
  262. <h2>Added non-MFC figures</h2>
  263. <div class='form'>
  264. <div id='nonMfcFigureList' class='item-icons'>
  265. </div>
  266. </div>
  267. </section>`
  268. $("#side section:last").after(addSection);
  269. drawAdditionalFigures();
  270. $("#addNonMfcItem").click((e) => {
  271. e.preventDefault();
  272. const name = $("#nonMfcItemName").val() || "Non-MFC figure";
  273. const image = $("#nonMfcItemImage").val();
  274. const link = $("#nonMfcItemLink").val();
  275. const date = $("#nonMfcItemReleaseDate").val();
  276. const editId = $("#nonMfcItemEditId").val();
  277. if(image && link && date && name) {
  278. if(date.match(/^\d{4}-0[1-9]|1[0-2]$/)) {
  279. if(editId) {
  280. additionalFigures[editId] = {
  281. name: name,
  282. image: image,
  283. link: link,
  284. date: date
  285. }
  286. } else {
  287. additionalFigures.push({
  288. name: name,
  289. image: image,
  290. link: link,
  291. date: date
  292. });
  293. }
  294. additionalFigures.sort((a, b) => (a.date < b.date) ? 1 : -1);
  295. GM_setValue("additionalFigures", JSON.stringify(additionalFigures));
  296. drawAdditionalFigures();
  297. resetNonMfcItemForm();
  298. } else {
  299. alert("Please enter a valid date in YYYY-MM format");
  300. }
  301. } else {
  302. alert("Please fill in all mandatory fields");
  303. }
  304. });
  305. }
  306. });
  307.  
  308. })();