This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan
<p>In my trials and tribulations to detect when a field has been autofilled,
I need to create a shim for <a href="https://paul.kinlan.me/monitoring-all-events-on-an-element/"><code>monitorEvents</code></a>
so that I can see the event life-cycle of that element and ultimately try to
debug it.</p>
<p>One thing that I found is that <code>monitorEvents</code> requires an element but for what
I am doing I know that there will be an element with an id at some point but
I don't know when it will be created.</p>
<p>I quickly knocked out a small function called <code>waitForElement</code> that uses
the <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"><code>MutationObserver</code></a>
to look for when an element with a given <code>id</code> is added to the DOM. When that
element has been detected it will resolve the promise and return the element.</p>
<p>The code is as follows:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">waitForElement</span>(<span style="color:#a6e22e">selector</span>) {
<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> Promise(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">resolve</span>, <span style="color:#a6e22e">reject</span>) {
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">element</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#a6e22e">selector</span>);
<span style="color:#66d9ef">if</span>(<span style="color:#a6e22e">element</span>) {
<span style="color:#a6e22e">resolve</span>(<span style="color:#a6e22e">element</span>);
<span style="color:#66d9ef">return</span>;
}
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">observer</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">MutationObserver</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">mutations</span>) {
<span style="color:#a6e22e">mutations</span>.<span style="color:#a6e22e">forEach</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">mutation</span>) {
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">nodes</span> <span style="color:#f92672">=</span> Array.<span style="color:#a6e22e">from</span>(<span style="color:#a6e22e">mutation</span>.<span style="color:#a6e22e">addedNodes</span>);
<span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">node</span> <span style="color:#66d9ef">of</span> <span style="color:#a6e22e">nodes</span>) {
<span style="color:#66d9ef">if</span>(<span style="color:#a6e22e">node</span>.<span style="color:#a6e22e">matches</span> <span style="color:#f92672">&&</span> <span style="color:#a6e22e">node</span>.<span style="color:#a6e22e">matches</span>(<span style="color:#a6e22e">selector</span>)) {
<span style="color:#a6e22e">observer</span>.<span style="color:#a6e22e">disconnect</span>();
<span style="color:#a6e22e">resolve</span>(<span style="color:#a6e22e">node</span>);
<span style="color:#66d9ef">return</span>;
}
};
});
});
<span style="color:#a6e22e">observer</span>.<span style="color:#a6e22e">observe</span>(document.<span style="color:#a6e22e">documentElement</span>, { <span style="color:#a6e22e">childList</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span>, <span style="color:#a6e22e">subtree</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span> });
});
}
</code></pre></div><p><a href="https://gist.github.com/PaulKinlan/2d7cd4e78a63a97387137a0a9fb7ee6e">Here is the gist if that is your bag</a>.</p>
<p>It is pretty simple to use this simple API.</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#a6e22e">waitForElement</span>(<span style="color:#e6db74">"#test"</span>).<span style="color:#a6e22e">then</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">element</span>) {
<span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">"Element Added"</span>, <span style="color:#a6e22e">element</span>);
});
</code></pre></div><p>Now combining in the <a href="https://paul.kinlan.me/monitoring-all-events-on-an-element/"><code>monitorEvents</code></a>
function from my previous post, I can now set a breakpoint early in the
life-cycle of a page (because scripts in the head block) and set up a
<code>waitForElement</code> call that can now start logging all the events that are
firing on that element.</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#a6e22e">waitForElement</span>(<span style="color:#e6db74">"#test"</span>).<span style="color:#a6e22e">then</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">element</span>) {
<span style="color:#a6e22e">monitorEvents</span>(<span style="color:#a6e22e">element</span>);
});
</code></pre></div><p>Technically I still haven't solved the issue of "how can you tell when Firefox
has autocompleted fields" but I have the tools at my disposal.</p>
<p>Pretty chuffed.</p>
This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan