Có công cụ tự động thay đổi độ cao iframe miền chéo nào hoạt động không?


109

Tôi đã thử một vài giải pháp nhưng không thành công. Tôi tự hỏi liệu có giải pháp nào tốt hơn với một hướng dẫn dễ làm theo không.


2
Bạn đã thử những giải pháp nào mà không thành công?
Yzmir Ramirez

1
Tôi đã thử cái này nhưng nó xuất hiện trong trình duyệt webkit như đã nêu trong bài viết: css-tricks.com/cross-domain-iframe-resizing Có một cái khác nhưng tôi không thể nhớ url.
J82


Câu trả lời:


68

Bạn có ba lựa chọn thay thế:

1. Sử dụng iFrame-resizer

Đây là một thư viện đơn giản để giữ cho iFrames có kích thước phù hợp với nội dung của chúng. Nó sử dụng các API PostMessage và MutationObserver, dự phòng cho IE8-10. Nó cũng có các tùy chọn cho trang nội dung để yêu cầu iFrame chứa có kích thước nhất định và cũng có thể đóng iFrame khi bạn làm xong.

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

2. Sử dụng Easy XDM (kết hợp PostMessage + Flash)

Easy XDM sử dụng một bộ sưu tập các thủ thuật để cho phép giao tiếp miền chéo giữa các cửa sổ khác nhau trong một số trình duyệt và có các ví dụ để sử dụng nó để thay đổi kích thước iframe:

http://easyxdm.net/wp/2010/03/17/resize-iframe-based-on-content/

http://kinsey.no/blog/index.php/2010/02/19/resizing-iframes-using-easyxdm/

Easy XDM hoạt động bằng cách sử dụng PostMessage trên các trình duyệt hiện đại và giải pháp dựa trên Flash làm dự phòng cho các trình duyệt cũ hơn.

Xem thêm chủ đề này trên Stackoverflow (cũng có những chủ đề khác, đây là một câu hỏi thường gặp). Ngoài ra, Facebook dường như sẽ sử dụng một cách tiếp cận tương tự .

3. Giao tiếp qua máy chủ

Một tùy chọn khác là gửi chiều cao iframe đến máy chủ của bạn và sau đó thăm dò ý kiến ​​từ máy chủ đó từ trang web mẹ với JSONP (hoặc sử dụng một cuộc thăm dò dài nếu có thể).


1
Đối với PostMessage, nếu bạn đã sử dụng jQuery, bạn cũng có thể muốn xem plugin postMessage tuyệt vời của Ben Alman: benalman.com/projects/jquery-postmessage-plugin
rinogo

8
iFrame-resizer cần quyền truy cập vào máy chủ lưu trữ nội dung iframe. Vì vậy, bạn chỉ có thể sử dụng nó cho các miền bạn kiểm soát.
Hokascha

Tốt lắm, @Hokascha. Dự án tuyên bố hỗ trợ iframe tên miền chéo, nhưng đọc tài liệu cho thấy rằng nó vẫn yêu cầu máy chủ truy cập vào miền nhúng.
StockB

1
Không có "lựa chọn thay thế" nào là giải pháp thực tế cho vấn đề này. Người hỏi muốn đặt chiều cao iFrame của iFrame tên miền chéo từ các trang web mà họ không có quyền kiểm soát. 1. Yêu cầu quyền truy cập máy chủ. 2. Yêu cầu phần mềm tôi cho là kém. Easy XDM đã được thực hiện như 10 năm trước. Phiên bản mới nhất, từ năm 2019, yêu cầu flash . Rất may, Flash đã chết và không ai nên dựa vào nó. 3. Yêu cầu quyền truy cập máy chủ.
redanimalwar

26

