iframeから親ウィンドウ関数を呼び出す


281

親ウィンドウのJavaScript関数をiframeから呼び出したいのですが。

<script>
    function abc()
    {
        alert("sss");
    }
</script>

<iframe id="myFrame">
    <a onclick="abc();" href="#">Call Me</a>
</iframe>

1
現時点では何も表示できません(2016)。古いバウアーがサポートするかどうかはわかりません
Weijing Jay Lin

回答:


438
<a onclick="parent.abc();" href="#" >Call Me </a>

window.parentを参照してください

現在のウィンドウまたはサブフレームの親への参照を返します。

ウィンドウに親がない場合、その親プロパティはそれ自体への参照です。

ウィンドウがにロードされたとき<iframe><object>または<frame>、その親ウィンドウを埋め込む要素とウィンドウです。


17
親ドキュメントとiframeドキュメントがプロトコルとドメイン名で一致する必要があることを常に考慮してください。そうしないと、クロスドメインスクリプティングが許可されないため、セキュリティエラーが発生します。
a4bike

Mは、2つalertのうちどちらが呼び出されるのか疑問に思っています。親のalert関数またはiframeのalert関数(parent.abc();iframeで呼び出された場合)
Prakhar Mishra 2016

@PrakharMishra混乱しないでください。親は親を意味します。
Sahu V Kumar 2017

3
そのようなシナリオでは@ a4bike window.postMessage()(またはwindow.parent.postMessage())が存在します。@Andriiの回答を
Fr0zenFyr

81

私は最近、なぜこれもうまくいかないのかを知る必要がありました。

子iframeから呼び出すJavaScriptは、親の先頭にある必要があります。本文にある場合、スクリプトはグローバルスコープでは使用できません。

<head>
    <script>
    function abc() {
        alert("sss");
    }
    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="parent.abc();" href="#">Click Me</a>
    </iframe>
</body>

これがこの問題に再び遭遇した人を助けることを願っています。


1
この投稿で説明されている手法はChromeでは機能しません。これに対する解決策はありますか?
Kumar Kush

3
正しく覚えていれば、iframeが親とは異なるドメインを持っている場合、これを期待どおりに機能させることができませんでした。申し訳ありませんが、これは解決策ではありませんが、機能しない理由を説明している可能性があります。
Ash Clarke

1
はい。異なるドメインが原因であることがわかりますが、これを回避する方法はありませんか?
Kumar Kush

1
私はあなたの問題の回避策かもしれないものを投稿しました。他の答えを見てください。
Ash Clarke

1
同じ発信元ポリシー決定ルール(en.wikipedia.org/wiki/…を参照)に従って、サブドメインはドメインのサブドメインとは異なるホスト名と見なされます。まだの場合は、document.domainをサブドメインに設定してみてください。
Ash Clarke

72

Window.postMessage()

この方法は安全にcross-origin通信を可能にします。

また、親ページのコードにアクセスできる場合は、任意の親メソッドを呼び出すことができ、データをから直接渡すことができますIframe。ここに小さな例があります:

親ページ:

if (window.addEventListener) {
    window.addEventListener("message", onMessage, false);        
} 
else if (window.attachEvent) {
    window.attachEvent("onmessage", onMessage, false);
}

function onMessage(event) {
    // Check sender origin to be trusted
    if (event.origin !== "http://example.com") return;

    var data = event.data;

    if (typeof(window[data.func]) == "function") {
        window[data.func].call(null, data.message);
    }
}

// Function to be called from iframe
function parentFunc(message) {
    alert(message);
}

iframeコード:

window.parent.postMessage({
    'func': 'parentFunc',
    'message': 'Message text from iframe.'
}, "*");
// Use target origin instead of *

更新:

セキュリティ上の注意:

*他のウィンドウのドキュメントを配置する場所がわかっている場合は、特定のtargetOriginではなく、常に指定してください。特定のターゲットを提供しないと、関心のある悪意のあるサイトに送信するデータが開示されます(ZalemCitizenによるコメント)。

参照:


1
私は他のものよりもこれを使用することを好みます。特に、クロスオリジンドキュメントでiframeを使用する方が理にかなっているため(プログラマーはiframeを悪用することが多いですが)、ブラウザーでこの機能を幅広くサポートしています。
Fr0zenFyr

1
ありがとう!私は常に1時間以上かけて、複雑で冗長な例を使用してメッセージングを行う方法を調査する必要があります。これは60秒で機能しました。簡潔で要点のある例をありがとう。
Randall19年

2
それを上げる価値があります(MDN web docsから):他のウィンドウのドキュメントの場所を知っている場合は、*ではなく、常に特定のtargetOriginを指定します。特定のターゲットを提供しないと、興味のある悪意のあるサイトに送信したデータが開示されます
ZalemCitizen

20

これは私の既存の回答とは関係がないため、別の回答として投稿しました。

この問題は最近、サブドメインを参照するiframeから親にアクセスするために再び発生し、既存の修正は機能しませんでした。

今回の答えは、親ページとiframeのdocument.domainを同じになるように変更することでした。これは、同じ発信元ポリシーチェックをだまして、まったく同じドメインに共存していると考えさせます(サブドメインは別のホストと見なされ、同じ発信元ポリシーチェックに失敗します)。

以下を<head>iframeのページのに挿入して、親ドメインに一致させます(Doctypeに合わせて調整します)。

<script>
    document.domain = "mydomain.com";
</script>

これはlocalhost開発時にエラーをスローすることに注意してください。したがって、エラーを回避するには、次のようなチェックを使用してください。

if (!window.location.href.match(/localhost/gi)) {
    document.domain = "mydomain.com";
} 

そして、これをlocalhostでテストするのはどうですか?そのための回避策はありますか?
Umesh Awasthi

