IGDB List Extra Info

Adds additional information (genre, rating, keywords)to igdb.com lists. They can be loaded witha button

当前为 2017-11-18 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name IGDB List Extra Info
  3. // @namespace https://greasyfork.org/de/users/155913-nkay08
  4. // @version 0.8
  5. // @description Adds additional information (genre, rating, keywords)to igdb.com lists. They can be loaded witha button
  6. // click. Needs an IGDB api key.
  7. // @author NKay
  8. // @include http*://www.igdb.com/*
  9. // @grant none
  10. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
  11. // ==/UserScript==
  12.  
  13.  
  14. //insert your API-KEY here
  15. var apikey = '';
  16.  
  17. var gametextarray = [];
  18. var genresnodearray = [];
  19. var keywordsnodearray = [];
  20. var ratingnodearray = [];
  21.  
  22.  
  23. function addAdditionalInfo(jnode) {
  24. 'use strict';
  25. // Your code here...
  26. console.log('Adding button and placeholders for extra info');
  27. //api urls
  28. var apikey = 'a219bebccdba1921822242709439c6e4';
  29. var apiurl = 'https://api-2445582011268.apicast.io';
  30. var req = '/games/?search=';
  31. var reqid = '/games/1942?fields=*';
  32. var corsproxy = 'https://cors-anywhere.herokuapp.com/';
  33.  
  34. var sidebar = document.getElementsByClassName("nopad");
  35. var sidebarchild = sidebar[0].childNodes[0];
  36. if (sidebar && sidebarchild) {
  37.  
  38.  
  39. }
  40.  
  41.  
  42. // btn.appendChild(btntext);
  43. // sidebar[0].appendChild(btn);
  44.  
  45.  
  46. var pageDivs = document.getElementsByClassName("media-body");
  47.  
  48. var promises = [];
  49. var sequence = Promise.resolve();
  50. //set header for apikey and json
  51. var myheaders = new Headers();
  52. myheaders.append('user-key', apikey);
  53. //myheaders.append('Accept', 'application/json');
  54.  
  55. //for every element "media-body" do
  56. for (var i = 0; i < pageDivs.length; i++)
  57. //for (var i = 0; i < 1; i++)
  58. {
  59. //add a textnode
  60. // modify with .nodeValue=
  61.  
  62. //set some elements
  63. // var filler = document.createTextNode(' | ');
  64. var genrestext = document.createTextNode('Genres: ');
  65. var genresspan = document.createElement('span');
  66. genresspan.style.fontSize = 'medium';
  67. genresspan.style.textDecoration = 'underline';
  68. genresspan.appendChild(genrestext);
  69. pageDivs[i].appendChild(genresspan);
  70. var genresnode = document.createElement('span');
  71. genresnode.setAttribute("id", "usgenre" + i.toString());
  72. pageDivs[i].appendChild(genresnode);
  73. genresnodearray.push(genresnode);
  74. pageDivs[i].appendChild(document.createTextNode(' | '));
  75. var keywordstext = document.createTextNode('Keywords: ');
  76. var kwspan = document.createElement('span');
  77. kwspan.style.fontSize = 'medium';
  78. kwspan.style.textDecoration = "underline";
  79. kwspan.appendChild(keywordstext);
  80. pageDivs[i].appendChild(kwspan);
  81. var keywordsnode = document.createElement('span');
  82. keywordsnode.setAttribute("id", "uskw" + i.toString());
  83. pageDivs[i].appendChild(keywordsnode);
  84. keywordsnodearray.push(keywordsnode);
  85. pageDivs[i].appendChild(document.createTextNode(' | '));
  86. var ratingtext = document.createTextNode('Rating: ');
  87. var rtspan = document.createElement('span');
  88. rtspan.style.fontSize = 'medium';
  89. rtspan.style.textDecoration = "underline";
  90. rtspan.appendChild(ratingtext);
  91. pageDivs[i].appendChild(rtspan);
  92. var ratingnode = document.createTextNode('');
  93. pageDivs[i].appendChild(ratingnode);
  94. ratingnodearray.push(ratingnode);
  95.  
  96.  
  97. //get the game name
  98. var gametext = 'test';
  99. var span1 = pageDivs[i].getElementsByTagName('span');
  100. gametext = span1[0].innerHTML;
  101. gametextarray.push(corsproxy + apiurl + req + gametext);
  102.  
  103. // var ref = pageDivs[i].getElementsByClassName("link-dark");
  104. // text = document.createTextNode(ref[0].href);
  105. }
  106.  
  107. var btn = document.createElement("button");
  108. var btntext = document.createTextNode('Load additional info');
  109. btn.appendChild(btntext);
  110. var firstbtn = document.getElementsByClassName("btn btn-primary btn-block mar-md-bottom");
  111. firstbtn[0].parentNode.insertBefore(document.createElement('hr'), firstbtn[0]);
  112. firstbtn[0].parentNode.insertBefore(btn, firstbtn[0]);
  113. firstbtn[0].parentNode.insertBefore(document.createElement('hr'), firstbtn[0]);
  114. btn.addEventListener("click", load, false);
  115.  
  116. function load() {
  117. genresnodearray.forEach(element => element.innerHTML = 'loading..');
  118. keywordsnodearray.forEach(element => element.innerHTML = 'loading..');
  119. ratingnodearray.forEach(element => element.nodeValue = 'loading..');
  120.  
  121. //execute multiple fetch promises
  122. //first fetch the game-id for a given name
  123. Promise.all(
  124. gametextarray.map(
  125. (url, index) => fetch(url, {
  126. headers: myheaders
  127. })
  128. .then(res => res.json())
  129. .then(data => {
  130. var gameidnum = data[0].id;
  131. var gameid = gameidnum.toString();
  132. //generate new url with id to query for the data
  133. var newurl = (corsproxy + apiurl + '/games/' + gameid + '?fields=*');
  134. return fetch(newurl, {
  135. headers: myheaders
  136. });
  137. })
  138. .then(res2 => res2.json())
  139. .then(data2 => {
  140. if (data2) {
  141. var ratingstr = '';
  142. ratingstr = ratingstr.concat('User: ');
  143. if (data2[0].rating) {
  144. ratingstr = ratingstr.concat(Math.round(data2[0].rating).toString());
  145. ratingstr = ratingstr.concat(' (' + data2[0].rating_count.toString() + ')');
  146. } else {
  147. ratingstr = ratingstr.concat('/');
  148. }
  149. ratingstr = ratingstr.concat(', ');
  150. ratingstr = ratingstr.concat('Critics: ');
  151. if (data2[0].aggregated_rating) {
  152. ratingstr = ratingstr.concat(Math.round(data2[0].aggregated_rating).toString());
  153. ratingstr = ratingstr.concat(' (' + data2[0].aggregated_rating_count.toString() + ')');
  154. } else {
  155. ratingstr = ratingstr.concat('/');
  156. }
  157. ratingstr = ratingstr.concat(', ');
  158. ratingstr = ratingstr.concat('Total: ');
  159. if (data2[0].total_rating) {
  160. ratingstr = ratingstr.concat(Math.round(data2[0].total_rating).toString());
  161. ratingstr = ratingstr.concat(' (' + data2[0].total_rating_count.toString() + ')');
  162. } else {
  163. ratingstr = ratingstr.concat('/');
  164. }
  165. ratingnodearray[index].nodeValue = ratingstr;
  166.  
  167.  
  168.  
  169.  
  170. //concat all genrenames. fetch for all genre-ids at once
  171. if (data2[0].genres) {
  172. var genresid = data2[0].genres;
  173. var genresurl = corsproxy + apiurl + '/genres/' + data2[0].genres.toString();
  174. fetch(genresurl, {
  175. headers: myheaders
  176. })
  177. .then(resgenre => resgenre.json())
  178. .then(datagenre => {
  179. var newgenres = '';
  180. genresnodearray[index].innerHTML = '';
  181. datagenre.forEach((tgenre, genreindex) => {
  182. var newgenre = document.createElement('a');
  183. newgenre.setAttribute("href", tgenre.url);
  184. var comma = ', ';
  185. if (genreindex == datagenre.length) {
  186. comma = '';
  187. }
  188. newgenre.appendChild(document.createTextNode(tgenre.name + comma));
  189. genresnodearray[index].appendChild(newgenre);
  190.  
  191. });
  192. });
  193. }
  194.  
  195. //concat all keywords. fetch for all keyword-ids at once
  196. if (data2[0].keywords) {
  197. var keywordsid = data2[0].keywords;
  198. var keywordsurl = corsproxy + apiurl + '/keywords/' + data2[0].keywords.toString();
  199. fetch(keywordsurl, {
  200. headers: myheaders
  201. })
  202. .then(reskey => reskey.json())
  203. .then(datakey => {
  204. keywordsnodearray[index].innerHTML = '';
  205. datakey.forEach((tkey, keyindex) => {
  206. var newkey = document.createElement('a');
  207. newkey.setAttribute('href', tkey.url);
  208. var comma = ', ';
  209. if (keyindex == datakey.length) {
  210. comma = '';
  211. }
  212. newkey.appendChild(document.createTextNode(tkey.name + comma));
  213. keywordsnodearray[index].appendChild(newkey);
  214. });
  215.  
  216.  
  217. });
  218.  
  219. }
  220.  
  221. }
  222. })
  223. )
  224. );
  225.  
  226. }
  227. }
  228.  
  229. //only execute function if this element is loaded via ajax
  230. waitForKeyElements("#content-page > div > div.content-left.col-md-pull-10.col-md-2 > div > a:nth-child(3)", addAdditionalInfo, true);
  231.  
  232. /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts,
  233. that detects and handles AJAXed content.
  234.  
  235. Usage example:
  236.  
  237. waitForKeyElements (
  238. "div.comments"
  239. , commentCallbackFunction
  240. );
  241.  
  242. //--- Page-specific function to do what we want when the node is found.
  243. function commentCallbackFunction (jNode) {
  244. jNode.text ("This comment changed by waitForKeyElements().");
  245. }
  246.  
  247. IMPORTANT: This function requires your script to have loaded jQuery.
  248. */
  249. function waitForKeyElements (
  250. selectorTxt, /* Required: The jQuery selector string that
  251. specifies the desired element(s).
  252. */
  253. actionFunction, /* Required: The code to run when elements are
  254. found. It is passed a jNode to the matched
  255. element.
  256. */
  257. bWaitOnce, /* Optional: If false, will continue to scan for
  258. new elements even after the first match is
  259. found.
  260. */
  261. iframeSelector /* Optional: If set, identifies the iframe to
  262. search.
  263. */
  264. ) {
  265. var targetNodes, btargetsFound;
  266.  
  267. if (typeof iframeSelector == "undefined")
  268. targetNodes = $(selectorTxt);
  269. else
  270. targetNodes = $(iframeSelector).contents ()
  271. .find (selectorTxt);
  272.  
  273. if (targetNodes && targetNodes.length > 0) {
  274. btargetsFound = true;
  275. /*--- Found target node(s). Go through each and act if they
  276. are new.
  277. */
  278. targetNodes.each ( function () {
  279. var jThis = $(this);
  280. var alreadyFound = jThis.data ('alreadyFound') || false;
  281.  
  282. if (!alreadyFound) {
  283. //--- Call the payload function.
  284. var cancelFound = actionFunction (jThis);
  285. if (cancelFound)
  286. btargetsFound = false;
  287. else
  288. jThis.data ('alreadyFound', true);
  289. }
  290. } );
  291. }
  292. else {
  293. btargetsFound = false;
  294. }
  295.  
  296. //--- Get the timer-control variable for this selector.
  297. var controlObj = waitForKeyElements.controlObj || {};
  298. var controlKey = selectorTxt.replace (/[^\w]/g, "_");
  299. var timeControl = controlObj [controlKey];
  300.  
  301. //--- Now set or clear the timer as appropriate.
  302. if (btargetsFound && bWaitOnce && timeControl) {
  303. //--- The only condition where we need to clear the timer.
  304. clearInterval (timeControl);
  305. delete controlObj [controlKey];
  306. }
  307. else {
  308. //--- Set a timer, if needed.
  309. if ( ! timeControl) {
  310. timeControl = setInterval ( function () {
  311. waitForKeyElements ( selectorTxt,
  312. actionFunction,
  313. bWaitOnce,
  314. iframeSelector
  315. );
  316. },
  317. 300
  318. );
  319. controlObj [controlKey] = timeControl;
  320. }
  321. }
  322. waitForKeyElements.controlObj = controlObj;
  323. }