Search code examples
greasemonkeyuserscriptstampermonkey

In a Greasemonkey script, how can I target a page by its elements?


I would like to change a page using a Greasemonkey script, but the page is the result of a CGI POST call and thus the URL looks like this:

http://www.example.com/cgi-bin/foo.pl

So obviously I cannot use the @include in the Greasemonkey script, because that URL fits a lot of pages the app can generate.

I could just look for some elements on the page within the script before doing stuff:

if (document.getElementById('someIdentifier')) {
  // do changes in here
}

But I was wondering if there is a better, maybe built-in way to do this.


Solution

  • Greasemonkey (and most userscript engines) has no built-in way to target a page by its elements. Your script needs to poll or use mechanisms like Mutation Observers to check for the desired elements.

    A handy way to do this is to use the waitForKeyElements() utility, and you still want to use the @include, @exclude, and/or @match directives to narrow down the page firings as much as possible.

    Here is a complete Greasemonkey/Tampermonkey script illustrating the process:

    // ==UserScript==
    // @name     _Do something after select posts
    // @include  http://www.example.com/cgi-bin/foo.pl*
    // @require  http://ajax.googleapis.com/ajax/libs/jquery/1.8.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 processTargetElement (jNode) {
        //***** YOUR CODE HERE *****
        jNode.css ("background", "pink");   
    }
    
    waitForKeyElements ("#someIdentifier", processTargetElement);