Tôi có giải pháp để đặt chiều cao của iframe động dựa trên nội dung của nó. Điều này hoạt động cho nội dung tên miền chéo. Có một số bước cần thực hiện để đạt được điều này.

  1. Giả sử bạn đã thêm iframe vào trang web "abc.com/page"

    <div> <iframe id="IframeId" src="http://xyz.pqr/contactpage" style="width:100%;" onload="setIframeHeight(this)"></iframe> </div>

  2. Tiếp theo, bạn phải ràng buộc sự kiện "tin nhắn" cửa sổ trong trang web "abc.com/page"

window.addEventListener('message', function (event) {
//Here We have to check content of the message event  for safety purpose
//event data contains message sent from page added in iframe as shown in step 3
if (event.data.hasOwnProperty("FrameHeight")) {
        //Set height of the Iframe
        $("#IframeId").css("height", event.data.FrameHeight);        
    }
});

Khi tải iframe, bạn phải gửi tin nhắn đến nội dung cửa sổ iframe với thông báo "FrameHeight":

function setIframeHeight(ifrm) {
   var height = ifrm.contentWindow.postMessage("FrameHeight", "*");   
}
  1. Trên trang chính được thêm dưới iframe tại đây "xyz.pqr / contactpage", bạn phải liên kết sự kiện "thông báo" cửa sổ trong đó tất cả thư sẽ nhận được từ cửa sổ mẹ của "abc.com/page"
window.addEventListener('message', function (event) {

    // Need to check for safety as we are going to process only our messages
    // So Check whether event with data(which contains any object) contains our message here its "FrameHeight"
   if (event.data == "FrameHeight") {

        //event.source contains parent page window object 
        //which we are going to use to send message back to main page here "abc.com/page"

        //parentSourceWindow = event.source;

        //Calculate the maximum height of the page
        var body = document.body, html = document.documentElement;
        var height = Math.max(body.scrollHeight, body.offsetHeight,
            html.clientHeight, html.scrollHeight, html.offsetHeight);

       // Send height back to parent page "abc.com/page"
        event.source.postMessage({ "FrameHeight": height }, "*");       
    }
});

3
Hoạt động mượt mà. Cảm ơn đống!
Alex Leonov

đơn giản đây là phương pháp kỹ thuật nhất mà tôi có thể tìm thấy, rất tốt @sudhir, Cảm ơn bạn :)
java acm

14

Những gì tôi đã làm là so sánh Chiều rộng khung nội tuyến cho đến khi nó thay đổi kích thước trong khi tôi tăng dần Chiều cao khung nội tuyến. Và nó hoạt động tốt cho tôi. Bạn có thể điều chỉnh mức tăng thành bất kỳ thứ gì bạn muốn.

   <script type="text/javascript">
    function AdjustIFrame(id) {
        var frame = document.getElementById(id);
        var maxW = frame.scrollWidth;
        var minW = maxW;
        var FrameH = 100; //IFrame starting height
        frame.style.height = FrameH + "px"

        while (minW == maxW) {
            FrameH = FrameH + 100; //Increment
            frame.style.height = FrameH + "px";
            minW = frame.scrollWidth;
        }
    }

   </script>


<iframe id="RefFrame" onload="AdjustIFrame('RefFrame');" class="RefFrame"
    src="http://www.YourUrl.com"></iframe>

4
bạn có thể muốn thêm giới hạn về số lượng vòng lặp, nếu không thì 'while' có thể biến thành một vòng lặp vô hạn.
Kevin Seifert

1
Điều này đang làm hỏng trang của tôi.
DDDD

Giải pháp đơn giản tốt. Nhưng trong caes của tôi, sự gia tăng kích thước bị giới hạn bởi kích thước màn hình.
Zeta

1

Tôi có một tập lệnh bị rớt trong iframe với nội dung của nó. Nó cũng đảm bảo rằng iFrameResizer tồn tại (nó chèn nó dưới dạng tập lệnh) và sau đó thực hiện thay đổi kích thước.

Tôi sẽ đưa ra một ví dụ đơn giản bên dưới.

