Jak komunikować się między ramką iframe a witryną nadrzędną?

184

Strona internetowa w ramce iframe nie znajduje się w tej samej domenie , ale obie są moje i chciałbym się komunikować między iframewitryną nadrzędną a nią. Czy to możliwe?

Danny Fox
źródło

Odpowiedzi:

307

W przypadku różnych domen nie można wywoływać metod ani uzyskiwać bezpośredniego dostępu do dokumentu treści iframe.

Musisz używać przesyłania wiadomości między dokumentami .

Na przykład w górnym oknie:

 myIframe.contentWindow.postMessage('hello', '*');

oraz w ramce iframe:

window.onmessage = function(e){
    if (e.data == 'hello') {
        alert('It works!');
    }
};

Jeśli publikujesz wiadomość z elementu iframe w oknie nadrzędnym

window.top.postMessage('hello', '*')
użytkownik123444555621
źródło
2
dziękuję, ale niestety nie działa w starszych przeglądarkach.
Danny Fox
106
W dominującej: window.onmesage = function().... W window.top.postMessage('hello', '*')
ramce
3
To nie jest błąd. Adresy plików mogą być bardzo niebezpieczne, a przeglądarki traktują je z coraz większą ostrożnością. W dawnych czasach można było umieścić link file://C:/Windows/system32/whateverna stronie internetowej i skierować go bezpośrednio do folderu systemowego użytkownika. Obecnie przeglądarki najczęściej ignorują kliknięcia takich linków. Uruchom serwer WWW i uzyskaj dostęp do swojego kodu, a zobaczysz, że błędy znikają.
Stijn de Witt
4
Jako dobrą praktykę nigdy nie używaj „*” jako celu. W rzeczywistości MDN mówi - „Zawsze podaj konkretny celOrigin, a nie *, jeśli wiesz, gdzie powinien znajdować się dokument drugiego okna. Brak określonego celu ujawnia dane, które wysyłasz do dowolnej zainteresowanej złośliwej witryny”.
rodiwa
2
Możemy nawet użyć, window.frames[index]aby uzyskać child frame ( <iframe>, <object>, <frame>), równoważne z getElementsByTagName("iframe")[index].contentWindow. Aby uzyskać obiekt okna nadrzędnego z ramek IFrame, lepiej jest użyć window.parent, ponieważ window.topreprezentuje najwyższe okno nadrzędne
phoenisx
46

Musi tu być, ponieważ zaakceptowano odpowiedź z 2012 roku

W 2018 roku i we współczesnych przeglądarkach możesz wysłać niestandardowe zdarzenie z iframe do okna nadrzędnego.

iframe:

var data = { foo: 'bar' }
var event = new CustomEvent('myCustomEvent', { detail: data })
window.parent.document.dispatchEvent(event)

rodzic:

window.document.addEventListener('myCustomEvent', handleEvent, false)
function handleEvent(e) {
  console.log(e.detail) // outputs: {foo: 'bar'}
}

PS: Oczywiście możesz wysyłać zdarzenia w przeciwnym kierunku w ten sam sposób.

document.querySelector('#iframe_id').contentDocument.dispatchEvent(event)
Nieznajomy w Q
źródło
1
Witaj, czy muszę to robić w tej samej domenie?
Guillaume Harari,
1
Należy zauważyć, że dispatchEventjest obsługiwany we wszystkich głównych przeglądarkach. IE9 była pierwszą wersją, w której się pojawiła, więc większość systemów operacyjnych teraz z nią współpracuje. caniuse.com/#search=dispatchEvent
Dan Atkinson
1
Za pomocą tej metody nie jestem w stanie komunikować się z nadrzędnego na iframe.
Avan
Tak, też nie mogę go uruchomić, iframe js ładuje się po oknie nadrzędnym, więc nie ma tam wiadomości msg po wysłaniu. dla mnie działa tylko od iframe do parent.
radtek
14

Ta biblioteka obsługuje HTML5 postMessage i starsze przeglądarki z funkcją resize + hash https://github.com/ternarylabs/porthole

Edycja: Teraz w 2014 r. Zużycie IE6 / 7 jest dość niskie, IE8 i przede wszystkim obsługa, postMessagewięc teraz sugeruję, aby po prostu z niego korzystać.

https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage

jpillora
źródło
Z zastrzeżeniem, że IE8 / 9 obsługuje tylko łańcuchy caniuse.com/#search=postmessage (Zobacz znane problemy)
Harry
można to obejść, kodując obiekty zdarzeń do formatu json i dekodując je po drugiej stronie.
codewandler
3

window.topnieruchomość powinna być w stanie dać to, czego potrzebujesz.

Na przykład

alert(top.location.href)

Zobacz http://cross-browser.com/talk/inter-frame_comm.html

sambomartin
źródło
10
Ponieważ element iframe nie znajduje się w tej samej domenie, nie może uzyskać dostępu do jego elementu nadrzędnego.
Andreas Köberle,
1

Możesz także użyć

postMessage(message, '*');

gonzarodriguezt
źródło
1

Użyj, event.source.window.postMessageaby odesłać z powrotem do nadawcy.

Z iframe

window.top.postMessage('I am Iframe', '*')
window.onmessage = (event) => {
    if (event.data === 'GOT_YOU_IFRAME') {
        console.log('Parent received successfully.')
    }
}

Następnie od rodzica odpowiedz.

window.onmessage = (event) => {
    event.source.window.postMessage('GOT_YOU_IFRAME', '*')
}
Binh Ho
źródło