Prevent my Elm app from crashing when a 3rd party changes the DOM

282 Views Asked by At

I have an Elm app. A while ago I realized that my app was crashing locally when I used FontAwesome icons. I came to understand that it happened because I chose SVG icons and therefore FontAwesome was modifying the DOM. That conflicted with Elm's VDOM mechanism.

Elm crashes because FontAwesome adds/removes SVG nodes on the fly

This was easy to fix--I migrated to the CSS version of FontAwesome that uses pseudo elements. Recently some users complained that the app in production freezes and they showed screenshots of states that were not matching the log data I had. It took a while until I realized that all these users had Google Translate automatically translated the page for them. Google Translate clearly alters the DOM, so I'm not surprised that it made Elm crash.

How can I prevent my Elm app from crashing? Is there a way to be notified if a 3rd party changes the DOM? So that I could even notify the user that they have an extension that interferes with the app.

4

There are 4 best solutions below

1
On

I don't know about preventing the crashes, but I think you should be able to register changes to the DOM with the current mutation observer API.

Before that were several deprecated mutation events like DOMSubtreeModified that could also help, but well they are deprecated.

1
On

I had the same problem as you and solved it by migrating to the Elm-FontAwesome library. Basically all you have to do is replace this syntax:

i [ Svga.class "fas fa-check" ] []

with this one:

Icon.viewIcon Icon.check

You can have a look to the example project for more details: https://github.com/Lattyware/elm-fontawesome-example

1
On

Have a look here - How we made Elm and Google Translate work together.

Their approach is to hijack the Elm replaceData method that is called by Elm during dom updates using the function below. You would run this just before giving Elm control of the dom.

HTMLFontElement.prototype.replaceData =
  function replaceData(_0, _1, string) {
    this.parentNode.replaceChild(
      document.createTextNode(string),
      this
    );
  };

Apparently, "Google Translate replaces every text node in the DOM with a tag containing at least one more tag – one for each sentence". For example:

<span>Insurello. Rätt ersättning till alla</span>

is translated into

<span><font><font>Insurello. </font><font>The right compensation for everyone</font></font></span>

This method avoids attempting to edit the span and instead replace it with a new one. Once the node is added, Google Translate will translate that text.

0
On

This problem is very closely linked to that of Google Maps or Google Places Autocomplete in Elm. The solution I've used in the past is to provide a childless div with an id I can point to from JavaScript.

Because the div is childless, Elm does not look under the hood to check whether it has changed internally.

Check out this blog post or google "maps in elm" for instructions on how to do this

-- EDIT -- Ive read the question better and this will probably not work for Google translate issues as it changes all text in the entire DOM. Ill leave it here incase the question brings otger people who have more regular problems caused when a 3rd party changes the DOM