クロスドメインなiframeの高さを自動調整する(Porthole版)
(2013/04/03 16時20分 追記)
IE系はこのエントリのコードでは全滅だった・・・・。しくしく。
(2013/04/03 16時50分 追記)
IE9以上は動くようになった。
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>
- 送信先の親を指定して、portholeを初期化し、
- 親にメッセージを送信
おお、簡単!
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の高さにそれを指定します。
こっちも簡単!!
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等、別の手段でやるしかなさそうです。