// /js/embed-iframe-content.js

(function(){
    // Note the id, we need to set this correctly on the script tag responsible for
    // requesting this file.
    var me = document.getElementById('my-iframe-content-loader-script-tag');

    function loadIFrame() {
        var ifrm = document.createElement('iframe');
        ifrm.id = 'my-iframe-identifier';
        ifrm.setAttribute('src', 'http://www.google.com');
        ifrm.style.width = '100%';
        ifrm.style.border = 0;
        // we initially hide the iframe to avoid seeing the iframe resizing
        ifrm.style.opacity = 0;
        ifrm.onload = function () {
            // this will resize our iframe
            iFrameResize({ log: true }, '#my-iframe-identifier');
            // make our iframe visible
            ifrm.style.opacity = 1;
        };

        me.insertAdjacentElement('afterend', ifrm);
    }

    if (!window.iFrameResize) {
        // We first need to ensure we inject the js required to resize our iframe.

        var resizerScriptTag = document.createElement('script');
        resizerScriptTag.type = 'text/javascript';

        // IMPORTANT: insert the script tag before attaching the onload and setting the src.
        me.insertAdjacentElement('afterend', ifrm);

        // IMPORTANT: attach the onload before setting the src.
        resizerScriptTag.onload = loadIFrame;

        // This a CDN resource to get the iFrameResizer code.
        // NOTE: You must have the below "coupled" script hosted by the content that
        // is loaded within the iframe:
        // https://unpkg.com/iframe-resizer@3.5.14/js/iframeResizer.contentWindow.min.js
        resizerScriptTag.src = 'https://unpkg.com/iframe-resizer@3.5.14/js/iframeResizer.min.js';
    } else {
        // Cool, the iFrameResizer exists so we can just load our iframe.
        loadIFrame();
    }    
}())

Sau đó, nội dung iframe có thể được đưa vào bất kỳ đâu trong một trang / trang web khác bằng cách sử dụng tập lệnh như sau:

<script
  id="my-iframe-content-loader-script-tag"
  type="text/javascript"
  src="/js/embed-iframe-content.js"
></script>

Nội dung iframe sẽ được đưa vào bên dưới bất cứ nơi nào bạn đặt thẻ script.

Hy vọng điều này là hữu ích cho ai đó. 👍


Thật tuyệt, tôi đã thêm <script ... data-src="http://google.com">và điền vào iframe src với nó.
BananaAcid

Theo văn bản, phiên bản hiện tại làiframe-resizer@4.2.10
BananaAcid

1
... được mở rộng thành một mẫu mã có thể sử dụng đầy đủandbox.io/s/remote
embed

@BananaAcid - liên kết hộp thư đến mã của bạn không còn hoạt động
ctrlplusb

cảm ơn vì đã đề cập đến nó, các liên kết đã trở thành: Codeandbox.io/s/remote-embed-ifrm-yz0xl . (lưu ý: Codeandbox "hàng giả" sử dụng nhiều trang và có thể bị treo. Tải lại có thể hữu ích)
BananaAcid

1

Đây là giải pháp đơn giản của tôi tại trang này. http://lab.ohshiftlabs.com/iframesize/

Đây là cách nó làm việc;

nhập mô tả hình ảnh ở đây

Về cơ bản nếu bạn có thể chỉnh sửa trang ở tên miền khác, bạn có thể đặt một trang iframe khác thuộc về máy chủ của bạn để lưu chiều cao vào cookie. Với cookie đọc khoảng thời gian khi nó được cập nhật, hãy cập nhật chiều cao của khung nội tuyến. Đó là tất cả.

Tải xuống; http://lab.ohshiftlabs.com/iframesize/iframesizepost.zip

Chỉnh sửa: Tháng 12 2019

