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?
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.
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.
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');
};
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.
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.
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;
}