Invoquer le code JavaScript dans une iframe à partir de la page mère

fondamentalement, j'ai un iframe intégré dans une page et le iframe a quelques routines JavaScript que je dois invoquer à partir de la page mère.

Maintenant, le contraire est assez simple puisque vous n'avez qu'à appeler parent.functionName() , mais malheureusement, j'ai besoin exactement le contraire.

s'il vous Plaît noter que mon problème n'est pas de changer la source URL de la iframe , mais l'invocation d'une fonction définie dans le iframe .

561
demandé sur Shashank Agrawal 2008-10-30 22:27:56

17 réponses

supposons que l'id de votre iFrame est "targetFrame" et que la fonction que vous voulez appeler est 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(); 
503
répondu Joel Anair 2016-03-10 20:38:48

il y a quelques bizarreries à savoir ici.

  1. HTMLIFrameElement.contentWindow est probablement la manière la plus facile, mais ce n'est pas tout à fait une propriété standard et certains navigateurs ne le prennent pas en charge, la plupart du temps plus anciens. C'est parce que le standard HTML DOM niveau 1 N'a rien à dire sur l'objet window .

  2. vous pouvez également essayer HTMLIFrameElement.contentDocument.defaultView , ce qu'un couple de navigateurs plus anciens permettent mais IE ne le fait pas. Même ainsi., la norme ne dit pas explicitement que vous récupérez l'objet window , pour la même raison que (1), mais vous pouvez récupérer quelques versions supplémentaires du navigateur ici si vous vous en souciez.

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

  4. window.frames[number] est également très fiable, mais connaître le bon index est l'astuce. Vous pouvez vous en sortir avec cette par exemple. si vous savez que vous avez seulement un iframe sur la page.

  5. il est tout à fait possible que l'enfant iframe n'ait pas encore chargé, ou que quelque chose d'autre ait mal tourné pour le rendre inaccessible. Vous pouvez trouver plus facile à inverser le flux de la communication: c'est, demandez à l'enfant iframe de notifier son script window.parent lorsqu'il a fini chargé et qu'il est prêt à être rappelé. En passant un de ses propres objets (par ex. une fonction de rappel) au script parent, ce parent peut alors communiquer directement avec le script dans l'iframe sans avoir à se soucier de ce à quoi il est associé.

140
répondu bobince 2012-08-02 15:00:20

appeler une fonction JS parent de iframe est possible, mais seulement si le parent et la page chargée dans le iframe sont du même domaine, c'est-à-dire abc.com, et les deux utilisent le même protocole c.-à-d. les deux sont soit sur http:// ou https:// .

l'appel échouera dans les cas ci-dessous mentionnés:

  1. Page mère et la page iframe sont de domaine différent.

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

toute solution à cette restriction serait extrêmement peu sûre.

par exemple, imaginez que j'ai enregistré le domaine superwinningcontest.com et envoyé des liens vers les e-mails des gens. Quand ils ont chargé la page principale, je pourrais cacher quelques iframe S là-dedans et lire leur fil Facebook, vérifier Amazon récente ou PayPal les transactions, ou--s'ils ont utilisé un service qui n'a pas mis en place une garantie suffisante--transfèrent de l'argent de leurs comptes. C'est pourquoi JavaScript est limité au même domaine et au même protocole.

63
répondu Vivek Singh CHAUHAN 2012-10-31 19:09:00

dans L'IFRAME, rendez votre fonction publique à l'objet window:

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

pour accéder à la page mère, utilisez ceci:

var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);
29
répondu Tomalak 2011-09-07 12:31:37

si l'iFrame et le document contenant se trouvent sur un domaine différent, les méthodes précédemment publiées pourraient ne pas fonctionner, mais il y a 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 fenêtre du document B, alors un événement message sera déclenché sur cet objet, marqué comme provenant de la fenêtre du document A. le script du document A pourrait ressembler à:

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 à:

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 regarde le message, qu'il affiche à l'utilisateur, ou 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

