So greifen Sie über JavaScript auf den übergeordneten Iframe zu

170

Nun, ich habe einen IFrame, der dieselbe Domain-Seite aufruft. Mein Problem ist, dass ich über diese aufgerufene Seite (über JavaScript) auf einige Informationen von diesem übergeordneten Iframe zugreifen möchte. Wie kann ich auf diesen Iframe zugreifen?

Details: Es gibt mehrere Iframes wie diesen, auf denen dieselbe Seite geladen werden kann, da ich eine Windows-Umgebung programmiere. Ich habe vor, diesen Iframe zu schließen, deshalb muss ich wissen, welchen ich aus seinem Inneren schließen soll. Ich habe ein Array, das Verweise auf diese Iframes enthält.

EDIT: Dort werden iframes dynamisch generiert

José Leal
quelle
Selbst wenn iframes dynamisch generiert werden, können Sie mithilfe eines Zählers eine neue eindeutige ID zuweisen. Schließlich müssen Sie die ID nicht kennen, aber Sie können einfach suchen, siehe meine Antwort.
Akash Kava

Antworten:

138

Sie können auch Name und ID auf gleiche Werte setzen

<iframe id="frame1" name="frame1" src="any.html"></iframe>

So können Sie den nächsten Code auf der untergeordneten Seite verwenden

parent.document.getElementById(window.name);
Wasser
quelle
16
Vielleicht ist es nicht für alle offensichtlich, aber mit dieser Methode können Sie auf ein Bibliotheksobjekt des übergeordneten Elements zugreifen (nur wenn das übergeordnete Element die Bibliothek bereits geladen hat). Beispiel: Zugriff auf jQuery mit übergeordnetem
Element
1
Diese Lösung ist mit dem IE5 + -Kompatibilitätsmodus kompatibel.
Slayner
Selbst im Jahr 2016 funktioniert dies hervorragend als Teil einer Lösung für das Problem, dass der IE den Inhalt eines iframezu kleinen druckt . Aber warum funktioniert es? window.namegibt eine Zeichenfolge zurück. Was ist anders daran, window.nameals nur den ID-Namen als Zeichenfolge zu übergeben, was nicht funktioniert.)?
Karl
3
Hallo, es läuft nicht mit Chrome 59 ..: VM111: 1 Nicht erfasst DOMException: Blockiert einen Frame mit dem Ursprung " xxx " für den Zugriff auf einen Cross-Origin-Frame.
Didier68
Chrome zeigt Dateien im selben Ordner wie Cross-Origin an, wenn nicht CORS festgelegt ist. Sie sagen, es ist für die Sicherheit. Für die Einstellung von CORS ist ein Server erforderlich. Geben Sie den Benutzern eine Nachricht zum Einrichten eines Servers oder zum Ändern des Browsers, wenn Chrome erkannt wird.
90

Rufen window.frameElementSie einfach von Ihrer gerahmten Seite an. Wenn sich die Seite nicht in einem Frame befindet, frameElementwird dies der Fall sein null.

Der andere Weg (das Fensterelement in einen Rahmen zu bekommen ist weniger trivial), aber der Vollständigkeit halber:

/**
 * @param f, iframe or frame element
 * @return Window object inside the given frame
 * @effect will append f to document.body if f not yet part of the DOM
 * @see Window.frameElement
 * @usage myFrame.document = getFramedWindow(myFrame).document;
 */
