0

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.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Spevak
  • 55
  • 5
  • A script placed at the end of the document will run before the first 'render' but after all the elements are created. Since this is a new page load it can be assumed that all the current elements have just been 'added', which may be a usable approach. – user2864740 Jul 09 '15 at 21:50
  • You might want to have a look at web components. – Bergi Jul 09 '15 at 22:10

2 Answers2

0

Maybe you are asking the wrong question? Why not load the page with whatever shell or bare-bones frame you need and then use something like AngularJS to render what you need dynamically? You don't necessarily need a server for something like that.

Rob
  • 612
  • 1
  • 7
  • 11
0

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.

Mindastic
  • 4,023
  • 3
  • 19
  • 20
  • I would like to use this approach, but I can't find an event that fires when the element is first added to the DOM – Spevak Jul 09 '15 at 23:28
  • As I mentioned in the original question, I tried DOMNodeInserted, but it did not work for me. I was not able to capture any DOMNodeInserted events while the document was loading the first time. After the DOM has loaded, inserting new nodes asynchronously fired the event, but that is not what I'm looking for. I need an event that fires as the original DOM elements are loaded. – Spevak Jul 10 '15 at 01:08
  • I think i found a possible solution for you. Based on this link (http://davidwalsh.name/detect-node-insertion) , i created the following jsFiddle (http://jsfiddle.net/0y4jet4L/) and it seems to work (at least with what i tested). This may not be the best solution, but it might help :) – Mindastic Jul 10 '15 at 01:34
  • Cool find! After some initial tests it looks like even with this method, the events get handled after the document.readyState changes to 'complete.' But this seems like the closest to what I'm trying to achieve. Reacting earlier than this is probably not possible. – Spevak Jul 10 '15 at 17:58