I have the following Greasemonkey script that fetches some data from a Yahoo webpage and injects it into a webpage. It has the feature that it only fetches the data once per day instead of fetching it every single time the page is loaded.
I think my displayresults function is a little messy just because it has to access a lot of variables to work.
You can test this script for yourself by installing it and loading this page.
// ==UserScript==
// @name Yahoo Fantasy Football Rank
// @author Bijan
// @version 2.5
// @description Very simple script to conveniently see how many points a team gives up
// @namespace http://albuyeh.com
// @match *://football.fantasysports.yahoo.com/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @grant GM_xmlhttpRequest
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
//Map Team Name to abbreviation
var teamNameList = {
"Arizona Cardinals": "Ari",
"Atlanta Falcons": "Atl",
"Baltimore Ravens": "Bal",
"Buffalo Bills": "Buf",
"Carolina Panthers": "Car",
"Chicago Bears": "Chi",
"Cincinnati Bengals": "Cin",
"Cleveland Browns": "Cle",
"Dallas Cowboys": "Dal",
"Denver Broncos": "Den",
"Detroit Lions": "Det",
"Green Bay Packers": "GB",
"Houston Texans": "Hou",
"Indianapolis Colts": "Ind",
"Jacksonville Jaguars": "Jax",
"Kansas City Chiefs": "KC",
"Miami Dolphins": "Mia",
"Minnesota Vikings": "Min",
"New England Patriots": "NE",
"New Orleans Saints": "NO",
"New York Giants": "NYG",
"New York Jets": "NYJ",
"Oakland Raiders": "Oak",
"Philadelphia Eagles": "Phi",
"Pittsburgh Steelers": "Pit",
"San Diego Chargers": "SD",
"San Francisco 49ers": "SF",
"Seattle Seahawks": "Sea",
"St. Louis Rams": "StL",
"Tampa Bay Buccaneers": "TB",
"Tennessee Titans": "Ten",
"Washington Redskins": "Was",
}
const playerPositions = ["QB", "WR", "RB", "TE", "K", "DEF"]; //Positions to fetch data for
const numPositions = playerPositions.length;
const baseURL = "http://football.fantasysports.yahoo.com/f1/326198/pointsagainst?pos="; //Page to create fetch request to
var rankingsTable = {}; //This will be filled by the AJAX parser.
var final = {}; //Final table that holds all of the team/position info
var numPagesFetched = 0;
var tableName = "FF_Array2";
//Display notification of Update
var ver = GM_info.script.version;
if (GM_getValue("version", "") < ver) {
GM_setValue("version", ver);
alert("Updated Yahoo Fantasy Football Rank by Bijan to v" + ver);
}
//Fetch results once per day.
var now = new Date();
var currdate = Math.floor(now/8.64e7);
if (GM_getValue("date2", "") < currdate || GM_getValue (tableName, "").length == 0) {
GM_setValue("date2", currdate);
console.log("Fetched results @ :" + currdate);
main(); //Go to main() to fetch data
}
else {
console.log("Already fetched data. Continuing to display results");
displayResults();
}
function main () {
for (var J in playerPositions) {
GM_xmlhttpRequest ( {
method: "GET",
url: baseURL + playerPositions[J],
context: playerPositions[J],
onload: parseResponse,
onerror: function (e) { console.error ('**** error ', e); },
onabort: function (e) { console.error ('**** abort ', e); },
ontimeout: function (e) { console.error ('**** timeout ', e); }
} );
}
}
function parseResponse (response) {
var playerPosition = response.context;
var parser = new DOMParser ();
var ajaxDoc = parser.parseFromString (response.responseText, "text/html");
var statRows = ajaxDoc.querySelectorAll ("#statTable0 > tbody > tr");
var newStatTable = $(statRows).map ( function () {
var tblRow = $(this);
var teamRank = parseInt (tblRow.find (".rank-indicator").text().trim(), 10);
var teamName = teamNameList[tblRow.find ("td:eq(1)").text().trim().split(" vs")[0]];
return [ [teamName, teamRank] ];
} ).get ();
numPagesFetched++;
console.log ('Fetched page ' + numPagesFetched + ' of ' + numPositions + '.');
/*--- Now loop over the fetched rows and collate them into the master table, depending
on playerPosition.
*/
var columnIdx = playerPositions.indexOf (playerPosition);
for (var K in newStatTable) {
var teamName = newStatTable[K][0];
var teamRank = newStatTable[K][1];
var teamStats = rankingsTable[teamName] || new Array (numPositions);
teamStats[columnIdx] = teamRank;
rankingsTable[teamName] = teamStats;
}
if (numPagesFetched === numPositions) {
displayFinalResult ();
}
}
function displayFinalResult () {
//Sort team name
var sortedTeamNames = Object.keys (rankingsTable).sort ( function (zA, zB) {
return zA.localeCompare (zB);
} );
//Store team name and rank array in a single array
for (var J in sortedTeamNames) {
var teamName = sortedTeamNames[J];
if (rankingsTable.hasOwnProperty (teamName) ) {
final[teamName] = rankingsTable[teamName]
}
}
//Save array to browser
GM_setValue (tableName, JSON.stringify (final) );
displayResults(final)
}
function displayResults(result) {
//Get saved results
var myList = {};
var myListObj = GM_getValue (tableName, "");
if (myListObj) {
myList = JSON.parse (myListObj);
}
//Check if we have already fetched results for the day
if (typeof result === 'undefined') { result = myList; console.log("Loading pre-loaded data");}
var player = document.querySelectorAll('span[class="Fz-xxs"]'); //Get player element
var opp = document.querySelectorAll('a[class="F-reset"]'); //Get opposing team element
if(opp[0].innerHTML == "View Details") opp = Array.prototype.slice.call(opp, 1, opp.length);
if(player.length == opp.length) {
console.log("Player length = Opposing Team length. We can continue")
for (i=0; i < player.length; i++) {
var playerPos = player[i].innerHTML.split(" - ").splice(-1)[0]; //Returns position (i.e. QB)
var playerIndex = playerPositions.indexOf(playerPos);
if (playerIndex == -1) {console.log("Skipped " + playerPos); continue;} //Currently does not fetch Defensive players.
var oppTeam = opp[i].innerHTML.split(" ").splice(-1)[0]; //Returns opposing team (i.e. SF)
var rank = result[oppTeam][playerIndex]; //Get rank # based on opposing team and player position
if (1 <= rank && rank <= 10) color = "F-rank-good"; //Green
else if (11 <= rank && rank <= 22) color = "F-rank-neutral"; //Yellow
else if (23 <= rank && rank <= 32) color = "F-rank-bad"; //Red
console.log(oppTeam + " gives up the #" + rank + " points to the " + playerPos + " position")
opp[i].innerHTML = opp[i].innerHTML.split(/\@|vs/)[0] + " @ <span class='" + color + "'>" + oppTeam + " - " + rank + "</span>"; //Modify element to include rank and color
}
}
else {
console.log("Player & Team mismatch: " + player.length + " & " + opp.length)
}
}
// End
innerHTMLis poor practice and has pitfalls. Search SO for why. Then try to write the code to use DOM methods and/or jQuery and/ortextContentbut NOTinnerHTMLand NOT.html(). \$\endgroup\$.lengthin the conditional part of anifstatement. Lookup why on SO. \$\endgroup\$querySelectorAll, the other half uses jQuery \$\endgroup\$