web-dev-qa-db-ja.com

クロスドメインiframeのサイズ変更

別のドメインからiframeのサイズを変更するにはどうすればよいですか

-編集

いくつかのソリューションをスクロールダウンします。または、これを実行しない方法をお読みください:D

何時間もコードをハッキングした後、結論は、iframe内のすべてのものはアクセスできず、私のドメインでレンダリングするスクロールバーもアクセスできないということです。私は役に立たない多くのテクニックを試しました。

時間を節約するために、このルートを下るだけでなく、ドメイン間通信にsendMessagesを使用するだけです。私が使用しているHTML <5のプラグインがあります。ニースの例については下に移動してください:)


過去数日、iframeをサイトに統合しようと試みてきました。これは短期的なソリューションであり、反対側が開発し、API(数か月かかる可能性があります...)そして、これは短期的なソリューションであるため、easyXDMを使用したいと思います-他のドメインにアクセスできますが、 p3pヘッダーをそのまま追加します.....

3 iframes

私が見つけた最も近い解決策は3つのiframesでしたが、chromeとsafariのように精神的になるので、私はそれを使用できません。

クロムで開く

http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179

スクロールバーを測定する

Scrollheightを使用してフォームのサイズを変更する方法に関する別の投稿を見つけました。理論的にはうまくいきますが、iframeのスクロールの高さを使用して適切に適用できませんでした。

document.body.scrollHeight

それはわざと体の高さを使用します(これらのプロパティに100%アクセスできないのは、x-domainsドキュメントの高さではなく、クライアントの表示canvazに基づいています)

私はjqueryを使用してiframeの高さを取得しようとしました

$('#frameId').Height()

$('#frameId').clientHeight

$('#frameId').scrollHeight

chromeで異なる値を返します。つまり、まったく意味がありません。問題は、フレーム内のすべてが拒否されていることです。スクロールバーも...

計算されたスタイル

しかし、私が調べて、chrome iframeの要素をiframe内のドキュメントの大きさを示しています(jquery x-domainを使用してiframe.heighを取得-アクセスが拒否されました)計算されたCSS enter image description here

では、chrome=をどのように計算しますか?(編集ブラウザは、これらすべての設定を計算するためにレンダリングエンジンのビルドを使用してページを再レンダリングしますが、クロスドメイン詐欺を防ぐためにどこにも接続されません。そう..)

HTML4

私はHTML4.xの仕様を読み、document.elementを介して公開された読み取り専用の値があるべきだと言っていますが、jqueryを介してアクセスが拒否されました

プロキシフレーム

ユーザーがiframeを介してログインし、プロキシが実際のコンテンツの代わりにログインページを取得するまで、サイトをプロキシして元に戻す計算を行います。また、ページを2回呼び出すことは受け入れられません

http://www.codeproject.com/KB/aspnet/asproxy.aspx

http://www.johnchapman.name/aspnet-proxy-page-cross-domain-requests-from-ajax-and-javascript/

ページの再レンダリング

ここまでは行かなかったが、ソースを見て、ソースファイルに基づいてページを再レンダリングするjscriptエンジンがあります。ただし、これらのjscriptをハッキングする必要があります。商業エンティティにとっては理想的な状況ではありません。純粋なJavaアプレットまたはサーバー側レンダリング

http://en.wikipedia.org/wiki/Server-side_JavaScript

http://htmlunit.sourceforge.net/ <jscriptではなくJava

http://maxq.tigris.org/


