0

When writing user scripts for various websites I often come across the problem of dealing with elements or JS functions that don't exist yet at the time of execution. I'd like to know how to get to those functions or elements.
An obvious solution is a setTimeout, but that's very inelegant. I've also experimented with the various events like DOMContentLoaded and window.onload, but I often find that these events are still too early, due to content and code being dynamically generated/loaded afterwards.

Protector one
  • 6,926
  • 5
  • 62
  • 86
  • implement custom events: http://stackoverflow.com/questions/2059456/how-do-i-create-a-custom-event-class-in-javascript – zamnuts Dec 06 '13 at 12:25
  • Wha…? How would I know when to fire it?? – Protector one Dec 06 '13 at 12:26
  • If you have access to the code that is dynamically generated/loaded after dom ready, trigger the custom event. you should also listen for the event before the dynamic content has begun to load. alternatively using `setInterval` to keep checking for the existence of what you want should do the trick, although this will cause quite a bit of overhead (relatively speaking) - subsequently clear the interval when successful. – zamnuts Dec 06 '13 at 12:29
  • There's an event called `DOMSubtreeModified`. IIRC, I have read somewhere that its deprecated. This will probably work for you. – UltraInstinct Dec 06 '13 at 12:36
  • For elements, you can use Mutation Observers. For javascript you could use intercept and replace **on Firefox only**. Otherwise in both cases, interval polling is really the best, most robust, and straightforward solution. See the [the waitForKeyElements() utility](http://stackoverflow.com/a/11197969/331508) for an easy implementation. (It's for elements. Adapt it for JS objects too, if needed.) – Brock Adams Dec 06 '13 at 20:34

2 Answers2

1

Make sure that whatever you're loading emits an event, that you can hook into.

If you're loading a script file you can hook into the onload event. If you do an AJAX call you can hook into the onreadystatechange event.

These are some useful native events.

You can also make more custom events by using Promises.

var modules = {/* */};
var foo = modules.load("foo"); // returns a promise
foo.done(function (foo_module) {
    // we now have the foo-module
});

requirejs might be worthwhile to look at, just to see how they do things.

As for promises, this is a good read: What’s so great about JavaScript Promises?

Halcyon
  • 57,230
  • 10
  • 89
  • 128
  • 1
    The OP can't "Make sure that whatever you're loading emits an event, that you can hook into." This is a **userscripts** question. The OP does not control the target page. – Brock Adams Dec 06 '13 at 20:24
  • In that case, I like the idea of using mutation observers. My answer doesn't change much, just that origin of your event is 2nd-hand. – Halcyon Dec 08 '13 at 01:20
0

Make sure you're not doing something wrong before jumping to conclusions. Like, remember that user scripts in Chrome for example, are sandboxed, and you'll need to jump through a hoop or two to even access code on the target page. For small scripts, I suggest the "Location Hack". https://stackoverflow.com/a/5006952/125938

Community
  • 1
  • 1
Protector one
  • 6,926
  • 5
  • 62
  • 86