クロスドメインなiframeの高さを自動調整する(Porthole版)

(2013/04/03 16時20分 追記)

 IE系はこのエントリのコードでは全滅だった・・・・。しくしく。

(2013/04/03 16時50分 追記)

 IE9以上は動くようになった。

1.やりたいこと

クロスドメインなiframeの高さを自動調整したい!

2.前提情報

通常、iframeのsrcが親フレームと同じドメインの場合は、親フレームから子フレームのdomに直接アクセスを行い、高さの自動調整を実現することができます。
しかし、クロスドメインの場合はブラウザのセキュリティ制約上、子フレームのdomへの直接アクセスはできません。
それでも、どーーにかして、自動調整したい場合、モダンブラウザで実装されている、安全にクロスドメイン通信を可能にするためのメソッド「postMessage」を利用して実現することができます。

参考:https://developer.mozilla.org/ja/docs/DOM/window.postMessage

今回、「どーーにかしてーーー」という強いリクエストがあり、調査しました。

!!注意!!「postMessage」はIE6等の古いブラウザではそもそも実装されていませんので、この方法では実現できません。

3.利用するライブラリ

postMessageを利用して、クロスドメインなiframeとデータをやり取りするためのライブラリである、Porthole by ternarylabsを利用します。

クロスドメインでiframe内のコンテンツとメッセージの授受「Porthole」|オープンソース・ソフトウェア、ITニュースを毎日紹介するエンジニア、デザイナー向けブログでも紹介されています。

4.親子の準備

どちらにもportholeを読み込ませておきます。

  • 親(http://aaa.example.com/parent.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<div id="container" style="width: 810px; margin: 0 auto;">
    <h1></h1>
    <p>Lorem ipsum dolor sit amet...</p>
    <iframe id="childIFrame" name="childIFrame" src="http://bbb.example.com/child.html" width="810px" scrolling="no" frameborder="0">
    </iframe>
</div>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="porthole.min.js"></script>
</body>
</html>

iframeのsrcに親とは別ドメインを指定します。

  • 子(http://bbb.example.com/child.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<div>
<h1></h1>
<p>Lorem ipsum dolor sit amet....</p>
</div>
<script type="text/javascript" src="porthole.min.js"></script>
</body>
</html>

ここでは省略してますが、コンテンツに十分な高さを持たせた方がわかりやすいです。

5.子から親へメッセージを送信する

ロード完了時に自分自身のコンテンツの高さを親に伝えるため、以下のJavaScriptを子に記述します。

<script type="text/javascript">
var windowProxy;
window.onload = function() {
    windowProxy = new Porthole.WindowProxy("http://aaa.example.com/parent.html");
    windowProxy.post({'height': document.documentElement.offsetHeight});
};
</script>
  1. 送信先の親を指定して、portholeを初期化し、
  2. 親にメッセージを送信

おお、簡単!

6.子からのメッセージを受け取ってiframeの高さを調整する

次は親側です。

<script type="text/javascript">
var windowProxy;
window.onload=function(){ 
    windowProxy = new Porthole.WindowProxy('http://bbb.example.com/child.html', 'childIFrame');
    windowProxy.addEventListener(function(e) {
        var childHeight = e.data.height;
        $("#childIFrame").height(childHeight);
    });
};
</script>

送信元の子およびiframeのidnameを指定して、porholeを初期化します。
windowProxy.addEventListenerを利用して、メッセージ受信時の振る舞いを定義します。
メッセージを受信すると、イベントオブジェクトに格納されている子の高さを取得し、iframeの高さにそれを指定します。
こっちも簡単!!

7.動作確認

  • ビフォー

  • アフター

できたでござる!!

8.最後に

はじめにも書きましたが、portholeが利用している「postMessage」はIE6等の古いブラウザはそもそも実装されていません。
portholeも

IE: 7 - should work.
IE: 6 - probably won't work. who cares.

としています。

どーーしてもIE6, 7もサポートもしないといけない場合は、swfファイルを利用するeasyXDM - Cross-domain messaging made easy等、別の手段でやるしかなさそうです。