515

私は iGoogle のようなアプリケーションに取り組んでいます。(他のドメインの) 他のアプリケーションからのコンテンツは、iframe を使用して表示されます。

iframe のコンテンツの高さに合わせて iframe のサイズを変更するにはどうすればよいですか?

Google が使用する JavaScript を解読しようとしましたが、難読化されており、Web を検索してもこれまでのところ成果がありませんでした。

更新:コンテンツは他のドメインから読み込まれるため、同一オリジン ポリシーが適用されることに注意してください。

4

26 に答える 26

593

この種の問題が発生しましたが、状況とは少し逆になりました。他のドメインのサイトにiframedコンテンツを提供していたため、同一生成元ポリシーも問題でした。グーグルのトロール網に何時間も費やした後、私たちは最終的に(ある程度..)実行可能な解決策を見つけました。それはあなたのニーズに適応できるかもしれません。

同一生成元ポリシーを回避する方法はありますが、iframedコンテンツとフレーミングページの両方で変更が必要なため、両側で変更をリクエストする機能がない場合、この方法はあまり役に立ちません。私は怖いです。

同じオリジンポリシーを回避できるブラウザの癖があります-javascriptは、独自のドメイン上のページ、またはiframされたページと通信できますが、フレーム化されたページとは通信できません。

 www.foo.com/home.html, which iframes
 |-> www.bar.net/framed.html, which iframes
     |-> www.foo.com/helper.html

その後、 (iframed)および(同じドメイン)とhome.html通信できます。framed.htmlhelper.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れているiframeのサイズを変更できframed.htmlます。

framed.htmlからにメッセージを渡す最も簡単な方法はhelper.html、URL引数を使用することでした。これを行うにframed.htmlは、指定されたiframeがありsrc=''ます。起動する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>
于 2008-12-12T12:04:38.810 に答える
79

別のドメインからの 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>
于 2009-03-31T15:15:00.717 に答える
43

https://developer.mozilla.org/en/DOM/window.postMessage

window.postMessage()

window.postMessage は、クロスオリジン通信を安全に有効にする方法です。通常、異なるページ上のスクリプトは、スクリプトを実行したページが同じプロトコル (通常は両方とも http)、ポート番号 (http のデフォルトは 80)、およびホスト (モジュロ) を持つ場所にある場合にのみ、相互にアクセスできます。 document.domain は両方のページで同じ値に設定されています)。window.postMessage は、適切に使用すると安全な方法でこの制限を回避するための制御されたメカニズムを提供します。

概要

window.postMessage が呼び出されると、実行する必要がある保留中のスクリプトが完了すると、ターゲット ウィンドウで MessageEvent がディスパッチされます (たとえば、window.postMessage がイベント ハンドラーから呼び出された場合の残りのイベント ハンドラー、以前に設定された保留中のタイムアウトなど)。 )。MessageEvent にはタイプ メッセージ、window.postMessage に提供される最初の引数の文字列値に設定されるデータ プロパティ、時間ウィンドウで window.postMessage を呼び出すウィンドウ内のメイン ドキュメントの起点に対応する起点プロパティがあります。 postMessage が呼び出され、window.postMessage が呼び出されたウィンドウであるソース プロパティ。(イベントのその他の標準プロパティは、期待値とともに存在します。)

iFrame- Resizer ライブラリは、postMessage を使用して iFrame のサイズをそのコンテンツに合わせて維持し、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 による Cross-Window Messaging の説明

http://ejohn.org/blog/cross-window-messaging/

于 2010-07-10T16:24:44.627 に答える
8

jQuery を使用する最も簡単な方法:

$("iframe")
.attr({"scrolling": "no", "src":"http://www.someotherlink.com/"})
.load(function() {
    $(this).css("height", $(this).contents().height() + "px");
});
于 2012-08-30T17:50:38.927 に答える
6

最後に、を使用して iframe から親 Web サイトにデータを送信するための他のソリューションを見つけましwindow.postMessage(message, targetOrigin);た。ここで、私がどのように行ったかを説明します。

サイト A = http://foo.com サイト B = http://bar.com

SiteB が siteA Web サイト内で読み込まれている

SiteB Webサイトにはこの行があります

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);
于 2014-06-12T07:54:23.947 に答える
5

http://www.phinesolutions.com/use-jquery-to-adjust-the-if ​​rame-height.htmlのソリューションはうまく機能します (jQuery を使用):

<script type=”text/javascript”&gt;
  $(document).ready(function() {
    var theFrame = $(”#iFrameToAdjust”, parent.document.body);
    theFrame.height($(document.body).height() + 30);
  });
</script>

長さに30を追加する必要があることを知りません... 1でうまくいきました。

参考までに: iFrameに既に "height" 属性がある場合は、style="height: xxx" を追加するだけです。これはあなたが望むものではないかもしれません。

于 2008-10-30T14:07:20.580 に答える
4

他のすべての回答が古いため、少し遅れる可能性があります:-)しかし...これが私の解決策です。実際の 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
        });
    });
});

これが誰にも役立つことを願っています。

于 2013-12-25T23:55:41.943 に答える
3

この回答は、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/

http://getbootstrap.com/components/#responsive-embed

于 2015-02-03T03:38:41.317 に答える
2

これは、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 のレンダリングされたコンテンツのサイズを計算できるサーバー側のロジックが必要です。

于 2010-06-09T03:10:32.060 に答える
1

私はConroyPのフレームインフレームソリューションを実装して、document.domainの設定に基づいたソリューションを置き換えていますが、さまざまなブラウザーで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()は、ExtCoreの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);
}

コードは最適化されていません、それは私の開発テストからのものです:)

誰かがこれがお役に立てば幸いです!

于 2012-03-20T22:49:54.667 に答える
1
<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>
于 2013-08-19T21:55:24.437 に答える
0

これは、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);
于 2013-01-23T18:37:39.067 に答える
0

Webページをズームアウトしてiframeサイズに合わせる場合:

  1. コンテンツに合わせてiframeのサイズを変更する必要があります
  2. 次に、読み込まれた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>
于 2011-06-01T06:43:38.300 に答える
0

iframe コンテンツの高さを取得してから、この iframe に渡します

 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);
 }
于 2013-12-11T02:49:19.250 に答える
0

iGoogle ガジェットはサイズ変更を積極的に実装する必要があるため、私の推測では、クロスドメイン モデルでは、リモート コンテンツが何らかの形で関与しない限り、これを行うことはできません。典型的なクロスドメイン通信技術を使用して、コンテンツが新しいサイズのメッセージをコンテナー ページに送信できる場合、残りは簡単です。

于 2008-10-30T14:22:23.017 に答える
-1

jQuery の使用:

親.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>
于 2015-09-17T02:36:30.167 に答える
-2

これは、iframe ページがいつ読み込まれたかを知る必要があるため、少し注意が必要です。これは、そのコンテンツを制御できない場合には困難です。onload ハンドラーを iframe に追加することは可能ですが、私は過去にこれを試しましたが、ブラウザー間で動作が大きく異なります (誰が最も迷惑かはわかりません...)。おそらく、サイズ変更を実行する iframe ページに関数を追加し、ロード イベントまたはサイズ変更イベントをリッスンするスクリプトをコンテンツに挿入してから、前の関数を呼び出す必要があります。安全性を確保したいので、ページに機能を追加することを考えていますが、それがどれほど簡単かはわかりません。

于 2008-09-30T14:12:16.683 に答える
-2

この行の何かがうまくいくはずです。

parent.document.getElementById(iFrameID).style.height=framedPage.scrollHeight;

iframe コンテンツに body onload を使用してこれをロードします。

于 2008-09-30T14:13:07.493 に答える
-4

簡単な解決策があり、リンクの幅と高さを決定する必要があります。試してみてください (ほとんどのブラウザーで動作します)。

<a href='#' onClick=" document.getElementById('myform').src='t2.htm';document.getElementById('myform').width='500px'; document.getElementById('myform').height='400px'; return false">500x400</a>
于 2012-02-20T05:59:12.570 に答える