私はiGoogleのようなアプリケーションに取り組んでいます。他のアプリケーション(他のドメイン上)のコンテンツは、iframeを使用して表示されます。
iframeのコンテンツの高さに合わせてiframeのサイズを変更するにはどうすればよいですか?
私はGoogleが使用するJavaScriptを解読しようとしましたが、難読化されており、Webの検索はこれまでのところ無意味でした。
更新:コンテンツは他のドメインから読み込まれるため、同一生成元ポリシーが適用されることに注意してください。
私はiGoogleのようなアプリケーションに取り組んでいます。他のアプリケーション(他のドメイン上)のコンテンツは、iframeを使用して表示されます。
iframeのコンテンツの高さに合わせてiframeのサイズを変更するにはどうすればよいですか?
私はGoogleが使用するJavaScriptを解読しようとしましたが、難読化されており、Webの検索はこれまでのところ無意味でした。
更新:コンテンツは他のドメインから読み込まれるため、同一生成元ポリシーが適用されることに注意してください。
回答:
この種の問題がありましたが、状況とは少し逆です。他のドメインのサイトにiframe化されたコンテンツを提供していたため、同じ生成元ポリシーも問題でした。グーグルの調査に何時間も費やした後、最終的に(ある程度..)実行可能なソリューションが見つかりました。これは、ニーズに適応できる可能性があります。
同じオリジンポリシーを回避する方法はありますが、iFrameされたコンテンツとフレーミングページの両方で変更を行う必要があるため、両側で変更を要求する機能がない場合、この方法はあまり役に立ちません。私は怖いです。
同じオリジンポリシーを回避できるブラウザの癖があります。JavaScriptは、独自のドメインのページまたはフレーム化されたページと通信できますが、フレーム化されたページとは通信できません。
www.foo.com/home.html, which iframes
|-> www.bar.net/framed.html, which iframes
|-> www.foo.com/helper.html
その後home.html、framed.html(iframed)およびhelper.html(同じドメイン)と通信できます。
Communication options for each page:
+-------------------------+-----------+-------------+-------------+
| | home.html | framed.html | helper.html |
+-------------------------+-----------+-------------+-------------+
| www.foo.com/home.html | N/A | YES | YES |
| www.bar.net/framed.html | NO | N/A | YES |
| www.foo.com/helper.html | YES | YES | N/A |
+-------------------------+-----------+-------------+-------------+
framed.htmlhelper.html(iframed)にはメッセージを送信できますが、 home.html(子は親とクロスドメインで通信できません)。
ここで重要なのはそれがあるhelper.htmlからメッセージを受信することができframed.html、そしてまた、通信することができてhome.html。
したがって、基本的には、framed.htmlロード時に独自の高さhelper.htmlを計算し、に通知します。home.htmlこれにより、にメッセージが渡され、framed.html座っているiframeのサイズを変更できます。
からframed.htmlにメッセージを渡す最も簡単な方法はhelper.html、URL引数を使用することでした。これを行うにframed.htmlは、src=''指定されたiframeがあります。そのときonload火災は、それはそれ自身の高さを評価し、この時点でのiframeのSRCを設定し、helper.html?height=N
facebookがそれをどのように処理するかについての説明がここにあります。これは、上記のものより少し明確かもしれません!
ではwww.foo.com/home.html、次のjavascriptコードが必要です(これは、偶然にも、任意のドメインの.jsファイルからロードできます。)。
<script>
// Resize iframe to full height
function resizeIframe(height)
{
// "+60" is a general rule of thumb to allow for differences in
// IE & and FF height reporting, can be adjusted as required..
document.getElementById('frame_name_here').height = parseInt(height)+60;
}
</script>
<iframe id='frame_name_here' src='http://www.bar.net/framed.html'></iframe>
でwww.bar.net/framed.html:
<body onload="iframeResizePipe()">
<iframe id="helpframe" src='' height='0' width='0' frameborder='0'></iframe>
<script type="text/javascript">
function iframeResizePipe()
{
// What's the page height?
var height = document.body.scrollHeight;
// Going to 'pipe' the data to the parent through the helpframe..
var pipe = document.getElementById('helpframe');
// Cachebuster a precaution here to stop browser caching interfering
pipe.src = 'http://www.foo.com/helper.html?height='+height+'&cacheb='+Math.random();
}
</script>
の内容www.foo.com/helper.html:
<html>
<!--
This page is on the same domain as the parent, so can
communicate with it to order the iframe window resizing
to fit the content
-->
<body onload="parentIframeResize()">
<script>
// Tell the parent iframe what height the iframe needs to be
function parentIframeResize()
{
var height = getParam('height');
// This works as our parent's parent is on our domain..
parent.parent.resizeIframe(height);
}
// Helper function, parse param from request string
function getParam( name )
{
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return results[1];
}
</script>
</body>
</html>
parentIframeResize()JQueryを使用して、ページの読み込みとサイズ変更イベントの両方をキャッチしました。$(document).ready(iframeResizePipe); $(window).resize(iframeResizePipe);これにより、iframeを設定しwidth="100%"、ウィンドウの幅を変更してテキストを折り返すか何かを設定することができます。内部フレームは、サイズを変更する必要があることを認識します。
別のドメインのiframeコンテンツを処理する必要がない場合は、次のコードを試してください。問題が完全に解決され、簡単です。
<script language="JavaScript">
<!--
function autoResize(id){
var newheight;
var newwidth;
if(document.getElementById){
newheight=document.getElementById(id).contentWindow.document .body.scrollHeight;
newwidth=document.getElementById(id).contentWindow.document .body.scrollWidth;
}
document.getElementById(id).height= (newheight) + "px";
document.getElementById(id).width= (newwidth) + "px";
}
//-->
</script>
<iframe src="usagelogs/default.aspx" width="100%" height="200px" id="iframe1" marginheight="0" frameborder="0" onLoad="autoResize('iframe1');"></iframe>
document.getElementById(id)のsをすべて回避し、コードを簡略化する方が最適な場合があります。
https://developer.mozilla.org/en/DOM/window.postMessage
window.postMessage()
window.postMessageは、クロスオリジン通信を安全に有効にするためのメソッドです。通常、異なるページのスクリプトは、それらを実行したページが同じプロトコル(通常はhttpの両方)、ポート番号(httpのデフォルトは80)、およびホスト(modulo)の場所にある場合にのみ、相互にアクセスできます。 document.domainは両方のページで同じ値に設定されています)。window.postMessageは、適切に使用したときに安全な方法でこの制限を回避するための制御されたメカニズムを提供します。
概要
window.postMessageが呼び出されると、実行する必要のある保留中のスクリプトが完了すると、ターゲットウィンドウでMessageEventが送出されます(たとえば、イベントハンドラーからwindow.postMessageが呼び出された場合の残りのイベントハンドラー、以前に設定された保留中のタイムアウトなど)。 )。MessageEventにはメッセージタイプ、つまりwindow.postMessageに提供された最初の引数の文字列値に設定されるデータプロパティ、タイムウィンドウでwindow.postMessageを呼び出すウィンドウのメインドキュメントの起点に対応する起点プロパティがあります。 postMessageが呼び出され、window.postMessageが呼び出されたウィンドウであるソースプロパティ。(イベントの他の標準プロパティは、それらの期待値とともに存在します。)
iFrameの-リサイズのライブラリはと一緒に、それの内容にサイズのiFrameを維持するためのpostMessageを使用していますMutationObserverコンテンツへの変更を検出するとjQueryには依存しません。
https://github.com/davidjbradshaw/iframe-resizer
jQuery:クロスドメインスクリプティングの良さ
http://benalman.com/projects/jquery-postmessage-plugin/
iframeウィンドウのサイズ変更のデモがあります...
http://benalman.com/code/projects/jquery-postmessage/examples/iframe/
この記事では、jQueryへの依存関係を削除する方法を示します... Plusには、多くの役立つ情報と他のソリューションへのリンクがあります。
http://www.onlineaspect.com/2010/01/15/backwards-compatible-postmessage/
ベアボーンの例...
http://onlineaspect.com/uploads/postmessage/parent.html
window.postMessageのHTML 5ワーキングドラフト
http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
クロスウィンドウメッセージングに関するJohn Resig
http://www.phinesolutions.com/use-jquery-to-adjust-the-iframe-height.htmlのソリューションはうまく機能します(jQueryを使用):
<script type=”text/javascript”>
$(document).ready(function() {
var theFrame = $(”#iFrameToAdjust”, parent.document.body);
theFrame.height($(document.body).height() + 30);
});
</script>
長さに30を追加する必要があることを知りません... 1がうまくいきました。
参考:iFrameに「height」属性がすでにある場合は、style = "height:xxx"が追加されます。これはあなたが望むものではないかもしれません。
他のすべての回答が古いため、少し遅れる可能性があります:-)しかし...これが私の解決策です。実際のFF、Chrome、Safari 5.0でテスト済み。
css:
iframe {border:0; overflow:hidden;}
javascript:
$(document).ready(function(){
$("iframe").load( function () {
var c = (this.contentWindow || this.contentDocument);
if (c.document) d = c.document;
var ih = $(d).outerHeight();
var iw = $(d).outerWidth();
$(this).css({
height: ih,
width: iw
});
});
});
これが誰かを助けることを願っています。
最後に、iframeから親Webサイトにデータを送信するための他の解決策を見つけました window.postMessage(message, targetOrigin);。ここで私はどのようにしたかを説明します。
サイトA = http://foo.com サイトB = http://bar.com
SiteBがsiteAウェブサイト内に読み込まれている
SiteBウェブサイトにはこの行があります
window.parent.postMessage("Hello From IFrame", "*");
または
window.parent.postMessage("Hello From IFrame", "http://foo.com");
次に、siteAは次のコードを持っています
// Here "addEventListener" is for standards-compliant web browsers and "attachEvent" is for IE Browsers.
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
// Listen to message from child IFrame window
eventer(messageEvent, function (e) {
alert(e.data);
// Do whatever you want to do with the data got from IFrame in Parent form.
}, false);
セキュリティ接続を追加したい場合は、このif条件を使用できます eventer(messageEvent, function (e) {})
if (e.origin == 'http://iframe.example.com') {
alert(e.data);
// Do whatever you want to do with the data got from IFrame in Parent form.
}
IEの場合
IFrame内:
window.parent.postMessage('{"key":"value"}','*');
外側:
eventer(messageEvent, function (e) {
var data = jQuery.parseJSON(e.data);
doSomething(data.key);
}, false);
これは、iframeコンテンツと同じサーバーによって提供される動的に生成されたスタイルシートを使用した簡単なソリューションです。スタイルシートは、iframeの内容を "認識"しており、iframeのスタイルを設定するために使用する寸法を認識しています。これは、同じ発信元ポリシーの制限を回避します。
http://www.8degrees.co.nz/2010/06/09/dynamically-resize-an-iframe-depending-on-its-content/
したがって、提供されるiframeコードには、次のようなスタイルシートが付随します。
<link href="http://your.site/path/to/css?contents_id=1234&dom_id=iframe_widget" rel="stylesheet" type="text/css" />
<iframe id="iframe_widget" src="http://your.site/path/to/content?content_id=1234" frameborder="0" width="100%" scrolling="no"></iframe>
これには、サーバー側のロジックがiframeのレンダリングされたコンテンツのサイズを計算できる必要があります。
この回答は、Bootstrapを使用するWebサイトにのみ適用されます。Bootstrapのレスポンシブ埋め込み機能がその役割を果たします。コンテンツの幅(高さではない)に基づいています。
<!-- 16:9 aspect ratio -->
<div class="embed-responsive embed-responsive-16by9">
<iframe class="embed-responsive-item" src="http://www.youtube.com/embed/WsFWhL4Y84Y"></iframe>
</div>
jsfiddle:http ://jsfiddle.net/00qggsjj/2/
document.domainの設定に基づいてソリューションを置き換えるためにConroyPのフレームインフレームソリューションを実装していますが、さまざまなブラウザーでiframeのコンテンツの高さを正しく判断するのが非常に難しいことがわかりました(現在FF11、Ch17、IE9でテストしています) )。
ConroyPは以下を使用します:
var height = document.body.scrollHeight;
ただし、これは最初のページの読み込みでのみ機能します。iframeに動的コンテンツがあり、特定のイベントでiframeのサイズを変更する必要があります。
私がやったことは、ブラウザーごとに異なるJSプロパティを使用することでした。
function getDim () {
var body = document.body,
html = document.documentElement;
var bc = body.clientHeight;
var bo = body.offsetHeight;
var bs = body.scrollHeight;
var hc = html.clientHeight;
var ho = html.offsetHeight;
var hs = html.scrollHeight;
var h = Math.max(bc, bo, bs, hc, hs, ho);
var bd = getBrowserData();
// Select height property to use depending on browser
if (bd.isGecko) {
// FF 11
h = hc;
} else if (bd.isChrome) {
// CH 17
h = hc;
} else if (bd.isIE) {
// IE 9
h = bs;
}
return h;
}
getBrowserData()は、Ext Coreのhttp://docs.sencha.com/core/source/Ext.html#method-Ext-applyにインスパイアされたブラウザ検出関数です
これはFFとIEではうまく機能しましたが、Chromeで問題が発生しました。その1つはタイミングの問題でした。どうやらChromeでiframeの高さを設定/検出するにはしばらく時間がかかります。また、iframeがコンテンツよりも高い場合、Chromeはiframeのコンテンツの高さを正しく返しませんでした。これは、高さが低くなると動的コンテンツでは機能しません。
これを解決するには、コンテンツの高さを検出する前に常にiframeを低い高さに設定し、iframeの高さを正しい値に設定します。
function resize () {
// Reset the iframes height to a low value.
// Otherwise Chrome won't detect the content height of the iframe.
setIframeHeight(150);
// Delay getting the dimensions because Chrome needs
// a few moments to get the correct height.
setTimeout("getDimAndResize()", 100);
}
コードは最適化されていません、それは私の開発テストからです:)
これが役立つと誰かが願っています!
<html>
<head>
<script>
function frameSize(id){
var frameHeight;
document.getElementById(id).height=0 + "px";
if(document.getElementById){
newheight=document.getElementById(id).contentWindow.document.body.scrollHeight;
}
document.getElementById(id).height= (frameHeight) + "px";
}
</script>
</head>
<body>
<iframe id="frame" src="startframe.html" frameborder="0" marginheight="0" hspace=20 width="100%"
onload="javascript:frameSize('frame');">
<p>This will work, but you need to host it on an http server, you can do it locally. </p>
</body>
</html>
iGoogleガジェットは積極的にサイズ変更を実装する必要があるので、リモートドメインが何らかの形で参加しなければ、クロスドメインモデルではこれを実行できないと思います。コンテンツが通常のクロスドメイン通信技術を使用して新しいサイズのメッセージをコンテナページに送信できる場合、残りは簡単です。
Webページを縮小してiframeサイズに合わせる場合:
次に例を示します。
<div id="wrap">
<IFRAME ID="frame" name="Main" src ="http://www.google.com" />
</div>
<style type="text/css">
#wrap { width: 130px; height: 130px; padding: 0; overflow: hidden; }
#frame { width: 900px; height: 600px; border: 1px solid black; }
#frame { zoom:0.15; -moz-transform:scale(0.15);-moz-transform-origin: 0 0; }
</style>
以下は、iframeのsrc属性を介してjsonに情報を追加するjQueryアプローチです。これがデモです。このウィンドウのサイズを変更してスクロールします。jsonを使用した結果のURLは次のようになります... http://fiddle.jshell.net/zippyskippy/RJN3G/show/#{docHeight:5124,windowHeight:1019,scrollHeight: 571}#
ここにソースコードフィドルがありますhttp://jsfiddle.net/zippyskippy/RJN3G/
function updateLocation(){
var loc = window.location.href;
window.location.href = loc.replace(/#{.*}#/,"")
+ "#{docHeight:"+$(document).height()
+ ",windowHeight:"+$(window).height()
+ ",scrollHeight:"+$(window).scrollTop()
+"}#";
};
//setInterval(updateLocation,500);
$(window).resize(updateLocation);
$(window).scroll(updateLocation);
var iframes = document.getElementsByTagName("iframe");
for(var i = 0, len = iframes.length; i<len; i++){
window.frames[i].onload = function(_i){
return function(){
iframes[_i].style.height = window.frames[_i].document.body.scrollHeight + "px";
}
}(i);
}
ロード時にjqueryを操作する(クロスブラウザー):
<iframe src="your_url" marginwidth="0" marginheight="0" scrolling="No" frameborder="0" hspace="0" vspace="0" id="containiframe" onload="loaderIframe();" height="100%" width="100%"></iframe>
function loaderIframe(){
var heightIframe = $('#containiframe').contents().find('body').height();
$('#frame').css("height", heightFrame);
}
レスポンシブページのサイズ変更時:
$(window).resize(function(){
if($('#containiframe').length !== 0) {
var heightIframe = $('#containiframe').contents().find('body').height();
$('#frame').css("height", heightFrame);
}
});
jQueryの使用:
parent.html
<body>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<style>
iframe {
width: 100%;
border: 1px solid black;
}
</style>
<script>
function foo(w, h) {
$("iframe").css({width: w, height: h});
return true; // for debug purposes
}
</script>
<iframe src="child.html"></iframe>
</body>
child.html
<body>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
$(function() {
var w = $("#container").css("width");
var h = $("#container").css("height");
var req = parent.foo(w, h);
console.log(req); // for debug purposes
});
</script>
<style>
body, html {
margin: 0;
}
#container {
width: 500px;
height: 500px;
background-color: red;
}
</style>
<div id="container"></div>
</body>
iframeページがいつ読み込まれたかを知る必要があるため、これは少し注意が必要です。これは、コンテンツを制御していない場合は困難です。iframeにonloadハンドラーを追加することは可能ですが、これを以前に試したことがあり、ブラウザーによって動作が大きく異なります(誰が最も迷惑なのかはわかりません...)。おそらく、サイズ変更を実行するiframeページに関数を追加し、ロードイベントまたはサイズ変更イベントをリッスンするコンテンツにスクリプトを挿入してから、前の関数を呼び出す必要があります。安全を確保したいので、ページに関数を追加することを考えていますが、それがどれほど簡単かはわかりません。
これの私が信じている何かがうまくいくはずです。
parent.document.getElementById(iFrameID).style.height=framedPage.scrollHeight;
これをiframeコンテンツのonloadでロードします。