Wywołanie kodu JavaScript w ramce iframe ze strony nadrzędnej

Zasadniczo, mam iframe osadzony na stronie i iframe ma pewne JavaScript procedury, które muszę wywołać ze strony nadrzędnej.

Teraz przeciwieństwo jest dość proste, ponieważ wystarczy zadzwonić parent.functionName(), ale niestety, potrzebuję dokładnie przeciwieństwa.

Proszę zauważyć, że moim problemem nie jest zmiana źródła URL z iframe, ale wywołanie funkcji zdefiniowanej w iframe.

Author: Shashank Agrawal, 2008-10-30

17 answers

Załóżmy, że id ramki iFrame to "targetFrame", a funkcja, którą chcesz wywołać to targetFunction():

document.getElementById('targetFrame').contentWindow.targetFunction();

Możesz również uzyskać dostęp do ramki używając window.frames zamiast document.getElementById.

// this option does not work in most of latest versions of chrome and Firefox
window.frames[0].frameElement.contentWindow.targetFunction(); 
 503
Author: Joel Anair,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-10 20:38:48

Są pewne dziwactwa, o których należy pamiętać.

  1. HTMLIFrameElement.contentWindow prawdopodobnie jest to łatwiejszy sposób, ale nie jest to dość standardowa właściwość i niektóre przeglądarki jej nie obsługują, głównie starsze. Dzieje się tak dlatego, że standard HTML poziomu 1 DOM nie ma nic do powiedzenia o obiekcie window.

  2. Możesz również spróbować HTMLIFrameElement.contentDocument.defaultView, Na co pozwala kilka starszych przeglądarek, ale IE nie. mimo to standard nie mówi wprost, że odzyskujesz obiekt window z tego samego powodu, co (1), ale możesz wybrać kilka dodatkowych wersji przeglądarki tutaj, jeśli Ci zależy.

  3. window.frames['name'] zwrócenie okna jest najstarszym i co za tym idzie najbardziej niezawodnym interfejsem. Ale musisz użyć atrybutu name="...", aby móc uzyskać ramkę po nazwie, która jest nieco brzydka/przestarzała/transitional. (id="..." byłoby lepiej, ale IE tego nie lubi.)

  4. window.frames[number] jest również bardzo wiarygodne, ale znajomość odpowiedniego indeksu jest sztuką. Możesz uciec z tym np. jeśli wiesz masz tylko jeden iframe na stronie.

  5. Jest całkowicie możliwe, że dziecko iframe jeszcze się nie załadowało lub coś poszło nie tak, aby było niedostępne. Może okazać się łatwiejsze odwrócenie przepływu komunikacji: to znaczy, że dziecko iframe powiadomi swój skrypt window.parent, gdy skończy się załadować i będzie gotowe do ponownego wywołania. Mijając jeden z własnych obiektów (np. funkcji callback) do skryptu rodzica, ten rodzic może wtedy komunikować się bezpośrednio ze skryptem w iframe bez martwienia się o to, co HTMLIFrameElement jest związany z.

 140
Author: bobince,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-02 15:00:20

Wywołanie nadrzędnej funkcji JS z iframe jest możliwe, ale tylko wtedy, gdy zarówno rodzic, jak i strona załadowana w iframe pochodzą z tej samej domeny, tzn. abc.com, i oba używają tego samego protokołu tzn. oba są albo na http:// lub https://.

Wywołanie nie powiedzie się w wymienionych poniżej przypadkach:

  1. Strona nadrzędna i strona iframe pochodzą z różnych domen.
  2. używają różnych protokołów, jeden jest na http://, a drugi na https://.

Any obejście tego ograniczenia byłoby bardzo niebezpieczne.

