MithrilJS / mithril.js

A JavaScript Framework for Building Brilliant Applications
https://mithril.js.org
MIT License
14.02k stars 925 forks source link

Mounting DOM inside iFrame - Does not work in Firefox #999

Closed hari-narasimhan closed 7 years ago

hari-narasimhan commented 8 years ago

I followed the approach outlined in https://github.com/lhorie/mithril.js/issues/698 to mount DOM to iframe, while it works perfectly well in chrome, does not work in firefox.

Code used for the scenario is given below

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Mithril Firefox Iframe</title>
</head>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/0.2.3/mithril.js"></script>
  <script>

    var FrameComponent = {
      controller: function () {},

      view: function (ctrl) {
        return m('h1', 'Hello, World from IFrame!');
      },
    };

    var myFrame = {
      controller: function () {},

      view: function (ctrl) {
        return m('iframe', {
          config: function (element, isInitialized, context) {
            if (isInitialized) return;
            m.mount(element.contentWindow.document, FrameComponent);
          },
        });
      },
    };

    m.mount(document.body, myFrame);
  </script>
</body>
</html>
dead-claudia commented 8 years ago

Sorry, but Mithril does not currently support multiple mount points, and it would be infeasible to do so with the current API and architecture. You're not the first to suggest this or run into this issue, and it's already under consideration with @lhorie's rewrite (which is currently only just now progressing past the purely conceptual stages). :frowning:

Closing for now.

hari-narasimhan commented 8 years ago

Thanks for the response, but why does it work in chrome. If I understand you correct, it should not work in chrome as well.

dead-claudia commented 8 years ago

@hari-narasimhan If it works in Chrome, it's unspecified behavior that's best to not rely on.

dead-claudia commented 8 years ago

Sorry about that.

pygy commented 8 years ago

@isiahmeadows This is very odd, and unrelated to mounting nested apps:

<!doctype html>
<title>Iframe Test</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/0.2.3/mithril.js"></script>
<body>
<script>
    m.mount(document.body, {
      controller: function () {},

      view: function (ctrl) {
        return m('div#foo', {config: function(parent, notFirst, context){
            if (notFirst) return;

            console.log(
              'parent, body == B?',
              parent.firstChild.contentWindow.document.body === B
            )
          }},
          m('iframe#bar', {config: function(element, notFirst, context){
            if (notFirst) return;

            window.B = element.contentWindow.document.body
          }})
        );
      }
    });
    console.log(
      'after mount, body == B?',
      // In Safari, bar.contentWindow === undefined :-/
      (bar.document || bar.contentWindow.document).body === B
    )

    setTimeout(function(){
      console.log(
        'timeout, body == B?',
        (bar.document || bar.contentWindow.document).body === B
      )
    })
</script>

In Chrome and Safari, I get

parent, body == B? true
after mount, body == B? true
timeout, body == B? true

But in Firefox, it is true, true, false. The content of the iframe is replaced after the first tick ends.

Live here: http://bl.ocks.org/pygy/46059b1f228e454747cb Source: https://gist.github.com/pygy/46059b1f228e454747cb

Adding context.retain = true doesn't alter the result.

dead-claudia commented 8 years ago

@pygy Good catch. The initial bug report specifically dealt with nested apps, but yours does very clearly seem very odd. Would you be able to figure out a way to feature-detect this without Mithril?

hiteshjoshi commented 7 years ago

was this ever fixed? Any alternative for this?

barneycarroll commented 7 years ago

Me and @hiteshjoshi have been trying to come up with a solution. We've found that Firefox will render content to an iframe's document but clear it immediately thereafter. Introducing an empty onload handler to the iframe element seems to work (example). The alarming thing is that onload seems to be triggering perpetually. The search continues…

hiteshjoshi commented 7 years ago

https://jsbin.com/kevasedede/2/edit?js,output Just need to constantly check for document ready state of your iframe. Nothing to be linked with mithril. You may close this now.