最新のブラウザーと一部のIE8には、このタスクを以前よりも簡単にするいくつかの新機能があります。
PostMessage
postMessage APIは、iFrameとその親の間で通信するための簡単なメソッドを提供します。
親ページにメッセージを送信するには、次のように呼び出します。
parent.postMessage('Hello parent','http://origin-domain.com');
他の方向では、次のコードを使用してメッセージをiFrameに送信できます。
var iframe = document.querySelector('iframe');
iframe.contentWindow.postMessage('Hello my child', 'http://remote-domain.com:8080');
メッセージを受信するには、メッセージイベントのイベントリスタナーを作成します。
function receiveMessage(event)
{
if (event.origin !== "http://remote-domain.com:8080")
return;
console.log(event.data);
}
if ('addEventListener' in window){
window.addEventListener('message', receiveMessage, false);
} else if ('attachEvent' in window){ //IE
window.attachEvent('onmessage', receiveMessage);
これらの例では、originプロパティを使用して、メッセージの送信先を制限し、メッセージの送信元を確認しています。任意のドメインへの送信を許可するように指定することが可能*
であり、場合によっては、任意のドメインからのメッセージを受け入れたい場合があります。ただし、これを行う場合は、セキュリティへの影響を考慮し、着信メッセージに独自のチェックを実装して、期待どおりのメッセージが含まれていることを確認する必要があります。この場合、複数の親ドメインがある可能性があるため、iframeはその高さを「*」にポストできます。ただし、着信メッセージがiFrameからのものであることを確認することをお勧めします。
function isMessageFromIFrame(event,iframe){
var
origin = event.origin,
src = iframe.src;
if ((''+origin !== 'null') && (origin !== src.substr(0,origin.length))) {
throw new Error(
'Unexpect message received from: ' + origin +
' for ' + iframe.id + '. Message was: ' + event.data
);
}
return true;
}
MutationObserver
最新のブラウザのもう1つの進歩は、DOMの変更を監視できるMutationObserverです。そのため、setIntervalで常にポーリングしなくても、iFrameのサイズに影響を与える可能性のある変更を検出できるようになりました。
function createMutationObserver(){
var
target = document.querySelector('body'),
config = {
attributes : true,
attributeOldValue : false,
characterData : true,
characterDataOldValue : false,
childList : true,
subtree : true
},
observer = new MutationObserver(function(mutations) {
parent.postMessage('[iframeResize]'+document.body.offsetHeight,'*');
});
log('Setup MutationObserver');
observer.observe(target, config);
}
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
if (MutationObserver){
createMutationObserver();
}
正確な高さを計算する
iFrameの正確な高さを取得することは、チェックできる6つの異なるプロパティの選択肢があり、それらのどれも常に正しい答えを与えないため、本来あるべきほど単純ではありません。私が思いついた最善の解決策は、CSSを使用してbodyタグをオーバーフローさせない限り機能するこの関数です。
function getIFrameHeight(){
function getComputedBodyStyle(prop) {
return parseInt(
document.defaultView.getComputedStyle(document.body, null),
10
);
}
return document.body.offsetHeight +
getComputedBodyStyle('marginTop') +
getComputedBodyStyle('marginBottom');
}
これはIE9バージョンです。非常に長いIE8バージョンについては、この回答を参照してください。
本文がオーバーフローし、コードを修正してこれを停止できない場合は、offsetHeight
またはscrollHeight
のプロパティのいずれかを使用するのdocument.documentElement
が最善のオプションです。どちらにも長所と短所があり、両方をテストしてどちらが効果的かを確認するのが最善です。
その他の問題
考慮すべきその他の事項には、ページに複数のiFrameがある、ページのサイズ変更を引き起こすCSS:Checkboxおよび:Hoverイベント、iFrameの本文とhtmlタグでの高さ自動の使用の回避、最後にウィンドウのサイズ変更などがあります。
IFrameリサイザーライブラリ
私はこれらすべてを単純な依存関係のないライブラリにまとめました。これは、ここで説明されていないいくつかの追加機能も提供します。
https://github.com/davidjbradshaw/iframe-resizer
これはIE8+で動作します。