Aufrufen einer übergeordneten Fensterfunktion aus einem Iframe

281

Ich möchte eine JavaScript-Funktion eines übergeordneten Fensters von einem Iframe aus aufrufen.

<script>
    function abc()
    {
        alert("sss");
    }
</script>

<iframe id="myFrame">
    <a onclick="abc();" href="#">Call Me</a>
</iframe>
Arjun Singh
quelle
1
Ich kann
momentan

Antworten:

438
<a onclick="parent.abc();" href="#" >Call Me </a>

Siehe window.parent

Gibt einen Verweis auf das übergeordnete Element des aktuellen Fensters oder Unterrahmens zurück.

Wenn ein Fenster kein übergeordnetes Fenster hat, ist seine übergeordnete Eigenschaft ein Verweis auf sich selbst.

Wenn ein Fenster in ein <iframe>, <object>oder <frame>, geladen wird , ist sein übergeordnetes Fenster das Fenster, in das das Element das Fenster einbettet.

rahul
quelle
17
Berücksichtigen Sie immer, dass das übergeordnete Dokument und das Iframe-Dokument nach Protokoll und Domänenname übereinstimmen müssen. Wenn dies nicht der Fall ist, wird ein Sicherheitsfehler angezeigt, da keine domänenübergreifende Skripterstellung zulässig ist.
a4bike
Ich frage mich nur, welches der beiden alertaufgerufen wird. Elternfunktion alertoder Iframe- alertFunktion, falls parent.abc();iframe aufgerufen wird?
Prakhar Mishra
@PrakharMishra Sei nicht verwirrt. Eltern bedeutet Eltern.
Sahu V Kumar
3
@ a4bike für solche Szenarien existiert window.postMessage()(oder window.parent.postMessage()). Überprüfen Sie @Andrii Antwort
Fr0zenFyr
81

Ich musste kürzlich herausfinden, warum dies auch nicht funktionierte.

Das Javascript, das Sie vom untergeordneten iframe aufrufen möchten, muss sich im Kopf des übergeordneten Elements befinden. Wenn es sich im Hauptteil befindet, ist das Skript im globalen Bereich nicht verfügbar.

<head>
    <script>
    function abc() {
        alert("sss");
    }
    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="parent.abc();" href="#">Click Me</a>
    </iframe>
</body>

Hoffe, das hilft jedem, der wieder auf dieses Problem stößt.

Ash Clarke
quelle
1
Keine der in diesem Beitrag erwähnten Techniken funktioniert in Chrome. Irgendwelche Lösungen dafür?
Kumar Kush
3
Wenn ich mich richtig erinnere, konnte ich dies nicht wie erwartet zum Laufen bringen, wenn der Iframe eine andere Domäne als der übergeordnete hatte. Entschuldigung, dies ist keine Lösung, aber es könnte erklären, warum es nicht funktioniert.
Ash Clarke
1
Ja. Ich weiß, dass es an verschiedenen Domänen liegt, aber gibt es keine Möglichkeit, dies zu umgehen?
Kumar Kush
1
Ich habe gerade veröffentlicht, was eine Problemumgehung für Ihr Problem sein könnte. Schauen Sie sich die andere Antwort an.
Ash Clarke
1
Gemäß denselben Regeln zur Bestimmung der Ursprungsrichtlinie (siehe: en.wikipedia.org/wiki/… ) werden Subdomains als ein anderer Hostname als eine Subdomain einer Domain betrachtet. Wenn Sie es noch nicht getan haben, können Sie versuchen, document.domain auf die Subdomain zu setzen.
Ash Clarke
72

Window.postMessage ()

Diese Methode ermöglicht sicher die cross-originKommunikation.

Wenn Sie Zugriff auf den übergeordneten Seitencode haben, können Sie jede übergeordnete Methode aufrufen und alle Daten direkt von übergeben Iframe. Hier ist ein kleines Beispiel:

Übergeordnete Seite:

if (window.addEventListener) {
    window.addEventListener("message", onMessage, false);        
} 
else if (window.attachEvent) {
    window.attachEvent("onmessage", onMessage, false);
}

function onMessage(event) {
    // Check sender origin to be trusted
    if (event.origin !== "http://example.com") return;

    var data = event.data;

    if (typeof(window[data.func]) == "function") {
        window[data.func].call(null, data.message);
    }
}

// Function to be called from iframe
function parentFunc(message) {
    alert(message);
}

Iframe-Code:

window.parent.postMessage({
    'func': 'parentFunc',
    'message': 'Message text from iframe.'
}, "*");
// Use target origin instead of *

AKTUALISIERUNG:

Sicherheitshinweis:

Geben *Sie immer ein bestimmtes targetOrigin an, NICHT , wenn Sie wissen, wo sich das Dokument des anderen Fensters befinden soll. Wenn Sie kein bestimmtes Ziel angeben , werden die Daten, die Sie an eine interessierte schädliche Website senden, offengelegt (Kommentar von ZalemCitizen ).