Giải pháp ở trên về cơ bản sử dụng một iframe khác bên trong iframe thứ 3 của iframe thuộc về miền trang trên cùng mà bạn gọi là trang này với chuỗi truy vấn lưu giá trị kích thước vào cookie, trang bên ngoài kiểm tra truy vấn này với một khoảng thời gian. Nhưng nó không phải là một giải pháp tốt, vì vậy bạn nên làm theo một trong những cách sau:

Trong trang đầu:

window.addEventListener("message", (m)=>{iframeResizingFunction(m)});

Ở đây bạn có thể kiểm tra m.originxem nó đến từ đâu.

Trong trang khung:

window.parent.postMessage({ width: 640, height:480 }, "*")

Mặc dù, xin đừng quên rằng đây không phải là cách an toàn. Để đảm bảo an toàn, hãy cập nhật giá trị * (targetOrigin) với giá trị mong muốn của bạn. Vui lòng làm theo tài liệu: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage


1
Các liên kết này hiện đã chết (404) và nội dung không được tóm tắt trong câu trả lời. :(
StockB

1
liên kết vẫn còn chết. 404
Arslan Ameer

0

Tôi đã tìm thấy một giải pháp phía máy chủ khác dành cho nhà phát triển web sử dụng PHP để lấy kích thước của iframe.

Đầu tiên là sử dụng tập lệnh máy chủ PHP cho một cuộc gọi bên ngoài thông qua hàm bên trong: (giống như file_get_contentsvới nhưng curl và dom).

function curl_get_file_contents($url,$proxyActivation=false) {
    global $proxy;
    $c = curl_init();
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($c, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7");
    curl_setopt($c, CURLOPT_REFERER, $url);
    curl_setopt($c, CURLOPT_URL, $url);
    curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
    if($proxyActivation) {
        curl_setopt($c, CURLOPT_PROXY, $proxy);
    }
    $contents = curl_exec($c);
    curl_close($c);
    $dom = new DOMDocument();
    $dom->preserveWhiteSpace = false;
    @$dom->loadHTML($contents);
    $form = $dom->getElementsByTagName("body")->item(0);
    if ($contents) //si on a du contenu
        return $dom->saveHTML();
    else
        return FALSE;
}
$url = "http://www.google.com"; //Exernal url test to iframe
<html>
    <head>
    <script type="text/javascript">

    </script>
    <style type="text/css">
    #iframe_reserve {
        width: 560px;
        height: 228px
    }
    </style>
    </head>

    <body>
        <div id="iframe_reserve"><?php echo curl_get_file_contents($url); ?></div>

        <iframe id="myiframe" src="http://www.google.com" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"  style="overflow:none; width:100%; display:none"></iframe>

        <script type="text/javascript">
            window.onload = function(){
            document.getElementById("iframe_reserve").style.display = "block";
            var divHeight = document.getElementById("iframe_reserve").clientHeight;
            document.getElementById("iframe_reserve").style.display = "none";
            document.getElementById("myiframe").style.display = "block";
            document.getElementById("myiframe").style.height = divHeight;
            alert(divHeight);
            };
        </script>
    </body>
</html>

Bạn cần hiển thị dưới div ( iframe_reserve) html được tạo bởi lệnh gọi hàm bằng cách sử dụngecho curl_get_file_contents("location url iframe","activation proxy")

Sau khi thực hiện việc này, một hàm sự kiện nội dung được tải lên với javascript lấy chiều cao của khung nội tuyến của trang chỉ bằng một điều khiển đơn giản đối với nội dung div ( iframe_reserve)

Vì vậy, tôi đã sử dụng divHeight = document.getElementById("iframe_reserve").clientHeight;để lấy chiều cao của trang bên ngoài mà chúng tôi sẽ gọi sau khi che vùng chứa div ( iframe_reserve). Sau đó, chúng tôi tải iframe với chiều cao tốt của nó.


0

Tôi gặp sự cố này khi đang làm việc gì đó tại nơi làm việc (sử dụng React). Về cơ bản, chúng tôi có một số nội dung html bên ngoài mà chúng tôi lưu vào bảng tài liệu của mình trong cơ sở dữ liệu và sau đó chèn vào trang trong một số trường hợp nhất định khi bạn đang ở trong tập dữ liệu Tài liệu.

Vì vậy, các dòng nội tuyến nhất định n, trong đó ncó thể chứa html bên ngoài, chúng tôi cần thiết lập một hệ thống để tự động thay đổi kích thước iframe của mỗi nội tuyến sau khi nội dung được tải đầy đủ trong mỗi dòng. Sau khi quay bánh xe của tôi một chút, đây là cách tôi thực hiện nó:

  1. Đặt trình xử lý messagesự kiện trong chỉ mục của ứng dụng React của chúng tôi để kiểm tra một khóa cụ thể mà chúng tôi sẽ đặt từ iframe của người gửi.
  2. Trong thành phần thực sự hiển thị iframe, sau khi chèn html bên ngoài vào nó, tôi thêm một <script>thẻ sẽ đợi iframe window.onloadkích hoạt. Sau khi kích hoạt, chúng tôi sử dụng postMessageđể gửi thông báo đến cửa sổ mẹ với thông tin về id iframe, chiều cao được tính toán, v.v.
  3. Nếu nguồn gốc khớp và khóa được thỏa mãn trong trình nghe chỉ mục, hãy lấy DOM idcủa iframe mà chúng tôi truyền vào MessageEventđối tượng
  4. Khi chúng ta có iframe, chỉ cần đặt chiều cao từ giá trị được chuyển từ iframe postMessage.
// index
if (window.postMessage) {
    window.addEventListener("message", (messageEvent) => {
        if (
            messageEvent.data.origin &&
            messageEvent.data.origin === "company-name-iframe"
        ) {
            const iframe = document.getElementById(messageEvent.data.id)
            // this is the only way to ensure that the height of the iframe container matches its body height
            iframe.style.height = `${messageEvent.data.height}px`
            // by default, the iframe will not expand to fill the width of its parent
            iframe.style.width = "100%"
            // the iframe should take precedence over all pointer events of its immediate parent
            // (you can still click around the iframe to segue, for example, but all content of the iframe
            // will act like it has been directly inserted into the DOM)
            iframe.style.pointerEvents = "all"
            // by default, iframes have an ugly web-1.0 border
            iframe.style.border = "none"
        }
    })
}
// in component that renders n iframes
<iframe
    id={`${props.id}-iframe`}
    src={(() => {
        const html = [`data:text/html,${encodeURIComponent(props.thirdLineData)}`]
        if (window.parent.postMessage) {
            html.push(
                `
                <script>
                window.onload = function(event) {
                    window.parent.postMessage(
                        {
                            height: document.body.scrollHeight,
                            id: "${props.id}-iframe",
                            origin: "company-name-iframe",
                        },
                        "${window.location.origin}"
                    );
                };
                </script>
                `
            )
        }

        return html.join("\n")
    })()}
    onLoad={(event) => {
        // if the browser does not enforce a cross-origin policy,
        // then just access the height directly instead
        try {
            const { target } = event
            const contentDocument = (
                target.contentDocument ||
                // Earlier versions of IE or IE8+ where !DOCTYPE is not specified
                target.contentWindow.document
            )
            if (contentDocument) {
                target.style.height = `${contentDocument.body.scrollHeight}px`
            }
        } catch (error) {
            const expectedError = (
                `Blocked a frame with origin "${window.location.origin}" ` +
                `from accessing a cross-origin frame.`
            )
            if (error.message !== expectedError) {
                /* eslint-disable no-console */
                console.err(
                    `An error (${error.message}) ocurred while trying to check to see ` +
                    "if the inner iframe is accessible or not depending " +
                    "on the browser cross-origin policy"
                )
            }
        }
    }}
/>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.