177

JavaScriptからiframeを作成し、次のように任意のHTMLで埋めようとしています。

var html = '<body>Foo</body>';
var iframe = document.createElement('iframe');
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);

iframeその場合、有効なウィンドウとドキュメントが含まれると思います。ただし、これは当てはまりません。

> console.log(iframe.contentWindow);
ヌル

自分で試してみてください:http://jsfiddle.net/TrevorBurnham/9k9Pe/

私は何を見落としていますか?

4

8 に答える 8

264

あなたはうまくいくsrc = encodeURIはずですが、私は別の方法で行ったでしょう:

var iframe = document.createElement('iframe');
var html = '<body>Foo</body>';
document.body.appendChild(iframe);
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(html);
iframe.contentWindow.document.close();

これにはxドメインの制限がなく、iframeハンドルを介して完全に実行されるため、後でフレームのコンテンツにアクセスして操作することができます。確認する必要があるのは、コンテンツがレンダリングされていることです。これは、(ブラウザーの種類に応じて).writeコマンドの発行中/発行後に開始されますが、呼び出されたときに必ずしも実行されるわけではありませんclose()

コールバックを実行する100%互換性のある方法は、次のアプローチである可能性があります。

<html><body onload="parent.myCallbackFunc(this.window)"></body></html>

ただし、Iframeにはonloadイベントがあります。DOM(js)として内部htmlにアクセスする方法は次のとおりです。

iframe.onload = function() {
   var div=iframe.contentWindow.document.getElementById('mydiv');
};
于 2012-05-03T14:31:44.677 に答える
146

src新しく作成されたjavascriptのを設定するとiframe、要素がドキュメントに挿入されるまでHTMLパーサーはトリガーされません。次に、HTMLが更新され、HTMLパーサーが呼び出され、期待どおりに属性が処理されます。

http://jsfiddle.net/9k9Pe/2/

var iframe = document.createElement('iframe');
var html = '<body>Foo</body>';
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
document.body.appendChild(iframe);
console.log('iframe.contentWindow =', iframe.contentWindow);

また、これはあなたの質問に答えます。このアプローチには一部のブラウザとの互換性の問題があることに注意することが重要です。クロスブラウザソリューションについては、@mschrの回答を参照してください。

于 2012-05-02T17:53:53.743 に答える
17

あなたの素晴らしい質問に感謝します、これは私を数回捕らえました。dataURI HTMLソースを使用する場合、完全なHTMLドキュメントを定義する必要があることがわかりました。

以下の変更された例を参照してください。

var html = '<html><head></head><body>Foo</body></html>';
var iframe = document.createElement('iframe');
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);

<html>タグと文字列でラップされたhtmlコンテンツに注意してくださいiframe.src

解析するには、iframe要素をDOMツリーに追加する必要があります。

document.body.appendChild(iframe);

ブラウザを使用しiframe.contentDocumentない限り、検査することはできません。disable-web-securityメッセージが届きます

DOMException:「HTMLIFrameElement」からの「contentDocument」プロパティの読み取りに失敗しました:オリジン「http:// localhost:7357」のフレームがクロスオリジンフレームにアクセスするのをブロックしました。

于 2015-03-01T03:58:34.210 に答える
16

内容がHTMLの文字列であるiframeを作成する別の方法があります:srcdoc属性。これは古いブラウザー(主にInternet Explorer、場合によってはSafari?)ではサポートされていませんが、この動作にはポリフィルがあり、IEの条件付きコメントを入力したり、has.jsなどを使用して条件付きで遅延したりできます。それをロードします。

于 2014-06-24T18:43:46.763 に答える
10

srcdocこれは古い質問ですが、これは現在広くサポートされており、この質問は頻繁に表示されるため、属性を使用した例を提供すると思いました。

このsrcdoc属性を使用して、埋め込むインラインHTMLを提供できます。srcサポートされている場合は、属性をオーバーライドします。srcサポートされていない場合、ブラウザは属性にフォールバックします。

