javascripteventsdomdomready

Is it possible to respond to elements being added to the DOM before the document load event is fired in Javascript?


I'm trying to make a javascript embed that will manipulate the page as it loads. The script is in the header, and I want it to be able to manipulate an element as soon as it can be found by document.querySelector. In other words, it needs to react to changes in the DOM while the document.readyState is "interactive", before it is "loaded". I can't use a timeout/interval because the document loading blocks until the full document is loaded, so if I put a timeout of 0ms it will not execute until the document.readyState is "loaded".

Are there any events that fire as elements are added to the DOM? I tried DOMNodeInserted, but it seems to only fire for elements added asynchronously after the document is loaded.

Lastly, this must be accomplished with only javascript; I do not have access to the html or server. The embed is going on other people's sites.


Solution

  • You should attach the events to the document itself and then check the event's target and, in case it is what you need, perform the action you want. For example:

    document.addEventListener("click", function(e){
      var element = e.target;
      if (element.nodeName === "A") {
        //I am gonna do something with <a> elements
        //Don't forget to return true if it is an anchor and you want the default event to trigger because if not, it will cancel the event.
    
      } else if (element.className.match("myClass")) {
        //OK, this element contains the class i am looking for, let's do something with it
      } else if (element.id === "myId") {
        //I finally found the element with the ID i was looking for
      }
    });
    

    Update (For nodes insertion):

    document.addEventListener("DOMNodeInserted", function(e){
          // e is a MutationEvent
          var element = e.target;
          //Behavior here is pretty much the same as above
          if (element.nodeName === "A") {
            //I am gonna do something with <a> elements
            //Don't forget to return true if it is an anchor and you want the default event to trigger because if not, it will cancel the event.
    
          } else if (element.className.match("myClass")) {
            //OK, this element contains the class i am looking for, let's do something with it
          } else if (element.id === "myId") {
            //I finally found the element with the ID i was looking for
          }
        });
    

    Another update:

    I found this link that may result interesting. It uses animations to determine when an object has been inserted into the DOM. I created a fiddle with a little POC and it seems to do what you want.