javascript - Kako mogu stvoriti iframe element i dinamički postaviti njegov HTML?


Pokušavam stvoriti iframe iz JavaScripta i napuniti ga proizvoljnim HTML-om, ovako:

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

Očekivao bih da iframe tada sadrži valjano prozorsko i dokumentno okruženje. Međutim, to nije slučaj:

> console.log(iframe.contentWindow);
null

Probajte sami: http://jsfiddle.net/TrevorBurnham/9k9Pe/

Što previdam?

Odgovor #1

Iako bi vaš src=encodeURI trebao raditi, ja bih išao drugačijim putem:

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

Budući da ovo nema ograničenja x-domene i potpuno se izvodi putem iframe rukovanja, možete kasnije pristupiti i manipulirati sadržajem okvira. Sve što trebate osigurati jest da je sadržaj prikazan, što će (ovisno o vrsti preglednika) započeti tijekom/nakon izvršenja naredbe .write - ali nije nužno završeno kada se pozove close().

100% kompatibilan način za izvršavanje povratnog poziva mogao bi biti ovaj pristup:

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

Iframes imaju onload događaj, međutim. Evo pristupa za pristup unutarnjem HTML-u kao DOM-u (js):

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

Odgovor #2

Postavljanje src novostvorenog iframe u javascripta ne pokreće HTML parser dok element nije umetnut u dokument. HTML se tada ažurira i HTML parser će biti pozvan i obraditi atribut kao što se očekuje.

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

Također, za odgovor na vaše pitanje važno je napomenuti da ovaj pristup ima problema s kompatibilnošću s nekim preglednicima, molimo pogledajte odgovor @mschr za rješenje koje radi na više preglednika.

Odgovor #3

Znam da je ovo staro pitanje, ali pomislio sam da bih dao primjer korištenja srcdoc atributa jer je sada široko podržan i ovo pitanje se često pregledava.

Korištenjem atributa srcdoc, možete pružiti HTML unutar elementa za ugradnju. On nadjačava atribut src ako je podržan. Preglednik će se vratiti na atribut src ako nije podržan.

Također bih preporučio korištenje atributa sandbox za primjenu dodatnih ograničenja na sadržaj u okviru. Ovo je posebno važno ako HTML nije vaš.

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

Ako trebate podržati starije preglednike, možete provjeriti podršku za srcdoc i vratiti se na jednu od drugih metoda iz drugih odgovora.

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

Odgovor #4

Hvala na vašem odličnom pitanju, ovo me je nekoliko puta zateklo. Kada koristim dataURI HTML izvor, primjećujem da moram definirati potpuni HTML dokument.

Pogledajte dolje izmijenjeni primjer.

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

obratite pažnju na HTML sadržaj omeđen oznakama <html> i na string iframe.src.

Elemnt iframe treba biti dodan u DOM stablo kako bi se mogao analizirati.

document.body.appendChild(iframe);

Nećete moći pregledati iframe.contentDocument osim ako ne onemogućite web-sigurnost u svom pregledniku. Dobit ćete poruku

DOMException: Neuspjelo čitanje svojstva 'contentDocument' iz 'HTMLIFrameElement': Blokiran okvir s podrijetlom 'http://localhost:7357' u pristupu okviru drugog podrijetla.

Odgovor #5

Postoji alternativa za stvaranje iframe-a čiji su sadržaji niz HTML-a: atribut srcdoc. Ovo nije podržano u starijim preglednicima (među njima prvenstveno: Internet Explorer, i moguće Safari?), ali postoji polyfill za ovo ponašanje, koji možete staviti u uvjetne komentare za IE, ili koristiti nešto poput has.js za uvjetno odgađano učitavanje.

Odgovor #6

Pristup putem URL-a će raditi samo za male HTML fragmente. Čvršći pristup je generirati URL objekta iz bloba i koristiti ga kao izvor dinamičkog iframe-a.

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

Povezani članci