Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I reload a Greasemonkey script when AJAX changes the URL without reloading the page?

I have an application that I am trying to create a Greasemonkey script for. It utilizes a lot of jQuery and AJAX to load content dynamically.

I've noticed that the URL does change each time I load a new item, even though the page doesn't refresh.

Is there a listener I can place on the page to relaunch the script each time the URL changes?

like image 730
Sugitime Avatar asked Sep 24 '13 18:09

Sugitime


1 Answers

How you do this depends on the site/application and on what you are trying to do. Here are your options, easiest and most robust first:

  1. Don't try to catch URL changes. Use calls to waitForKeyElements() to act on the parts of the various pages that you wanted to manipulate in the first place. This neatly handles a whole slew of timing issues inherent with all the other approaches.
    See also: "Choosing and activating the right controls on an AJAX-driven site".

  2. Just poll for URL changes. It's simple and works well in practice, with fewer timing issues than all but technique #1.

  3. If the site uses AJAX that changes the fragment (AKA "hash"), fire on the hashchange event. Alas, fewer and fewer AJAX sites do this.

  4. Use Mutation Observers to monitor changes to the <title> tag. Most AJAX pages are nice enough to change the title too. This may fire before your target content is loaded, though.

  5. Hack into the history.pushState function. This gives faster notice of page changes, BUT 95% of the time, it fires before your target elements have loaded. You will usually still need a timer. Plus, it brings in cross-scope problems, in a userscript environment.


For reference, here is a polling example. It's still the best, bare-bones, cross-browser, catch-all method:

/*--- Note, gmMain () will fire under all these conditions:
    1) The page initially loads or does an HTML reload (F5, etc.).
    2) The scheme, host, or port change.  These all cause the browser to
       load a fresh page.
    3) AJAX changes the URL (even if it does not trigger a new HTML load).
*/
var fireOnHashChangesToo    = true;
var pageURLCheckTimer       = setInterval (
    function () {
        if (   this.lastPathStr  !== location.pathname
            || this.lastQueryStr !== location.search
            || (fireOnHashChangesToo && this.lastHashStr !== location.hash)
        ) {
            this.lastPathStr  = location.pathname;
            this.lastQueryStr = location.search;
            this.lastHashStr  = location.hash;
            gmMain ();
        }
    }
    , 111
);

function gmMain () {
    console.log ('A "New" page has loaded.');
    // DO WHATEVER YOU WANT HERE.
}
like image 168
Brock Adams Avatar answered Nov 19 '22 21:11

Brock Adams