it-swarm.com.de

Aufrufen von JavaScript-Code in einem Iframe von der übergeordneten Seite

Grundsätzlich habe ich ein iframe in eine Seite eingebettet und das iframe hat einige JavaScript -Routinen, die ich von der übergeordneten Seite aufrufen muss.

Jetzt ist das Gegenteil ganz einfach, da Sie nur parent.functionName() aufrufen müssen, aber leider brauche ich genau das Gegenteil davon.

Bitte beachten Sie, dass mein Problem nicht die Quelle URL des iframe ändert, sondern eine in iframe definierte Funktion aufruft.

589
Tamas Czinege

Angenommen, die ID Ihres iFrames lautet "targetFrame" und die aufzurufende Funktion ist targetFunction():

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

Sie können auch mit window.frames anstelle von document.getElementById auf den Frame zugreifen.

// this option does not work in most of latest versions of chrome and Firefox
window.frames[0].frameElement.contentWindow.targetFunction(); 
527
Joel Anair

Hier sind einige Besonderheiten zu beachten.

  1. HTMLIFrameElement.contentWindow ist wahrscheinlich der einfachere Weg, aber es ist keine Standardeigenschaft, und einige Browser unterstützen dies nicht, meistens ältere. Dies liegt daran, dass der HTML-Standard DOM Level 1 nichts über das Objekt window zu sagen hat.

  2. Sie können auch HTMLIFrameElement.contentDocument.defaultView ausprobieren, was einige ältere Browser zulassen, IE jedoch nicht. Trotzdem besagt der Standard nicht explizit, dass Sie das Objekt window aus dem gleichen Grund wie (1) zurückerhalten, aber Sie können hier ein paar zusätzliche Browserversionen auswählen, wenn Sie sich dafür interessieren.

  3. window.frames['name'] Die Rückgabe des Fensters ist die älteste und damit zuverlässigste Schnittstelle. Sie müssen dann jedoch ein name="..." -Attribut verwenden, um einen Rahmen mit Namen zu erhalten, der leicht hässlich ist.veraltetÜbergang. (id="..." wäre besser, aber IE mag das nicht.)

  4. window.frames[number] ist ebenfalls sehr zuverlässig, aber den richtigen Index zu kennen, ist der Trick. Sie können damit zB durchkommen. Wenn Sie wissen, dass Sie nur den einen Iframe auf der Seite haben.

  5. Es ist durchaus möglich, dass der untergeordnete Iframe noch nicht geladen wurde oder dass ein anderer Fehler aufgetreten ist, der den Zugriff unmöglich gemacht hat. Möglicherweise ist es einfacher, den Kommunikationsfluss umzukehren: Lassen Sie das untergeordnete iframe sein window.parent -Skript benachrichtigen, wenn es vollständig geladen wurde und zum Rückruf bereit ist. Durch Übergabe eines eigenen Objekts (z. B. einer Rückruffunktion) an das übergeordnete Skript kann dieses übergeordnete Objekt dann direkt mit dem Skript im iframe kommunizieren, ohne sich Gedanken darüber machen zu müssen, welchem ​​HTMLIFrameElement es zugeordnet ist.

143
bobince

Das Aufrufen einer übergeordneten JS-Funktion von iframe aus ist nur möglich, wenn sowohl die übergeordnete als auch die in iframe geladene Seite von derselben Domäne stammen, dh abc.com, und beide dasselbe Protokoll verwenden, dh beide entweder auf http:// oder https://.

Der Anruf wird in den folgenden Fällen fehlschlagen:

  1. Übergeordnete Seite und Iframe-Seite stammen aus einer anderen Domäne.
  2. Sie verwenden unterschiedliche Protokolle, eines befindet sich auf http: // und das andere auf https: //.

Eine Umgehung dieser Einschränkung wäre äußerst unsicher.

Stellen Sie sich zum Beispiel vor, ich hätte die Domain superwinningcontest.com registriert und Links zu den E-Mails der Leute gesendet. Wenn sie die Hauptseite hoch geladen haben, konnte ich ein paar iframe darin verstecken und ihren Facebook-Feed lesen, die letzten Amazon- oder Paypal-Transaktionen überprüfen oder - wenn sie einen Dienst verwendeten, der keine ausreichende Sicherheit implementierte - übertragen Geld von ihren Konten. Aus diesem Grund ist JavaScript auf dieselbe Domain und dasselbe Protokoll beschränkt.

64

Machen Sie im IFRAME Ihre Funktion für das Fensterobjekt öffentlich:

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

Verwenden Sie für den Zugriff von der übergeordneten Seite Folgendes:

var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);
30
Tomalak

Wenn sich der iFrame und das enthaltene Dokument in einer anderen Domäne befinden, funktionieren die zuvor veröffentlichten Methoden möglicherweise nicht, es gibt jedoch eine Lösung:

