wake-up-neo.com

Ein iframe mit gegebenem HTML-Code dynamisch erstellen

Ich versuche, einen iframe aus JavaScript zu erstellen und ihn mit beliebigem HTML-Code zu füllen.

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

Ich würde erwarten, dass iframe dann ein gültiges Fenster und Dokument enthält. Dies ist jedoch nicht der Fall:

> console.log (iframe.contentWindow);
Null

Probieren Sie es aus: http://jsfiddle.net/TrevorBurnham/9k9Pe/

Was überblicke ich?

113
Trevor Burnham

Das Festlegen der src einer neu erstellten iframe in Javascript löst den HTML-Parser erst aus, wenn das Element in das Dokument eingefügt wird. Das HTML wird dann aktualisiert und der HTML-Parser wird aufgerufen und verarbeitet das Attribut wie erwartet. 

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);

Auch bei der Beantwortung Ihrer Frage ist zu beachten, dass dieser Ansatz bei einigen Browsern Kompatibilitätsprobleme aufweist. Informationen zu einer browserübergreifenden Lösung finden Sie in der Antwort von @mschr.

94
GillesC

Obwohl dein src = encodeURI funktionieren sollte, wäre ich einen anderen Weg gegangen:

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();

Da dies keine Beschränkungen für x-Domains hat und vollständig über das iframe-Handle erfolgt, können Sie auf den Inhalt des Frames später zugreifen und ihn bearbeiten. Sie müssen lediglich sicherstellen, dass der Inhalt gerendert wurde. Dieser wird (abhängig vom Browsertyp) während/nach der Ausgabe des Befehls .write gestartet -, aber wird nicht unbedingt ausgeführt, wenn close() aufgerufen wird.

Ein zu 100% kompatibler Weg, einen Rückruf durchzuführen, könnte dieser Ansatz sein:

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

Iframes hat jedoch das Onload-Ereignis. Hier ist ein Ansatz, um auf das innere HTML als DOM (js) zuzugreifen:

iframe.onload = function() {
   var div=iframe.contentWindow.document.getElementById('mydiv');
};
196
mschr

Danke für Ihre tolle Frage, das hat mich ein paar Mal erwischt. Bei der Verwendung der dataURI-HTML-Quelle muss ich ein vollständiges HTML-Dokument definieren.

Siehe unten ein modifiziertes Beispiel. 

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

beachten Sie den HTML-Inhalt, der mit <html>-Tags und der iframe.src-Zeichenfolge umschlossen ist.

Das iframe-Element muss der zu analysierenden DOM-Struktur hinzugefügt werden. 

document.body.appendChild(iframe);

Sie können den iframe.contentDocument nur überprüfen, wenn Sie disable-web-security in Ihrem Browser angezeigt haben. Sie erhalten eine Nachricht

DOMException: Fehler beim Lesen der 'contentDocument'-Eigenschaft aus' HTMLIFrameElement ': Blockierte Frames mit Origin " http: // localhost: 7357 " beim Zugriff auf einen Origin-Frames.

11
halfcube

Es gibt eine Alternative zum Erstellen eines iframe, dessen Inhalt eine Zeichenfolge aus HTML ist: das Attribut srcdoc . Dies wird in älteren Browsern nicht unterstützt (hauptsächlich unter ihnen: Internet Explorer und möglicherweise Safari ?), Aber es gibt ein polyfill für dieses Verhalten, das Sie in einen bedingten Kommentar für den IE setzen oder verwenden könnten so etwas wie has.js, um es faul zu laden.

7
zedd45

Mach das

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

var frame_win = getIframeWindow(el);

console.log(frame_win);
...

getIframeWindowwird hier definiert

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;
}
0