function getFramedWindow(f)
{
    if(f.parentNode == null)
        f = document.body.appendChild(f);
    var w = (f.contentWindow || f.contentDocument);
    if(w && w.nodeType && w.nodeType==9)
        w = (w.defaultView || w.parentWindow);
    return w;
}
Ian Carter
quelle
2
Vielen Dank! Funktioniert mit IE 6+, FF und Chrome!
Rustyx
11
window.frameElementnullGibt zurück, wenn Fenster und Iframe unterschiedliche Domänen haben, dh Cross-Origin-Messaging.
Qwerty
@Qwerty hast du eine lösung gefunden?
Ajay Patidar
@ AjayPatidar Ich glaube ich habe aufgegeben. :(
Qwerty
78

Ich würde empfehlen, die postMessage-API zu verwenden .

Rufen Sie in Ihrem Iframe an:

window.parent.postMessage({message: 'Hello world'}, 'http://localhost/');

Auf der Seite, auf der Sie den Iframe einfügen, können Sie auf Ereignisse wie dieses warten:

window.addEventListener('message', function(event) {
      if(event.origin === 'http://localhost/')
      {
        alert('Received message: ' + event.data.message);
      }
      else
      {
        alert('Origin not allowed!');
      }

    }, false);

Übrigens ist es auch möglich, andere Fenster und nicht nur Iframes aufzurufen.

Lesen Sie mehr über die API auf John postmessage Resigs Blog hier

Kenneth Lynne
quelle
7
Ich denke, dies ist eindeutig die beste Antwort, der <iframe>Inhalt muss nichts über die Eltern wissen und umgekehrt. Sie müssen nur den einfachen Nachrichtenvertrag einhalten. Genial!
Mfeineis
1
Der <iframe> muss immer noch die Domain des Elternteils kennen, oder?
Homr Zodyssey
1
@HomrZodyssey Die übergeordnete Domain ist nur als Sicherheitsmechanismus verfügbar, falls nicht bekannt, können Sie festlegen '*'.
Amir Ali Akbari
Verwendung '*'auf Clients. Alle anderen Lösungen geben einen Fehler in einem Chrome-Browser aus, der Dateien im Client-Ordner als nicht gleich Origin behandelt, da kein Server eingerichtet ist. Dies ist die beste und einzige Lösung: dyn-web.com/tutorials/iframes/postmessage
30

Alte Frage, aber ich hatte gerade das gleiche Problem und fand einen Weg, um den Iframe zu bekommen. Es geht einfach darum, das Frames [] -Array des übergeordneten Fensters zu durchlaufen und das contentWindow jedes Frames anhand des Fensters zu testen, in dem Ihr Code ausgeführt wird. Beispiel:

var arrFrames = parent.document.getElementsByTagName("IFRAME");
for (var i = 0; i < arrFrames.length; i++) {
  if (arrFrames[i].contentWindow === window) alert("yay!");
}

Oder mit jQuery:

parent.$("iframe").each(function(iel, el) {
  if(el.contentWindow === window) alert("got it");
});

Diese Methode spart das Zuweisen einer ID zu jedem Iframe, was in Ihrem Fall gut ist, da sie dynamisch erstellt werden. Ich konnte keinen direkteren Weg finden, da Sie das iframe-Element nicht mit window.parent abrufen können - es geht direkt zum übergeordneten Fensterelement (Überspringen des iframe). Das Durchlaufen scheint also der einzige Weg zu sein, es sei denn, Sie möchten IDs verwenden.

Zutat_15939
quelle
1
Update: Dies funktionierte nicht genau wie angekündigt und ich musste contentWindow.document === document verwenden. Keine Ahnung warum. Auch in einigen Browsern habe ich contentDocument verwendet. Nun, das gefällt mir!
Christophe
1
Entschuldigung, zugegebenermaßen habe ich es nur in Firefox getestet. :) Ich hatte jedoch Erfolg mit der jQuery-Methode und contentWindow in mehreren Browsern.
ingredient_15939
1
Update: Ich habe herausgefunden, dass Sie auch window.frameElement verwenden können, bin mir aber nicht sicher, welche Browser dies unterstützen.
Christophe
2
Ich glaube nicht, dass solche Sachen mehr funktionieren. Sie erhalten einen Ursprungsfehler.
Andrew Mao
@ AndrewMao Die Frage bezieht sich auf Dokumente mit demselben Ursprung, daher kein Grund, Probleme mit unterschiedlichen Ursprüngen zu bekommen.
Christophe
21

Sie können verwenden, parentum auf die übergeordnete Seite zuzugreifen. Um auf eine Funktion zuzugreifen, wäre dies:

var obj = parent.getElementById('foo');
kemiller2002
quelle
1
Kevin, das Problem ist, die ID zu kennen. Ich habe mehrere Iframes und möchte über den darin enthaltenen Code darauf zugreifen
José Leal
Erhalten Sie weiterhin "Blocked a Frame with Origin" other-localhost: 8000 "vom Zugriff auf einen Cross-Origin-Frame."
user2568374
13

Sobald die ID des Iframes festgelegt ist, können Sie wie unten gezeigt vom inneren Dokument aus auf den Iframe zugreifen.

var iframe = parent.document.getElementById(frameElement.id);

Funktioniert gut in IE, Chrome und FF.

Akash Kava
quelle
Dies scheint eine var iframe = frameElement
Oriol
frameElement gibt ein Objekt im aktuellen Fensterkontext zurück, aber parent.document.getElementById (frameElement.id) gibt ein Objekt im Kontext des übergeordneten Fensters zurück. Sie können die Javascript-Funktionen des übergeordneten Fensters nicht mit frameElement ausführen. Versuchen Sie es in jsfiddle und geben Sie mir ein Beispiel, wenn Sie können .
Akash Kava
6

Vielleicht einfach benutzen

window.parent

in Ihren Iframe, um den aufrufenden Frame / die aufrufenden Fenster zu erhalten. Wenn Sie mehrere Anrufrahmen hatten, können Sie verwenden

window.top
Klauenfeuer
quelle
3

Versuchen Sie Folgendes: Richten Sie in Ihrem übergeordneten Frame IFRAMEs wie folgt ein:

<iframe id="frame1" src="inner.html#frame1"></iframe>
<iframe id="frame2" src="inner.html#frame2"></iframe>
<iframe id="frame3" src="inner.html#frame3"></iframe>

Beachten Sie, dass die ID jedes Frames als Anker im src übergeben wird.

Dann können Sie in Ihrem inneren HTML-Code über location.hash auf die ID des Frames zugreifen, in den es geladen wurde:

<button onclick="alert('I am frame: ' + location.hash.substr(1))">Who Am I?</button>

Anschließend können Sie auf parent.document.getElementById () zugreifen, um aus dem iframe heraus auf das iframe-Tag zuzugreifen

Mark Porter
quelle
Ja, dies wäre die logischste Lösung, aber manchmal muss ich den Quellcode des Iframes ändern. Wenn ich diesen Hash- oder GET-Parameter übergebe, ist jede Anforderung nicht gut.
José Leal
Warum ist es schlecht, den Hash jedes Mal weiterzugeben? Es ist nur für den Browser sichtbar, nicht für den Server, und es beeinflusst das Caching nicht wie ein get-Parameter.
Mark Porter
-1
// just in case some one is searching for a solution
function get_parent_frame_dom_element(win)
{
    win = (win || window);
    var parentJQuery = window.parent.jQuery;
    var ifrms = parentJQuery("iframe.upload_iframe");
    for (var i = 0; i < ifrms.length; i++)
    {
        if (ifrms[i].contentDocument === win.document)
            return ifrms[i];
    }
    return null;
}
Alex
quelle