JavaScript インラインフレーム(iframe)関連
Rev.7を表示中。最新版はこちら。
いろいろハマリがちなJavaScriptでインラインフレームを扱う場合のメモ。特に断らない限りブラウザのバージョンは以下が前提。
IE6
FireFox1.5
FireFox1.5
1.iframeのwindow,documentオブジェクトの取得
iframeのwindow,documentの取得方法はIEとMozilla系(NN,FireFox)で異なる。IEはframes配列のwindow,documentプロパティから取得できる。Mozilla系はiframeエレメントのcontentWindow,contentDocumentプロパティから取得できる。
IEでもMozilla系と同じくiframeエレメントのプロパティから取得することもできるが、contentDocumentについてはIEには存在しないので、documentはcontentWindow.documentとしてcontentWindow経由で取得しなければならない。
IEIEでもMozilla系と同じくiframeエレメントのプロパティから取得することもできるが、contentDocumentについてはIEには存在しないので、documentはcontentWindow.documentとしてcontentWindow経由で取得しなければならない。
frames配列から取得する場合 frames['xxxx'].window; frames['xxxx'].document; xxxxはiframeのID値。 iframeエレメントからも取得できる。 idはiframeのID値。 IEにはcontentDocumentプロパティは存在しないので注意。 iframe = document.getElementById(id); iframe.contentWindow; //window iframe.contentWindow.document; //document
Mozilla系
iframeエレメントのcontentWindow,contentDocument プロパティから取得する iframe = document.getElementById(id); iframe.contentWindow; // window iframe.contentDocument; // document
2. iframeへのエレメントの追加
インラインフレームの中にappendChild()などでエレメントを挿入する場合、そのエレメントはインラインフレームのドキュメントで作成されていないといけない(以下の例参照)。var doc; // インラインフレームのドキュメント if (document.all) { // IE doc = frames[id].document; } else { // Mozilla doc = document.getElementById(id).contentDocument; } // インラインフレームのドキュメントでエレメント作成 var container = doc.createElement("div"); // インラインフレーム内に追加 doc.body.appendChild(container);Mozilla系ではdocument.createElement()で作成したエレメントでもインラインフレームにappendChild()できるが、IE6ではエラーとなるので注意。
3. onloadイベント
iframe内のコンテンツの読み込みが完了したら何か処理を行う場合、以下のonloadイベントで実現できる。<iframe src="frame.html" onload="alert('complete');">
JavaScriptでcreateElement()で動的に作成したiframeに対して同じことを行いたい場合は、iframeエレメントのonloadに関数を登録しておけばよい(Mozilla系)。
IEの場合、onloadに関数を登録しておいてもなぜか関数は呼び出されない。このため、代わりにonreadystatechageを使う。onreadystatechageイベントは読み込み状態を示すreadyStateが変化した時に発生する(IE固有)。イベントハンドラ内でreadyStateをチェックして"complete"になっていれば読み込みが完了している。
var iframe = document.createElement("iframe"); iframe.src = "frame.html"; if (document.all) { // IEでのonload代用処理 iframe.onreadystatechange = function () { if (this.readyState == "complete") { alert("complete"); this.onreadystatechange = null; } } } else { iframe.onload = function () { alert("complete"); } } document.body.appendChild(iframe);
4.作成直後のiframeへの書き込み
JavaScriptで動的にiframeを作成(createElement())して書き込みをする場合は、書き込み前にwriteln()で<body>タグを書き出すようにする。これがないとまだ、bodyタグがないため正常に書き込めない。
<html>
<body>
<script>
var iframedoc;
function onLoad() {
var iframe = document.createElement("iframe");
document.getElementById("frame").appendChild(iframe);
if (document.all) {
iframedoc = iframe.contentWindow.document;
} else {
iframedoc = iframe.contentDocument;
}
iframedoc.writeln("<body></body>");
iframedoc.body.innerHTML = "Inline Frame"; // *1
}
window.onload = onLoad;
</script>
<div id="frame"></div>
</body>
</html>
writeln()がない場合の動作のメモ
IEだと、iframeをappendChild()した直後に、まだiframeにbodyがないため(iframedoc.body == null)、(*1)でiframedoc.body.innerHTMLにアクセスした時点でエラーになってしまう。FireFoxだとエラーにはならないが、なぜか正しく出力されない。
writeln()でbodyを書き込まなくても、イベントハンドラ(上記の例だとonLoad())を一旦終了して、ブラウザに処理を戻してやれば、bodyは自動で作成される模様。3.のonreadystatechageイベントを使ってbodyが作られてから書き込みを行うこともできる。(面倒だけど)