Programing

교차 도메인 iframe 크기 조정

lottogame 2020. 9. 19. 11:55
반응형

교차 도메인 iframe 크기 조정


다른 도메인에서 iframe 크기를 조정하려면 어떻게합니까

-편집하다

일부 솔루션을 보려면 아래로 스크롤하십시오. 또는 이렇게하지 않는 방법을 읽으십시오. D

몇 시간의 코드 해킹 후 결론은 내 도메인에서 렌더링되는 스크롤바를 포함하여 iframe 내부의 모든 항목에 액세스 할 수 없다는 것입니다. 나는 아무 소용이없는 많은 기술을 시도했다.

시간을 절약하려면이 경로를 따르지 말고 도메인 간 통신에 sendMessages를 사용하십시오. 내가 사용하는 HTML <5 용 플러그인이 있습니다. 좋은 예를 보려면 맨 아래로 이동하십시오.


지난 며칠 동안 iframe을 사이트에 통합하려고했습니다. 이것은 다른 쪽이 개발하고 API를 개발하는 동안 단기적인 솔루션입니다 (몇 달이 걸릴 수도 있습니다 ...). 그리고 이것이 우리가 한 단기 솔루션이기 때문에 easyXDM을 사용하고 싶습니다. 다른 도메인에 액세스 할 수 있지만 요청하기가 충분히 어렵습니다. p3p 헤더를 그대로 추가합니다 .....

3 개의 iframe

내가 찾은 가장 가까운 해결책은 3 개의 iframe 이었지만 크롬과 사파리를 염두에 두어 사용할 수 없습니다.

크롬에서 열기

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

스크롤바 측정

스크롤 높이를 사용하여 양식 크기를 조정하는 방법에 대한 또 다른 게시물을 찾았습니다. 이론적으로는 잘 작동하지만 iframe 스크롤 높이를 사용하여 제대로 적용 할 수 없었습니다 ..

document.body.scrollHeight

그것은 obvoisly body height를 사용합니다 (이 속성에 100 % 액세스 할 수 없음은 x-domains 문서 높이가 아니라 클라이언트 디스플레이 canvaz를 기반으로 함)

iframe 높이를 얻기 위해 jquery를 사용해 보았습니다.

$('#frameId').Height()

$('#frameId').clientHeight

$('#frameId').scrollHeight

크롬과 ie에서 다른 값을 반환하거나 전혀 의미가 없습니다. 문제는 프레임 내부의 모든 것이 거부된다는 것입니다. 스크롤바도 마찬가지입니다.

계산 된 스타일

그러나 iframe의 크롬에서 요소를 검사하고 요소를 검사하면 iframe 내부의 문서 크기가 표시됩니다 (jquery x-domain을 사용하여 iframe.heigh-액세스 거부 됨) 계산 된 CSS에는 아무것도 없습니다. 여기에 이미지 설명 입력

이제 크롬은 그것을 어떻게 계산합니까? (편집-브라우저는 이러한 모든 설정을 계산하기 위해 렌더링 엔진의 빌드를 사용하여 페이지를 다시 렌더링하지만 도메인 간 사기를 방지하기 위해 어디에도 첨부되지 않습니다 ..)

HTML4

HTML4.x의 사양을 읽었으며 document.element를 통해 노출 된 읽기 전용 값이 있어야하지만 jquery를 통해 액세스가 거부되었다고 말합니다.

프록시 프레임

나는 사용자가 iframe을 통해 로그인하고 프록시가 실제 콘텐츠 대신 로그인 페이지를 얻을 때까지 사이트를 다시 프록시하고 계산하는 경로를 따라갔습니다. 또한 일부 페이지를 두 번 호출하는 것은 허용되지 않습니다.

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

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

페이지 다시 렌더링

