Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create new iframe and load content synchronously

The goal is to create an iframe dynamically and synchronously append a SVG element to its document body.

We are trying to get this to work in Firefox.

Our research suggests Firefox resets iframes with a new document after appending iframes to the HTML. This triggers a load event, and only after this event can you successfully append content. Any content appended prior to the load event gets discarded.

The workaround, which is not ideal, is to wait for the load event then append the SVG element to the iframe.

Is it possible to avoid asynchronous behavior? We want to append the SVG element synchronously after creating the iframe.

Codepen: https://codepen.io/anon/pen/yWXjgM

var newElem = $(document.createElement("div"));
newElem.html("hi there");
var iframe = $(document.createElement("iframe"));
iframe.contents().find("body").append(newElem);
$("#box").append(iframe);
$("#box").append(newElem);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="box"></div>
like image 374
Crashalot Avatar asked May 18 '19 03:05

Crashalot


People also ask

Do iframes load asynchronously?

iframes should load asynchronously without any effort on your part.

Do iframes slow down page load?

So, you should not use iframe excessively without monitoring what's going on, or you might end up harming your page performance. To avoid having your iframes slow down your pages, a good technique is to lazy load them (i.e., loading them only when they are required like when the user scrolls near them).

What is iframe Srcdoc?

The srcdoc attribute specifies the HTML content of the page to show in the inline frame. Tip: This attribute is expected to be used together with the sandbox and seamless attributes. If a browser supports the srcdoc attribute, it will override the content specified in the src attribute (if present).

How can I make my iframe load faster?

Use the iFrame fallback embed The fastest way to load an embedded form is by using the iframe fallback method as outlined in the fallback documentation. If you go with this method, make sure you review the gotchas in the linked documentation to ensure this approach is right for you.


1 Answers

tl:dr Regardless of what is done the asynchronous nature of the iframe being loaded doesn't appear to be avoidable, however there is a synchronous way to add content dynamically to the iframe via srcdoc which "overrides" the default iframe src attribute from being used.

It would also appear there may be a solution with using createHTMLDocument but I have yet to be successful.

Solution with srcdoc

Explanation

assuming that your dynamic iframes does not load content via src attribute

According to the HTML iframe specifications

When an iframe element is inserted into a document that has a browsing context, the user agent must create a nested browsing context, and then process the iframe attributes for the "first time".

The thing to take note is "process the iframe attributes for the first time". There is no mention to whether or not this process is synchronous nor asynchronous and it comes down to each browser's implementation.

As it has been mentioned, Chrome and Firefox have understood this process as asynchronous, which does make sense as the goal of the iframe is to load content from its src attribute and to invoke the onload callback.

If no src attribute is available it'll set it to "about:blank"

It is worth mentioning that before the browser checks to see if there is a src attribute exists, it'll first check to see if srcdoc is available which according to MDN iframe doc:

srcdoc

Inline HTML to embed, overriding the src attribute. If a browser does not support the srcdoc attribute, it will fall back to the URL in the src attribute.

Working Example

const container = document.getElementById("container");
const iframe = document.createElement("iframe");

iframe.addEventListener("load", function(){
  console.log("loaded...");
});

iframe.srcdoc = `
  <svg height="100" width="100">
      <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
      Sorry, your browser does not support inline SVG.  
  </svg>
`;

iframe.srcdoc += `
  <svg height="100" width="100">
      <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="blue" />
      Sorry, your browser does not support inline SVG.  
  </svg>
`

container.append(iframe);
<div id="container"></div>

Solution with Web Extensions

If you're developing a web extension you will have access the mozbrowser api and thus stop

The stop() method of the HTMLIFrameElement interface is used to stop loading the content of the <iframe>.

like image 76
kemicofa ghost Avatar answered Sep 22 '22 07:09

kemicofa ghost