web-dev-qa-db-ja.com

コンテンツに基づいてiframeのサイズを変更する

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

Iframeのコンテンツの高さに合わせてiframeのサイズを変更する方法

私はGoogleが使用するJavaScriptを解読しようとしましたが、それは難読化されており、ウェブ検索はこれまでのところ無駄です。

更新:コンテンツは他のドメインからロードされるため、 same-originポリシー が適用されます。

490
larssg

別のドメインからの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>
80
Ahmy

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

window.postMessage()

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

まとめ

window.postMessageを呼び出すと、実行する必要がある保留中のスクリプトが完了したときにMessageEventがターゲットウィンドウに送出されます(たとえば、window.postMessageがイベントハンドラから呼び出された場合は残りのイベントハンドラ、以前に設定された保留タイムアウトなど)。 ) MessageEventは、messageという型のデータ、window.postMessageに渡される最初の引数の文字列値に設定されるdataプロパティ、時間ウィンドウでwindow.postMessageを呼び出すウィンドウ内のメイン文書のOriginに対応するOriginプロパティを持ちます。 postMessageが呼び出され、window.postMessageが呼び出された元のウィンドウであるsourceプロパティ(イベントの他の標準的な特性は、それらの期待値とともに存在します。)

iFrame-Resizerライブラリは、postMessageを使用して、 MutationObserver とともに、そのサイズに合わせてiFrameのサイズを変更しません。コンテンツへの変更を検出し、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://ejohn.org/blog/cross-window-messaging/

40
Chris Jacob

JQueryを使用した最も簡単な方法:

$("iframe")
.attr({"scrolling": "no", "src":"http://www.someotherlink.com/"})
.load(function() {
    $(this).css("height", $(this).contents().height() + "px");
});
9
Omer Arshad

http://www.phinesolutions.com/use-jquery-to-adjust-the-if​​rame-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"が追加されるだけです。これはあなたが望むものではないかもしれません。

6
Macho Matt

他のすべての答えは古くなっているので、少し遅れるかもしれません:-)しかし...これが私の解決策です。実際の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
        });
    });
});

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

4
ddlab

最後に、window.postMessage(message, targetOrigin);を使ってiframeから親ウェブサイトにデータを送るための他の解決策を見つけました。ここで私は自分のやり方を説明します。

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

SiteBはsiteA Webサイト内にロードされています

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); 

セキュリティ接続を追加したい場合はeventer(messageEvent, function (e) {})のif条件を使うことができます。

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);
3
Selvamani

この回答は、ブートストラップを使用している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

2
Razan Paul

これは、iframeコンテンツと同じサーバーによって提供される動的に生成されたスタイルシートを使用した簡単な解決策です。単純にスタイルシートは、iframeの内容を「認識」し、iframeのスタイルを設定するために使用する寸法を認識します。これは同じOriginポリシーの制限を回避します。

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のレンダリングされたコンテンツの寸法を計算できることを必要とします。

2
Vaughan Rowsell
<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>
1
webd3sign

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);
}

コードは最適化されていません、私の開発したテストによるものです:)

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

1
Tor Olsson

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>
0
kaw

ロード時に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);
}
});

これは、iframeのsrc属性を介してjsonに情報を追加するjQueryアプローチです。これがデモです。このウィンドウのサイズを変更してスクロールします。jsonのURLは次のようになります。 http://fiddle.jshell.net/zippyskippy/RJN3G/show/#{docHeight :5124、ウィンドウの高さ:1019、スクロールの高さ: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);
0
chad steele

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>
0
Nino Škopac

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);
 }
0
YellowGlue

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

0
Joeri Sebrechts