746 votes

Comment identifier si une page web est chargée dans un iframe ou directement dans la fenêtre du navigateur ?

J'écris une application facebook basée sur une iframe. Maintenant, je veux utiliser la même page html pour rendre le site web normal ainsi que la page canvas dans facebook. Je veux savoir si je peux déterminer si la page a été chargée dans l'iframe ou directement dans le navigateur ?

3 votes

Quelques bonnes manières (y compris les commentaires) : tommcfarlin.com/check-if-a-page-is-in-an-iframe

1 votes

Les liens externes ne sont pas un très bon moyen de répondre aux questions. Surtout si le contenu de ces liens externes peut être réduit à return window.location !== window.parent.location .

1353voto

Greg Points 132247

Les navigateurs peuvent bloquer l'accès à window.top en raison de politique de même origine . IE ont également lieu. Voici le code de travail :

function inIframe () {
    try {
        return window.self !== window.top;
    } catch (e) {
        return true;
    }
}

top et self sont tous deux window (ainsi que les objets parent ), donc vous voyez si votre fenêtre est la fenêtre supérieure.

5 votes

Cela semble fonctionner correctement dans Firefox. Cela fonctionne-t-il aussi dans d'autres navigateurs ?

7 votes

Ayant une page avec une iframe dans une iframe, pour tester à partir de mon iframe enfant si mon iframe parent était intégré dans la page, j'ai utilisé if (parent === top)

8 votes

@sglessard Si la page enfant et la page parent proviennent de domaines différents, Firefox se plaindra de la politique Same Origin Policy (www.w3.org/Security/wiki/Same_Origin_Policy) et le code ne fonctionnera pas.

111voto

Lorsqu'il se trouve dans un iframe de la même origine que le parent, l'élément window.frameElement renvoie l'élément (par exemple iframe ou object ) dans lequel la fenêtre est intégrée. Sinon, si l'on navigue dans un contexte de niveau supérieur, ou si le cadre parent et le cadre enfant ont des origines différentes, il sera évalué à null .

window.frameElement
  ? 'embedded in iframe or object'
  : 'not embedded or cross-origin'

Il s'agit d'un Norme HTML avec une prise en charge de base dans tous les navigateurs modernes.

4 votes

Note tentant de lire frameElement déclenchera une exception SecurityError dans les iframes d'origine croisée, conformément à la directive W3C ( WHATWG dit qu'il devrait retourner null à la place). Donc, vous pourriez vouloir l'envelopper dans un fichier try...catch déclaration.

14 votes

Obtenir null à l'intérieur et à l'extérieur de iframe

8 votes

La description à MDN indique que "si le document dans lequel il est intégré a une origine différente (par exemple, s'il a été localisé à partir d'un domaine différent), il est nul".

29voto

scunliffe Points 30964

RoBorg a raison, mais je voulais ajouter une note complémentaire.

Dans IE7/IE8, lorsque Microsoft a ajouté les onglets à son navigateur, il a cassé un élément qui peut causer des ravages dans votre JS si vous ne faites pas attention.

Imaginez cette mise en page :

MainPage.html
  IframedPage1.html   (named "foo")
  IframedPage2.html   (named "bar")
    IframedPage3.html (named "baz")

Maintenant, dans le cadre "baz", vous cliquez sur un lien (pas de cible, se charge dans le cadre "baz"), cela fonctionne bien.

Si la page qui est chargée, appelons-la special.html, utilise JS pour vérifier si "it" a un cadre parent nommé "bar", elle retournera true (attendu).

Maintenant, disons que la page special.html, lorsqu'elle se charge, vérifie l'existence du cadre parent et son nom, et si c'est "bar", elle se recharge dans le cadre bar, par exemple.

if(window.parent && window.parent.name == 'bar'){
  window.parent.location = self.location;
}

Jusqu'ici tout va bien. Maintenant vient le bug.

Supposons qu'au lieu de cliquer sur le lien original comme d'habitude, et de charger la page special.html dans le cadre "baz", vous avez fait un clic moyen ou choisi de l'ouvrir dans un nouvel onglet.

Lorsque ce nouvel onglet se charge ( sans aucun cadre parental ! ) IE entrera dans une boucle sans fin de chargement de page ! parce qu'IE "copie" la structure du cadre en JavaScript de telle sorte que le nouvel onglet A un parent, et ce parent A le nom "bar".

La bonne nouvelle, c'est que la vérification :

if(self == top){
  //this returns true!
}

dans ce nouvel onglet renvoie bien vrai, et vous pouvez donc tester cette condition étrange.

0 votes

Le bug a-t-il été corrigé entre-temps ? Je n'arrive pas à le reproduire dans IE8. J'obtiens toujours l'affichage correct window.parent .

1 votes

Je ne suis pas sûr - je vais relancer ma suite de tests contre IE9 et les versions inférieures et poster une mise à jour.

0 votes

On est en 2021, et je danse encore sur la tombe d'IE.

21voto

magnoz Points 176

La réponse acceptée n'a pas fonctionné pour moi à l'intérieur du contenu script d'une extension Firefox 6.0 (Addon-SDK 1.0) : Firefox exécute le contenu script dans chacun : la fenêtre de niveau supérieur et dans toutes les iframes.

Dans le contenu script, j'obtiens les résultats suivants :

 (window !== window.top) : false 
 (window.self !== window.top) : true

Ce qui est étrange avec cette sortie, c'est qu'elle est toujours la même, que le code soit exécuté dans une iframe ou dans la fenêtre de niveau supérieur.

D'autre part, Google Chrome semble n'exécuter mon contenu script qu'une seule fois dans la fenêtre de niveau supérieur, de sorte que ce qui précède ne fonctionnerait pas du tout.

Ce qui a finalement fonctionné pour moi dans un contenu script dans les deux navigateurs est le suivant :

 console.log(window.frames.length + ':' + parent.frames.length);

Sans iframes, cette impression 0:0 dans une fenêtre de niveau supérieur contenant une image, il imprime 1:1 et dans l'unique iframe d'un document, il imprime 0:1 .

Cela permet à mon extension de déterminer dans les deux navigateurs si des iframes sont présentes, et en plus dans Firefox si elle est exécutée à l'intérieur d'une des iframes.

2 votes

Essayez document.defaultView.self === document.defaultView.top ou window !== window.top . Dans le contenu script du SDK de l'add-on de Firefox, la balise globale self est un objet utilisé pour communiquer avec le script principal.

5voto

mikewolf78 Points 31

J'utilise ceci :

var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);

0 votes

Pourquoi faites-vous cela ? .indexOf("HTMLIFrameElement") ?

0 votes

.indexOf('foobarbaz') > -1 est un moyen de vérifier la "correspondance entre les sous-chaînes" (c'est-à-dire, "foobarbaz" peut-il être trouvé quelque part dans la chaîne ?), mais sans utiliser d'expressions régulières. C'est logiquement équivalent à .match(/foobarbaz/). Elle (avait l'habitude de :-) fonctionner sur un plus grand nombre de navigateurs, et peut encore être utilisée par habitude ou par crainte des performances des expressions régulières.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X