6

I need a way to listen for changes for when a node's children are removed or added. I made an autoscrolling plugin that keeps an element scrolled to the bottom as new items are added. The event I'm listening to is DOMNodeInserted and DOMNodeRemoved.

I was looking for polyfills for DOMNodeInserted and DOMNodeRemoved. Looking around I wasn't able to find any that already existed. The event is not supported in all browsers and is currently deprecated.I have a simple (likely naive) polyfill I wrote quickly but I doubt it works (well).

I know these events are deprecated, but is there a better way to listen for element children changes?

(function() {
    var works = false;
    var $test = document.createElement("div");
    var $testchild = document.createElement("a");

    $test.addEventListener("DOMNodeInserted", function() {
        works = true;
    }, false);

    $test.appendChild($testchild);

    if(!works) {
        var nodeproto = Node.prototype;
        var nativeAppend = nodeproto.appendChild;
        var nativeRemove = nodeproto.removeChild;

        nodeproto.appendChild = function() {
            nativeAppend.apply(this, arguments);
            this.fireEvent("DOMNodeInserted");
        };

        nodeproto.removeChild = function() {
            nativeRemove.apply(this, arguments);
            this.fireEvent("DOMNodeRemoved");
        };
    }
})();
megawac
  • 10,953
  • 5
  • 40
  • 61
  • 1
    There's always the [`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) object for **modern browsers**. For old browsers you have no other choice than using an override approach, however like you said it might be hard to implement something that will work cross-browser because not all browsers will expose the DOM objects such as `Element`. – plalx Nov 13 '13 at 20:23
  • That's true - probably be better to polyfill the mutationobserver as it will not apply to node's we're not watching. I also saw some keyframe animation hack methods but I don't think I could get them working for ie>7 – megawac Nov 13 '13 at 20:30
  • It will be even harder to polyfill the `MutationObserver`. At a small scale you could always use `observedEl.cloneNode()` to take a snapshot of the node at specific intervals and recursively compare the `childNodes` with the live element. If you know which targets might be observed, you can then do something like `startObserving(node)` which would fire `DOMNodeInserted`/`DOMNOdeRemoved` events on these nodes when a change is detected. – plalx Nov 13 '13 at 20:42
  • I found a few mutationobserver polyfills which already exist and fall back on the inserted/remove event http://codereview.stackexchange.com/questions/18269/simple-dom-mutation-abstraction https://github.com/Polymer/MutationObservers. Guess I'll look into these, thanks @plalx – megawac Nov 13 '13 at 20:49
  • Unfortunately I believe these are built upon other features that aren't supported by old browsers either, but give it a try. – plalx Nov 13 '13 at 20:59
  • https://github.com/WebReflection/document-register-element/blob/master/src/dre-ie8-upfront-fix.js – 4esn0k Sep 26 '15 at 04:07

1 Answers1

2

I ended up writing a reasonably compliant polyfill for MutationObserver using interval checks of a cloned childList (similar to what @plalx mentioned in his comments) instead of falling back on the MutationEvents. MutationEvents will be more performant for most scenarios as any poll vs interrupt implementations but compatibility sucks

Simple auto scrolling example using my shim

megawac
  • 10,953
  • 5
  • 40
  • 61