1

I have some links in a page. I want to count the responses of each link and insert the numbers in front of the links. Here is what I have:

var links = document.evaluate('..../td[1]/font//a[@href]', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var headings = document.evaluate('.../td[1]',document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
for(var i = 0; i < links.snapshotLength; i++){
  var urls = links.snapshotItem(i).href;
  GM_xmlhttpRequest({
    method: 'GET',
    url: urls,
    onload function (res){
      var dt = document.implementation.createDocumentType("html", 
          "-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd");
          doc = document.implementation.createDocument('', '', dt);
          html = doc.createElement('html');
          html.innerHTML = res.responseText;
          doc.appendChild(html);
      var responses = doc.evaluate('.../tr', doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
      var nResponse = responses.snapshotLength - 1;
      var numResponse = document.createElement('font');
      numResponse.innerHTML = 
       '<b>' + nResponse +
       '</b>' ;
      headings.snapshotItem(i).parentNode.insertBefore(numResponse, headings.snapshotItem(i));
    }
  });
}

And I got the error message:

TypeError: headings.snapshotItem(...) is null

Brock Adams
  • 90,639
  • 22
  • 233
  • 295

1 Answers1

3

There are at least 3 problems:

  1. Trying to pass a value to GM_xmlhttpRequest's onload without a closure.
  2. Looping on links, but trying to index headings.
  3. Missing colon after the onload property.

(1) GM_xmlhttpRequest operates asynchronously. Which means by the time onload fires that the variables i and headings will either be undefined or will be their ultimate value, not the loop value you want.

To pass a value to onload, use a closure. (In the code below, parseURL provides the closure.)

(2) The variable i is looping on links, but the code is trying to use it to index headings! It is very unlikely that there are the same number of each (and poor practice, even if there are). Is the "heading" always a parent of the link? If so use that.

Putting it all together, use code like this:

var links = document.evaluate (
    '..../td[1]/font//a[@href]', document, null, 
    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null
);
//-- "Headings" are relative to links

for (var J = links.snapshotLength - 1;  J >= 0;  --J) {
    var targUrl = links.snapshotItem (J).href;
    parseURL (targUrl, J);
}

function parseURL (targUrl, J) {
    GM_xmlhttpRequest ( {
        method: 'GET',
        url:    targUrl,
        onload: function (res) {
            var dt = document.implementation.createDocumentType (
                "html", "-//W3C//DTD HTML 4.01 Transitional//EN", 
                "http://www.w3.org/TR/html4/loose.dtd"
            );
            var doc         = document.implementation.createDocument ('', '', dt);
            var html        = doc.createElement ('html');
            html.innerHTML  = res.responseText;
            doc.appendChild (html);

            var responses = doc.evaluate (
                '.../tr', doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null
            );
            var nResponse = responses.snapshotLength - 1;
            var numResponse = document.createElement ('font');
            numResponse.innerHTML = '<b>' + nResponse + '</b>';

            var heading     = links.snapshotItem (J).parentNode.parentNode;
            heading.parentNode.insertBefore (numResponse, heading);
        }
    } );
}
Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • One more question, after I add these numbers to the page. The page loads very slowly.Is there anyway to speed up? run-at document-start can execute code before the page loaded but I still have some stuff to run at document-end. – wonderful93 Jul 08 '13 at 15:52
  • You may need to open a new question. In general: make sure not using GM_xmlhttpRequest in synch mode (it's off by default); make sure you're not running in iframes, unnecessarily; restrict processed links; start script after window load; Don't use XPath on the AJAX results. – Brock Adams Jul 08 '13 at 23:38