Wenn beispielsweise Dokument A ein iframe-Element enthält, das Dokument B enthält, und Skript in Dokument A postMessage () für das Window-Objekt von Dokument B aufruft, wird für dieses Objekt ein Nachrichtenereignis ausgelöst, das als aus dem Window von stammend markiert ist Dokument A. Das Skript in Dokument A könnte folgendermaßen aussehen:

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

Um einen Ereignishandler für eingehende Ereignisse zu registrieren, würde das Skript addEventListener () (oder ähnliche Mechanismen) verwenden. Das Skript in Dokument B könnte beispielsweise folgendermaßen aussehen:

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

Dieses Skript überprüft zunächst, ob es sich bei der Domäne um die erwartete Domäne handelt, und überprüft dann die Nachricht, die dem Benutzer entweder angezeigt wird, oder antwortet, indem eine Nachricht an das Dokument zurückgesendet wird, das die Nachricht ursprünglich gesendet hat.

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

16
19greg96

Nur zur Veranschaulichung, ich bin heute auf dasselbe Problem gestoßen, aber dieses Mal war die Seite in ein Objekt eingebettet, nicht in einen Iframe (da es sich um ein XHTML 1.1-Dokument handelte). So funktioniert es mit Objekten:

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

(Entschuldigung für die hässlichen Zeilenumbrüche, passte nicht in eine einzelne Zeile)

9
Tamas Czinege

Quirksmode hatte ein Beitrag daz .

Da die Seite jetzt kaputt und nur über archive.org zugänglich ist, habe ich sie hier reproduziert:

IFrames

Auf dieser Seite gebe ich einen kurzen Überblick über den Zugriff auf Iframes von der Seite, auf der sie sich befinden. Es überrascht nicht, dass es einige Überlegungen zum Browser gibt.

Ein iframe ist ein Inline-Frame, ein Frame, der zwar eine vollständig separate Seite mit einer eigenen URL enthält, sich jedoch in einer anderen HTML-Seite befindet. Dies gibt sehr schöne Möglichkeiten im Webdesign. Das Problem besteht darin, auf den iframe zuzugreifen, um beispielsweise eine neue Seite darin zu laden. Diese Seite erklärt, wie es geht.

Rahmen oder Objekt?

Die grundsätzliche Frage ist, ob der iframe als Frame oder als Objekt gesehen wird.

  • Wie auf den Seiten Einführung in Frames erläutert, erstellt der Browser bei Verwendung von Frames eine Frame-Hierarchie für Sie (_top.frames[1].frames[2]_ und so weiter). Passt der iframe in diese Rahmenhierarchie?
  • Oder sieht der Browser einen iframe nur als ein anderes Objekt, ein Objekt, das zufällig eine src-Eigenschaft hat? In diesem Fall müssen wir einen Standard DOM-Aufruf (wie document.getElementById('theiframe')) verwenden, um darauf zuzugreifen. Im Allgemeinen erlauben Browser beide Ansichten für 'echte' (fest codierte) Iframes, aber generierte Iframes nicht als Frames zugegriffen werden.

NAME-Attribut

Die wichtigste Regel ist, jedem iframe ein name-Attribut zuzuweisen, selbst wenn Sie auch ein id verwenden.

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

Die meisten Browser benötigen das Attribut name, um den Iframe in die Rahmenhierarchie aufzunehmen. Einige Browser (insbesondere Mozilla) benötigen id, um den Iframe als Objekt zugänglich zu machen. Indem Sie dem iframe beide Attribute zuweisen, behalten Sie Ihre Optionen offen. Aber name ist weitaus wichtiger als id.

Zugriff

Entweder greifen Sie auf den iframe als Objekt zu und ändern dessen src, oder Sie greifen auf den iframe als Frame zu und ändern dessen _location.href_.

document.getElementById ('iframe_id'). src = 'newpage.html'; frames ['iframe_name']. location.href = 'newpage.html'; Die Frame-Syntax ist etwas vorzuziehen, da Opera 6 sie unterstützt, nicht jedoch die Objekt-Syntax.

Zugriff auf den Iframe

Für eine vollständige Cross-Browser-Erfahrung sollten Sie dem iframe einen Namen geben und den verwenden

_frames['testiframe'].location.href
_

syntax. Soweit ich weiß funktioniert das immer.

Zugriff auf das Dokument

Der Zugriff auf das Dokument im iframe ist recht einfach, vorausgesetzt, Sie verwenden das Attribut name. Führen Sie frames['testiframe'].document.links.length aus, um die Anzahl der Verknüpfungen im Dokument im iframe zu ermitteln.

Generierte Iframes

