最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - iframe problems: <script src="..."> not loaded at all - Stack Overflow

programmeradmin0浏览0评论

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 \marginpars, 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&shy;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 \marginpars, 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&shy;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.

Share Improve this question edited Jun 2, 2018 at 11:22 MiB asked Jun 1, 2018 at 22:49 MiBMiB 4801 gold badge5 silver badges16 bronze badges 1
  • 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
Add a ment  | 

1 Answer 1

Reset to default 6

Option 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.

发布评论

评论列表(0)

  1. 暂无评论