Mam projekt, w którym muszę utworzyć element <iframe> przy użyciu JavaScript i dołączyć go do DOM. Następnie muszę wstawić zawartość do <iframe>. To widżet, który zostanie osadzony w witrynach innych firm.
Nie ustawiam atrybutu „src” elementu <iframe>, ponieważ nie chcę ładować strony; służy raczej do izolowania / piaskownicy zawartości, którą do niego wstawiam, aby nie napotkać konfliktów CSS lub JavaScript ze stroną nadrzędną. Używam JSONP do załadowania zawartości HTML z serwera i wstawienia jej do tego <iframe>.
Mam to dobrze, z jednym poważnym wyjątkiem - jeśli właściwość document.domain jest ustawiona na stronie nadrzędnej (co może być w niektórych środowiskach, w których ten widget jest wdrażany), Internet Explorer (prawdopodobnie wszystkie wersje, ale mam potwierdzone w 6, 7 i 8) wyświetla błąd „Odmowa dostępu”, gdy próbuję uzyskać dostęp do obiektu dokumentu tej <iframe>, którą utworzyłem. Nie dzieje się tak w innych przeglądarkach, w których testowałem (we wszystkich głównych współczesnych).
Ma to sens, ponieważ zdaję sobie sprawę, że Internet Explorer wymaga ustawienia document.domain wszystkich okien / ramek, które będą się ze sobą komunikować, na tę samą wartość. Jednak nie znam żadnego sposobu na ustawienie tej wartości w dokumencie, do którego nie mam dostępu.
Czy ktoś wie, jak to zrobić - ustawić w jakiś sposób właściwość document.domain tej dynamicznie utworzonej <iframe>? A może nie patrzę na to pod odpowiednim kątem - czy jest inny sposób na osiągnięcie tego, do czego zmierzam, bez napotkania tego problemu? W każdym przypadku muszę używać elementu <iframe>, ponieważ izolowane / piaskownica ma kluczowe znaczenie dla funkcjonalności tego widżetu.
Oto mój kod testowy:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Document.domain Test</title>
<script type="text/javascript">
document.domain = 'onespot.com'; // set the page's document.domain
</script>
</head>
<body>
<p>This is a paragraph above the <iframe>.</p>
<div id="placeholder"></div>
<p>This is a paragraph below the <iframe>.</p>
<script type="text/javascript">
var iframe = document.createElement('iframe'), doc; // create <iframe> element
document.getElementById('placeholder').appendChild(iframe); // append <iframe> element to the placeholder element
setTimeout(function() { // set a timeout to give browsers a chance to recognize the <iframe>
doc = iframe.contentWindow || iframe.contentDocument; // get a handle on the <iframe> document
alert(doc);
if (doc.document) { // HEREIN LIES THE PROBLEM
doc = doc.document;
}
doc.body.innerHTML = '<h1>Hello!</h1>'; // add an element
}, 10);
</script>
</body>
</html>
Hostowałem to pod adresem:
http://troy.onespot.com/static/access_denied.html
Jak zobaczysz, jeśli załadujesz tę stronę w IE, w miejscu, w którym wywołam alert (), mam uchwyt do obiektu okna <iframe>; Po prostu nie mogę wejść głębiej w obiekt dokumentu.
Bardzo dziękuję za pomoc lub sugestie! Będę wdzięczny komukolwiek, kto pomoże mi znaleźć rozwiązanie tego problemu.
Odpowiedzi:
Westchnienie. Tak, jest to problem z IE (błąd? Trudno powiedzieć, ponieważ nie ma udokumentowanego standardu dla tego rodzaju nieprzyjemności). Kiedy tworzysz ramkę iframe bez źródła, otrzymuje ona
document.domain
z dokumentu nadrzędnegolocation.host
zamiast swojegodocument.domain
. W tym momencie straciłeś prawie wszystko, ponieważ nie możesz tego zmienić.Przerażającym obejściem jest ustawienie
src
javascript: URL (urgh!):iframe.src= "javascript:'<html><body><p>Hello<\/p><script>do things;<\/script>'";
Ale z jakiegoś powodu taki dokument nie może ustawić własnego
document.domain
ze skryptu w IE (stary dobry „nieokreślony błąd”), więc nie możesz go użyć do odzyskania pomostu między rodzicem (*). Państwo mogli używać go napisać cały dokument HTML, zakładając widżet nie trzeba mówić do swojego dokumentu macierzystego po jego wystąpienia.Jednak adresy URL JavaScript iframe nie działają w Safari, więc nadal potrzebujesz jakiegoś rodzaju przeglądarki, aby wybrać metodę do użycia.
*: Z jakiegoś innego powodu, to może , w IE, ustawiony
document.domain
z drugim dokumencie, document.written przez pierwszego dokumentu. Więc to działa:if (isIE) iframe.src= "javascript:'<script>window.onload=function(){document.write(\\'<script>document.domain=\\\""+document.domain+"\\\";<\\\\/script>\\');document.close();};<\/script>'";
W tym momencie poziom ohydności jest dla mnie zbyt wysoki, wypadam. Zrobiłbym zewnętrzny HTML, tak jak powiedział David.
źródło
void()
połączenie, ponieważ funkcja już zwracaundefined
.Cóż, tak, wyjątek dostępu wynika z faktu, że
document.domain
musi pasować do elementu nadrzędnego i elementu iframe, a zanim to zrobią, nie będziesz w stanie programowo ustawićdocument.domain
właściwości elementu iframe.Myślę, że najlepszą opcją jest wskazanie strony na własny szablon:
iframe.src = '/myiframe.htm#' + document.domain;
A w myiframe.htm:
document.domain = location.hash.substring(1);
źródło
cóż, mam bardzo podobny problem, ale z niespodzianką ... powiedzmy, że witryna najwyższego poziomu to a.foo.com - teraz ustawiłem domenę dokumentu na a.foo.com
następnie w utworzonej / posiadanej przeze mnie ramce iframe również ustawiam ją jako a.foo.com
zwróć uwagę, że nie mogę ich też ustawić foo.com b / c na stronie wskazującej na bafoo.com znajduje się inna ramka iframe (która ponownie używa a.foo.com, ale nie mogę tam zmienić kodu skryptu)
zauważysz, że zasadniczo ustawiam document.domain na to, co i tak już by było ... ale muszę to zrobić, aby uzyskać dostęp do drugiej ramki iframe, o której wspomniałem z bafoo.com
wewnątrz mojej ramki, po ustawieniu domeny, chociaż wszystkie elementy iframe mają to samo ustawienie, nadal pojawia się błąd podczas sięgania do rodzica w IE 6/7
są inne rzeczy, które są naprawdę bizaree
na zewnętrznym / najwyższym poziomie, jeśli poczekam na zdarzenie onload i ustawię licznik czasu, w końcu mogę sięgnąć do ramki, do której muszę uzyskać dostęp .... ale nigdy nie mogę sięgnąć od dołu do góry ... i naprawdę trzeba umieć
również jeśli ustawię wszystko na foo.com (czego, jak powiedziałem, nie mogę zrobić) TO DZIAŁA! ale z jakiegoś powodu, gdy używasz tej samej wartości co location.host .... nie działa i jego cholernie mnie zabija .....
źródło
Po prostu używam
<iframe src="about:blank" ...></iframe>
i działa dobrze.źródło
dla IE port ma znaczenie. Pomiędzy domenami powinien to być ten sam port.
źródło
Czy próbowałeś już jQuery.contents () ?
źródło
Wygląda na to, że problem z IE pojawia się, gdy próbujesz uzyskać dostęp do elementu iframe za pośrednictwem obiektu document.frames - jeśli przechowujesz odniesienie do utworzonej ramki iframe w zmiennej, możesz uzyskać dostęp do wstrzykniętego elementu iframe za pośrednictwem zmiennej (my_iframe w kodzie poniżej ).
Mam to do pracy w IE6 / 7/8
var my_iframe; var iframeId = "my_iframe_name" if (navigator.userAgent.indexOf('MSIE') !== -1) { // IE wants the name attribute of the iframe set my_iframe = document.createElement('<iframe name="' + iframeId + '">'); } else { my_iframe = document.createElement('iframe'); } iframe.setAttribute("src", "javascript:void(0);"); iframe.setAttribute("scrolling", "no"); iframe.setAttribute("frameBorder", "0"); iframe.setAttribute("name", iframeId); var is = iframe.style; is.border = is.width = is.height = "0px"; if (document.body) { document.body.appendChild(my_iframe); } else { document.appendChild(my_iframe); }
źródło
Miałem podobny problem, a moim rozwiązaniem był ten fragment kodu (testowany w IE8 / 9, Chrome i Firefox)
var iframe = document.createElement('iframe'); document.body.appendChild(iframe); iframe.src = 'javascript:void((function(){var script = document.createElement(\'script\');' + 'script.innerHTML = "(function() {' + 'document.open();document.domain=\'' + document.domain + '\';document.close();})();";' + 'document.write("<head>" + script.outerHTML + "</head><body></body>");})())'; iframe.contentWindow.document.write('<div>foo</div>');
Wypróbowałem kilka metod, ale ta okazała się najlepsza. Możesz znaleźć kilka wyjaśnień w moim wpisie na blogu tutaj .
źródło
Postępowanie zgodnie z niezwykle prostą metodą z Andralor rozwiązało problem dla mnie: https://github.com/fancyapps/fancyBox/issues/766
Zasadniczo wywołaj element iframe ponownie onUpdate:
$('a.js-fancybox-iframe').fancybox({ type: 'iframe', scrolling : 'visible', autoHeight: true, onUpdate: function(){ $("iframe.fancybox-iframe"); } });
źródło
IE działa z iframe jak wszystkie inne przeglądarki (przynajmniej dla głównych funkcji). Musisz tylko przestrzegać zestawu zasad:
kiedy wszystkie zasoby iframe zostaną załadowane, zmień document.domain na taką samą, jak zdefiniowana w parent. (Musisz to zrobić później, ponieważ ustawienie domeny spowoduje niepowodzenie żądania zasobu iframe)
teraz możesz utworzyć odniesienie do okna nadrzędnego: var winn = window.parent
źródło
Dla mnie stwierdziłem, że lepszą odpowiedzią jest sprawdzenie uprawnień do pliku, do których odmawia się dostępu.
Właśnie zaktualizowałem do jQuery-1.8.0.js i otrzymałem błąd odmowy dostępu w IE9.
Z Eksploratora Windows
Przetestowano witrynę. Koniec z problemem.
Musiałem zrobić to samo dla skryptu jQuery-UI, który właśnie zaktualizowałem
źródło