Add movie ratings to IMDB links

Adds movie ratings and number of voters to any imdb link. Modified version of http://userscripts.org/scripts/show/96884

目前为 2018-04-25 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Add movie ratings to IMDB links
  3. // @description Adds movie ratings and number of voters to any imdb link. Modified version of http://userscripts.org/scripts/show/96884
  4. // @author StackOverflow community (especially Brock Adams)
  5. // @version 2015-11-24-8-joeytwiddle
  6. // @match *://www.imdb.com/*
  7. // @grant GM_xmlhttpRequest
  8. // @grant unsafeWindow
  9. // @namespace https://gf.qytechs.cn/users/8615
  10. // @derived-from https://gf.qytechs.cn/en/scripts/2033-add-imdb-rating-votes-next-to-all-imdb-movie-series-links-improved
  11. // ==/UserScript==
  12. // Special Thanks to Brock Adams for this script: http://stackoverflow.com/questions/23974801/gm-xmlhttprequest-data-is-being-placed-in-the-wrong-places/23992742
  13.  
  14. var maxLinksAtATime = 100; //-- pages can have 100's of links to fetch. Don't spam server or browser.
  15. var fetchedLinkCnt = 0;
  16. var skipEpisodes = true; //-- I only want to see ratings for movies or TV shows, not TV episodes
  17.  
  18. var $ = unsafeWindow.$;
  19.  
  20. function processIMDB_Links () {
  21. //--- Get only links that could be to IMBD movie/TV pages.
  22. var linksToIMBD_Shows = document.querySelectorAll ("a[href*='/title/']");
  23.  
  24. for (var J = 0, L = linksToIMBD_Shows.length; J < L; J++) {
  25. var currentLink = linksToIMBD_Shows[J];
  26.  
  27. /*--- Strict tests for the correct IMDB link to keep from spamming the page
  28. with erroneous results.
  29. */
  30. if ( ! /^(?:www\.)?IMDB\.com$/i.test (currentLink.hostname)
  31. || ! /^\/title\/tt\d+\/?$/i.test (currentLink.pathname)
  32. )
  33. continue;
  34.  
  35. // I am beginning to think a whitelist might be better than this blacklist!
  36.  
  37. // Skip thumbnails on the search results page
  38. if ($(currentLink).closest('.primary_photo').length) {
  39. continue;
  40. }
  41.  
  42. // Skip thumbnails in the six recommendations area of a title page
  43. if ($(currentLink).closest('.rec_item').length) {
  44. continue;
  45. }
  46.  
  47. // Skip top-rated episodes on the right-hand sidebar of TV series pages; they already display a rating anyway!
  48. if ($(currentLink).closest('#top-rated-episodes-rhs').length) {
  49. continue;
  50. }
  51.  
  52. // Skip thumbnail of title at top of Season page
  53. if ($(currentLink).find(':only-child').prop('tagName') === 'IMG') {
  54. continue;
  55. }
  56.  
  57. // Skip the thumbnail of each episode on a season page (episode names still processed)
  58. if ($(currentLink).closest('.image').length) {
  59. continue;
  60. }
  61.  
  62. // Skip thumbnails in "Known For" section of actor pages
  63. if ($(currentLink).closest('.known-for').length && $(currentLink).find('img').length) {
  64. continue;
  65. }
  66.  
  67. // Skip episodes on actor pages
  68. if (skipEpisodes && $(currentLink).closest('.filmo-episodes').length) {
  69. continue;
  70. }
  71.  
  72. if (! currentLink.getAttribute ("data-gm-fetched") ){
  73. if (fetchedLinkCnt >= maxLinksAtATime){
  74. //--- Position the "continue" button.
  75. continueBttn.style.display = 'inline';
  76. currentLink.parentNode.insertBefore (continueBttn, currentLink);
  77. break;
  78. }
  79.  
  80. fetchTargetLink (currentLink); //-- AJAX-in the ratings for a given link.
  81.  
  82. //---Mark the link with a data attribute, so we know it's been fetched.
  83. currentLink.setAttribute ("data-gm-fetched", "true");
  84. fetchedLinkCnt++;
  85. }
  86. }
  87. }
  88.  
  89. function fetchTargetLink (linkNode) {
  90. //--- This function provides a closure so that the callbacks can work correctly.
  91.  
  92. /*--- Must either call AJAX in a closure or pass a context.
  93. But Tampermonkey does not implement context correctly!
  94. (Tries to JSON serialize a DOM node.)
  95. */
  96. GM_xmlhttpRequest ( {
  97. method: 'get',
  98. url: linkNode.href,
  99. //context: linkNode,
  100. onload: function (response) {
  101. prependIMDB_Rating (response, linkNode);
  102. },
  103. onload: function (response) {
  104. prependIMDB_Rating (response, linkNode);
  105. },
  106. onabort: function (response) {
  107. prependIMDB_Rating (response, linkNode);
  108. }
  109. } );
  110. }
  111.  
  112. function prependIMDB_Rating (resp, targetLink) {
  113. var isError = true;
  114. var ratingTxt = "** Unknown Error!";
  115. var colnumber = 0;
  116. var justrate = 'RATING_NOT_FOUND';
  117.  
  118. if (resp.status != 200 && resp.status != 304) {
  119. ratingTxt = '** ' + resp.status + ' Error!';
  120. }
  121. else {
  122. // Example value: ["Users rated this 8.5/10 (", "8.5/10"]
  123. //var ratingM = resp.responseText.match (/Users rated this (.*) \(/);
  124. // Example value: ["(1,914 votes) -", "1,914"]
  125. //var votesM = resp.responseText.match (/\((.*) votes\) -/);
  126.  
  127. var doc = document.createElement('div');
  128. doc.innerHTML = resp.responseText;
  129. var elem = doc.querySelector('.title-overview .vital .ratingValue strong');
  130. var title = elem && elem.title || '';
  131.  
  132. var ratingT = title.replace(/ based on .*$/, '');
  133. var votesT = title.replace(/.* based on /, '').replace(/ user ratings/, '');
  134.  
  135. // The code below expects arrays (originally returned by string match)
  136. var ratingM = [ratingT, ratingT + "/10"];
  137. var votesM = [votesT, votesT];
  138.  
  139. //console.log('ratingM', ratingM);
  140. //console.log('votesM', votesM);
  141.  
  142. if (/\(awaiting \d+ votes\)|\(voting begins after release\)|in development,/i.test (resp.responseText) ) {
  143. ratingTxt = "NR";
  144. isError = false;
  145. colnumber = 0;
  146. } else {
  147. if (ratingM && ratingM.length > 1 && votesM && votesM.length > 1) {
  148. isError = false;
  149.  
  150. justrate = ratingM[1].substr(0, ratingM[1].indexOf("/"));
  151.  
  152. var votes = votesM[1];
  153. var votesNum = Number( votes.replace(/,/,'','') );
  154. var commas_found = votes.match(/,/,'g');
  155. if (commas_found && commas_found.length === 1) {
  156. votes = votes.replace(/,.../, 'k');
  157. } else if (commas_found && commas_found.length === 2) {
  158. votes = votes.replace(/,.*,.*/, 'M');
  159. }
  160.  
  161. // ratingTxt = ratingM[1] + " - " + votesM[1];
  162. ratingTxt = "<strong>" + justrate + "</strong>" + " / " + votes;
  163. colnumber = Math.round(justrate);
  164. }
  165. }
  166. }
  167.  
  168.  
  169. // NOTE: I switched from <b> to <strong> simply because on Season pages, the rating injected after episode titles was getting uglified by an IMDB CSS rule: .list_item .info b { font-size: 15px; }
  170. targetLink.setAttribute("title", "Rated " + ratingTxt.replace(/<\/*strong>/g,'').replace(/\//,'by') + " users." );
  171.  
  172. if (justrate < 5) {
  173. return;
  174. }
  175.  
  176.  
  177. // Slowly approach full opacity as votesNum increases. 10,000 votes results in opacity 0.5 (actually 0.6 when adjusted).
  178. var opacity = 1 - 1 / (1 + 0.0001 * votesNum);
  179. // Actually let's not start from 0; we may still want to see the numbers!
  180. opacity = 0.2 + 0.8*opacity;
  181. // Don't use too many decimal points; it's ugly!
  182. //opacity = Math.round(opacity * 10000) / 10000;
  183. opacity = opacity.toFixed(3);
  184.  
  185. var color = ["#Faa", "#Faa","#Faa", "#Faa","#Faa", "#F88","#Faa", "#ff7","#7e7", "#5e5", "#0e0", "#ddd"];
  186. var resltSpan = document.createElement ("span");
  187. // resltSpan.innerHTML = '<b><font style="border-radius: 5px;padding: 1px;border: #575757 solid 1px; background-color:' + color[colnumber] + ';">' + ' [' + ratingTxt + '] </font></b>&nbsp;';
  188. // resltSpan.innerHTML = '<b><font style="background-color:' + justrate + '">' + ' [' + ratingTxt + '] </font></b>&nbsp;';
  189. // I wanted vertical padding 1px but then the element does not fit in the "also liked" area, causing the top border to disappear! Although reducing the font size to 70% is an alternative.
  190. resltSpan.innerHTML = '&nbsp;<font style="font-weight: normal;font-size: 80%;opacity: '+opacity+';border-radius: 3px;padding: 0.1em 0.6em;border: rgba(0,0,0,0.1) solid 1px; background-color:' + color[colnumber] + ';color: black;">' + '' + ratingTxt + '</font>';
  191.  
  192.  
  193. if (isError)
  194. resltSpan.style.color = 'red';
  195.  
  196. //var targetLink = resp.context;
  197. //console.log ("targetLink: ", targetLink);
  198.  
  199. //targetLink.parentNode.insertBefore (resltSpan, targetLink);
  200. targetLink.parentNode.insertBefore (resltSpan, targetLink.nextSibling);
  201. }
  202.  
  203. //--- Create the continue button
  204. var continueBttn = document.createElement ("button");
  205. continueBttn.innerHTML = "Get more ratings";
  206.  
  207. continueBttn.addEventListener ("click", function (){
  208. fetchedLinkCnt = 0;
  209. continueBttn.style.display = 'none';
  210. processIMDB_Links ();
  211. },
  212. false
  213. );
  214.  
  215. processIMDB_Links ();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址