Question Invocation de code JavaScript dans un iframe de la page parent


Fondamentalement, j'ai un iframe intégré dans une page et le iframe a quelques JavaScript routines que j'ai besoin d'invoquer de la page parente.

Maintenant, le contraire est assez simple car il suffit d'appeler parent.functionName(), mais malheureusement, j'ai exactement besoin du contraire.

S'il vous plaît noter que mon problème ne change pas la source URL du iframe, mais en invoquant une fonction définie dans le iframe.


555
2017-10-30 19:27


origine


Réponses:


Supposons que l'identifiant 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 à l'image 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(); 

495
2017-10-30 19:35



Il y a quelques bizarreries à connaître ici.

  1. HTMLIFrameElement.contentWindow est probablement le moyen le plus simple, mais ce n'est pas tout à fait une propriété standard et certains navigateurs ne le supportent pas, surtout les plus anciens. C'est parce que la norme DOM niveau 1 HTML n'a rien à dire sur le window objet.

  2. Vous pouvez aussi essayer HTMLIFrameElement.contentDocument.defaultView, que quelques navigateurs plus anciens autorisent, mais pas IE. Même ainsi, la norme ne dit pas explicitement que vous obtenez le window renvoyer l'objet, pour la même raison que (1), mais vous pouvez prendre quelques versions de navigateur supplémentaires si vous y tenez.

  3. window.frames['name'] retourner la fenêtre est l'interface la plus ancienne et donc la plus fiable. Mais vous devez ensuite utiliser un name="..." attribut pour être en mesure d'obtenir une image par son nom, ce qui est légèrement laide /déconseillé/de transition. (id="..." serait 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 ça, par exemple. Si vous savez que vous avez seulement un iframe sur la page.

  5. Il est tout à fait possible que l'iframe de l'enfant n'ait pas encore été chargé ou que quelque chose d'autre ait mal tourné pour le rendre inaccessible. Vous trouverez peut-être plus facile d'inverser le flux des communications: c'est-à-dire que l'iframe de l'enfant notifie son window.parent script quand il a fini chargé et est prêt à être rappelé. En passant un de ses propres objets (par exemple, une fonction de rappel) au script parent, ce parent peut alors communiquer directement avec le script dans l'iframe sans avoir à se soucier de l'HTMLIFrameElement auquel il est associé.


140
2017-10-30 20:27



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

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

  1. La page parent et la page iframe proviennent d'un domaine différent.
  2. Ils utilisent des protocoles différents, l'un est sur http: // et l'autre sur https: //.

Toute solution de contournement à cette restriction serait extrêmement précaire.

Par exemple, imaginez que j'ai enregistré le domaine superwinningcontest.com et envoyé des liens vers les courriels des gens. Quand ils ont chargé la page principale, je pouvais cacher quelques iframeConsultez leur flux Facebook, vérifiez les transactions Amazon ou PayPal récentes ou, s'ils utilisaient un service qui n'implémente pas la sécurité, transférez de l'argent sur leurs comptes. C'est pourquoi JavaScript est limité au même domaine et au même protocole.


62
2018-04-18 17:11



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

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

Pour accéder à la page parent, utilisez ceci:

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

29
2017-10-30 19:39



Si le iFrame et le document conteneur se trouvent sur un domaine différent, les méthodes précédemment publiées peuvent ne pas fonctionner, mais il existe une solution:

Par exemple, si le document A contient un élément iframe contenant le document B et que le script du document A appelle postMessage () sur l'objet Window du document B, un événement de message sera déclenché sur cet objet, marqué comme provenant de la fenêtre de 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 dans le document B peut 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 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


15
2017-10-29 10:22



Juste pour l'enregistrement, j'ai rencontré le même problème aujourd'hui mais cette fois la page était intégrée dans un objet, pas un 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 les ruptures de ligne laids, ne rentrait pas dans une seule ligne)


8
2018-06-30 12:48



L'IFRAME devrait être dans le frames[] collection. Utilisez quelque chose comme

frames['iframeid'].method();

8
2017-10-30 19:36



Quirksmode avait un poster 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 depuis la page où ils se trouvent. Sans surprise, il y a quelques considérations de navigateur.

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

Cadre ou objet?

La question fondamentale est de savoir si l'iframe est vu comme un cadre ou un objet.

  • Comme expliqué sur le Introduction aux cadres pages, si vous utilisez des cadres, le navigateur crée une hiérarchie de cadres pour vous (top.frames[1].frames[2] et autres choses de ce genre). Est-ce que l'iframe s'intègre dans cette hiérarchie de cadres?
  • Ou le navigateur voit-il un iframe comme un autre objet, un objet qui possède une propriété src? Dans ce cas, nous devons utiliser une norme Appel DOM (comme document.getElementById('theiframe')) pour y accéder. En règle générale, les navigateurs autorisent les vues sur les iframes «réels» (codés en dur), mais les iframes générés ne sont pas accessibles en tant que cadres.

Attribut NAME

La règle la plus importante est de donner à tout iframe que vous créez un name attribut, même si vous utilisez également un id.

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

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

Accès

Soit vous accédez à l'iframe en tant qu'objet et changez son src ou vous accédez à l'iframe comme un cadre et changez son location.href.

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

Accéder à l'iframe

Donc, pour une expérience complète de votre navigateur, vous devez donner un nom à l'iframe et utiliser

frames['testiframe'].location.href

syntaxe. Pour autant que je sache, cela fonctionne toujours.

Accéder au document

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

Iframes générées

Lorsque vous générez un iframe via le W3C DOM l'iframe n'est pas immédiatement entré dans le frames tableau, cependant, et le frames['testiframe'].location.href la syntaxe ne fonctionnera pas tout de suite. Le navigateur a besoin d'un peu de temps avant que l'iframe ne s'affiche dans le tableau, temps pendant lequel aucun script ne peut être exécuté.

le document.getElementById('testiframe').src la syntaxe fonctionne bien dans toutes les circonstances.

le target L'attribut 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 iframe généré à la fois un name Et un id.

Le manque de target support signifie que vous devez utiliser JavaScript pour changer le contenu d'un iframe généré, mais puisque vous avez besoin de JavaScript pour le générer en premier lieu, je ne vois pas cela comme un problème.

Taille du texte dans les iframes

Un curieux bug d'Explorer 6 seulement:

Lorsque vous modifiez la taille du texte via le menu Affichage, les tailles de texte dans les iframes sont correctement modifiées. Toutefois, ce navigateur ne modifie pas les sauts de ligne dans le texte d'origine, de sorte qu'une partie du texte peut devenir invisible, ou des sauts de ligne peuvent se produire alors que la ligne peut toujours contenir un autre mot.


8
2017-10-30 19:31



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

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

Quand mon iframe se charge, j'appelle une fonction située sur le document parent, en passant en 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);

Lorsque l'iframe se charge, il appellera parent.tunnel (YourFunctionReference), qui exécutera la fonction reçue dans le paramètre.

C'est simple, sans avoir à gérer toutes les méthodes non standards des différents navigateurs.


7
2018-02-08 17:44