Na przykład wyobraź sobie, że zarejestrowałem domenę superwinningcontest.com i wysyłał linki do e-maili. Kiedy załadowali stronę główną, mogłem ukryć tam kilka iframe s i przeczytać ich kanał Facebook, sprawdzić ostatnie transakcje Amazon lub PayPal,lub -- jeśli korzystali z usługi, która nie wdrożyła wystarczających zabezpieczeń -- przelać pieniądze z ich kont. Dlatego JavaScript jest ograniczony do tej samej domeny i ten sam protokół.

 63
Author: Vivek Singh CHAUHAN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-31 19:09:00

W ramce IFRAME dodaj swoją funkcję do obiektu window:

window.myFunction = function(args) {
   doStuff();
}

Aby uzyskać dostęp ze strony nadrzędnej, użyj tego:

var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);
 29
Author: Tomalak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-07 12:31:37

Jeśli ramka iFrame i zawierający dokument znajdują się w innej domenie, wcześniej opublikowane metody mogą nie działać, ale istnieje rozwiązanie:

Na przykład, jeśli dokument A zawiera element iframe zawierający dokument B, a skrypt w dokumencie a wywoła metodę postMessage() na obiekcie Window dokumentu B, to zostanie wywołane zdarzenie wiadomości, oznaczone jako pochodzące z okna dokumentu A. skrypt w dokumencie a może wyglądać następująco:

var o = document.getElementsByTagName('iframe')[0];
o.contentWindow.postMessage('Hello world', 'http://b.example.org/');

Aby zarejestrować obsługa zdarzeń przychodzących skrypt użyłby metody addeventlistener () (lub podobnych mechanizmów). Na przykład skrypt w dokumencie B może wyglądać następująco:

window.addEventListener('message', receiver, false);
function receiver(e) {
  if (e.origin == 'http://example.com') {
    if (e.data == 'Hello world') {
      e.source.postMessage('Hello', e.origin);
    } else {
      alert(e.data);
    }
  }
}

Ten skrypt najpierw sprawdza domenę, która jest domeną oczekiwaną, a następnie patrzy na wiadomość, którą albo wyświetla użytkownikowi, albo na którą odpowiada, wysyłając wiadomość z powrotem do dokumentu, który wysłał wiadomość w pierwszej kolejności.

Via http://dev.w3.org/html5/postmsg/#web-messaging

 16
Author: 19greg96,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-18 17:08:55

Tak dla przypomnienia, natknąłem się dziś na ten sam problem, ale tym razem strona została osadzona w obiekcie, a nie w ramce iframe (ponieważ był to dokument XHTML 1.1). Oto jak to działa z obiektami:

document
  .getElementById('targetFrame')
  .contentDocument
  .defaultView
  .targetFunction();

(przepraszam za brzydkie łamanie linii, nie zmieściło się w jednej linii)

 8
Author: Tamas Czinege,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-30 12:48:58

Ramka IFRAME powinna znajdować się w kolekcji frames[]. Użyj czegoś w stylu

frames['iframeid'].method();
 8
Author: dkretz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-18 14:19:21

Quirksmode miał post na ten.

Ponieważ strona jest teraz zepsuta i dostępna tylko za pośrednictwem archive.org, odtworzyłem go tutaj:

IFrames

Na tej stronie podaję krótki przegląd dostępu do ramek iFrame ze strony, na której się znajdują. Nic dziwnego, że istnieją pewne względy dotyczące przeglądarki.

Ramka iframe to ramka wbudowana, ramka, która, choć zawiera całkowicie oddzielną stronę z własnym adresem URL, jest jednak umieszczona wewnątrz innej Strona HTML. Daje to bardzo ładne możliwości w projektowaniu stron internetowych. Problem polega na uzyskaniu dostępu do ramki iframe, na przykład w celu załadowania do niej nowej strony. Ta strona wyjaśnia, jak to zrobić.

Ramka czy obiekt?

