682 votes

Invoquer du code JavaScript dans un iframe à partir de la page mère

En gros, j'ai un iframe intégré dans une page et le iframe a quelques JavaScript routines que je dois invoquer à partir de la page parent.

L'inverse est assez simple, puisqu'il suffit d'appeler parent.functionName() mais malheureusement, c'est exactement le contraire dont j'ai besoin.

S'il vous plaît noter que mon problème n'est pas de changer la source URL de la iframe mais en invoquant une fonction définie dans le iframe .

1 votes

Notez que lors du débogage, vous pouvez faire des choses comme window.location.href ou parent.location.href pour afficher l'url de la iframe, si vous voulez vérifier que vous avez une référence à la iframe que vous recherchez.

610voto

Joel Anair Points 8561

Supposons que l'identifiant de votre iFrame est "targetFrame" et que la fonction que vous souhaitez appeler est la suivante targetFunction() :

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

Vous pouvez également accéder au cadre en utilisant window.frames au lieu de document.getElementById .

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

3 votes

Fonctionne dans FF 7, Chrome 12, IE 8/9, et Safari (pas sûr de cette version)

3 votes

Cette solution ne fonctionne pas pour mon gadget, voici mon code document.getElementById('remote_iframe_0').contentWindow.my.‌​create_element_gadg‌​et('verify_user');" remote_iframe_0 est créé par programme par un serveur apache shindig mais window.parent.document.getElementById('remote_iframe_0').con‌​tentWindow.my.create‌​_element_gadget('v‌​erify_user');" travaux

0 votes

Cela ne fonctionne pas lorsque la fonction dans l'iframe est définie comme une fonction jQuery.

162voto

bobince Points 270740

Il y a quelques bizarreries à connaître ici.

  1. HTMLIFrameElement.contentWindow est probablement le moyen le plus simple, mais il ne s'agit pas d'une propriété standard et certains navigateurs ne la prennent pas en charge, surtout les plus anciens. Cela est dû au fait que la norme DOM Level 1 HTML n'a rien à dire sur la propriété window objet.

  2. Vous pouvez également essayer HTMLIFrameElement.contentDocument.defaultView Ce qui est autorisé par quelques anciens navigateurs, mais pas par IE. Malgré cela, la norme ne stipule pas explicitement que vous obtenez le format window pour la même raison que (1), mais vous pouvez obtenir quelques versions supplémentaires du navigateur ici si vous le souhaitez.

  3. window.frames['name'] le retour de la fenêtre est l'interface la plus ancienne et donc la plus fiable. Mais vous devez alors utiliser un name="..." pour pouvoir obtenir un cadre par son nom, ce qui est légèrement laid. déprécié /transitionnel. ( id="..." serait mieux, mais IE n'aime pas ça).

  4. window.frames[number] est également très fiable, mais le secret consiste à connaître le bon indice. Vous pouvez vous en sortir, par exemple, si vous savez que vous n'avez qu'une seule iframe sur la page.

  5. Il est tout à fait possible que la iframe enfant n'ait pas encore été chargée, ou que quelque chose d'autre se soit mal passé pour la rendre inaccessible. Il peut être plus facile d'inverser le flux de communication, c'est-à-dire de faire en sorte que l'iframe enfant notifie son window.parent script lorsqu'il a terminé son chargement et est prêt à être rappelé. En passant un de ses propres objets (par exemple une fonction de rappel) au script parent, ce dernier peut alors communiquer directement avec le script dans l'iframe sans avoir à se soucier de l'HTMLIFrameElement auquel il est associé.

16 votes

C'est génial ! En particulier, votre suggestion 5. s'est révélée extrêmement précieuse. Elle m'a évité bien des maux de tête lorsque j'essayais d'accéder aux fonctions iFrame à partir du parent dans Chrome. En passant l'objet de la fonction à partir de l'iFrame, cela fonctionne comme un charme dans Chrome, FF et même IE de 9 à 7 et il est également très facile de vérifier si la fonction a déjà été chargée. Merci !

0 votes

Le numéro 3 fonctionne, mais c'est mieux si vous le faites comme @le dorfier l'a mis dans son commentaire. Remarquez que le methode() partie.

0 votes

Veuillez également noter qu'en raison des restrictions de sécurité dans les navigateurs modernes (testés sur FF29 et Chrome34), l'endroit où vous placez votre appel de fonction a une grande importance. Le simple fait d'appeler la fonction depuis une balise script ou $(document).ready() ne fonctionnera pas. Placez plutôt l'appel à l'intérieur de la balise onload du corps, ou dans une ancre <a href="javascript:doit() ;">do it</a> comme suggéré ailleurs (cf. stackoverflow.com/questions/921387/ ). Passer l'appel de fonction à un script comme callback fonctionne aussi généralement.