Wenn Sie einen iframe über W3C DOM generieren, wird der iframe jedoch nicht sofort in das Array frames eingegeben, und die Syntax _frames['testiframe'].location.href_ funktioniert nicht sofort. Der Browser benötigt eine Weile, bis der Iframe im Array angezeigt wird. In dieser Zeit wird möglicherweise kein Skript ausgeführt.

Die Syntax document.getElementById('testiframe').src funktioniert unter allen Umständen einwandfrei.

Das target Attribut eines Links funktioniert auch nicht mit generierten Iframes, außer in Opera, obwohl ich meinem generierten Iframe sowohl ein name als auch ein id gegeben habe.

Das Fehlen von target -Unterstützung bedeutet, dass Sie JavaScript verwenden müssen, um den Inhalt eines generierten Iframes zu ändern. Da Sie jedoch ohnehin JavaScript benötigen, um ihn zu generieren, ist dies für mich kein großes Problem.

Textgröße in Iframes

Ein merkwürdiger Explorer 6-Fehler:

Wenn Sie die Textgröße über das Menü Ansicht ändern, werden die Textgrößen in Iframes korrekt geändert. Dieser Browser ändert jedoch nicht die Zeilenumbrüche im Originaltext, sodass ein Teil des Texts möglicherweise unsichtbar wird oder Zeilenumbrüche auftreten, während die Zeile möglicherweise noch ein anderes Wort enthält.

8
activout.se

Der IFRAME sollte sich in der Sammlung frames[] befinden. Verwenden Sie so etwas wie

frames['iframeid'].method();
8
dkretz

Ich habe eine ziemlich elegante Lösung gefunden.

Wie Sie sagten, ist es ziemlich einfach, Code auszuführen, der sich im übergeordneten Dokument befindet. Und das ist die Basis meines Codes, genau das Gegenteil zu tun.

Wenn mein iframe geladen wird, rufe ich eine Funktion auf, die sich im übergeordneten Dokument befindet, und übergebe als Argument einen Verweis auf eine lokale Funktion, die sich im iframe-Dokument befindet. Das übergeordnete Dokument hat jetzt über diese Referenz direkten Zugriff auf die Funktion des iframes.

Beispiel:

Auf dem Elternteil:

function tunnel(fn) {
    fn();
}

Auf dem iframe:

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

parent.tunnel(myFunction);

Wenn der iframe geladen wird, ruft er parent.tunnel (YourFunctionReference) auf, der die in parameter empfangene Funktion ausführt.

So einfach, ohne sich mit den nicht standardmäßigen Methoden der verschiedenen Browser auseinandersetzen zu müssen.

7
Julien L

Einige dieser Antworten behandeln das CORS-Problem nicht oder machen nicht deutlich, wo Sie die Code-Schnipsel platzieren, um die Kommunikation zu ermöglichen.

Hier ist ein konkretes Beispiel. Angenommen, ich möchte auf der übergeordneten Seite auf eine Schaltfläche klicken und diese im iframe ausführen. Hier ist, wie ich es machen würde.

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

Um in die andere Richtung zu wechseln (klicken Sie auf die Schaltfläche innerhalb von iframe, um die Methode außerhalb von iframe aufzurufen), wechseln Sie einfach den Speicherort des Code-Snippets und ändern Sie Folgendes:

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

dazu:

window.parent.postMessage('foo','*')
4
Cybernetic

Weiter mit JoelAnairs Antwort:

Verwenden Sie für mehr Robustheit Folgendes:

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

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

Arbeitete wie Charme :)

3
Nitin Bansal

Folge der Antwort von Nitin Bansal

und für noch mehr Robustheit:

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

und

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

var frame_win = getIframeWindow(el);

if (frame_win) {
  frame_win.targetFunction();
  ...
}
...
3

Die gleichen Dinge, aber ein bisschen einfacher, werden sein So aktualisieren Sie die übergeordnete Seite von der Seite innerhalb von iframe . Rufen Sie einfach die Funktion der übergeordneten Seite auf, um die Javascript-Funktion aufzurufen und die Seite neu zu laden:

window.location.reload();

Oder machen Sie dies direkt von der Seite in iframe:

window.parent.location.reload();

Beides funktioniert.

2
sangam
       $("#myframe").load(function() {
            alert("loaded");
        });
2
GeverGever

Probieren Sie einfach parent.myfunction()

1
Saeid Zebardast

Wenn Sie die JavaScript-Funktion für das übergeordnete Element aus dem Iframe aufrufen möchten, der von einer anderen Funktion (z. B. shadowbox oder lightbox) generiert wurde.

Sie sollten versuchen, das Objekt window zu verwenden und die übergeordnete Funktion aufzurufen:

window.parent.targetFunction();
1
Santhanakumar