Podstawowe pytanie brzmi, czy ramka iframe jest postrzegana jako ramka, czy jako obiekt.

  • jak wyjaśniono na stronach Wprowadzenie do ramek , Jeśli używasz ramek, przeglądarka tworzy dla Ciebie hierarchię ramek (top.frames[1].frames[2] i tym podobne). Czy iframe pasuje do ta hierarchia ramek?
  • czy przeglądarka widzi iframe jako kolejny obiekt, obiekt, który ma właściwość src? W takim przypadku musimy użyć standardowego wywołania DOM (Jak document.getElementById('theiframe')) aby uzyskać do niego dostęp. Ogólnie przeglądarki zezwalają na oba widoki na 'prawdziwych' (zakodowanych na twardo) ramkach iFrame, ale wygenerowane ramki iFrame nie mogą być dostępne jako ramki.

Atrybut nazwy

Najważniejszą regułą jest nadanie dowolnemu iframe ' owi atrybutu name, nawet jeśli również użyj id.

<iframe src="iframe_page1.html"
    id="testiframe"
    name="testiframe"></iframe>

Większość przeglądarek potrzebuje atrybutu name, aby uczynić ramkę iframe częścią hierarchii ramek. Niektóre przeglądarki (zwłaszcza Mozilla) wymagają id, aby ramka iframe była dostępna jako obiekt. Przypisując oba atrybuty do ramki iframe zachowujesz otwarte opcje. Ale name jest o wiele ważniejsza niż id.

Dostęp

Albo uzyskujesz dostęp do ramki iframe jako obiekt i zmienisz jej src lub uzyskasz dostęp do ramki iframe jako ramki i zmienisz jej location.href.

Dokument.getElementById ('iframe_id').src = " newpage.html"; ramki ['iframe_name'].miejsce.href = ' newpage.html"; Składnia ramki jest nieco korzystniejsza, ponieważ Opera 6 obsługuje ją, ale nie składnię obiektu.

Dostęp do iframe

Aby uzyskać pełną obsługę między przeglądarkami, należy nadać ramce iframe nazwę i użyć
frames['testiframe'].location.href

Składnia. Z tego co wiem, to zawsze działa.

Dostęp do dokument

Dostęp do dokumentu wewnątrz ramki iframe jest dość prosty, pod warunkiem, że użyjesz atrybutu name. Aby policzyć liczbę linków w dokumencie w ramce iframe, należy frames['testiframe'].document.links.length.

Generowane iframes

Podczas generowania ramki iframe przez W3C DOM ramka iframe nie jest od razu wprowadzana do tablicy frames, a składnia frames['testiframe'].location.href nie będzie działać od razu. Przeglądarka potrzebuje trochę czasu, zanim pojawi się iframe w tablicy czas, w którym nie może być uruchomiony żaden skrypt.

Składnia document.getElementById('testiframe').src działa dobrze w każdych okolicznościach.

Atrybut target linku również nie działa z wygenerowanymi ramkami iFrame, z wyjątkiem Opery, mimo że dałem wygenerowanemu iframe zarówno name, jak i id.

Brak wsparcia target oznacza, że musisz użyć JavaScript, aby zmienić zawartość generowanego iframe, ale ponieważ i tak potrzebujesz JavaScript, aby go wygenerować, nie widzę tego jako duży problem.

Rozmiar tekstu w ramkach iframes

Ciekawy Explorer 6 tylko bug:

Gdy zmienisz rozmiar tekstu za pomocą menu Widok, rozmiary tekstu w ramkach iFrame zostaną poprawnie zmienione. Jednak ta przeglądarka nie zmienia podziałów wierszy w oryginalnym tekście, tak że część tekstu może stać się niewidoczna lub mogą wystąpić podziały wierszy, gdy wiersz może nadal zawierać inne słowo.

 8
Author: activout.se,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-03 13:22:15

Znalazłem całkiem eleganckie rozwiązanie.

Jak powiedziałeś, dość łatwo jest wykonać kod znajdujący się w dokumencie nadrzędnym. I to jest podstawa mojego kodu, zrób coś przeciwnego.