74voto

Appeler une fonction JS parent depuis iframe est possible, mais seulement lorsque le parent et la page chargée dans la fenêtre iframe proviennent du même domaine, c'est-à-dire abc.com, et utilisent le même protocole, c'est-à-dire que les deux sont soit sur http:// o https:// .

L'appel échouera dans les cas suivants :

  1. La page mère et la page iframe proviennent de domaines différents.

  2. Ils utilisent des protocoles différents, l'un est sur http:// et l'autre sur https://.

Toute solution de contournement de cette restriction serait extrêmement peu sûre.

Par exemple, imaginons que j'enregistre le domaine superwinningcontest.com et que j'envoie des liens aux courriels des gens. Lorsqu'ils chargent la page principale, je pourrais cacher quelques iframe s'y trouve et lit son flux Facebook, vérifie ses récentes transactions Amazon ou PayPal ou, s'il a utilisé un service qui n'a pas mis en place une sécurité suffisante, transfère de l'argent depuis son compte. C'est pourquoi JavaScript est limité au même domaine et au même protocole.

6 votes

La solution de contournement est d'utiliser le beau et dangereux fr.wikipedia.org/wiki/Cross-document_messaging

0 votes

Quelqu'un sait-il si un sous-domaine différent peut faire échouer l'opération ? J'ai des difficultés à déboguer un problème qui, je pense, est lié à cela : l'iframe appelle une fonction de la fenêtre parent, mais l'appel n'a pas lieu.

1 votes

Notez que cela échouerait également pour des numéros de port différents, c'est-à-dire abc.com:80 != abc.com:8080

43voto

Tomalak Points 150423

Dans le IFRAME, rendez votre fonction publique à l'objet fenêtre :

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

Pour un accès à partir de la page parentale, utilisez ceci :

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

0 votes

Excellente réponse. Je ne suis pas sûr de la convention ici. J'ai une question complémentaire. Si je dois commencer une nouvelle question, je le ferai. J'ai un problème. L'iframe de ma page est alimenté dynamiquement. Il contient un bouton dont onclick() L'événement appelle simplement window.print() . Ceci imprime le contenu de la iframe parfaitement. Mais lorsque la fonction publique de la page de l'iframe appelle window.print() et si la page parente appelle la fonction publique, le contenu de la page parente est imprimé. Comment dois-je coder cela pour que l'appel à window.print() dans la fonction publique se comporte comme dans la fonction onclick événement ?

1 votes

@Karl Vous ne voulez pas appeler onclick . Vous voulez appeler iframe.contentWindow.print() .

0 votes

Malheureusement, cela ne fonctionne pas. Peut-être devrais-je commencer une nouvelle question et documenter mon code ? Dans tous les cas, le contenu de la page parent s'imprime également. document.getElementById('myFrame').contentWindow.print();' and the pubic function printContent()` (pas le gestionnaire d'événement oncick) qui appelle window.print() a été appelé de cette façon : document.getElementById('myFrame').contentWindow.printConten‌​t();

28voto

19greg96 Points 1114

Si la cible de l'iFrame et le document qui la contient se trouvent sur un domaine différent, les méthodes affichées précédemment risquent de ne pas fonctionner, mais il existe une solution :

Par exemple, si le document A contient un élément iframe qui contient le document B, et que le script du document A appelle postMessage() sur l'objet Window du document B, alors un événement message sera déclenché sur cet objet, marqué comme provenant de la Window du document A. Le script du document A pourrait ressembler à ceci :

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

Pour enregistrer un gestionnaire d'événements pour les événements entrants, le script utiliserait addEventListener() (ou des mécanismes similaires). Par exemple, le script du document B pourrait ressembler à ceci :

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

Ce script vérifie d'abord que le domaine est le domaine attendu, puis examine le message, qu'il affiche à l'utilisateur ou auquel il répond en renvoyant un message au document qui a envoyé le message en premier lieu.

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

1 votes

easyXDM fournit une abstraction sur PostMessage pour les navigateurs plus anciens (y compris une solution de repli Flash (LocalConnection) pour les dinosaures récalcitrants).

1 votes

C'est génial... après avoir essayé les réponses ci-dessus, j'ai finalement obtenu votre réponse, merci !

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