Search code examples
javascriptxpathxhtmlgreasemonkeyweibo

XPath, in a Greasemonkey script, is not selecting right nodes on an XHTML page


I'm working on a Greasemonkey script for weibo.com. I can't pick the elements using XPath on the XHTML page.

This code fails to grab the elements I want:

function resolver(prefix) {
    return prefix === 'x' ? 'http://www.w3.org/1999/xhtml' : null;
}
var allLinks, thisLink;
allLinks = document.evaluate(
  "//x:a[@href]", 
  document, 
  resolver, 
  XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, 
  null 
);

Only the <a> elements on the sidebar are picked and the rest are still there. Please refer to this, weibo.com, target page. 

Is there anyway to pick all the elements with attribute action-type="login"?

I used "//x:a[@action-type='login']", but It didn't work.


Solution

  • The problem is that the script is running before all of these nodes are added to the page. They are added by the page's AJAX later.

    So, you could add a time-delay to your script. But:

    1. If you just want to grab select elements, you almost never need to use XPath. Use querySelectorAll() or jQuery instead. Here's a basic example with querySelectorAll and no time delay:

      var allLinks = document.querySelectorAll ("a[action-type='login']");
      if (allLinks.length) {
          // PROCESS NODES AS DESIRED, HERE.
      }
      


    2. Here's a complete Greasemonkey script, that handles the delayed content problem using jQuery and the waitForKeyElements() utility:

      // ==UserScript==
      // @name        _Weibo, hilite login links
      // @include     http://s.weibo.com/weibo/*
      // @require     http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
      // @require     https://gist.github.com/raw/2625891/waitForKeyElements.js
      // @grant    GM_addStyle
      // ==/UserScript==
      /*- The @grant directive is needed to work around a design change
          introduced in GM 1.0.   It restores the sandbox.
      */
      
      function processLoginLinks (jNode) {
          //***** YOUR CODE HERE *****
          jNode.css ("background", "lime");
      }
      
      waitForKeyElements ("a[action-type='login']", processLoginLinks);