Gdy mój iframe ładuje się, wywołuję funkcję znajdującą się w dokumencie nadrzędnym, przekazując jako argument odniesienie do lokalnej funkcji, znajdującej się w dokumencie iframe. Dokument nadrzędny ma teraz bezpośredni dostęp do funkcji iframe za pośrednictwem tego odniesienia.

Przykład:

On "rodzic": {]}

function tunnel(fn) {
    fn();
}

Na iframe:

var myFunction = function() {
    alert("This work!");
}

parent.tunnel(myFunction);

Gdy ramka iframe wczytuje się, wywoła rodzica.tunnel (YourFunctionReference), który wykona funkcję otrzymaną w parametrze.

To proste, bez konieczności radzenia sobie ze wszystkimi niestandardowymi metodami z różnych przeglądarek.

 7
Author: Julien L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-08 17:44:45

Niektóre z tych odpowiedzi nie odnoszą się do problemu Kors, lub nie sprawiają, że oczywiste jest, gdzie umieszczasz fragmenty kodu, aby umożliwić komunikację.

Oto konkretny przykład. Powiedzmy, że chcę kliknąć przycisk na stronie nadrzędnej i zrobić coś wewnątrz ramki iframe. Oto jak bym to zrobił.

Parent_frame.html

<button id='parent_page_button' onclick='call_button_inside_frame()'></button>

function call_button_inside_frame() {
   document.getElementById('my_iframe').contentWindow.postMessage('foo','*');
}

Iframe_page.html

window.addEventListener("message", receiveMessage, false);

function receiveMessage(event)
    {
      if(event) {
        click_button_inside_frame();
    }
}

function click_button_inside_frame() {
   document.getElementById('frame_button').click();
}

Aby przejść w drugą stronę (kliknij przycisk wewnątrz iframe aby wywołać metodę poza iframe) wystarczy przełączyć gdzie znajduje się fragment kodu i zmień to:

document.getElementById('my_iframe').contentWindow.postMessage('foo','*');

Do tego:

window.parent.postMessage('foo','*')
 4
Author: Cybernetic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-07 16:42:04

Kontynuacja Joel ' s odpowiedź:

Aby uzyskać większą wytrzymałość, użyj następującego wzoru:

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

if(el.contentWindow)
{
   el.contentWindow.targetFunction();
}
else if(el.contentDocument)
{
   el.contentDocument.targetFunction();
}

Workd like charm:)

 3
Author: Nitin Bansal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:04

Folowing Nitin Bansal ' s answer

I dla jeszcze większej solidności:

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

I

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

getIframeWindow(el).targetFunction();
...
 3
Author: Dominique Fortin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-03 12:55:05
       $("#myframe").load(function() {
            alert("loaded");
        });
 2
Author: GeverGever,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-21 20:08:48

Te same rzeczy, ale nieco prostszym sposobem będzie Jak odświeżyć Stronę nadrzędną ze strony wewnątrz iframe. Wystarczy wywołać funkcję strony nadrzędnej, aby wywołać funkcję javascript, aby ponownie załadować stronę:

window.location.reload();

Lub zrobić to bezpośrednio ze strony w iframe:

window.parent.location.reload();

Oba działa.

 2
Author: sangam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-30 06:44:56

Jeśli chcemy wywołać Stronę nadrzędną funkcji javascript z iframe, który wygenerowany z kodowania. ex shadowbox lub lightbox

Okno.rodzic.targetFunction ();

 1
Author: Santhanakumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-05 05:43:42

Try just parent.myfunction()

 1
Author: Saeid Zebardast,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-14 11:33:03

Użyj następującej do wywołania funkcji ramki na stronie nadrzędnej

parent.document.getElementById('frameid').contentWindow.somefunction()
 -3
Author: Sandy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-17 06:56:54