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
.
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();
il y a quelques bizarreries à savoir ici.
-
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'objetwindow
. -
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'objetwindow
, 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. -
window.frames['name']
retourner la fenêtre est l'interface la plus ancienne et donc la plus fiable. Mais vous devez alors utiliser un attributname="..."
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.) -
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. -
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é.
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:
- Page mère et la page iframe sont de domaine différent.
- 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.
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);
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.
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)
L'IFRAME doit être dans la collection frames[]
. Utilisez quelque chose comme
frames['iframeid'].method();
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.
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.
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','*')
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 :)
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();
...
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.
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 ();
utiliser la suite pour appeler la fonction d'un cadre dans la page parent
parent.document.getElementById('frameid').contentWindow.somefunction()