基本的に、私はiframe
ページに埋め込まれていiframe
て、親ページから呼び出す必要があるいくつかのJavaScriptルーチンがあります。
今は、を呼び出すだけでよいので、その反対は非常に簡単ですparent.functionName()
が、残念ながら、私はそれとは正反対のことが必要です。
私の問題はのソースURLを変更するのではなく、iframe
で定義された関数を呼び出すことiframe
です。
基本的に、私はiframe
ページに埋め込まれていiframe
て、親ページから呼び出す必要があるいくつかのJavaScriptルーチンがあります。
今は、を呼び出すだけでよいので、その反対は非常に簡単ですparent.functionName()
が、残念ながら、私はそれとは正反対のことが必要です。
私の問題はのソースURLを変更するのではなく、iframe
で定義された関数を呼び出すことiframe
です。
回答:
iFrameのIDが「targetFrame」であり、呼び出す関数がtargetFunction()
次のとおりであるとします。
document.getElementById('targetFrame').contentWindow.targetFunction();
のwindow.frames
代わりにを使用してフレームにアクセスすることもできますdocument.getElementById
。
// this option does not work in most of latest versions of chrome and Firefox
window.frames[0].frameElement.contentWindow.targetFunction();
document.getElementById('remote_iframe_0').contentWindow.my.create_element_gadget('verify_user');"
remote_iframe_0がapache shindigサーバーによってプログラムで作成されていますが、window.parent.document.getElementById('remote_iframe_0').contentWindow.my.create_element_gadget('verify_user');"
機能します
ここで注意すべきいくつかの癖があります。
HTMLIFrameElement.contentWindow
おそらくもっと簡単な方法ですが、これはかなり標準的なプロパティではなく、一部のブラウザはそれをサポートしていません。これは、DOM Level 1 HTML標準がwindow
オブジェクトについて何も言うことがないためです。
またHTMLIFrameElement.contentDocument.defaultView
、いくつかの古いブラウザでは許可されていますが、IEでは許可されていません。それでも、window
(1)と同じ理由で、標準ではオブジェクトを元に戻すことを明示的に述べていませんが、必要に応じて、ここでいくつかの追加のブラウザーバージョンを選択できます。
window.frames['name']
ウィンドウを返すことは最も古く、したがって最も信頼性の高いインターフェイスです。しかし、あなたは、次に使用する必要がname="..."
少し醜い/である、名前でフレームを取得することができるように属性を非推奨 /移行。(id="..."
より良いでしょうが、IEはそれが好きではありません。)
window.frames[number]
も非常に信頼性が高いですが、正しいインデックスを知ることがトリックです。あなたはこれで逃げることができます例えば。ページにiframeが1つしかないことがわかっている場合。
子iframeがまだロードされていないか、何かに問題が発生してアクセスできなくなっている可能性があります。通信の流れを逆にする方が簡単な場合があります。つまり、window.parent
ロードが完了してコールバックの準備ができたときに、子iframeにスクリプトに通知させます。独自のオブジェクト(コールバック関数など)の1つを親スクリプトに渡すことにより、その親は、関連付けられているHTMLIFrameElementを気にすることなく、iframe内のスクリプトと直接通信できます。
methode()
パーツに注目してください。
から親JS関数を呼び出すことiframe
は可能ですが、親とロードされたページのiframe
両方が同じドメイン、つまりabc.comからのもので、両方が同じプロトコルを使用している場合、つまり両方がかのどちらかであるhttp://
場合に限りますhttps://
。
以下の場合、呼び出しは失敗します。
この制限に対する回避策は非常に安全ではありません。
たとえば、superwinningcontest.comというドメインを登録して、人々のメールへのリンクを送信したとします。彼らがメインページをロードしたとき、私はiframe
そこにいくつかのsを隠してFacebookフィードを読んだり、最近のAmazonやPayPalの取引をチェックしたり、十分なセキュリティを実装していないサービスを使用した場合は、彼らからお金を送金したりできます。アカウント。これが、JavaScriptが同じドメインと同じプロトコルに制限されている理由です。
IFRAMEで、関数をウィンドウオブジェクトに公開します。
window.myFunction = function(args) {
doStuff();
}
親ページからアクセスするには、これを使用します。
var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);
onclick()
イベントが単にを呼び出すボタンが含まれていますwindow.print()
。これは完全に内容を印刷しますiframe
。ただし、iframeのページのパブリック関数が呼び出されwindow.print()
、親ページがパブリック関数を呼び出した場合、親のコンテンツが印刷されます。これをコーディングしwindow.print()
て、パブリック関数の呼び出しがonclick
イベントのように動作するようにするにはどうすればよいですか?
onclick
。あなたが電話したいiframe.contentWindow.print()
。
document.getElementById('myFrame').contentWindow.print();' and the pubic function
呼び出すprintContent() `(oncickイベントハンドラーではない)window.print()
は次のように呼び出されました:document.getElementById('myFrame').contentWindow.printContent();
iFrameのターゲットとそれを含むドキュメントが異なるドメインにある場合、以前に投稿されたメソッドは機能しない可能性がありますが、解決策があります:
たとえば、ドキュメントAにドキュメントBを含むiframe要素が含まれ、ドキュメントAのスクリプトがドキュメントBのウィンドウオブジェクトでpostMessage()を呼び出す場合、そのオブジェクトでメッセージイベントが発生し、ウィンドウのドキュメントA。ドキュメントAのスクリプトは次のようになります。
var o = document.getElementsByTagName('iframe')[0];
o.contentWindow.postMessage('Hello world', 'http://b.example.org/');
着信イベントのイベントハンドラーを登録するには、スクリプトでaddEventListener()(または同様のメカニズム)を使用します。たとえば、ドキュメントBのスクリプトは次のようになります。
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);
}
}
}
このスクリプトは、最初にドメインが予想されるドメインであることを確認してから、メッセージを確認し、ユーザーに表示するか、最初にメッセージを送信したドキュメントにメッセージを送信して応答します。
Quirksmodeがこれについて投稿しました。
このページは壊れており、archive.orgからのみアクセスできるため、ここに再現しました。
iFrame
このページでは、iframeが表示されているページからiframeにアクセスする方法の概要を説明します。当然のことながら、ブラウザに関する考慮事項がいくつかあります。
iframeはインラインフレームであり、独自のURLを持つ完全に別のページを含みながら、別のHTMLページ内に配置されるフレームです。これにより、Webデザインに非常に優れた可能性が生まれます。問題は、iframeにアクセスすることです。たとえば、新しいページをiframeにロードします。このページでは、その方法について説明します。
フレームまたはオブジェクト?
基本的な問題は、iframeがフレームと見なされるか、オブジェクトと見なされるかです。
top.frames[1].frames[2]
など)。iframeはこのフレーム階層に適合しますか?document.getElementById('theiframe'))
それにアクセスするなど)。一般に、ブラウザーは「実際の」(ハードコードされた)iframeの両方のビューを許可しますが、生成されたiframeにはフレームとしてアクセスできません。NAME属性
最も重要なルールは、name
属性を作成するすべてのiframeに、id
。
<iframe src="iframe_page1.html"
id="testiframe"
name="testiframe"></iframe>
ほとんどのブラウザでは、name
iframeをフレーム階層の一部にするために属性が必要です。一部のブラウザー(特にMozilla)ではid
、iframeをオブジェクトとしてアクセス可能にする必要があります。両方の属性をiframeに割り当てることにより、オプションを開いたままにします。しかしname
、よりもはるかに重要ですid
。
アクセス
iframeにオブジェクトとしてアクセスして変更するsrc
か、iframeにフレームとしてアクセスして変更しlocation.href
ます。
document.getElementById( 'iframe_id')。src = 'newpage.html'; frames ['iframe_name']。location.href = 'newpage.html'; Opera 6はフレーム構文をサポートしていますが、オブジェクト構文はサポートしていないため、フレーム構文の方が少し望ましいです。
iframeへのアクセス
したがって、完全なクロスブラウザエクスペリエンスを実現するには、iframeに名前を付けて、
frames['testiframe'].location.href
構文。私の知る限り、これは常に機能します。
ドキュメントにアクセスする
name
属性を使用すれば、iframe内のドキュメントへのアクセスは非常に簡単です。iframe内のドキュメント内のリンクの数をカウントするには、を実行します
frames['testiframe'].document.links.length
。
生成されたiframe
ただし、W3C DOMを介してiframeを生成する場合、iframeはすぐにはframes
配列に入力されず、frames['testiframe'].location.href
構文はすぐには機能しません。ブラウザーでiframeが配列に表示されるまでに少し時間がかかります。この間、スクリプトは実行されません。
document.getElementById('testiframe').src
構文は、すべての状況で正常に動作します。
target
リンクの属性は、生成されたiframeにa name
との両方を指定した場合でも、Operaを除いて、生成されたiframeでは機能しませんid
。
target
サポートの欠如は、生成されたiframeのコンテンツを変更するためにJavaScriptを使用する必要があることを意味しますが、そもそもJavaScriptを生成してそれを生成する必要があるため、これはそれほど問題にはなりません。
iframe内のテキストサイズ
奇妙なExplorer 6のみのバグ:
[表示]メニューでテキストサイズを変更すると、iframe内のテキストサイズが正しく変更されます。ただし、このブラウザは元のテキストの改行を変更しないため、テキストの一部が表示されない場合や、行が別の単語を保持しているときに改行が発生する場合があります。
私は非常にエレガントな解決策を見つけました。
あなたが言ったように、親ドキュメントにあるコードを実行するのはかなり簡単です。そしてそれが私のコードのベースです。正反対のことをしてください。
iframeが読み込まれると、親ドキュメントにある関数を呼び出し、iframeのドキュメントにあるローカル関数への参照を引数として渡します。親ドキュメントは、この参照を通じてiframeの機能に直接アクセスできるようになりました。
例:
親:
function tunnel(fn) {
fn();
}
iframeで:
var myFunction = function() {
alert("This work!");
}
parent.tunnel(myFunction);
iframeが読み込まれると、parent.tunnel(YourFunctionReference)が呼び出され、パラメーターで受け取った関数が実行されます。
さまざまなブラウザからのすべての非標準メソッドを処理する必要なしに、それは簡単です。
これらの回答の一部はCORSの問題に対応していないか、通信を可能にするためにコードスニペットをどこに配置するかを明確に示していません。
これが具体例です。親ページのボタンをクリックして、iframe内で何かを実行したいとします。ここに私がそれをする方法があります。
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();
}
別の方向に移動するには(iframe内のボタンをクリックしてiframe外のメソッドを呼び出す)、コードスニペットを配置する場所を切り替え、これを変更します。
document.getElementById('my_iframe').contentWindow.postMessage('foo','*');
これに:
window.parent.postMessage('foo','*')
JoelAnairの回答を続けます。
堅牢性を高めるには、次のように使用します。
var el = document.getElementById('targetFrame');
if(el.contentWindow)
{
el.contentWindow.targetFunction();
}
else if(el.contentDocument)
{
el.contentDocument.targetFunction();
}
魅力のように働いた:)
Nitin Bansalの回答をフォローする
さらに堅牢性を高めるために:
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;
}
そして
...
var el = document.getElementById('targetFrame');
var frame_win = getIframeWindow(el);
if (frame_win) {
frame_win.targetFunction();
...
}
...
同じことですが、少し簡単な方法は、iframe内のページから親ページを更新する方法です。親ページの関数を呼び出して、JavaScript関数を呼び出し、ページをリロードするだけです。
window.location.reload();
または、iframeのページから直接これを実行します。
window.parent.location.reload();
どちらも機能します。
ちょうど試してください parent.myfunction()
シャドウボックスやライトボックスなどの別の関数によって生成されたiframeから、親のJavaScript関数を呼び出す場合。
あなたはwindow
オブジェクトを利用して親関数を呼び出そうとする必要があります:
window.parent.targetFunction();