クロスドメインでiframeのサイズを動的に変更する
いま作りたいサービスがあり、暇を見ては作っているのですがクロスドメイン問題に直面しました。
クロスドメインについてはセキュリティー上のことなので当然のことなのですが、実際に解決するとなるとそれなりに制限やハードルがあるので試した方法と回避策について記載します。
作成したサービスはちょっとした小窓で表示するものでしたのでiframeで軽く表示させようと思っていました。
表示させるだけならいいのですが、iframe内のコンテンツは伸縮するのでそれにあわせてiframe自身も伸縮させようと考えました。
とりあえずローカル環境の元コンテンツでサイズを取得して親のiframeに高さを変更するものを追加しました。
/* 親ウィンドウ(iframe)操作 */
$('.strech_click').click(function(){
/* strech_clickクリック時に親iframe height 30pixに変更 */
var box_height = $('.iframe_box').height();
$('.support_frame',parent.document).height(300);
if( box_height == '30' ) {
$('.support_frame',parent.document).height(30);
}
});
parentというので親と子の間でコントロール出来るみたいです。
動作としてはiframe内のコンテンツの伸縮ボタン(strech_click)がクリックされたら
1.今のiframe内のコンテンツの高さを取得
2.親のiframeを300の高さにする
3.iframe内のコンテンツの高さが30の場合は、親のiframeの高さを30にする
これを元になるコンテンツ内に入れることで、子から親のiframeのサイズを操作できます。
ちなみにこれはローカルの開発環境で試して問題なく機能しておりました。
実際のサービスは各所から参照してもらうタイプのものでしたので、実運用を想定して複数のドメインからiframeで参照すると、中身は機能するのですがiframeの伸縮がうまくいかない……
異なるドメイン間でのデータの受け渡しや操作はセキュリティー的に問題があるので、ブラウザー側でちゃんと制限してアレコレしてくれているクロスドメインの問題が発生しました。
要は今までローカルの同一ドメイン同士だからうまくいっていたと…
そこでiframeでのやり取りではなく、ドメイン間で値をやり取りする方法に変更
元になるコンテンツのJavaScript部分を以下に修正
(元になるコンテンツで値を取得してzeijaku.netに送信します)
/* 親ウィンドウ(iframe)にHeight通知 */
$('.strech_click').click(function(){
// クリック時の高さを取得
var support_height = $('.iframe_box').height();
// 高さデータを送信する
window.parent.postMessage(support_height, 'http://zeijaku.net');
});
iframeに以下を追加
(受け取ったデータのoriginを確認したら、受け取った値にiframeのサイズを変更する)
<script type='text/javascript'>
function changeFrameSize(event){
// zeijaku.netからである事を確認(Originチェック)
if (event.origin != "http://zeijaku.net") {
return;
}
var child_height = event.data;
var target = document.getElementById('support_frame');
// 受け取った数値を高さに設定
target.height = child_height;
}
// message が来たら changeFrameSize を発動
window.addEventListener('message', changeFrameSize, false);
</script>
ドメイン間でデータをやり取りすることで解決できました。
postMessageで送り、addEventListenerで受け取ります。
まだSSLと非SSL間でのやり取りなどは行ってませんので完全解決ではないですが、クロスドメイン間でのiframeの動的サイズ変更を行うことができました。
クロスドメインでiframeを動的に操作したい場合は、postMessageとaddEventListenerでデータをやり取りすることで解消することが出来るので選択肢の1つとして覚えておきたいと思います。
関連記事