16
répondu 19greg96 2016-08-18 17:08:55

juste pour info, j'ai rencontré le même problème aujourd'hui mais cette fois la page était intégrée dans un objet, pas une iframe (puisqu'il s'agissait d'un document XHTML 1.1). Voici comment cela fonctionne avec les objets:

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

(désolé pour le laid sauts de ligne, ne rentre pas dans une seule ligne)

8
répondu Tamas Czinege 2009-06-30 12:48:58

L'IFRAME doit être dans la collection frames[] . Utilisez quelque chose comme

frames['iframeid'].method();
8
répondu dkretz 2011-07-18 14:19:21

Quirksmode avait un post sur ce .

puisque la page est maintenant cassée, et seulement accessible via archive.org, Je l'ai reproduit ici:

IFrames

sur cette page je donne un bref aperçu de l'accès aux iframes à partir de la page où elles se trouvent. Comme il fallait s'y attendre, il y a certaines considérations liées au navigateur.

une iframe est un cadre en ligne, un cadre cela, tout en contenant une page complètement séparée avec sa propre URL, est néanmoins placé à l'intérieur d'une autre page HTML. Cela donne de très belles possibilités dans le web design. Le problème est l'accès à l'iframe, par exemple pour charger une nouvelle page. Cette page explique comment le faire.

cadre ou objet?

la question fondamentale est de savoir si l'iframe est considéré comme un cadre ou comme un objet.

  • comme expliqué sur les pages Introduction aux frames , si vous utilisez des frames, le navigateur crée une hiérarchie de Frames pour vous ( top.frames[1].frames[2] et autres). Est-ce que l'iframe s'inscrit dans cette hiérarchie de cadres?
  • ou est-ce que le navigateur voit une iframe comme juste un autre objet, un objet qui se trouve avoir une propriété src? Dans ce cas, nous devons utiliser une norme appel DOM (comme document.getElementById('theiframe')) pour y accéder. En général, les navigateurs permettent les deux vues sur les iframes' réelles ' (codées en dur), mais les iframes générées ne peuvent pas être consultées en tant que frames.

attribut de nom

la règle la plus importante est de donner n'importe quel iframe que vous créez un attribut name , même si vous utilisez aussi un id .

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

la plupart des navigateurs ont besoin de l'attribut name pour faire de l'iframe une partie de la hiérarchie du cadre. Certains navigateurs (notamment Mozilla) ont besoin du id pour rendre l'iframe accessible en tant qu'objet. En assignant les deux attributs à l'iframe, vous gardez vos options ouvertes. Mais name est bien plus important que id .

accès

soit vous accédez à l'iframe en tant qu'objet et changez son src , soit vous accédez à l'iframe en tant que cadre et changez son location.href .

document.getElementById ("iframe_id").src = ' newpage.html'; les frames['iframe_name'].emplacement.href = ' newpage.html'; La syntaxe de frame est légèrement préférable car Opera 6 La supporte mais pas la syntaxe d'objet.

accès à l'iframe

donc pour une expérience complète de cross–browser, vous devez donner à l'iframe un nom et utiliser le

frames['testiframe'].location.href
"1519210920 de syntaxe". Pour autant que je sache, ça marche toujours.

accéder au document

accéder au document à l'intérieur de l'iframe est assez simple, à condition d'utiliser l'attribut name . Pour compter le nombre de liens dans le document dans l'iframe, ne frames['testiframe'].document.links.length .

iframes générées

quand vous générez une iframe à travers le W3C DOM l'iframe n'est pas Entrée immédiatement dans le tableau frames , cependant, et la syntaxe frames['testiframe'].location.href ne fonctionnera pas tout de suite. Le navigateur a besoin d'un peu de temps avant que l'iframe apparaisse dans le tableau, temps pendant lequel aucun script ne peut s'exécuter.

la syntaxe document.getElementById('testiframe').src fonctionne très bien en toutes circonstances.

l'attribut target d'un lien ne fonctionne pas non plus avec les iframes générées, sauf dans Opera, même si j'ai donné mon généré iframe à la fois un name et un id .

l'absence de target signifie que vous devez utiliser JavaScript pour modifier le contenu d'une iframe générée, mais puisque vous avez besoin de JavaScript de toute façon pour le générer en premier lieu, Je ne vois pas cela comme un problème.

Taille du texte dans iframes

Un curieux Explorer 6 ne bug:

quand vous changez le texte taille à travers le menu View, les tailles de texte dans iframes sont modifiées correctement. Cependant, ce navigateur ne modifie pas les sauts de ligne dans le texte original, de sorte qu'une partie du texte peut devenir invisible, ou les sauts de ligne peuvent se produire alors que la ligne pourrait encore contenir un autre mot.

8
répondu activout.se 2012-08-03 13:22:15

j'ai trouvé une solution assez élégante.

comme vous l'avez dit, il est assez facile d'exécuter le code situé sur le document parent. Et c'est la base de mon code, faire exactement le contraire.

quand mon iframe se charge, j'appelle une fonction située sur le document parent, passant comme argument une référence à une fonction locale, située dans le document de l'iframe. Le document parent a maintenant un accès direct à la fonction iframe à travers cette référence.

exemple:

sur le parent:

function tunnel(fn) {
    fn();
}

sur l'iframe:

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

parent.tunnel(myFunction);

quand l'iframe se charge, il appellera parent.tunnel (your Functionreference), qui exécutera la fonction reçue en paramètre.

que simple, sans avoir à traiter toutes les méthodes non-standards des différents navigateurs.

7
répondu Julien L 2014-02-08 17:44:45

certaines de ces réponses ne traitent pas de la question des CORS, ou ne rendent pas évident l'endroit où vous placez les bribes de code pour rendre la communication possible.

voici un exemple concret. Disons que je veux cliquer un bouton sur la page mère, et avoir que faire quelque chose à l'intérieur de l'iframe. Voici comment j'allais le faire.

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

aller De l' autre direction (cliquez sur le bouton à l'intérieur d'iframe pour appeler la méthode à l'extérieur d'iframe) il suffit de changer l'endroit où le code snippet live, et changez ceci:

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

à ceci:

window.parent.postMessage('foo','*')
4
répondu Cybernetic 2017-10-07 16:42:04

Poursuivre avec JoelAnair réponse:

pour plus de Robustesse, utilisez comme suit:

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

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

Fonctionnait comme un charme :)