sandboxまた、属性を使用して、フレーム内のコンテンツに追加の制限を適用することをお勧めします。HTMLが独自のものでない場合、これは特に重要です。

const iframe = document.createElement('iframe');
const html = '<body>Foo</body>';
iframe.srcdoc = html;
iframe.sandbox = '';
document.body.appendChild(iframe);

古いブラウザをサポートする必要がある場合は、srcdocサポートを確認し、他の回答から他の方法の1つにフォールバックできます。

function setIframeHTML(iframe, html) {
  if (typeof iframe.srcdoc !== 'undefined') {
    iframe.srcdoc = html;
  } else {
    iframe.sandbox = 'allow-same-origin';
    iframe.contentWindow.document.open();
    iframe.contentWindow.document.write(html);
    iframe.contentWindow.document.close();
  }
}

var iframe = document.createElement('iframe');
iframe.sandbox = '';
var html = '<body>Foo</body>';

document.body.appendChild(iframe);
setIframeHTML(iframe, html);

于 2020-03-27T14:29:29.650 に答える
5

URLアプローチは、小さなHTMLフラグメントに対してのみ機能します。より確実なアプローチは、blobからオブジェクトURLを生成し、それを動的iframeのソースとして使用することです。

const html = '<html>...</html>';
const iframe = document.createElement('iframe');
const blob = new Blob([html], {type: 'text/html'});
iframe.src = window.URL.createObjectURL(blob);
document.body.appendChild(iframe);
于 2020-06-09T22:56:39.763 に答える
0

これを行う

...
var el = document.getElementById('targetFrame');

var frame_win = getIframeWindow(el);

console.log(frame_win);
...

getIframeWindowはここで定義されます

function getIframeWindow(iframe_object) {
  var doc;

  if (iframe_object.contentWindow) {
    return iframe_object.contentWindow;
  }

  if (iframe_object.window) {
    return iframe_object.window;
  } 

  if (!doc && iframe_object.contentDocument) {
    doc = iframe_object.contentDocument;
  } 

  if (!doc && iframe_object.document) {
    doc = iframe_object.document;
  }

  if (doc && doc.defaultView) {
   return doc.defaultView;
  }

  if (doc && doc.parentWindow) {
    return doc.parentWindow;
  }

  return undefined;
}
于 2018-10-31T22:43:49.240 に答える
-2

(働き(){

var frame = document.createElement('iframe');
frame.src = 'https://1zr2h9xgfxqt.statuspage.io/embed/frame';
frame.style.position = 'fixed';
frame.style.border = 'none';
frame.style.boxShadow = '0 20px 32px -8px rgba(9,20,66,0.25)';
frame.style.zIndex = '9999';
frame.style.transition = 'left 1s ease, bottom 1s ease, right 1s ease';

var mobile;
if (mobile = screen.width < 450) {
  frame.src += '?mobile=true';
  frame.style.height = '20vh';
  frame.style.width = '100vw';
  frame.style.left = '-9999px';
  frame.style.bottom = '-9999px';
  frame.style.transition = 'bottom 1s ease';
} else {
  frame.style.height = '115px';
  frame.style.width = '320px';
  frame.style.left = 'auto';
  frame.style.right = '-9999px';
  frame.style.bottom = '60px';
}

document.body.appendChild(frame);

var actions = {
  showFrame: function() {
    if (mobile) {
      frame.style.left = '0';
      frame.style.bottom = '0';
    }
    else {
      frame.style.left = 'auto';
      frame.style.right = '60px'
    }
  },
  dismissFrame: function(){
    frame.style.left = '-9999px';
  }
}

window.addEventListener('message', function(event){
  if (event.data.action && actions.hasOwnProperty(event.data.action)) {
    actions[event.data.action](event.data);
  }
}, false);

window.statusEmbedTest = actions.showFrame;

})();

于 2021-04-26T18:53:17.653 に答える