여기까지 가지 않았지만 소스를보고 소스 파일을 기반으로 페이지를 다시 렌더링하는 jscript 엔진이 있습니다. 그러나 그것은 그 jscripts를 해킹해야 할 것입니다. 그리고 그것은 상업적인 엔티티에 이상적인 상황이 아닙니다 ... 그리고 일부는 순수한 자바 애플릿이나 서버 측 렌더링을 불러옵니다.

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

http://htmlunit.sourceforge.net/ <-java가 아닌 jscript

http://maxq.tigris.org/


2013 년 9 월 업데이트 수정

이 모든 것은 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마다 메시지를 게시하지 않는 경우에만 보낼 수 있습니다. 이 검사를 구현하면 폴링을 50ms까지 변경할 수 있습니다! 재미있게


여러 브라우저에서 작업하고 빠릅니다. 훌륭한 디버깅 기능 !!

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

솔루션 2 (작동하지만 좋지 않음)

따라서 기본적으로 다른 도메인과 상호 합의한 경우 sendmessage를 처리 할 라이브러리를 추가 할 수 있습니다. 다른 도메인에 대한 액세스 권한이없는 경우 .. 계속해서 더 많은 해킹을 찾으십시오. 내가 찾은 이들을 찾거나 완전히 정당화 할 수 없기 때문입니다.

따라서 다른 도메인은 여기에 헤드 태그를 포함합니다.

<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


문제는 한 도메인의 문서에서 다른 도메인의 문서로 계산 된 높이를 가져와야하기 때문에이를 위해 교차 도메인 메시징을 사용하는 것 외에 다른 방법이 없습니다.

따라서이를 사용하여 수행하거나 postMessage(모든 모더 브라우저에서 작동) easyXDM 크기 조정 iframe 예제조정 하는 데 5 분을 소비 합니다.

상대방은 실제로 도메인에 몇 개의 파일을 복사하고 문서에 한 줄의 코드를 추가하기 만하면됩니다.


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>

콘솔을 열면 콘솔 로그에 인쇄되는 높이가 표시됩니다. 이것은 디버깅에 도움이 될 것입니다.

Best, Baker


이에 대한 많은 다른 솔루션을 살펴본 결과 여러 가지 사용 사례를 고려하여 간단한 작은 라이브러리를 작성했습니다. 포털 페이지에서 여러 사용자 생성 iFrame을 지원하는 솔루션이 필요했기 때문에 지원되는 브라우저의 크기가 조정되고 iFrame 이후 호스트 페이지 JavaScript로드에 대처할 수있었습니다. 또한 너비 및 콜백 함수에 대한 크기 조정 지원을 추가하고이 값을 0으로 설정하고 싶을 것이므로 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
        );
    }
});

iframe에서 scroll = no를 사용하는 대신 "auto"로 변경합니다. 그런 다음 실제 창 크기를 얻습니다.

$(window).height();

iframe 높이 속성으로 사용합니다.

결과는 ...

"페이지"스크롤은없고 "iframe"스크롤 만 있습니다. 탐색 할 때 두루마리가 누구인지는 중요하지 않지만 중요한 것은 1 개만 있다는 것입니다.

음, 사용자가 탐색하는 동안 단순히 창 크기를 조정하는 문제가 있습니다. 이를 해결하기 위해 다음을 사용합니다.

setInterval(getDocHeight, 1);

그 솔루션이 버그를 유발할 것이라고 생각 했습니까? 그것은 나를 위해 일하고 있으며 iFrame에서 PHP에 의해 생성 된 동적 콘텍트가 있습니다. 나는 미래의 버그가 두렵습니다.


요즘 내가 아는 솔루션은 4 개뿐입니다.

세 번째 사람 만이 많은 문제를 해결할 수 있습니다. 예를 들어 반응 형 iFrame을 만들 수 있습니다 . 내부에서 닫거나 통신 할 수 있습니다 . 그러나이를 위해서는 Iframe의 iFrame과 "타사 쿠키"해결 방법 (선택 사항)이 필요합니다.

예를 들어 이에 대한 기사를 작성했습니다. 이벤트 기반 교차 도메인 iFrame


