I have a few problems with iframe
usage. I'll ask one question at a time. I am working on the LaTeX.js playground and wanted to add some JavaScript to process \marginpar
s, but whatever I do, neither Chrome nor Firefox even attempt to load the script. It works if the exact same code is used outside of any frames.
I tried both absolute and relative paths, and I tried file
, http
, and https
protocols. Always the same result.
Here is the relevant code:
<iframe id="preview" sandbox="allow-same-origin allow-scripts">
<html>
<head>
<title>LaTeX.js Show­case</title>
<meta charset="UTF-8">
<link type="text/css" rel="stylesheet" href="css/katex.css">
<link type="text/css" rel="stylesheet" href="css/article.css">
<link type="text/css" rel="stylesheet" href="css/error.css">
<script src=".js"></script>
</head>
...
The problem is base.js
. The developer tools show no error in the console, no entry in the sources tab, and no entry in the network tab.
UPDATE: as I said in the ments, the code above is the result from modifying the DOM using JavaScript; however, setting iframe.contentWindow.document.documentElement
does not seem to trigger loading the scripts in <head>
, only Option 2 in the answer works for me.
I have a few problems with iframe
usage. I'll ask one question at a time. I am working on the LaTeX.js playground and wanted to add some JavaScript to process \marginpar
s, but whatever I do, neither Chrome nor Firefox even attempt to load the script. It works if the exact same code is used outside of any frames.
I tried both absolute and relative paths, and I tried file
, http
, and https
protocols. Always the same result.
Here is the relevant code:
<iframe id="preview" sandbox="allow-same-origin allow-scripts">
<html>
<head>
<title>LaTeX.js Show­case</title>
<meta charset="UTF-8">
<link type="text/css" rel="stylesheet" href="css/katex.css">
<link type="text/css" rel="stylesheet" href="css/article.css">
<link type="text/css" rel="stylesheet" href="css/error.css">
<script src="https://latex.js/js/base.js"></script>
</head>
...
The problem is base.js
. The developer tools show no error in the console, no entry in the sources tab, and no entry in the network tab.
UPDATE: as I said in the ments, the code above is the result from modifying the DOM using JavaScript; however, setting iframe.contentWindow.document.documentElement
does not seem to trigger loading the scripts in <head>
, only Option 2 in the answer works for me.
- Unless the spec has drastically changed, I'm pretty sure you can't put content in iframes that way. Have you tried using a data URL instead? – Siguza Commented Jun 1, 2018 at 23:03
1 Answer
Reset to default 6Option 1: Using DOM
For me iframe.contentWindow.replaceChild(newDocumentElement, iframe.contentWindow.documentElement)
didn't work (replaceChild
wasn't a method, and iframe.contentWindow.documentElement.parentNode
is null). I had success replacing the iframe's head and the body:
var iframe = document.getElementById('preview');
var iframeDocument = iframe.contentDocument;
var head = document.createElement('head');
var body = document.createElement('body');
var library = document.createElement('script');
//library.src = 'https://latex.js/js/base.js';
library.src = 'https://d3js/d3.v4.min.js';
head.appendChild(library);
body.appendChild(document.createTextNode('Hello, World!'));
iframeDocument.head.parentNode.replaceChild(head, iframeDocument.head);
iframeDocument.body.parentNode.replaceChild(body, iframeDocument.body);
Here's a fiddle: https://jsfiddle/zkb91faf/
You can verify that the d3.v4.min.js
is loaded properly by navigating to the iframe in the debugger (See here for Chrome, and here for Firefox), and typing d3
into the console.
Option 2: Using src
/srcdoc
I'd be remiss if I didn't mention iframe.srcdoc
. It looks like you're just using static HTML, so it may be appropriate.
You'd just set it via something like:
iframe.srcdoc = newDocumentElement.outerHTML;
Alternatively, if you want to support older browsers you can set it via iframe.src
and a data URI:
iframe.src = 'data:text;base64,' + btoa(newDocumentElement.outerHTML);
If you need unicode support, refer to https://developer.mozilla/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
Note Using Relative URLs:
You probably will run into problems using relative URLs, like that in <link type="text/css" rel="stylesheet" href="css/article.css">
, because your iframe won't have the correct URI to it. You would probably need to use absolute URLs.
Update: Adding script tags after a document is loaded:
It looks like the culprit is in base.js
, where you attach and run code based on the DOMContentLoaded
event. The DOM is already loaded, so this event won't fire. What you can do is check whether the window is already loaded, and then run your initialization code, if it is. Via https://stackoverflow./a/9457996/6184972:
if (document.readyState === "plete" || document.readyState === "loaded") {
pleted();
}
In this case, you may need to replace the body before the head, just in case if pleted()
does any direct manipulations of the DOM.