[解決済み] クロスドメインiframeのリサイズ
質問
別ドメインのiframeをリサイズするには?
-編集
下にスクロールして、いくつかの解決策をご覧ください。
何時間もコードをハックした後、結論は、iframe 内のすべてのものは、私のドメインで表示されるスクロールバーでさえも、アクセスできない、ということです。多くのテクニックを試しましたが、無駄でした。
時間を節約するために、このルートを通らなくても、クロスドメイン通信のために sendMessages を使用してください。 私が使用しているHTML < 5のプラグインがあります-素敵な例のために一番下まで行ってください :)
過去数日間、私はサイトに iframe を統合しようとしていました。これは、相手側が API を開発している間の短期的な解決策です(数ヶ月かかるかもしれません...)。 そして、これは短期的なソリューションであるため、我々はeasyXDMを使用したいと思いました-私は他のドメインにアクセスできますが、そのままではp3pヘッダーを追加するように頼むのは難しいです....
3つのiframe
私が見つけた最も近い解決策は3つのiframeでしたが、それはクロームとサファリの精神に行くので、私はそれを使用することはできません。
クロームで開く
http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&高さ=1179
スクロールバーを計測する
私は、フォームのサイズを変更しようとするためにscrollheightを使用する方法についての別の記事を見つけました。理論的にはそれはうまく動作しますが、私はiframeのスクロール高さを使用して適切にそれを適用できませんでした...。
document.body.scrollHeight
これは明らかにボディの高さを使用しています(これらのプロパティにアクセスすることはできません 100%は、X-domainsのドキュメントの高さではなく、クライアントのディスプレイのキャンバスに基づきます)。
私はiframeの高さを取得するためにjqueryを使用してみました。
$('#frameId').Height()
$('#frameId').clientHeight
$('#frameId').scrollHeight
は、クロームとIEで異なる値を返すか、まったく意味をなしません。 問題は、フレーム内のすべてのものが拒否されることです - スクロールバーでさえも。
計算されたスタイル
しかし、私はiframeのクロームで要素と検査すると、それは私にiframe内のドキュメントの寸法をブラッディ表示されます(iframe.heighを得るためにjquery x -ドメインを使用 - アクセス拒否)。 計算されたCSSには何もありません
さて、クロームはどのようにこれを計算するのでしょうか? (編集 - ブラウザは内蔵のレンダリングエンジンを使ってページを再レンダリングし、これらの設定をすべて計算します - しかしクロスドメイン詐欺を防ぐためにどこにも添付されていません。)
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/ <-java not jscript
編集 09-2013 アップデイト
これらはすべて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>
送信されるパラメータを変更しました。もし、幅が正しく動作するようにしたいのであれば、他のドメインのページでは、どこか似たようなスタイルでページの幅を含める必要があります。
<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>
500msごとにメッセージを送信するのではなく、サイズが変更されたかどうかをチェックし、サイズが変更された場合のみ送信するようにすれば、より効率的な間隔になるでしょう。このチェックを実装すれば、ポーリングは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には、リサイズのためのカスタムコールとincludes.があります。
$(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 が少し含まれている必要がありますが、これは 2.8k (765 bytes Gzipped) のネイティブ JS で、依存関係がなく、親ページから呼び出されるまで何も行いません。これはつまり、他の人のシステムの素敵なゲストであるということです。
このコードは DOM の変更を検出するために mutationObserver を使用し、iFrame がコンテンツに合わせた大きさを保つように、resize イベントにも目を光らせています。IE8+ で動作します。
https://github.com/davidjbradshaw/iframe-resizer
どのように解決するのですか?
あるドメインのドキュメントから別のドメインのドキュメントに計算された高さを取得する必要があるため、これにはクロスドメインメッセージングを使用する以外の方法はないということです。
ですから、これを
postMessage
を使うか (すべてのモダンブラウザで動作)、5 分かけて
リサイズ iframe の例
を5分かけて適応させることもできます。
相手は本当にいくつかのファイルを自分のドメインにコピーし、1行のコードを自分のドキュメントに追加するだけでよいのです。
関連
-
[解決済み】divの高さを画面の残りスペースで埋めるようにする
-
[解決済み] div' コンテナに合わせて画像を自動リサイズするにはどうしたらいいですか?
-
[解決済み] チェックボックスとそのラベルをクロスブラウザーで一貫して揃える方法
-
[解決済み] コンテナの幅に応じたフォントの拡大縮小
-
[解決済み] CSS 100% height と padding/margin の関係
-
[解決済み] iframeの幅と高さをコンテンツに合わせて調整する
-
[解決済み】Iframeをコンテナの残り高さの100%にフィットさせる
-
[解決済み】フルスクリーンiframeの高さが100%になる件
-
[解決済み】iframeから親URLにアクセスする。
-
[解決済み] ExtJS 4のイベントハンドリングについて
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Google maps API V3 - 同一地点に複数のマーカーを設置する。
-
[解決済み] 文字列がすべて同じ部分文字列で構成されているかどうかを調べるにはどうすればよいですか?
-
[解決済み] WebStormで未解決の変数が大量にある場合の警告に対処する方法は?
-
[解決済み] アサインの左側にJavascriptのオブジェクトブラケット表記({ ナビゲーション } =)があります。
-
[解決済み] Javascript / jQueryでAndroid端末を検出する。
-
[解決済み] javascript includes() 大文字小文字を区別しない
-
[解決済み] JavaScript のオブジェクトの配列を比較し、最小値/最大値を取得する
-
[解決済み] Promise : then vs then + catch [重複].
-
[解決済み] <ng-content>が空かどうかを確認する方法は?(これまでのAngular 2+で)
-
[解決済み] JavaScriptでDIVを表示・非表示にするには?