IMDb List Helper

Makes creating IMDb lists more efficient and convenient

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

  1. // ==UserScript==
  2. // @name IMDb List Helper
  3. // @namespace imdb
  4. // @description Makes creating IMDb lists more efficient and convenient
  5. // @version 2.0
  6. // @include http://*imdb.com/list/edit*
  7. // ==/UserScript==
  8.  
  9. var jQuery = unsafeWindow.jQuery;
  10. var $ = jQuery;
  11.  
  12. //
  13. // CHANGELOG
  14. //
  15. // 2.0
  16. // added: import ratings
  17. // added: if regex doesn't match, skip entry
  18. //
  19. // 1.6.1.2
  20. // added: input text suggestion as a placeholder
  21. //
  22. // 1.6.1.1
  23. // fixed: some entries are skipped when adding imdb ids/urls
  24. //
  25.  
  26. //
  27. // milliseconds between each request
  28. //
  29. var REQUEST_DELAY = 1000;
  30.  
  31. var ListManager = {
  32. regex: "^(.*)$",
  33. processRegex: function(rx, cb) {
  34. var filmTitle = rx[1];
  35. cb(filmTitle);
  36. },
  37. handleSelection: function(imdbId, cb) {
  38. cb();
  39. }
  40. };
  41.  
  42. var RatingManager = {
  43. rating: 0,
  44. regex: "^([1-9]{1}|10),(.*)$",
  45. processRegex: function(rx, cb) {
  46. RatingManager.rating = rx[1];
  47. var filmTitle = rx[2];
  48. cb(filmTitle);
  49. },
  50. handleSelection: function(imdbId, cb) {
  51. console.log("RatingManager::handleSelection: Rating " + imdbId);
  52. $.get("http://www.imdb.com/title/" + imdbId, function(data) {
  53. var authHash = $(data).find("div[id^='" + imdbId + "']").data("auth");
  54. var params = {tconst: imdbId, rating: RatingManager.rating,
  55. auth: authHash, tracking_tag: "list"};
  56. $.post("http://www.imdb.com/ratings/_ajax/title", params, function(data) {
  57. if(data.status !== 200) {
  58. alert("Rating failed. Status code " + data.status);
  59. }
  60. else {
  61. cb();
  62. }
  63. }, "json");
  64. });
  65. }
  66. };
  67.  
  68. var App = {
  69. manager: ListManager,
  70. films: [],
  71. regexObj: null,
  72. isEmpty: function() {
  73. return App.films.length === 0;
  74. },
  75. next: function() {
  76. return App.films.shift();
  77. },
  78. run: function() {
  79. var textEdit = '<div id="imdbListTextEdit" style="'
  80. + 'padding: 10px; border: 1px solid #e8e8e8">'
  81. + '<p><b>Import mode:</b><input type="radio" name="importmode" value="list" checked="checked">List</input>'
  82. + '<input type="radio" name="importmode" value="ratings">Ratings</input></p>'
  83. + '<textarea id="filmList" rows="7" cols="60" placeholder="Input titles, IMDb URLs, and IDs here and click Start"></textarea><br />'
  84. + '<input type="button" id="doList" value="Start" /> '
  85. + '<input type="button" id="skipFilm" value="Skip" /> '
  86. + '<input type="button" id="retryPost" value="Retry" /> '
  87. + '<span style="font-weight: bold">Remaining: <span id="filmsRemaining">0</span></span><br /><br />'
  88. + '<span style="font-weight: bold;">Current: <input type="text" id="filmCurrent" size="65" style="font-family: monospace" /></span><br />'
  89. + '<span style="font-weight: bold;">Regexp: <input type="text" value="" id="filmRegexp" size="65" style="font-family: monospace; margin-top: 4px; margin-left: 1px" /></span><br />'
  90. + '</div>';
  91. $("div#main > div.list_edit > div.add").after(textEdit);
  92. $("#filmRegexp").val(App.manager.regex);
  93. $("#imdbListTextEdit").on("change", "input[name=importmode]", function() {
  94. var value = $(this).val();
  95. if(value === "list") {
  96. App.manager = ListManager;
  97. }
  98. else {
  99. App.manager = RatingManager;
  100. }
  101. $("#filmRegexp").val(App.manager.regex);
  102. });
  103. // When start button is clicked
  104. $("#imdbListTextEdit").on("click", "#doList", function(e) {
  105. $regexBox = $("#filmRegexp");
  106. if($regexBox.val()) {
  107. App.regexObj = RegExp($regexBox.val());
  108. }
  109. else {
  110. App.regexObj = RegExp(App.manager.regex);
  111. }
  112. // Disable the text area and the button and the regexp box
  113. // as well as the import mode
  114. $filmList = $("#filmList");
  115. $filmList.attr("disabled", "disabled");
  116. $regexBox.attr("disabled", "disabled");
  117. $("#doList").attr("disabled", "disabled");
  118. $("input[name=importmode]").attr("disabled", "disabled");
  119. App.films = $filmList.val().split("\n");
  120. App.handleNext();
  121. });
  122. // when skip button is clicked
  123. $("#imdbListTextEdit").on("click", "#skipFilm", function(e) {
  124. App.handleNext();
  125. });
  126. // Sometimes the request fails forcing the user to skip an entry to continue
  127. $("#imdbListTextEdit").on("click", "#retryPost", function(e) {
  128. $("button.search").trigger("click");
  129. });
  130. },
  131. reset: function() {
  132. App.films = [];
  133. App.regexObj = null;
  134. $("#filmList").removeAttr("disabled");
  135. $("#filmRegexp").removeAttr("disabled"); // leave regex
  136. $("#doList").removeAttr("disabled");
  137. $("input[name=importmode]").removeAttr("disabled");
  138. $("#filmCurrent").val("");
  139. $("input[name=add]", "div.add").val("");
  140. $("div.results", "div.add").html("");
  141. },
  142. search: function(filmTitle) {
  143. // remove unnecessary whitespace
  144. filmTitle = $.trim(filmTitle);
  145. // set current text to what we're searching
  146. $("#filmCurrent").val(filmTitle);
  147. // remove the first title from the text box and set the remaining number
  148. $filmList = $("#filmList");
  149. var newList = $filmList.val().split("\n");
  150. $("#filmsRemaining").text(newList.length-1);
  151. $filmList.val(newList.slice(1).join("\n"));
  152. // Run regex if it matches and let the manager process the result
  153. var result = App.regexObj.exec(filmTitle);
  154. if(result !== null) {
  155. App.manager.processRegex(result, function(filmTitle) {
  156. // Set imdb search input field to film title
  157. $("input[name=add]", "div.add").val(filmTitle);
  158. // Trigger search button click
  159. $("button.search").trigger("click");
  160. });
  161. }
  162. else {
  163. App.handleNext();
  164. }
  165. },
  166. handleNext: function() {
  167. if(!App.isEmpty()) {
  168. // if there's more items, search next...
  169. App.search(App.next());
  170. }
  171. else {
  172. // if last film
  173. App.reset();
  174. }
  175. }
  176. };
  177.  
  178. $(document).ready(App.run);
  179.  
  180. // When a search result item is clicked by user or script
  181. $("div.results").on("click", "li", function(e) {
  182. App.manager.handleSelection($(this).attr("id"), function() {
  183. App.handleNext();
  184. });
  185. });
  186.  
  187. // Monitors for changes to the search result box
  188. // If it recognizes an IMDBb URL/ID, it's clicked automatically
  189. // since there's only one result
  190. $("div.results").bind("DOMNodeInserted", function(e) {
  191. if($("#filmCurrent").val().match(/(tt[0-9]{7})/) !== null
  192. && $("div.results").find("li").length) {
  193. setTimeout(function() {
  194. $("li", "div.results").first()[0].click();
  195. }, REQUEST_DELAY);
  196. }
  197. });