您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds additional information (genre, rating, keywords)to igdb.com lists. They can be loaded witha button // click. Needs an IGDB api key.
当前为
// ==UserScript== // @name IGDB List Extra Info // @namespace https://greasyfork.org/de/users/155913-nkay08 // @description Adds additional information (genre, rating, keywords)to igdb.com lists. They can be loaded witha button // click. Needs an IGDB api key. // @author NKay // @include http*://www.igdb.com/* // @grant none // @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js // @version 0.0.1.20171118154921 // ==/UserScript== //insert your API-KEY here var apikey = ''; var gametextarray = []; var gameidarray = []; var genresnodearray = []; var keywordsnodearray = []; var ratingnodearray = []; function addAdditionalInfo(jnode) { 'use strict'; // Your code here... console.log('Adding button and placeholders for extra info'); //api urls var apikey = 'a219bebccdba1921822242709439c6e4'; var apiurl = 'https://api-2445582011268.apicast.io'; var req = '/games/?search='; var reqid = '/games/1942?fields=*'; var corsproxy = 'https://cors-anywhere.herokuapp.com/'; var fields = '?fields=*'; var sidebar = document.getElementsByClassName("nopad"); var sidebarchild = sidebar[0].childNodes[0]; if (sidebar && sidebarchild) { } // btn.appendChild(btntext); // sidebar[0].appendChild(btn); var pageDivs = document.getElementsByClassName("media-body"); var promises = []; var sequence = Promise.resolve(); //set header for apikey and json var myheaders = new Headers(); myheaders.append('user-key', apikey); //myheaders.append('Accept', 'application/json'); //for every element "media-body" do for (var i = 0; i < pageDivs.length; i++) //for (var i = 0; i < 1; i++) { // get sibling. sibling has game id var sib = pageDivs[i].nextSibling; var gameid = sib.getAttribute("data-game"); //set some elements // var filler = document.createTextNode(' | '); var genrestext = document.createTextNode('Genres: '); var genresspan = document.createElement('span'); genresspan.style.fontSize = 'medium'; genresspan.style.textDecoration = 'underline'; genresspan.appendChild(genrestext); pageDivs[i].appendChild(genresspan); var genresnode = document.createElement('span'); genresnode.setAttribute("id", "usgenre" + i.toString()); pageDivs[i].appendChild(genresnode); genresnodearray.push(genresnode); pageDivs[i].appendChild(document.createTextNode(' | ')); var keywordstext = document.createTextNode('Keywords: '); var kwspan = document.createElement('span'); kwspan.style.fontSize = 'medium'; kwspan.style.textDecoration = "underline"; kwspan.appendChild(keywordstext); pageDivs[i].appendChild(kwspan); var keywordsnode = document.createElement('span'); keywordsnode.setAttribute("id", "uskw" + i.toString()); pageDivs[i].appendChild(keywordsnode); keywordsnodearray.push(keywordsnode); pageDivs[i].appendChild(document.createTextNode(' | ')); var ratingtext = document.createTextNode('Rating: '); var rtspan = document.createElement('span'); rtspan.style.fontSize = 'medium'; rtspan.style.textDecoration = "underline"; rtspan.appendChild(ratingtext); pageDivs[i].appendChild(rtspan); var ratingnode = document.createTextNode(''); pageDivs[i].appendChild(ratingnode); ratingnodearray.push(ratingnode); //get the game name var span1 = pageDivs[i].getElementsByTagName('span'); gameidarray.push(corsproxy + apiurl + '/games/' + gameid + fields); // var ref = pageDivs[i].getElementsByClassName("link-dark"); // text = document.createTextNode(ref[0].href); } var btn = document.createElement("button"); var btntext = document.createTextNode('Load additional info'); btn.appendChild(btntext); var firstbtn = document.getElementsByClassName("btn btn-primary btn-block mar-md-bottom"); firstbtn[0].parentNode.insertBefore(document.createElement('hr'), firstbtn[0]); firstbtn[0].parentNode.insertBefore(btn, firstbtn[0]); firstbtn[0].parentNode.insertBefore(document.createElement('hr'), firstbtn[0]); btn.addEventListener("click", load, false); function load() { genresnodearray.forEach(element => element.innerHTML = 'loading..'); keywordsnodearray.forEach(element => element.innerHTML = 'loading..'); ratingnodearray.forEach(element => element.nodeValue = 'loading..'); //execute multiple fetch promises // first fetch rating for each id Promise.all( gameidarray.map( (url, index) => fetch(url, { headers: myheaders }) .then(res2 => res2.json()) .then(data2 => { if (data2) { var ratingstr = ''; ratingstr = ratingstr.concat('User: '); if (data2[0].rating) { ratingstr = ratingstr.concat(Math.round(data2[0].rating).toString()); ratingstr = ratingstr.concat(' (' + data2[0].rating_count.toString() + ')'); } else { ratingstr = ratingstr.concat('/'); } ratingstr = ratingstr.concat(', '); ratingstr = ratingstr.concat('Critics: '); if (data2[0].aggregated_rating) { ratingstr = ratingstr.concat(Math.round(data2[0].aggregated_rating).toString()); ratingstr = ratingstr.concat(' (' + data2[0].aggregated_rating_count.toString() + ')'); } else { ratingstr = ratingstr.concat('/'); } ratingstr = ratingstr.concat(', '); ratingstr = ratingstr.concat('Total: '); if (data2[0].total_rating) { ratingstr = ratingstr.concat(Math.round(data2[0].total_rating).toString()); ratingstr = ratingstr.concat(' (' + data2[0].total_rating_count.toString() + ')'); } else { ratingstr = ratingstr.concat('/'); } ratingnodearray[index].nodeValue = ratingstr; //concat all genrenames. fetch for all genre-ids at once if (data2[0].genres) { var genresid = data2[0].genres; var genresurl = corsproxy + apiurl + '/genres/' + data2[0].genres.toString(); fetch(genresurl, { headers: myheaders }) .then(resgenre => resgenre.json()) .then(datagenre => { var newgenres = ''; genresnodearray[index].innerHTML = ''; datagenre.forEach((tgenre, genreindex) => { var newgenre = document.createElement('a'); newgenre.setAttribute("href", tgenre.url); var comma = ', '; if (genreindex == datagenre.length) { comma = ''; } newgenre.appendChild(document.createTextNode(tgenre.name + comma)); genresnodearray[index].appendChild(newgenre); }); }); } //concat all keywords. fetch for all keyword-ids at once if (data2[0].keywords) { var keywordsid = data2[0].keywords; var keywordsurl = corsproxy + apiurl + '/keywords/' + data2[0].keywords.toString(); fetch(keywordsurl, { headers: myheaders }) .then(reskey => reskey.json()) .then(datakey => { keywordsnodearray[index].innerHTML = ''; datakey.forEach((tkey, keyindex) => { var newkey = document.createElement('a'); newkey.setAttribute('href', tkey.url); var comma = ', '; if (keyindex == datakey.length) { comma = ''; } newkey.appendChild(document.createTextNode(tkey.name + comma)); keywordsnodearray[index].appendChild(newkey); }); }); } } }) ) ); } } //only execute function if this element is loaded via ajax waitForKeyElements("#content-page > div > div.content-left.col-md-pull-10.col-md-2 > div > a:nth-child(3)", addAdditionalInfo, true); /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts, that detects and handles AJAXed content. Usage example: waitForKeyElements ( "div.comments" , commentCallbackFunction ); //--- Page-specific function to do what we want when the node is found. function commentCallbackFunction (jNode) { jNode.text ("This comment changed by waitForKeyElements()."); } IMPORTANT: This function requires your script to have loaded jQuery. */ function waitForKeyElements ( selectorTxt, /* Required: The jQuery selector string that specifies the desired element(s). */ actionFunction, /* Required: The code to run when elements are found. It is passed a jNode to the matched element. */ bWaitOnce, /* Optional: If false, will continue to scan for new elements even after the first match is found. */ iframeSelector /* Optional: If set, identifies the iframe to search. */ ) { var targetNodes, btargetsFound; if (typeof iframeSelector == "undefined") targetNodes = $(selectorTxt); else targetNodes = $(iframeSelector).contents () .find (selectorTxt); if (targetNodes && targetNodes.length > 0) { btargetsFound = true; /*--- Found target node(s). Go through each and act if they are new. */ targetNodes.each ( function () { var jThis = $(this); var alreadyFound = jThis.data ('alreadyFound') || false; if (!alreadyFound) { //--- Call the payload function. var cancelFound = actionFunction (jThis); if (cancelFound) btargetsFound = false; else jThis.data ('alreadyFound', true); } } ); } else { btargetsFound = false; } //--- Get the timer-control variable for this selector. var controlObj = waitForKeyElements.controlObj || {}; var controlKey = selectorTxt.replace (/[^\w]/g, "_"); var timeControl = controlObj [controlKey]; //--- Now set or clear the timer as appropriate. if (btargetsFound && bWaitOnce && timeControl) { //--- The only condition where we need to clear the timer. clearInterval (timeControl); delete controlObj [controlKey]; } else { //--- Set a timer, if needed. if ( ! timeControl) { timeControl = setInterval ( function () { waitForKeyElements ( selectorTxt, actionFunction, bWaitOnce, iframeSelector ); }, 300 ); controlObj [controlKey] = timeControl; } } waitForKeyElements.controlObj = controlObj; }