0

I write a lot of small GreaseMonkey UserScripts, usually for myself. Even though they do their job, there's one small problem I can't get my head around:

How do I deal with dynamically changing websites?

Example, webstores like Amazon don't directly reload everything anymore when clicking on "Next Page" and instead only update the actual entries dynamically. I have a script to highlight a few things, but every time I switch to a new page I have to F5 the entire page.

Right now I do this via an onclick Event and then a 3-seconds timeout before reapplying the script, but I feel like it's rather "dirty". Are there any cleaner methods?

Selbi
  • 813
  • 7
  • 23
  • Which browser do you use? Chrome or Firefox? – Long Nguyen Nov 18 '15 at 08:55
  • 1
    New content loaded this way must be done using ajax. Try and see if you can't modify this ajax function to automatically call your script on success of this ajax call instead of on click, it should be much 'cleaner' – user4467065 Nov 18 '15 at 09:01
  • 1
    @LongNguyen He uses GreaseMonkey so I guess he uses Firefox. – Delgan Nov 18 '15 at 09:13

1 Answers1

0

The answer below is DEPRECATED. You should use Use MutationObserver or setInterval instead. See this: Greasemonkey script to work on dynamically loaded posts on Facebook


Since you are using Firefox, you can trigger off the DOMSubtreeModified event.

To do this, first wrap the code part of your current script in a function; for example:

// ==UserScript==
// @name
// ==/UserScript==

function LocalMain ()
{
    //--- Do all of your actions here.
}

LocalMain (); //-- Fire GM script once, normally.

Next, find DOM node changed when clicking on "Next Page". Once you've identified the correct node, you can set the event listener. But, you also need a short time delay because the node changes come hundreds at a time and you need to wait until the current batch is done.

So, putting it all together, the code looks like this:

if (window.top != window.self)  //don't run on frames or iframes
    return;

function LocalMain ()
{
    //--- Do all of your actions here.
}

LocalMain (); //-- Fire GM script once, normally.


var ContentChangedByAJAX_Timer    = '';
//--- Change this next line to find the correct element; sample shown.
var ContentWrapperNode           = document.getElementById ('THE ID OF DOM NODE GOT UPDATE WHEN CLICKING ON NEXT PAGE');

ContentWrapperNode.addEventListener ("DOMSubtreeModified", PageBitHasLoaded, false);


function PageBitHasLoaded (zEvent)
{
    /*--- Set and reset a timer so that we run our code (LocalMain() ) only
        AFTER the last post -- in a batch -- is added.  Adjust the time if needed, e.g. 3 seconds.
    */
    if (typeof ContentChangedByAJAX_Timer == "number")
    {
        clearTimeout (ContentChangedByAJAX_Timer);
        ContentChangedByAJAX_Timer  = '';
    }
    ContentChangedByAJAX_Timer      = setTimeout (function() {LocalMain (); }, 3000);
}
Community
  • 1
  • 1
Long Nguyen
  • 11,075
  • 2
  • 18
  • 25
  • 2
    This code is from 5 years ago? It's horrendous. Stop using the deprecated and slow `DOMSubtreeModified` and similar mutation events. Use MutationObserver or setInterval. – wOxxOm Nov 18 '15 at 10:27
  • 1
    The author of that code already provides another easy-to-use function: [waitForKeyElements](https://gist.github.com/2625891). – wOxxOm Nov 18 '15 at 10:33