3
répondu Nitin Bansal 2017-05-23 12:03:04

Suivant Nitin Bansal la réponse de

et pour encore plus de robustesse:

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

et

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

getIframeWindow(el).targetFunction();
...
3
répondu Dominique Fortin 2012-08-03 12:55:05
       $("#myframe").load(function() {
            alert("loaded");
        });
2
répondu GeverGever 2008-11-21 20:08:48

mêmes choses, mais un peu plus facile sera comment rafraîchir la page parent à partir de la page dans iframe . Il suffit d'appeler la fonction de la page mère pour invoquer la fonction javascript pour recharger la page:

window.location.reload();

ou faites-le directement à partir de la page dans iframe:

window.parent.location.reload();

les deux œuvres.

2
répondu sangam 2011-08-30 06:44:56

si nous voulons appeler la fonction javascript de la page mère de l'iframe qui a généré à partir du codage. ex shadowbox ou lightbox

de la fenêtre.parent.targetFunction ();

1
répondu Santhanakumar 2011-12-05 05:43:42

juste parent.myfunction()

1
répondu Saeid Zebardast 2011-12-14 11:33:03

utiliser la suite pour appeler la fonction d'un cadre dans la page parent

parent.document.getElementById('frameid').contentWindow.somefunction()
-3
répondu Sandy 2014-11-17 06:56:54