Adam Taylor
Adam Taylor

Reputation: 7783

Why isn't this chrome / Greasemonkey script executing?

I have the following simple Greasemonkey script:

// ==UserScript==
// @name MetaCPAN Everywhere
// @description Add to every link to CPAN a link to MetaCPAN on a Google results page.
// @namespace http://ajct.info
// @match http://*/*
// @version 0.1
// ==/UserScript==

(function() {

    var page_links = document.links;
    for (var i=0; i<page_links.length; i++){
        if (page_links[i].href.match(/http:\/\/search\.cpan\.org\/perldoc\?(.*?)$/i)) {
            var match = page_links[i].href.match(/http:\/\/search\.cpan\.org\/perldoc\?(.*?)$/i);
            var span = document.createElement("span");
            span.innerHTML = "&nbsp; <a href=\"http://www.metacpan.org/module/"+match[1]+"\">MetaCPAN</a>";
            page_links[i].parentNode.insertBefore(span, page_links[i].nextSibling);
        }
    }

})();

If I run the JavaScript snippet through firebug it does the right thing but if I install it and visit the search results page it doesn't seem to execute the script.

It's presumably something trivial but can anyone point out what I missed?

Upvotes: 1

Views: 267

Answers (2)

Brock Adams
Brock Adams

Reputation: 93473

The main thing is that Google ajaxes-in just about all of its results, so you need a way to wait for the first batch and to check for later batches.

There are numerous techniques. A simple one is to use a timer:

//--- This handles both page-load delays, and AJAX changes.
var chkInterval = setInterval (checkForResultsLinks, 500);

function checkForResultsLinks () {
    var links = document.querySelectorAll ('#search a');
    if (links) {

        for (var J = links.length - 1;  J >= 0;  --J) {
            var link    = links[J];

            if (link.weHaveProcessed) 
                continue;

            if (link.href.match (/http:\/\/search\.cpan\.org\/perldoc\?(.*?)$/i) ) {
                var match   = link.href.match (/http:\/\/search\.cpan\.org\/perldoc\?(.*?)$/i);
                var span    = document.createElement("span");
                span.innerHTML = "&nbsp; <a href=\"http://www.metacpan.org/module/"+match[1]+"\">MetaCPAN</a>";
                link.parentNode.insertBefore (span, link.nextSibling);
                link.weHaveProcessed = true;
            }
        }
    }
}


Notes:

  1. Google search results appear inside a div with the id, "search".
  2. Best add the // @run-at document-end directive to this kind of script.
  3. The current script's@match directive is overly broad, the script will fire on every web page!
    You probably want to restrict it to:

    // @match http://www.google.com/*
    // @match http://google.com/*
    
  4. There is no need or point to wrapping the code in an anonymous function, like: (function() { ... })(); .

Upvotes: 1

Philbert McPleb
Philbert McPleb

Reputation: 325

I found that some scripts although really simple wouldn't run in chrome, however I did find a chrome extension that fully supports greasemonkey scripts, it's called Tampermonkey

Upvotes: 1

Related Questions