18
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

クロスサイトのiframeで親にコンテンツの高さを渡す方法

Last updated at Posted at 2016-01-07

iframeで読み込んだ、動的コンテンツの高さに応じて親フレームの高さも調整したい事ってありますね!
結構すんなり出来る事なんですけど、ただ、クロスサイトになると制約がいっぱいなので単純には行きま。
ググった結果web Messagingってのを使うことにしました。

Web Messagingを使う

web messagingとは、異なるサイト間でメッセージのやり取りが出来る機能です。クライアント間で完結します。
こちらに詳細載ってます。Web Messagingとは

この機能には、チャネルメッセージングクロスドキュメントメッセージングの二つのAPIが用意されています。
今回はクロスドキュメントメッセージングを使用します。

クロスドキュメントメッセージングは、この異なるオリジンの間での通信を安全に行うことを目的としたAPIで、そのために、メッセージの送受信を専用のメソッドとイベントだけに限定し、送受信時に相手先のオリジンを確認できるようになっています。

渡すメッセージに、子フレームのコンテンツの高さを入れてやろうって事です!

子フレームから親フレームにメッセージを渡す

子フレームにpostMessageを実装する

まず、子フレームにて、親フレームに渡すコンテンツの高さとスクロール位置を文字列にして渡します。

children.js
// ウィンドウload時のイベントで
window.addEventListener("load", postSize, false);
function postSize(e){
    var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);
    if (typeof target != "undefined") {
        target.postMessage("height"+document.body.scrollHeight+"_top100", "https://example.com");
    }
}

// または、何かしらのアクションでのイベントで
function doEntry() {
    var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);
    if(typeof target != "undefined"){
        target.postMessage("height"+document.getElementById('entryResult').scrollHeight+"_top0", "https://example.com");
  }
}
  • 親フレームがpostMessageを使えるかチェックします。
var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);
  • postMessageでメッセージを送る
target.postMessage("height"+document.body.scrollHeight+"_top100", "*");
param 意味
message 他のウィンドウに送られる文字列データ
targetOrigin 自身のURIか、 "*" というリテラル文字列(指定しないことを示します)で指定します。もしイベントが targetOrigin で指定されたものにマッチしない場合、そのイベントは伝達されません。
詳しくはこちら

親フレームにmessageイベントを受け取れるようにする

以下の例は、ウィンドウの高さとスクロールの位置をmessageから受け取る例です。

parent.js
// messageのイベントリスナー
window.addEventListener("message", receiveSize, false);
// 実行関数
function receiveSize(e) {
	// e.dataに「height1000_top0」のような文字列が入ってくる想定。
	var data = e.data.split('_');
	// originのチェック。
	if (e.origin === "https://example.com" && (0 == data[0].indexOf("height") && (0 == data[1].indexOf("top"))  ) {
		document.getElementById("entryform").style.height = parseInt(e.data.replace('height', '')) + "px";
		// FirefoxとIE11で動かなかったので一部修正
		$('html, body').scrollTop(parseInt(data[1].replace('top', '')));
	}
}

messageを受け取ったら、
window.addEventListener("message", receiveSize, false);receiveSize()を呼び出します。
イベントデータのプロパティは以下です。

プロパティ 意味
data postMessageで送ったmessage部分
origin postMessageで送ったtargetOrigin部分

セキュリティ上、if (e.origin === "https://example.com")でURIのチェックは行った方がよさ気です。

はい、以上で子フレームのコンテンツの高さを親に渡す事ができました。
他に良い方法があれば教えて下さい(・∀・)

18
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?