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?

Answers:

Answer

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.
}
Answer

"I've noticed the URL does change each time" with a lot of AJAX would lead me that they are using the History API. If that's the case, take a look at window.onpopstate. That should fire on each URL change using the History API.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.