title: Element location inside the DOM
body: <p>I'm trying to develop such thing as recording of user's actions on the website.</p>
  
  <p>Assuming I have the next (simplified) HTML page, at which recording is performing:</p>
  
  <pre><code>&lt;html&gt;
      &lt;head&gt;
          &lt;title&gt;Some title&lt;/title&gt;
          &lt;link rel="stylesheet" href="somestyle.css" /&gt;
          &lt;script src="myrecordscript.min.js"&gt;&lt;/script&gt;
      &lt;/head&gt;
      &lt;body&gt;
          &lt;h1&gt;Some header&lt;/h1&gt;
          &lt;p&gt;Lorem ipsum dolor sit amet&lt;/p&gt;
          &lt;button id="appearModal"&gt;appear modal window&lt;/button&gt;
      &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>When the page loads, I send initial markup to the server, then create a <code>MutationObserver</code> that observes <code>document.documentElement</code>, so I have all the mutations observed inside the document.</p>
  
  <p>With this JavaScript functions, for example, I can get the index path of inserted element </p>
  
  <pre><code>/* somewhere inside the ES6 class */
  getElementIndex = (element) =&gt; {
      return element.parentElement ? [...element.parentElement.children].indexOf(element) : 0
  }
  getInsertedPath = (mutation) =&gt; {
      var target = mutation.addedNodes[0]
      var parent = (mutation.previousSibling || mutation.nextSibling) ? (mutation.previousSibling || mutation.nextSibling).parentElement : mutation.target
      var indexPath = []
      if (!parent)
          return indexPath
  
      if (!mutation.previousSibling)
          indexPath.push(-1)
      else
          indexPath.push(this.getElementIndex(target) - 1)
  
      while (parent) {
          indexPath.push(this.getElementIndex(parent))
          parent = parent.parentElement
      }
  
      return indexPath.reverse()
  }
  </code></pre>
  
  <p>For example, assuming that modal window is appending at the end of <code>body</code>, <code>getInsertedPath</code> will return an array <code>[0, 1, 2]</code>, that means that I should insert modal's markup after the next element:</p>
  
  <pre><code>document.children[0].children[1].children[2]
  </code></pre>
  
  <p>And everything was fine until I found that different <s>foken awesome</s> awful browser's extensions are modifying the markup incorrectly. For example, Ghostery extension for Chrome adding extra <code>div</code> BETWEEN THE <code>head</code> and <code>body</code> (sic!), i.e. I got the next initial markup:</p>
  
  <pre><code>&lt;html&gt;
      &lt;head&gt;
          &lt;title&gt;Some title&lt;/title&gt;
          &lt;link rel="stylesheet" href="somestyle.css" /&gt;
          &lt;script src="myrecordscript.min.js"&gt;&lt;/script&gt;
      &lt;/head&gt;
      &lt;div id="anotherAwesomeGhosteryButtonOrSomething"&gt;&lt;/div&gt;
      &lt;body&gt;
          &lt;h1&gt;Some header&lt;/h1&gt;
          &lt;p&gt;Lorem ipsum dolor sit amet&lt;/p&gt;
          &lt;button id="appearModal"&gt;appear modal window&lt;/button&gt;
      &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>which results that <code>getInsertedPath</code> returns <code>[0, 2, 2]</code>.
  Fine, sounds like there is no problem. But when I try to recreate recording from it's data, I got that when I insert an invalid HTML into <code>iframe</code>, browsers (tested in Chrome and Firefox) are automatically fixing it, and instead I got this:</p>
  
  <pre><code>&lt;html&gt;
      &lt;head&gt;
          &lt;title&gt;Some title&lt;/title&gt;
          &lt;link rel="stylesheet" href="somestyle.css" /&gt;
          &lt;script src="myrecordscript.min.js"&gt;&lt;/script&gt;
      &lt;/head&gt;
      &lt;body&gt;
          &lt;div id="anotherAwesomeGhosteryButtonOrSomething"&gt;&lt;/div&gt;
          &lt;h1&gt;Some header&lt;/h1&gt;
          &lt;p&gt;Lorem ipsum dolor sit amet&lt;/p&gt;
          &lt;button id="appearModal"&gt;appear modal window&lt;/button&gt;
      &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>and it (obviously) breaks everything, because now I got <code>undefined</code> at <code>document.children[0].children[2]...</code></p>
  
  <p>Is there any other way to get the element position (more safely and more resistant to this kind of unexpected behaviours)?</p>