2

I am creating a Greasemonkey/Tampermonkey script that puts some stats into an array.

Using JavaScript, how would I make it so a page loads a URL (football.fantasysports.yahoo.com/f1/326198/pointsagainst?pos=QB) in the background and creates an array with the first two columns (Rank and Team)?

The problem I am having is doing all of this in the background, I presume I would be using AJAX. Any help would be appreciated.

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
Bijan
  • 7,737
  • 18
  • 89
  • 149

2 Answers2

2

For a static page (like the one you linked), use GM_xmlhttpRequest() and DOMParser to extract the elements you want. See below.

For a dynamic page(AJAX driven), use the techniques from How to get an AJAX get-request to wait for the page to be rendered before returning a response?


Here's a complete script showing how to extract info from a third party page and make it into an array variable:

// ==UserScript==
// @name        _Grab stuff of a *static*, third-party web site.
// @include     https://stackoverflow.com/questions/*
// @require     http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @grant       GM_xmlhttpRequest
// ==/UserScript==

GM_xmlhttpRequest ( {
    method:     "GET",
    url:        "http://football.fantasysports.yahoo.com/f1/326198/pointsagainst?pos=QB&ntid=",
    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 parser  = new DOMParser ();
    /* IMPORTANT!
        1) For older browsers, see
        https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
        for a work-around.

        2) jQuery.parseHTML() and similar is bad because it causes images, etc., to be loaded.
    */
    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    = tblRow.find ("td:eq(1)").text().trim();

        return [ [teamRank, teamName] ];
    } ).get ();

    /*-- newStatTable, is a 2-D array like:
        [   [1, "Team A"],
            [2, "Team B"],
            [3, "Team C"],
            //etc...
        ]
    */
    console.log (newStatTable);
    //alert (newStatTable);
}
Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • How would I modify this to get multiple pages of the same type and store it in a 2D array. i.e. right now it gets the QB position but what if I also wanted to get [This](http://football.fantasysports.yahoo.com/f1/326198/pointsagainst?season=2014&pos=WR) page and store it in the array. The array's first column would list all the teams, the 2nd column would have the teams rank for QB position, 3rd column would have teams rank for WR position and so on. – Bijan Sep 01 '15 at 04:44
  • 1
    You would use separate `GM_xmlhttpRequest`s for each table type (I'd make it a function), and you'd collate the different result types as they come in asynchronously. ... That is beyond the scope of this question and if you ask a new question for that, be sure you've made a **major** stab at solving it first. – Brock Adams Sep 01 '15 at 05:17
  • I posted a [new question](http://stackoverflow.com/questions/32338061/iterate-http-request-over-loop). My idea was to just iterate the GM_xmlhttpRequest over a for loop and then combine all the arrays after but this seems inefficient and the console.log is out of order for some reason. – Bijan Sep 01 '15 at 17:58
0

I think you want to do something like:

// ==UserScript==

// @name          Fantasy Stuff

// @namespace     http://football.fantasysports.yahoo.com/f1/326198/pointsagainst?pos=QB&ntid=

// @description   An example of Fantasy Stuff

// @include       *

// ==/UserScript==

var doc = document;
function T(t){
  return doc.getElementsByTagName(t);
}
var tms = T('tbody')[0].getElementsByTagName('a'), teams = [];
for(var i=0,n=1,l=tms.length; i<l; i++,n++){
  teams[n] = tms[i].text;
}
// teams array should hold results
console.log(teams); // in FireFox
StackSlave
  • 10,613
  • 2
  • 18
  • 35
  • This has lots of problems, the biggest being that it gets ***every link*** on every page browsed! Please test your code and never, ever, use `@include *` or equivalent. – Brock Adams Sep 01 '15 at 02:38