A Chrome extension that gives you finer control over MyAnimeList.net scores
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

331 lignes
11 KiB

  1. /* Constants */
  2. var MAX_BUCKETS = 256;
  3. var LOADING_IMG = '<img src="http://cdn.myanimelist.net/images/xmlhttp-loader.gif" align="center">';
  4. /* Miscellaneous functions */
  5. function get_anime_id_from_href(href) {
  6. var anime_id;
  7. if (href.indexOf("/anime/") != -1)
  8. anime_id = href.substr(href.indexOf("/anime/") + "/anime/".length);
  9. else
  10. anime_id = href.substr(href.indexOf("id=") + "id=".length);
  11. if (anime_id.indexOf("/") != -1)
  12. anime_id = anime_id.substr(0, anime_id.indexOf("/"));
  13. if (anime_id.indexOf("&") != -1)
  14. anime_id = anime_id.substr(0, anime_id.indexOf("&"));
  15. return anime_id;
  16. }
  17. function get_edit_id_from_href(href) {
  18. var anime_id = href.substr(href.indexOf("id=") + "id=".length);
  19. if (anime_id.indexOf("&") != -1)
  20. anime_id = anime_id.substr(0, anime_id.indexOf("&"));
  21. return anime_id;
  22. }
  23. function get_scores_from_element(elem) {
  24. var score_100 = parseInt(elem.val());
  25. var score_10 = Math.round(score_100 / 10.);
  26. if (isNaN(score_100) || score_100 < 1 || score_100 > 100) {
  27. alert("Invalid score: must be an integer between 1 and 100.");
  28. return null;
  29. }
  30. return [score_100, score_10];
  31. }
  32. /* Storage functions */
  33. function save_score(anime_id, score) {
  34. var bucket_id = (parseInt(anime_id) % MAX_BUCKETS).toString();
  35. chrome.storage.sync.get(bucket_id, function(data) {
  36. var bucket = data[bucket_id];
  37. if (bucket === undefined)
  38. bucket = data[bucket_id] = {};
  39. bucket[anime_id] = score;
  40. chrome.storage.sync.set(data);
  41. });
  42. }
  43. function retrieve_scores(anime_id, callback) {
  44. var bucket_id = null;
  45. if (anime_id !== null)
  46. bucket_id = (parseInt(anime_id) % MAX_BUCKETS).toString();
  47. chrome.storage.sync.get(bucket_id, function(data) {
  48. if (anime_id !== null) {
  49. var bucket = data[bucket_id];
  50. if (bucket !== undefined && bucket[anime_id] !== undefined)
  51. callback(bucket[anime_id]);
  52. else
  53. callback(null);
  54. }
  55. else
  56. callback(data);
  57. });
  58. }
  59. function remove_score(anime_id) {
  60. var bucket_id = (parseInt(anime_id) % MAX_BUCKETS).toString();
  61. chrome.storage.sync.get(bucket_id, function(data) {
  62. var bucket = data[bucket_id];
  63. if (bucket === undefined || bucket[anime_id] === undefined)
  64. return;
  65. delete bucket[anime_id];
  66. if ($.isEmptyObject(bucket))
  67. chrome.storage.sync.remove(bucket_id);
  68. else
  69. chrome.storage.sync.set(data);
  70. });
  71. }
  72. /* Event patches/injections */
  73. function update_list_score(anime_id) {
  74. var new_scores = get_scores_from_element($("#scoretext" + anime_id));
  75. if (new_scores === null)
  76. return;
  77. var new_score_100 = new_scores[0], new_score_10 = new_scores[1];
  78. var payload = {id: anime_id, score: new_score_10};
  79. $("#scorebutton" + anime_id).prop("disabled", true);
  80. $.post("/includes/ajax.inc.php?t=63", payload, function(data) {
  81. $("#scoreval" + anime_id).text(new_score_100);
  82. $("#scoretext" + anime_id).val("");
  83. $("#scorediv" + anime_id).css("display", "none");
  84. $("#scorebutton" + anime_id).prop("disabled", false);
  85. });
  86. save_score(anime_id, new_score_100);
  87. }
  88. function update_anime_score(anime_id, is_new) {
  89. var new_scores = get_scores_from_element($("#myinfo_score"));
  90. if (new_scores === null)
  91. return;
  92. var new_score_100 = new_scores[0], new_score_10 = new_scores[1];
  93. var t_id, payload = {score: new_score_10};
  94. payload["status"] = $("#myinfo_status").val();
  95. payload["epsseen"] = $("#myinfo_watchedeps").val();
  96. if (is_new) {
  97. payload["aid"] = anime_id;
  98. t_id = "61";
  99. }
  100. else {
  101. payload["alistid"] = anime_id;
  102. payload["aid"] = $("#myinfo_anime_id").val();
  103. payload["astatus"] = $("#myinfo_curstatus").val();
  104. t_id = "62";
  105. }
  106. $("#myinfoDisplay").html(LOADING_IMG);
  107. $.post("/includes/ajax.inc.php?t=" + t_id, payload, function(data) {
  108. if (is_new) {
  109. document.getElementById("myinfoDisplay").innerHTML = "";
  110. document.getElementById("addtolist").innerHTML = data;
  111. }
  112. else
  113. document.getElementById("myinfoDisplay").innerHTML = data;
  114. });
  115. save_score(anime_id, new_score_100);
  116. }
  117. function submit_add_form(submit_button) {
  118. var anime_id = $("input[name='series_title']").val();
  119. if (!anime_id)
  120. return submit_button[0].click();
  121. var new_scores = get_scores_from_element($("#score_input"));
  122. if (new_scores === null)
  123. return;
  124. var new_score_100 = new_scores[0], new_score_10 = new_scores[1];
  125. $("select[name='score']").val(new_score_10);
  126. save_score(anime_id, new_score_100);
  127. submit_button[0].click();
  128. }
  129. function submit_edit_form(anime_id, submit_type, submit_button) {
  130. if (submit_type == 2) {
  131. var new_scores = get_scores_from_element($("#score_input"));
  132. if (new_scores === null)
  133. return;
  134. var new_score_100 = new_scores[0], new_score_10 = new_scores[1];
  135. $("select[name='score']").val(new_score_10);
  136. save_score(anime_id, new_score_100);
  137. }
  138. else if (submit_type == 3)
  139. remove_score(anime_id);
  140. submit_button[0].click();
  141. }
  142. /* Extension hooks */
  143. function hook_list() {
  144. retrieve_scores(null, function(data) {
  145. $("span[id^='scoreval']").each(function(i, elem) {
  146. var anime_id = elem.id.split("scoreval")[1];
  147. var bucket_id = (parseInt(anime_id) % MAX_BUCKETS).toString();
  148. var bucket = data[bucket_id];
  149. if (bucket !== undefined && bucket[anime_id] !== undefined)
  150. $(elem).text(bucket[anime_id]);
  151. else {
  152. var current = parseInt($(elem).text());
  153. if (!isNaN(current))
  154. $(elem).text(current * 10);
  155. }
  156. $("#scorediv" + anime_id)
  157. .after($("<div>")
  158. .attr("id", "scorediv" + anime_id)
  159. .css("display", "none")
  160. .append($('<input>')
  161. .attr("type", "text")
  162. .attr("id", "scoretext" + anime_id)
  163. .attr("size", "2")
  164. .keydown(function(a_id) {
  165. return function(ev) {
  166. if ((window.event ? window.event.keyCode : ev.which) == 13)
  167. update_list_score(a_id);
  168. else
  169. return true;
  170. }
  171. }(anime_id)))
  172. .append($("<input>")
  173. .attr("type", "button")
  174. .attr("id", "scorebutton" + anime_id)
  175. .attr("value", "Go")
  176. .click(function(a_id) {
  177. return function() { return update_list_score(a_id); }
  178. }(anime_id))))
  179. .remove();
  180. });
  181. });
  182. }
  183. function hook_anime(anime_id) {
  184. retrieve_scores(anime_id, function(score) {
  185. var old_input = $("#myinfo_score");
  186. var old_button = $("input[name='myinfo_submit']");
  187. var is_new = old_button.attr("value") == "Add";
  188. if (!is_new && score === null) {
  189. var old_score = parseInt(old_input.val());
  190. score = old_score == 0 ? "" : old_score * 10;
  191. }
  192. old_input.after($("<span> / 100</span>"))
  193. .after($("<input>")
  194. .attr("type", "text")
  195. .attr("id", "myinfo_score")
  196. .attr("name", "myinfo_score")
  197. .attr("class", "inputtext")
  198. .attr("value", (score === null) ? "" : score)
  199. .attr("size", "3"))
  200. .remove();
  201. old_button.after($("<input>")
  202. .attr("type", "button")
  203. .attr("name", "myinfo_submit")
  204. .attr("value", old_button.attr("value"))
  205. .attr("class", "inputButton")
  206. .click(function(a_id, is_new) {
  207. return function() { return update_anime_score(a_id, is_new); }
  208. }(anime_id, is_new)))
  209. .remove();
  210. });
  211. }
  212. function hook_add() {
  213. var old_input = $("select[name='score']");
  214. var old_submit = $("input[type='button'][onclick='checkValidSubmit(1)']");
  215. old_input.after($("<span> / 100</span>"))
  216. .after($("<input>")
  217. .attr("type", "text")
  218. .attr("id", "score_input")
  219. .attr("class", "inputtext")
  220. .attr("size", "3"))
  221. .hide();
  222. old_submit.after($("<input>")
  223. .attr("type", "button")
  224. .attr("class", "inputButton")
  225. .attr("style", old_submit.attr("style"))
  226. .attr("value", old_submit.attr("value"))
  227. .click(function(button) {
  228. return function() { return submit_add_form(button); }
  229. }(old_submit)))
  230. .hide();
  231. }
  232. function hook_edit(anime_id) {
  233. retrieve_scores(anime_id, function(score) {
  234. var old_input = $("select[name='score']");
  235. var old_edit = $("input[type='button'][onclick='checkValidSubmit(2)']");
  236. var old_delete = $("input[type='button'][onclick='checkValidSubmit(3)']");
  237. if (score === null) {
  238. var old_score = parseInt(old_input.val());
  239. score = old_score == 0 ? "" : old_score * 10;
  240. }
  241. old_input.after($("<span> / 100</span>"))
  242. .after($("<input>")
  243. .attr("type", "text")
  244. .attr("id", "score_input")
  245. .attr("class", "inputtext")
  246. .attr("value", score)
  247. .attr("size", "3"))
  248. .hide();
  249. old_edit.after($("<input>")
  250. .attr("type", "button")
  251. .attr("class", "inputButton")
  252. .attr("style", old_edit.attr("style"))
  253. .attr("value", old_edit.attr("value"))
  254. .click(function(a_id, button) {
  255. return function() { return submit_edit_form(a_id, 2, button); }
  256. }(anime_id, old_edit)))
  257. .hide();
  258. old_delete.after($("<input>")
  259. .attr("type", "button")
  260. .attr("class", "inputButton")
  261. .attr("value", old_delete.attr("value"))
  262. .click(function(a_id, button) {
  263. return function() { return submit_edit_form(a_id, 3, button); }
  264. }(anime_id, old_delete)))
  265. .hide();
  266. });
  267. }
  268. function hook_addtolist() {
  269. /* TODO: this entry point is unimplemented - it's rarely used and difficult
  270. to inject into, so I'm avoiding it for now. */
  271. }
  272. /* Main extension hook */
  273. $(document).ready(function() {
  274. var href = window.location.href;
  275. if (href.indexOf("/animelist/") != -1)
  276. hook_list();
  277. else if (href.indexOf("/anime/") != -1 || href.indexOf("/anime.php") != -1)
  278. hook_anime(get_anime_id_from_href(href));
  279. else if (href.indexOf("/panel.php") != -1 && href.indexOf("go=add") != -1)
  280. hook_add();
  281. else if (href.indexOf("/editlist.php") != -1 && href.indexOf("type=anime") != -1)
  282. hook_edit(get_edit_id_from_href(href));
  283. else if (href.indexOf("/addtolist.php") != -1)
  284. hook_addtolist();
  285. });