'object-fit'HTML5 속성을 살펴 보셨습니까? iframe의 크기를 조정하는 대신 비디오 / 이미지를 iframe에 맞게 조정합니다 (폭이 5,000px로 끝나는 중간 크기 이미지를 잡는 경우 유용함). "fit"옵션 (다른 옵션은 "cover"및 "fill")은 가로 세로 비율을 유지하면서 소스를 맞추기 위해 일종의 레터 박스 접근 방식을 사용합니다. HTML5가없는 사람들이보기 위해서는 많은 폴리 ​​필을 사용할 수 있습니다. 이것은 훌륭하지만 Edge 끝의 버그로 인해 약 1 년 동안 Microsoft의 New Nightmare와 호환되지 않습니다. https://github.com/anselmh/object-fit

편집 : 교차 도메인 문제를 해결하려면 iframe을 고정하는 페이지의 일부라고 생각하기 때문에 Chrome 확장 콘텐츠 스크립트에서 작업을 수행 할 수 있습니다.


HTTPS 다른 링크는 iframe 자동 높이에 높이를 가져옵니다.

https://-a.com 콘텐츠 :

 <!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 콘텐츠 :

<!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 작업

xcom https> ycom http 작업

테스트 작업 스크린 샷


iframe에 포함 된 페이지의 높이를 찾고 계십니까? iframe 콘텐츠의 높이를 확인한 다음 iframe의 높이를 콘텐츠의 높이로 설정하는 자바 스크립트가 작동합니다.

var Height = document.getElementById('iFrameId').contentWindow.document.body.scrollHeight;

document.getElementById('iFrameId').height = Height;

그러나 이것은 iframe에 표시되는 페이지가 동일한 도메인에있는 경우에만 작동합니다. 그렇지 않은 경우 필요한 정보에 액세스 할 수 없습니다. 따라서 액세스 거부 오류입니다.


iframe의 크기를 조정하는 간단한 스크립트는 다음과 같습니다.

이것은 머리 속에 들어갑니다 : (이것은 php 스크립트를 위해 작성되었으며, html의 경우 '를 "로 변경하고 \"를'...

<script type='text/javascript'>
<!--
function resizeIframe(id){
/*
this.obj=obj
//this.obj.width=null
//this.obj.width=window.frames[\"sizeframe1\"].document.body.scrollWidth
this.obj.style.height=\"\" // for Firefox and Opera
setTimeout(\"this.obj.style.height=this.obj.contentWindow.document.body.scrollHeight+(notIE?heightOffset:0)\",10) // setTimeout required for Opera
*/

el=document.getElementById(id)
el.style.height='200px' // for Firefox and Opera
setTimeout('el.style.height=el.contentWindow.document.body.scrollHeight+\"px\"',1) // setTimeout required for Opera
}

// -->
</script>"

머리 끝

이것은 본문에 들어갑니다 (이는 PHP 스크립트 용으로 작성되었습니다. HTML의 경우 모든 '를 "로, \"을'...로 변경하십시오.)

<iframe onload='resizeIframe(this.id)' allowTransparency=\"true\" name='ccpaymentwindow' id='sizeframe1' marginwidth='1' marginheight='1' height='700' width='690' border='0' frameborder='1' scrolling='no' src='ccmslink.php?variable1=" . $variable1 . "'></iframe>

보너스 : 위에 몇 가지 힌트가 있습니다. PHP 스크립팅 용으로 설정되어 있으므로 많은 작업을 수행 할 수 있습니다.

이것의 핵심은 "sizeframe1".... 같은 페이지에있는 여러 "resizers"의 경우 동일한 스크립트를 복사하되 iframe의 ID와 헤드의 스크립트 이름을 변경하고 비올라! 같은 페이지에 여러 개의 리사이 저가 있습니다 ... 매우 잘 작동합니다!

푼이 있습니다.

참고 URL : https://stackoverflow.com/questions/5908676/cross-domain-iframe-resize

반응형