6

I know this could be handled in some way, but as of now, this is giving me a real hard time. I am writing a script and want to fire some particular functions when a DOM manipulation is complete. I cannot modify/add/remove any other script (as it might be injected into the page using some framework). The page is using ajax requests(not implemented in jQuery) to load/modify content. Now I want an event to be triggered when every DOM modification has been completed. My current approach is to fire the function at every DOMSubtreeModified event. Something like this

$(document).bind('DOMSubtreeModified', doSomeStuff);

But the drawback of this approach is, let say the ajax loads 10 elements in a call, then for each element doSomeStuff is fired. Can this be limited to only firing after the 10th element is loaded? Something like resetting the $(document).ready() event? so $(document).ready() is fired every time the DOM is ready (after loading ajax content)

whizzzkid
  • 1,174
  • 12
  • 30
  • DOMSubtreeModified is deprecated http://stackoverflow.com/questions/6659662/why-is-the-domsubtreemodified-event-deprecated-in-dom-level-3 and there are recommendations to use this instead http://updates.html5rocks.com/2012/02/Detect-DOM-changes-with-Mutation-Observers – Bernhard Oct 26 '13 at 11:30
  • @Bernhard DOMSubtreeModified still works with chrome, still how does mutation observers can tell me if the document is ready again? – whizzzkid Oct 26 '13 at 11:39

3 Answers3

2

With the Mutation Observer you can listen on changes and if the event is fired the document was changed.

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var observer = new MutationObserver(function(mutations, observer) {
    // Add the actions to be done here if a changes on DOM happened 
    console.log(mutations, observer);

});

// Register the element root you want to look for changes
observer.observe(document, {
  subtree: true,
  attributes: true
});
Bernhard
  • 4,855
  • 5
  • 39
  • 70
  • Totally valid, but I do not want it to fire up at every dom change. how about only firing at dom change complete?... something like ajaxComplete in jQuery but without jQuery... listening to all content loading... – whizzzkid Oct 26 '13 at 12:02
  • @whizzkid There's no event for all dome changes complete. This answear only watch if a single change is complete/happened. So if you need a listener for completion of an unknown number of changes you have to create a counter or something else and reduce the counter until 0 inside the observer callback. If it's 0 you know any change is complete. But thats not a good thing and better callback oriented architecture is more reasonable. – Bernhard Oct 26 '13 at 12:05
  • can something like $(document).ready() be reinitialized to fire again when ready again? – whizzzkid Oct 26 '13 at 12:07
  • No because document ready is quietly different from what you're trying to do. And there are reasons why javascript has a wide range of events to handle instead of a single one – Bernhard Oct 26 '13 at 12:09
  • don't explicitly take it to be "ready"... let's say fire event when dom completes loading new stuff. – whizzzkid Oct 26 '13 at 12:23
  • That's it.. your DOM dont load stuff... E.g. Ajax is able to load stuff.. and so there's an event for ajaxComplete. Or if you listen to an event e.g. click and insert something into your DOM that's all handled inside the registered callback for the click event. – Bernhard Oct 26 '13 at 12:26
  • For example if you change the DOM whats your definition of "changes are complete"? e.g. You insert things into the DOM by interval that's let the never fire your prefered complete event? – Bernhard Oct 26 '13 at 12:28
1

In jQuery, there is a method ajaxComplete, which calls a given function after every finished AJAX call. See more here.

I'd suggest to use jQuery or (in case this is not an option) analyze source code of this function to see how it's done there.

Michał Rybak
  • 8,648
  • 3
  • 42
  • 54
  • I was unsuccessful at implementing this. Does this only listens to jQuery ajax requests?... because the page in concern is not using jQuery's ajax function. – whizzzkid Oct 26 '13 at 11:41
  • the documentation says `Now, make an Ajax request using any jQuery method` so yes, I think it works only with jQuery requests. The deeper look at the sources might help :) – Michał Rybak Oct 26 '13 at 11:45
  • if you don't go with jQuery, don't expect things to be easy ;) take a look at $.ajax [source code](http://james.padolsey.com/jquery/#v=1.10.2&fn=jQuery.ajax), analyze all occurences of `fireGlobals`. Triggering `ajaxComplete` is just one line of code that has to be put in your AJAX requests ;) – Michał Rybak Oct 26 '13 at 11:55
  • Let's say I am building an extension, which cannot control how page is loading stuff. But I want to execute it only when the dom has completed loading the request. how about it? – whizzzkid Oct 26 '13 at 12:00
  • I am pretty much successful this way. Thanks for your answer. You deserve more +. – Rubyrider Jun 26 '14 at 14:42
0

I know I'm a bit late to the party, but it sounds like you may want to debounce your doSomeStuff function. If you're not opposed to introducing a dependency upon Underscore.js, it has a nice debounce function.

Tim Lowrimore
  • 2,024
  • 1
  • 17
  • 9