Verweise:

Andrii Verbytskyi
quelle
1
Ich benutze dies lieber als andere. Vor allem, weil es sinnvoller ist, Iframes in Cross-Origin-Dokumenten zu verwenden (obwohl Programmierer Iframes häufig ausnutzen) und diese Funktion in Browsern weitgehend unterstützt.
Fr0zenFyr
1
Vielen Dank! Ich muss immer eine Stunde oder länger zurückgehen und nachforschen, wie man das Messaging mit überkomplizierten, ausführlichen Beispielen macht. Dies funktionierte in 60 Sekunden. Vielen Dank für ein kurzes und präzises Beispiel.
RandallTo
2
Es lohnt sich, dies zu erwähnen (aus MDN-Webdokumenten ): Geben Sie immer ein bestimmtes targetOrigin an, nicht *, wenn Sie wissen, wo sich das Dokument des anderen Fensters befinden soll. Wenn Sie kein bestimmtes Ziel
angeben
20

Ich habe dies als separate Antwort veröffentlicht, da es nichts mit meiner vorhandenen Antwort zu tun hat.

Dieses Problem trat kürzlich erneut auf, wenn über ein Iframe, das auf eine Subdomain verweist, auf ein übergeordnetes Element zugegriffen wurde, und die vorhandenen Korrekturen funktionierten nicht.

Diesmal bestand die Antwort darin, die document.domain der übergeordneten Seite und den iframe so zu ändern, dass sie identisch sind. Dadurch werden dieselben Ursprungsrichtlinienprüfungen dahingehend getäuscht, dass sie auf genau derselben Domäne nebeneinander existieren (Subdomänen werden als ein anderer Host betrachtet und bestehen dieselbe Ursprungsrichtlinienprüfung nicht).

Fügen Sie Folgendes in die <head>Seite des Iframes ein, um es der übergeordneten Domäne anzupassen (passen Sie es an Ihren Doctype an).

<script>
    document.domain = "mydomain.com";
</script>

Bitte beachten Sie, dass dies einen Fehler bei der Entwicklung von localhost auslöst. Verwenden Sie daher eine Prüfung wie die folgende, um den Fehler zu vermeiden:

if (!window.location.href.match(/localhost/gi)) {
    document.domain = "mydomain.com";
} 
Ash Clarke
quelle
und was ist mit dem Testen in localhost? eine Problemumgehung dafür?
Umesh Awasthi
Siehe: "Bitte beachten Sie, dass dies einen Fehler bei der Entwicklung von localhost auslöst. Verwenden Sie daher eine Prüfung wie die folgende, um den Fehler zu vermeiden"
Ash Clarke
2
Es ist erwähnenswert, dass (zumindest in Google Chrome) sowohl Eltern als auch Kind document.domain SETZEN MÜSSEN, auch wenn einer von ihnen bereits "korrekt" ist! Beispiel: Parent ist example.comiframe is abc.example.com, dann müssen sowohl parent als auch iframe anrufendocument.domain = "example.com"
KillerX
Ja das ist richtig, ich habe hier einen Tippfehler gemacht: "Seite im Iframe soll gleich sein." sollte "Seite und der Iframe müssen gleich sein". ..... Vielen Dank!
Ash Clarke
für das if () warum würden Sie nicht einfach if (document.domain! = "mydomain.com" verwenden? Ich bin auch verwirrt, geht das <script> in das übergeordnete Fenster oder den iFrame? document.domain in iFrame generiert "Fehler beim Festlegen der Eigenschaft 'domain' für 'Document': 'localhost' ist kein Suffix von 'sc-localhost'.
user2568374
18

Sie können verwenden

window.top

siehe folgendes.

<head>
    <script>
    function abc() {
        alert("sss");
    }
    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="window.top.abc();" href="#">Click Me</a>
    </iframe>
</body>
Vinothkumar Arputharaj
quelle
Beim Versuch, parent.custom_function () aufzurufen; Wenn ein Iframe nicht funktioniert, finden Sie möglicherweise window.top.custom_function (). wird funktionieren. Funktioniert für mich aus irgendeinem Grund. Meine Javascripts im übergeordneten Fenster sind alle in die Fußzeile eingebettet. Ich habe irgendwo gelesen, dass das Einfügen von Javascript-Dateien in die Fußzeile das Problem verursacht, dass parent.custom_function () nicht funktioniert.
Friso Horstman
@ Vinothkumar, eine Frage bitte, was ist der Unterschied zwischen dem Aufruf von "window.top.abc ()" als dem Aufruf von nur "abc ()", danke im Voraus =)
Zilev av
@Zilev av Der gesamte Punkt dieses Threads ruft eine Funktion in einem übergeordneten Dokument von einem untergeordneten Iframe auf. Das ist der Unterschied. Das Aufrufen abc()würde nur funktionieren, wenn function abc()es im iframe und nicht auf der übergeordneten Seite deklariert wäre . window.top.abc()bricht aus dem iframe in das übergeordnete Dokument aus.
Sean Kendle
3

