19

Other than using a timer to count the number of elements over time and looking for changes, I can't think of a better way to simulate this event.

Is there some sort of proprietary IE version of DOMNodeInserted? Thanks.

Joe Frambach
  • 25,568
  • 9
  • 65
  • 95
CPrimer
  • 623
  • 1
  • 6
  • 13

6 Answers6

7

No, there isn't. The nearest is the propertychange event, which fires in response to a change in an attribute or CSS property of an element. It fires in response to changing the innerHTML property of an element directly but not when the contents of the elements are altered by some other means (e.g. by using DOM methods such as appendChild() or by altering the innerHTML of a child element).

UPDATE 6 February 2014

As pointed out in the comments, there is a workaround. It's based on an elaborate hack and I'd recommend using mutation observers instead wherever possible. See @naugtur's answer for details. @naugtur's answer has been deleted but the solution can be found at https://github.com/naugtur/insertionQuery

Community
  • 1
  • 1
Tim Down
  • 292,637
  • 67
  • 429
  • 506
  • javascript:var div = document.createElement("div"); div.onpropertychange = function() { var e = window.event; alert(e.propertyName + ": " + this[e.propertyName]); }; document.body.appendChild(div); div.innerHTML = "Hello"; void(0); – Sean Hogan Sep 21 '11 at 01:19
  • @Sean: OK, I wasn't clear. What I meant was that `propertychange` does not fire for `innerHTML` when the content of an element changes by any means other than setting its `innerHTML` property directly, which makes it pretty much useless as a workaround for `DOMNodeInserted`: http://jsfiddle.net/eze5V/8/. I've updated my answer. – Tim Down Sep 21 '11 at 08:22
  • See my answer. It is possible to simulate this event and it has been done, although it is probably more effort than it is worth. – Sean Hogan Sep 21 '11 at 09:41
  • @Sean: I saw it. Overriding all DOM methods and properties that could change the DOM is simply not possible, so that's a non-starter as a general solution. – Tim Down Sep 21 '11 at 10:01
  • There is a solution for IE10+ http://stackoverflow.com/questions/2143929/domnodeinserted-equivalent-in-ie/21600446#21600446 – naugtur Feb 06 '14 at 10:41
  • @naugtur: Thanks. I did read about that a few weeks ago. The approach is clever but an obvious hack. I don't like it, but I guess it's better than nothing. – Tim Down Feb 06 '14 at 11:32
  • @TimDown This is more of an outside-of-the-box idea than a hack. It's based on a feature from spec that was implemented earlier, it has its pros (free CSS selectors) and cons (delay in firing the event up to 40ms) but it's much less of a hack than JSONP, and look at the adoption ;) – naugtur Feb 06 '14 at 11:34
  • @naugtur: I don't like JSONP either :) – Tim Down Feb 06 '14 at 11:49
  • @naugtur, where did this infamous "actual, if hacky but not actually hacky solution" go? – Brad Jun 12 '15 at 13:48
  • @Brad: naugtur's answer has been deleted but I can still see it. The solution can be found at https://github.com/naugtur/insertionQuery. – Tim Down Jun 12 '15 at 14:19
  • I had multiple answers pointing to insertionQuery, but they got deleted. I wanted to bring them back, but couldn't get moderator support for it. I gave up. Only one of them got brought back. But the lib is working and stable. – naugtur Jun 13 '15 at 20:02
6

You can over-ride all the DOM-manipulation methods - appendChild, insertBefore, replaceChild, insertAdjacentHTML, etc - and monitor innerHTML with onpropertychange.

You might be able to come up with a solution that satisfies your requirements.

BTW, it seems that DOMNodeInserted, etc will be deprecated by browsers in the future. See http://www.w3.org/TR/DOM-Level-3-Events/#events-mutationevents

Sean Hogan
  • 2,816
  • 22
  • 22
  • just curious, where did you see the deprecation part about DOMNodeInserted? – Anurag Apr 14 '10 at 14:50
  • 3
    @Anurag Note: The MutationEvent interface was introduced in DOM Level 2 Events, but has not yet been completely and interoperably implemented across user agents. In addition, there have been critiques that the interface, as designed, introduces a performance and implementation challenge. A new specification is under development with the aim of addressing the use cases that mutation events solves, but in more performant manner. Thus, this specification describes mutation events for completeness, but deprecates the use of both the MutationEvent interface and the MutationNameEvent interface. – PetersenDidIt May 21 '10 at 14:38
  • 2
    Any idea what that new specification might be, or where it's implemented? – Kragen Javier Sitaker Mar 09 '11 at 15:58
  • "monitor innerHTML with onpropetrychange." - I don't understand. onproperychange will not fire if innerHTML is changed (http://msdn.microsoft.com/en-us/library/ms536956(v=vs.85).aspx) – ripper234 Sep 19 '11 at 11:25
  • @ripper234: From the page you referenced: "Changing the innerText or innerHTML of *child* elements will not cause the onpropertychange event to fire for the *parent* element. " – Sean Hogan Sep 21 '11 at 01:07
3

onreadystatechange will work in IE. A DHTML behavior must be attached to the element via htc, but the htc file does not have to exist:

if (!!document.addEventListener)
  {
  $(domnode).get(0).addEventListener("DOMNodeInserted", fixtext, false);
  }
else
  {
  $(domnode).get(0).addBehavior("foo.htc");
  $(domnode).get(0).attachEvent("onreadystatechange", fixtext);
  }

onreadystatechange event reference

Paul Sweatte
  • 22,871
  • 7
  • 116
  • 244
1

A dirty workaround is to intercept the prototype methods of type Element as follows:

window.attachEvent('onload', function() {
    invokeNodeInserted(document);
    (function(replace) {
        Element.prototype.appendChild = function(newElement, element) {
            invokeNodeInserted(newElement);
            return replace.apply(this, [newElement, element]);
        };
    })(Element.prototype.appendChild);
    (function(replace) {
        Element.prototype.insertBefore = function(newElement, element) {
            invokeNodeInserted(newElement);
            return replace.apply(this, [newElement, element]);
        };
    })(Element.prototype.insertBefore);
    (function(replace) {
        Element.prototype.replaceChild = function(newElement, element) {
            invokeNodeInserted(newElement);
            return replace.apply(this, [newElement, element]);
        };
    })(Element.prototype.replaceChild);
});
Tires
  • 1,153
  • 13
  • 22
0

Using onreadystatechange as suggested by Paul Sweatte does not really work. The readystatechange event is only triggered while loading foo.htc. It has nothing to do with changing the DOM node.

I've set up a little fiddle to demonstrate it. Have a look at http://jsfiddle.net/Kermit_the_frog/FGTDv/ or http://jsfiddle.net/Kermit_the_frog/FGTDv/embedded/result/.

HTML:

<input type="button" id="fooBtn" value="add" />
<div id="fooDiv"></div>

JS/Jquery:

function bar(e) {
    var state = $('#fooDiv').get(0).readyState;
    alert (state);
}

$("#fooBtn").on("click", function(){
    $('#fooDiv').get(0).addBehavior("foo.htc");
    $('#fooDiv').get(0).attachEvent("onreadystatechange", bar);
});

As you can see: even though there is no DOM manipulation going on there is a readystatechange event.

Lance Roberts
  • 21,279
  • 29
  • 106
  • 128
-2

Seems, DHTML Behaviors can be used in IE to emulative DOMNodeInserted.

axel22
  • 31,198
  • 9
  • 120
  • 134
4esn0k
  • 151
  • 1
  • 3