「これはlocalhost開発でエラーをスローするので、エラーを回避するには次のようなチェックを使用してください。」
Ash Clarke

2
(少なくともGoogle Chromeでは)親と子の両方がdocument.domainを設定する必要があることに注意してください。例:親がexample.comiframeでabc.example.comある場合、親とiframeの両方が呼び出す必要がありますdocument.domain = "example.com"
KillerX、

はい、それは正しいです。私はここにタイプミスをしました:「iframeのページは同じである」。「ページとiframeは同じである必要があります。」.....ありがとう!
アッシュクラーク

if()の場合、なぜif(document.domain!= "mydomain.com"を使用しないのですか?また、混乱していますが、<script>は親ウィンドウまたはiFrameに移動しますか?また、 iframe内にdocument.domainを「は『文書』に『ドメイン』プロパティの設定に失敗しまし生成: 『localhostの』 『SC-localhost』の接尾辞ではありません。
user2568374

18

使用できます

window.top

以下を参照してください。

<head>
    <script>
    function abc() {
        alert("sss");
    }
    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="window.top.abc();" href="#">Click Me</a>
    </iframe>
</body>

parent.custom_function();を呼び出そうとしたとき iframeからは動作しませんwindow.top.custom_function(); 動作します。奇妙な理由で私のために働く。親ウィンドウのjavascriptはすべてフッターに埋め込まれています。フッターにjavascriptファイルを含めると、parent.custom_function()が機能しないという問題が発生することをどこかで読みました。
Friso Horstman、2016

@ Vinothkumar、1つの質問をお願いします。 "window.top.abc()"を呼び出すのと "abc()"だけを呼び出すのとの違いです。事前に感謝=)
Zilev av

@Zilev avこのスレッドの要点は、子ドキュメントから親ドキュメントの関数を呼び出すことです。それが違いです。呼び出しabc()は、親ページではなくiframeでfunction abc()宣言されている場合にのみ機能します。 window.top.abc()iframeから親ドキュメントに分割されます。
Sean

3

それを必要とする人のためのもう一つの追加。Ash Clarkeのソリューションは、異なるプロトコルを使用している場合は機能しないため、SSLを使用している場合は、iframeもSSLを使用していることを確認してください。彼の解決策はドメイン自体に対しても機能しました。


2

Ash Clarkeがサブドメインに提供したソリューションはうまく機能しますが、document.domain = "mydomain.com"を含める必要があることに注意してください。iframeページのヘッドと親ページのヘッドの両方で、リンクの同一生成元ポリシーチェックで述べられているように

JavaScript DOMアクセス用に実装された同じ生成元ポリシーの重要な拡張機能(ただし、同じ生成元チェックの他のほとんどのフレーバーではない)は、共通のトップレベルドメインを共有する2つのサイトが「同じホスト」に失敗しても通信することを選択できることです。それぞれのdocument.domain DOMプロパティを相互に、現在のホスト名の同じ修飾された右側のフラグメントに設定して確認します。たとえば、http://en.example.com/http://fr.example.com/の両方がdocument.domainを "example.com"に設定した場合、それらはそのポイントからのものであり、 DOM操作の目的。


はい、それは正しいです。私はここにタイプミスをしました:「iframeのページは同じである」。「ページとiframeは同じである必要があります。」.....ありがとう!
Ash Clarke、

ローカルコンピュータでファイルを実行するのはどうですか?の価値はdocument.domain何ですか?
ラプター

それは可能でしょうlocalhostかマシン(通常のIPアドレス127.0.0.1)、URLアドレスバーにあるものに応じて。
アッシュクラーク

2

parent.abc()は、セキュリティ上の理由により、同じドメインでのみ機能します。私はこの回避策を試したところ、私のものは完全に機能しました。

<head>
    <script>
    function abc() {
        alert("sss");
    }

    // window of the iframe
    var innerWindow = document.getElementById('myFrame').contentWindow;
    innerWindow.abc= abc;

    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="abc();" href="#">Click Me</a>
    </iframe>
</body>

お役に立てれば。:)


これは、実際にはiframeのドキュメントの唯一の用途でもあり、親フォームのコントロールを参照する必要がある場合は、非常に複雑になります。
ポール、

1

FirefoxとChromeでは、次のものを使用できます。

<a href="whatever" target="_parent" onclick="myfunction()">

myfunctionがiframeと親の両方に存在する場合、親のものが呼び出されます。


動作しません。これが私のデモです:dotku.github.io/tech/html/iframe/iframe_function_container.html
Weijing Jay Lin

Ash Clarkeが述べたように、子iframeから呼び出すJavaScriptは親の頭にある必要があります。
スノーフレーク

受け入れられた回答では、スクリプトが頭にある必要はありません。このソリューションでもスクリプトを先頭に置く必要がないかどうかはテストしませんでした。
Guy Schalnat 2016

0

これらのソリューションの一部は機能する可能性がありますが、ベストプラクティスに従っていないものもあります。多くの場合、グローバル変数を割り当て、複数の親変数または関数を呼び出して、乱雑で脆弱な名前空間につながることがあります。

これを回避するには、モジュールパターンを使用します。親ウィンドウで:

var myThing = {
    var i = 0;
    myFunction : function () {
        // do something
    }
};

var newThing = Object.create(myThing);

次に、iframeで:

function myIframeFunction () {
    parent.myThing.myFunction();
    alert(parent.myThing.i);
};

これは、クロックフォードの独創的なテキスト「Javascript:The Good Parts」の継承の章で説明されているパターンに似ています。Javascriptのベストプラクティスについては、w3のページで詳細を学ぶこともできます。https://www.w3.org/wiki/JavaScript_best_practices#Avoid_globals

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.