Eine weitere Ergänzung für diejenigen, die es brauchen. Die Lösung von Ash Clarke funktioniert nicht, wenn unterschiedliche Protokolle verwendet werden. Stellen Sie daher sicher, dass Ihr Iframe bei Verwendung von SSL auch SSL verwendet, da sonst die Funktion beeinträchtigt wird. Seine Lösung hat jedoch für die Domains selbst funktioniert, also danke dafür.

Devon
quelle
2

Die von Ash Clarke für Subdomains angegebene Lösung funktioniert hervorragend. Beachten Sie jedoch, dass Sie document.domain = "mydomain.com" einschließen müssen. Sowohl im Kopf der Iframe-Seite als auch im Kopf der übergeordneten Seite, wie im Link angegeben, werden die Richtlinien zur Überprüfung des gleichen Ursprungs angegeben

Eine wichtige Erweiterung derselben Ursprungsrichtlinie, die für den JavaScript-DOM-Zugriff implementiert wurde (jedoch nicht für die meisten anderen Varianten von Überprüfungen mit demselben Ursprung), besteht darin, dass zwei Sites, die eine gemeinsame Domäne der obersten Ebene gemeinsam nutzen, sich möglicherweise für die Kommunikation entscheiden, obwohl der "gleiche Host" fehlschlägt. Überprüfen Sie dies, indem Sie die jeweilige document.domain-DOM-Eigenschaft gegenseitig auf dasselbe qualifizierte rechte Fragment ihres aktuellen Hostnamens festlegen. Wenn beispielsweise http://en.example.com/ und http://fr.example.com/ document.domain auf "example.com" setzen, werden sie ab diesem Zeitpunkt als gleicher Ursprung für die Zweck der DOM-Manipulation.

Frato
quelle
Ja das ist richtig, ich habe hier einen Tippfehler gemacht: "Seite im Iframe soll gleich sein." sollte "Seite und der Iframe müssen gleich sein". ..... Vielen Dank!
Ash Clarke
Wie wäre es mit dem Ausführen von Dateien auf einem lokalen Computer? Was ist der Wert von document.domain?
Raptor
Dies ist localhostoder die IP-Adresse des Computers (normalerweise 127.0.0.1), je nachdem, was in der URL-Adressleiste steht.
Ash Clarke
2

parent.abc () funktioniert aus Sicherheitsgründen nur in derselben Domain. Ich habe diese Problemumgehung ausprobiert und meine hat perfekt funktioniert.

<head>
    <script>
    function abc() {
        alert("sss");
    }

    // window of the iframe
    var innerWindow = document.getElementById('myFrame').contentWindow;
    innerWindow.abc= abc;

    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="abc();" href="#">Click Me</a>
    </iframe>
</body>

Hoffe das hilft. :) :)

Seph Remotigue
quelle
Dies ist auch wirklich nur eine Verwendung für das Iframe-Dokument, was zu massiven Komplikationen führt, wenn Sie auf Steuerelemente im übergeordneten Formular verweisen müssen.
Paul
1

Mit Firefox und Chrome können Sie Folgendes verwenden:

<a href="whatever" target="_parent" onclick="myfunction()">

Wenn meine Funktion sowohl im iframe als auch im übergeordneten Element vorhanden ist, wird das übergeordnete Element aufgerufen.

Schneeflocke
quelle
es funktioniert nicht Hier ist meine Demo: dotku.github.io/tech/html/iframe/iframe_function_container.html
Weijing Jay Lin
Wie von Ash Clarke angegeben, muss sich das Javascript, das Sie vom Kinder-Iframe aufrufen möchten, im Kopf des Elternteils befinden.
Schneeflocke
Für die akzeptierte Antwort muss sich das Skript nicht im Kopf befinden. Ich habe nicht getestet, ob diese Lösung auch nicht mehr benötigt, damit das Skript im Kopf ist oder nicht.
Guy Schalnat
0

Während einige dieser Lösungen möglicherweise funktionieren, folgt keine der Best Practices. Viele weisen globale Variablen zu, und Sie rufen möglicherweise mehrere übergeordnete Variablen oder Funktionen auf, was zu einem überfüllten, anfälligen Namespace führt.

Um dies zu vermeiden, verwenden Sie ein Modulmuster. Im übergeordneten Fenster:

var myThing = {
    var i = 0;
    myFunction : function () {
        // do something
    }
};

var newThing = Object.create(myThing);

Dann im Iframe:

function myIframeFunction () {
    parent.myThing.myFunction();
    alert(parent.myThing.i);
};

Dies ähnelt den Mustern, die im Kapitel Vererbung von Crockfords wegweisendem Text "Javascript: The Good Parts" beschrieben sind. Weitere Informationen zu den Best Practices von Javascript finden Sie auch auf der Seite von w3. https://www.w3.org/wiki/JavaScript_best_practices#Avoid_globals

William J. Littlefield
quelle