EDIT 09-2013[〜#〜] update [〜#〜]

これはすべて、HTML5ソケットで実行できます。しかし、easyXDMは、HTML5以外の苦情ページの優れたフォールバックです。

ソリューション1非常に素晴らしいソリューション!

EasyXDMを使用する

サーバーで、次の形式のページを設定します

<html>
<head>
<script src="scripts/easyXDM.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">

    var transport = new easyXDM.Socket(/** The configuration */{
    remote: "http://www.OTHERDOMAIN.com/resize_intermediate.html?url=testpages/resized_iframe_1.html",

    //ID of the element to attach the inline frame to
    container: "embedded",
    onMessage: function (message, Origin) {
        var settings = message.split(",");
        //Use jquery on a masterpage.
        //$('iframe').height(settings[0]);
        //$('iframe').width(settings[1]);

        //The normal solution without jquery if not using any complex pages (default)
        this.container.getElementsByTagName("iframe")[0].style.height = settings[0];
        this.container.getElementsByTagName("iframe")[0].style.width = settings[1];
    }
});

</script>

</head>

<body>
    <div id="embedded"></div>
</body>

呼び出し元のドメインでは、同じ場所にintermiedate_frame htmlとeasyXDM.jsを追加するだけです。親フォルダのように-相対ディレクトリまたは含まれているフォルダに自分だけにアクセスできます。

オプション1

すべてのページにスクリプトを追加したくない場合は、オプション2をご覧ください!

次に、サイズ変更が必要な各ページの末尾に単純なjscriptを追加するだけです。これらの各ページにeasyxdmを含める必要はありません。

 <script type="text/javascript">
            window.onload = function(){ parent.socket.postMessage( (parseInt(document.body.clientHeight)) + "," + ( document.body.clientWidth ) );  };
        </script>

送信するパラメーターを変更しました。幅を適切に機能させるには、otherdomainのページに、次のようなスタイルスタイルのページの幅を含める必要があります。

<style type="text/css">
            html, body {
                overflow: hidden;
                margin: 0px;
                padding: 0px;
                background-color: rgb(75,0,85);
                color:white;
                width:660px
            }
            a {
            color:white;
            visited:white;
            }
        </style>

これは私にとってはうまくいきます。幅が含まれていない場合、フレームは少し奇妙な振る舞いをし、種類がどうあるべきかを推測しようとします。必要に応じて縮小しません。

オプション2

変更をポーリングするために中間フレームを変更します

中間フレームは次のようになります。

    <!doctype html>
<html>
    <head>

        <title>Frame</title>
        <script type="text/javascript" src="easyXDM.js">
        </script>
        <script type="text/javascript">
            var iframe;
            var socket = new easyXDM.Socket({
                //This is a fallback- not needed in many cases
                swf: "easyxdm.swf",
                onReady: function(){
                    iframe = document.createElement("iframe");
                    iframe.frameBorder = 0;
                    document.body.appendChild(iframe);
                    iframe.src = "THE Host FRAME";
            iframe.onchange = messageBack();

                },
                onMessage: function(url, Origin){
                    iframe.src = url;
                }
            });

            //Probe child.frame for dimensions.
            function messageBack(){
                socket.postMessage ( iframe.contentDocument.body.clientHeight + "," + iframe.contentDocument.body.clientWidth); 
            };

            //Poll for changes on children every 500ms.
            setInterval("messageBack()",500); 

        </script>
        <style type="text/css">
            html, body {
                overflow: hidden;
                margin: 0px;
                padding: 0px;
                width: 100%;
                height: 100%;
            }

            iframe {
                width: 100%;
                height: 100%;
                border: 0px;
            }
        </style>
    </head>
    <body>

    </body>
</html>

サイズが変更された場合に間隔をより効率的にすることができ、ディメンションが変更された場合にのみ送信することができます。このチェックを実装すると、ポーリングを50ミリ秒に変更できます!楽しんで


ブラウザー間で動作し、高速です。素晴らしいデバッグ機能!!

Excellent Work to  Sean Kinsey  who made the script!!!

解決策2(うまくいくがうまくいかない)

したがって、基本的に他のドメインと相互に合意している場合は、sendmessageを処理するライブラリを追加できます。他のドメインへのアクセス権がない場合は、他のハックを探し続けてください。見つけられなかった、または完全に正当化できなかったためです。

そのため、他のドメインにはこれらがHeadタグに含まれます

<script src="scripts/jquery-1.5.2.min.js" type="text/javascript"></script>
<script src="scripts/jquery.postmessage.min.js" type="text/javascript"></script>
<script src="scripts/club.js" type="text/javascript"></script>

Club.jsには、サイズ変更の呼び出しと格納のために作成したカスタム呼び出しがいくつかあります。

 $(document).ready(function () {   
    var parent_url = decodeURIComponent( document.location.hash.replace( /^#/, '' ) ),link;
//Add source url hash to each url to authorise callback when navigating inside the frame.Without this clicking any links will break the communication and no messages will be received
$('a[href]').each(function(){ 
     this.href = this.href + document.location.hash ;
});
//Get the dimensions and send back to calling page.
var h1 = document.body.scrollHeight;
var w1 = document.body.scrollWidth;
$.postMessage({ if_height: h1, if_width: w1 }, parent_url, parent );
  });

そして、あなたのページはすべてのハードワークを行い、素敵なスクリプトを持っています...

  //This is almost like request.querystring used to get the iframe data
  function querySt(param, e) {
         gy = e.split("&");
         for (i = 0; i < gy.length; i++) {
             ft = gy[i].split("=");
             if (ft[0] == param) {
                 return ft[1];
             }
         }
     }


     $(function () {
         // Keep track of the iframe dimensions.
         var if_height;
         var if_width;
         // Pass the parent page URL into the Iframe in a meaningful way (this URL could be
         // passed via query string or hard coded into the child page, it depends on your needs).
         src = 'http://www.OTHERDOAMIN.co.uk/OTHERSTARTPAGE.htm' + '#' + encodeURIComponent(document.location.href),
         // Append the Iframe into the DOM.
         iframe = $('<iframe " src="' + src + '" width="100%" height="100%" scrolling="no" frameborder="0"><\/iframe>').appendTo('#iframe');

         // Setup a callback to handle the dispatched MessageEvent event. In cases where
         // window.postMessage is supported, the passed event will have .data, .Origin and
         // .source properties. Otherwise, this will only have the .data property.
         $.receiveMessage(function (e) {
             // Get the height from the passsed data.
             //var h = Number(e.data.replace(/.*if_height=(\d+)(?:&|$)/, '$1'));
             var h = querySt("if_height", e.data);
             var w = querySt("if_width", e.data);


             if (!isNaN(h) && h > 0 && h !== if_height) {
                 // Height has changed, update the iframe.
                 iframe.height(if_height = h);
             }
             if (!isNaN(w) && w > 0 && w !== if_width) {
                 // Height has changed, update the iframe.
                 iframe.width(if_width = w);
             }
             //For debugging only really- can remove the next line if you want
             $('body').prepend("Recieved" + h + "hX" + w + "w .. ");
             // An optional Origin URL (Ignored where window.postMessage is unsupported).
           //Here you must put the other domain.com name only! This is like an authentication to prevent spoofing and xss attacks! 
         }, 'http://www.OTHERDOMAIN.co.uk');
     });

オプション3

彼らは現在、クロスドメインiFrameのサイズ変更を管理するための小さなJSライブラリですが、iFrameにはJavaScriptが少し必要ですが、これは依存関係のないネイティブJSのたった2.8k(765バイトGzip圧縮)です親ページから呼び出されるまで何もしません。これは、それが他の人のシステム上の素敵なゲストであることを意味します。

このコードは、mutationObserverを使用してDOMの変更を検出し、iFrameがコンテンツに合わせてサイズ変更されないようにサイズ変更イベントも探します。 IE8 +で動作します。

https://github.com/davidjbradshaw/iframe-resizer

84
Piotr Kula

つまり、あるドメインのドキュメントから別のドメインのドキュメントに計算された高さを取得する必要があるため、クロスドメインメッセージングを使用する以外に方法はありません。

したがって、postMessage(すべてのモデラーブラウザーで動作)を使用してこれを行うか、easyXDMの iframeの例のサイズ変更 の調整に5分かかります。

相手は実際にいくつかのファイルを自分のドメインにコピーし、ドキュメントに1行のコードを追加するだけです。

10
Sean Kinsey

Seanが言及したことと同様に、postMessageを使用できます。クロスドメインでiframeのサイズを変更するさまざまな方法を試すのに多くの時間を費やしましたが、David Walshによるこの素晴らしいブログ投稿に出くわすまでは運がありませんでした: http://davidwalsh.name/window-iframe

これは、私のコードとDavidのソリューションの組み合わせです。私のソリューションは、iframeのサイズ変更に特化しています。

子ページで、ページの高さを見つけて親ページ(iframeを含む)に渡します。 element_idを要素ID(html、bodyなど)に置き換えます。

<script>
function adjust_iframe_height(){
    var actual_height = document.getElementById('element_id).scrollHeight;
    parent.postMessage(actual_height,"*"); 
    //* allows this to post to any parent iframe regardless of domain
}
</script>

<body onload="adjust_iframe_height();"> 
//call the function above after the content of the child loads

親ウィンドウで、このコードを追加します。 iframe_idをiframe IDに置き換えます。

<script>
// Create IE + others compatible event handler
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

// Listen to message from child window
eventer(messageEvent,function(e) {
  console.log('parent received message!:  ',e.data);
  document.getElementById('iframe_id').height = e.data + 'px';
},false);
</script>

コンソールを開くと、コンソールログに高さが印刷されます。これはデバッグに役立つので、そこに置いておくことにします。

ベスト、ベイカー

24
Baker Humadi

これに対する多くの異なる解決策を見た結果、いくつかの異なるユースケースを考慮に入れるために単純な小さなライブラリを書くことになりました。ポータルページで複数のユーザーが生成したiFrameをサポートするソリューションが必要だったため、サポートされているブラウザーのサイズが変更され、iFrame後のホストページJavaScriptの読み込みに対応できました。また、幅とコールバック関数へのサイジングのサポートを追加し、body.marginのオーバーライドを許可します。これは、おそらくこれをゼロに設定する必要があるためです。

https://github.com/davidjbradshaw/iframe-resizer

Iframeコードは、自己完結型のJavaScriptであるため、他の人のページの良いゲストです。

スクリプトは、ホストページで次の使用可能なオプションで初期化されます。

iFrameResize({
    log                    : true,  // For development
    autoResize             : true,  // Trigering resize on events in iFrame
    contentWindowBodyMargin: 8,     // Set the default browser body margin style (in px)
    doHeight               : true,  // Calculates dynamic height
    doWidth                : false, // Calculates dynamic width
    enablePublicMethods    : true,  // Enable methods within iframe hosted page 
    interval               : 32,    // interval in ms to recalculate body height, 0 to disable refreshing
    scrolling              : false, // Enable the scrollbars in the iFrame
    callback               : function(messageData){ // Callback fn when message is received
        $('p#callback').html(
            '<b>Frame ID:</b> '    + messageData.iframe.id +
            ' <b>Height:</b> '     + messageData.height +
            ' <b>Width:</b> '      + messageData.width + 
            ' <b>Event type:</b> ' + messageData.type
        );
    }
});
6
David Bradshaw

「object-fit」HTML5属性を調べましたか? iframeを拡大縮小するのではなく、ビデオ/画像をiframeに拡大縮小します(幅が5,000pxになる中規模の画像を取得する場合は便利です)。 「適合」オプション(その他は「カバー」と「塗りつぶし」)は、アスペクト比を維持しながら、ソースを適合させるために一種のレターボックスアプローチを使用します。 HTML5を使わないで見ると、大量のポリフィルが利用できるように見えます。これは素晴らしいことですが、Edgeの端にあるバグにより、MicrosoftのNew Nightmareと約1年間互換性がなくなりました: https://github.com/anselmh/object-fit

編集:クロスドメインの問題を回避するには、Chrome拡張コンテンツスクリプトで作業をいつでも行うことができます。これは、iframeを貼り付けているページの一部であると考えられるためです。

0
sparkholiday

HTTPS別のリンクがiframe autoheightへの高さを取得します

https://-a.com content:

 <!DOCTYPE html>
    <html>
    <head>
        <title>Test Page</title>
    </head>
    <body>
        Test Page:
        <hr/>
        <iframe id="iframe" src="https://-b.com" style="width:100%;min-height:600px;border:none;" scrolling="no" ></iframe>
        <script>
        // browser compatibility: get method for event 
        // addEventListener(FF, Webkit, Opera, IE9+) and attachEvent(IE5-8)
        var myEventMethod = 
            window.addEventListener ? "addEventListener" : "attachEvent";
        // create event listener
        var myEventListener = window[myEventMethod];
        // browser compatibility: attach event uses onmessage
        var myEventMessage = 
            myEventMethod == "attachEvent" ? "onmessage" : "message";
        // register callback function on incoming message
        myEventListener(myEventMessage, function (e) {
            // we will get a string (better browser support) and validate
            // if it is an int - set the height of the iframe #my-iframe-id
            if (e.data === parseInt(e.data)) 
                document.getElementById('iframe').height = e.data + "px";
        }, false);
        </script>
    </body>
    </html>

https://-b.com iframe content:

<!DOCTYPE html>
<html>
<head>
    <title>Test Iframe Content</title>
    <script type="text/javascript">
    // all content including images has been loaded
    window.onload = function() {
        // post our message to the parent
        window.parent.postMessage(
            // get height of the content
            document.body.scrollHeight
            // set target domain
            ,"*"
        )
    };
</script>
</head>
<body>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>1
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>2
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>3
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>4
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>5
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>6
</body>
</html>

ワークテーブル:

xcom http> ycom https WORK

xcom https> ycom https WORK

xcom http> ycom http WORK

xcom https> ycom http WORK

Test Work Screenshot

0
Limitless isa

現在、私が知っている解決策は4つだけです。

3番目の問題のみが多くの問題を解決できます。たとえば、レスポンシブiFrameを作成できます。内部から閉じるか、通信できます。ただし、そのためには、iframeのiFrameと「サードパーティCookie」の回避策(オプション)が必要です。

例についての記事を作成しました: Event-driven cross-domain iFrame

0

Iframeでscroll = noを使用する代わりに、「auto」に変更します。次に、実際のウィンドウのサイズを取得します

$(window).height();

それをiframeの高さ属性として使用します。

さて、結果は...

「ページ」スクロールはなく、「iframe」スクロールのみがあります。あなたがナビゲートするとき、誰が巻物であるかは関係ありませんが、重要なのは1つしかないことです。

まあ、ユーザーがナビゲートしている間に単にウィンドウのサイズを変更するという問題があります。それを解決するために、私は以下を使用します:

setInterval(getDocHeight, 1);

その解決策はバグを引き起こすと思いましたか?それは私のために働いており、iFrameではphpによって動的な接続が生成されました。私はそれに関する将来のバグが怖い...

0
Elton Morais