iGoogle과 유사한 응용 프로그램을 만들고 있습니다. 다른 응용 프로그램 (다른 도메인)의 컨텐츠는 iframe을 사용하여 표시됩니다.
iframe 콘텐츠의 높이에 맞게 iframe의 크기를 어떻게 조정합니까?
Google이 사용하는 자바 스크립트를 해독하려고 시도했지만 난독 화되었으며 웹 검색은 지금까지 아무런 성과가 없었습니다.
업데이트 : 다른 도메인에서 콘텐츠가로드되므로 동일한 출처 정책이 적용됩니다.
iGoogle과 유사한 응용 프로그램을 만들고 있습니다. 다른 응용 프로그램 (다른 도메인)의 컨텐츠는 iframe을 사용하여 표시됩니다.
iframe 콘텐츠의 높이에 맞게 iframe의 크기를 어떻게 조정합니까?
Google이 사용하는 자바 스크립트를 해독하려고 시도했지만 난독 화되었으며 웹 검색은 지금까지 아무런 성과가 없었습니다.
업데이트 : 다른 도메인에서 콘텐츠가로드되므로 동일한 출처 정책이 적용됩니다.
답변:
우리는 이런 유형의 문제를 겪었지만 상황과는 약간 반대입니다. 우리는 다른 도메인의 사이트에 불법 복제 된 컨텐츠를 제공하고 있었기 때문에 동일한 출처 정책 도 문제였습니다. Google을 트롤링하는 데 많은 시간을 소비 한 후에, 우리는 결국 (어떤 ..) 실행 가능한 솔루션을 찾았습니다.
동일한 출처 정책을 사용하는 방법이 있지만 iframed 컨텐츠와 프레임 페이지 모두에서 변경이 필요하므로 양쪽에 변경을 요청할 수있는 기능이 없으면이 방법이 유용하지 않습니다. 두렵습니다.
자바 스크립트는 자체 도메인의 페이지 또는 페이지가있는 페이지와 통신 할 수 있지만 프레임이있는 페이지와는 통신 할 수 없습니다 (예 : 다음과 같은 경우).
www.foo.com/home.html, which iframes
|-> www.bar.net/framed.html, which iframes
|-> www.foo.com/helper.html
그런 다음 (iframed) 및 (같은 도메인) 과 home.html
통신 할 수 있습니다 .framed.html
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.html
메시지를 보낼 수 있습니다 helper.html
(iframe이)하지만, 하지 home.html
(아이는 부모 도메인 간 통신 할 수 없습니다).
여기서 핵심은 helper.html
에서 메시지를 수신 framed.html
하고 통신 할 수 있다는 것 입니다 home.html
.
따라서 기본적으로 framed.html
로드 할 때 자체 높이 helper.html
를 계산하고 메시지를 전달 home.html
한 다음 framed.html
앉은 iframe의 크기를 조정할 수 있습니다 .
우리의 메시지를 전달하는 것으로 가장 간단한 방법 framed.html
으로는 helper.html
URL을 인수 통해서였다. 이렇게하려면 지정된 framed.html
iframe이 src=''
있습니다. onload
발사 되면 자체 높이를 평가 하고이 시점에서 iframe의 src를helper.html?height=N
페이스 북이 그것을 처리하는 방법에 대한 설명 이 있습니다.
에서 www.foo.com/home.html
다음과 같은 자바 스크립트 코드가 필요합니다 (이는 덧붙여 말하자면, 어떤 도메인은 .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)
당신이 가진 모든 것을 피하고 코드를 단순화 하기 위해 요소 자체를 함수에 전달하는 것이 더 최적 일 수 있습니다 .
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에 제공되는 첫 번째 인수의 문자열 값으로 설정되는 data 속성 인 message 유형이 있습니다. 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/
Barebones 예제 ...
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에 "높이"속성이 이미 있으면 style = "height : xxx"만 추가됩니다. 이것은 당신이 원하는 것이 아닐 수도 있습니다.
다른 모든 답변이 나이가 들기 때문에 조금 늦을 수도 있습니다 :-) 그러나 ... 여기 내 솔루션이 있습니다. 실제 FF, Chrome 및 Safari 5.0에서 테스트되었습니다.
CSS :
iframe {border:0; overflow:hidden;}
자바 스크립트 :
$(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에서 부모 웹 사이트로 데이터를 보내는 다른 솔루션을 찾았습니다 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);
보안 연결을 추가하려는 경우 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을 사용하는 웹 사이트에만 적용됩니다. 부트 스트랩의 반응 형 임베드 기능이 작업을 수행합니다. 내용의 너비 (높이 아님)를 기반으로합니다.
<!-- 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에 문제가있었습니다. 타이밍 문제 중 하나는 분명히 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>
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 페이지가로드 된 시점을 알아야하기 때문에 약간 까다로워서 내용을 제어 할 수없는 경우가 있습니다. iload에 onload 핸들러를 추가 할 수는 있지만 과거에 시도했지만 브라우저마다 동작이 크게 다릅니다 (누가 가장 성가 신지 추측하지 마십시오 ...). 크기 조정을 수행하고 이벤트로드를 수신하거나 이벤트 크기 조정을 수신하는 컨텐츠에 일부 스크립트를 삽입 한 다음 이전 함수를 호출하는 함수를 iframe 페이지에 추가해야합니다. 보안을 유지하기 위해 페이지에 기능을 추가하려고 생각하지만 얼마나 쉬운 지 알 수 없습니다.
쉬운 해결책이 있으며 링크의 너비와 높이를 결정해야합니다 (대부분의 브라우저에서 작동).
<a href='#' onClick=" document.getElementById('myform').src='t2.htm';document.getElementById('myform').width='500px'; document.getElementById('myform').height='400px'; return false">500x400</a>