Çalışan bir alanlar arası iframe yüksekliği otomatik yeniden boyutlandırıcısı var mı?


110

Birkaç çözüm denedim ama başarılı olamadım. Tercihen takip etmesi kolay bir öğretici ile orada bir çözüm olup olmadığını merak ediyorum.


2
Başarısız olan hangi çözümleri denediniz?
Yzmir Ramirez

1
Bunu denedim ancak makalede belirtildiği gibi webkit tarayıcılarında çıldırdı : css-tricks.com/cross-domain-iframe-resizing Bir tane daha vardı ama url'yi hatırlayamıyorum.
J82


Yanıtlar:


68

Üç seçeneğiniz var:

1. iFrame-resizer kullanın

Bu, iFrame'leri içeriklerine göre boyutlandırmak için basit bir kitaplıktır. IE8-10 için geri dönüşler ile PostMessage ve MutationObserver API'lerini kullanır. Ayrıca içerik sayfasının iFrame'in belirli bir boyutta olmasını isteme seçenekleri de vardır ve işiniz bittiğinde iFrame'i kapatabilir.

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

2. Easy XDM (PostMessage + Flash combo) kullanın

Easy XDM, bir dizi tarayıcıda farklı pencereler arasında etki alanları arası iletişimi etkinleştirmek için bir dizi püf noktası kullanır ve bunu iframe yeniden boyutlandırma için kullanma örnekleri vardır:

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 , modern tarayıcılarda PostMessage'ı ve eski tarayıcılar için yedek olarak Flash tabanlı bir çözümü kullanarak çalışır .

Stackoverflow'daki bu konuya da bakın (başkaları da var, bu yaygın olarak sorulan bir sorudur). Ayrıca, Facebook da benzer bir yaklaşım kullanıyor gibi görünüyor .

3. Bir sunucu aracılığıyla iletişim kurun

Diğer bir seçenek, iframe yüksekliğini sunucunuza göndermek ve ardından bu sunucudan JSONP ile ana web sayfasından anket yapmaktır (veya mümkünse uzun bir anket kullanmaktır).


1
PostMessage için, zaten jQuery kullanıyorsanız, Ben Alman'ın
rinogo

8
iFrame-resizer'ın iframe içeriğini barındıran sunucuya erişmesi gerekir. Yani onu yalnızca kontrol ettiğiniz alanlar için kullanabilirsiniz.
Hokascha

İyi yakaladın @Hokascha. Proje, etki alanları arası iframe'ler için destek talep ediyor, ancak belgeleri okunduğunda, yine de gömülü etki alanına sunucu erişimi gerektirdiği ortaya çıkıyor.
StockB

1
Yok , bu "alternatifler" nin bu soruna yönelik fiili çözümleridir. Soru soran kişi, üzerinde denetim sahibi olmadıkları web sitelerinden etki alanları arası iFrame'lerin iFrame yüksekliğini ayarlamak istiyor. 1. Sunucu erişimi gerektirir. 2. Zayıf olduğunu düşündüğüm yazılım gerektirir. Easy XDM 10 yıl önce yapıldı. 2019'dan itibaren en son sürüm, flash gerektirir . Flash, neyse ki öldü ve kimse ona güvenmemeli. 3. Sunucu erişimi gerektirir.
redanimalwar

26

İç çerçevenin yüksekliğini içeriğine göre dinamik olarak ayarlamak için bir çözüm buldum. Bu, etki alanları arası içerik için işe yarar. Bunu başarmak için izlenecek bazı adımlar var.

  1. "Abc.com/page" web sayfasına iframe eklediğinizi varsayalım

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

  2. Daha sonra, "abc.com/page" web sayfası altındaki pencereler "mesaj" olayını bağlamanız gerekir

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);        
    }
});

İframe yüklemesinde, iframe pencere içeriğine "FrameHeight" mesajıyla mesaj göndermeniz gerekir:

function setIframeHeight(ifrm) {
   var height = ifrm.contentWindow.postMessage("FrameHeight", "*");   
}
  1. Burada iframe altına eklenen ana sayfada "xyz.pqr / contactpage", tüm mesajların "abc.com/page" ana penceresinden alınacağı pencereler "mesaj" olayını bağlamanız gerekir
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
Sorunsuz çalışır. Çok teşekkürler!
Alex Leonov

basitçe bu bulabildiğim en teknik yöntem, harika iş @sudhir, Teşekkürler :)
java acm

14

Yaptığım şey, IFrame Yüksekliğini artımlı olarak ayarlarken boyutu değişene kadar iframe kaydırma genişliğini karşılaştırmaktı. Ve benim için iyi çalıştı. Artışı istediğiniz şekilde ayarlayabilirsiniz.

   <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
Muhtemelen döngülerin sayısına bir sınır eklemek istersiniz, aksi takdirde 'while' sonsuz bir döngüye dönüşebilir.
Kevin Seifert

1
Bu sayfamı çökertiyor.
DDDD

İyi, basit bir çözüm. Ama benim çekimlerimde, boyut artışı ekran boyutuyla sınırlıdır.
Zeta

1

İçeriğiyle iframe'e düşen bir komut dosyam var. Ayrıca, iFrameResizer'ın var olduğundan emin olur (onu bir komut dosyası olarak enjekte eder) ve ardından yeniden boyutlandırmayı yapar.

Aşağıda basitleştirilmiş bir örnek vereceğim.

// /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();
    }    
}())

Daha sonra iframe içeriği, komut dosyası kullanılarak başka bir sayfa / site içinde herhangi bir yere enjekte edilebilir:

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

İframe içeriği, komut dosyası etiketini yerleştirdiğiniz yere aşağıya enjekte edilecektir.

Umarım bu birine yardımcı olur. 👍


Güzel, <script ... data-src="http://google.com">iframe src'yi ekledim ve bununla doldurdum.
BananaAcid

Şu anki sürüm şu iframe-resizer@4.2.10
şekildedir:

1
... tam kullanılabilir bir örnek kodlarına
BananaAcid

@BananaAcid - kodlarınız ve alanınız artık çalışmıyor
ctrlplusb

bahsettiğiniz için teşekkürler, bağlantılar oldu: codesandbox.io/s/remote-embed-ifrm-yz0xl . (not: kodlar ve kutu birden fazla sayfa kullanarak "sahtedir" ve askıda kalabilir. Yeniden yüklemek işe yarayabilir)
BananaAcid

1

İşte bu sayfadaki basit çözümüm. http://lab.ohshiftlabs.com/iframesize/

İşte nasıl çalıştığı;

görüntü açıklamasını buraya girin

Temel olarak, sayfayı başka bir etki alanında düzenleyebiliyorsanız, sunucunuza ait olan ve çerezlere yükseklik kazandıran başka bir iframe sayfası yerleştirebilirsiniz. Çerezleri güncellendiğinde bir aralık okuma ile, iframe'in yüksekliğini güncelleyin. Hepsi bu.

İndir; http://lab.ohshiftlabs.com/iframesize/iframesizepost.zip

Düzenleme: 2019 Aralık

Yukarıdaki çözüm, temelde bir iframe'in içindeki başka bir iframe'i kullanır 3. iframe, bu sayfayı bir çereze boyut değerini kaydeden bir sorgu dizesiyle çağırdığınız sayfanın üst kısmına aittir, dış sayfa bu sorguyu belirli aralıklarla kontrol eder. Ancak bu iyi bir çözüm değil, bu yüzden şunu takip etmelisiniz:

Üst sayfada:

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

Buradan m.originnereden geldiğini kontrol edebilirsiniz .

Çerçeve sayfasında:

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

Yine de, lütfen bunun o kadar güvenli olmadığını unutmayın. Güncelleme * değerini (targetOrigin) istediğiniz değerle güvenli hale getirmek için. Lütfen belgeleri takip edin : https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage


1
Bu bağlantılar artık ölü (404) ve içerik yanıtta özetlenmiyor. :(
StockB

1
bağlantılar hala ölü. 404
Arslan Ameer

0

Bir iframe boyutunu elde etmek için PHP kullanan web geliştirici için başka bir sunucu tarafı çözümü buldum.

Birincisi, PHP sunucu betiğini dahili işlev aracılığıyla harici bir çağrıya kullanmaktır: ( file_get_contentswith but curl ve dom gibi).

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>

Div ( iframe_reserve) altında fonksiyon çağrısı tarafından oluşturulan html'yi basit birecho curl_get_file_contents("location url iframe","activation proxy")

Bunu yaptıktan sonra, javascript ile bir body event function onload, sadece div ( iframe_reserve) içeriğinin basit bir kontrolü ile sayfanın iframe yüksekliğini alır.

Bu yüzden kullandım divHeight = document.getElementById("iframe_reserve").clientHeight; div container ( iframe_reserve) maskesini aldıktan sonra arayacağımız dış sayfanın yüksekliğini alıyordum . Bundan sonra, iframe'i iyi yüksekliğiyle yüklüyoruz, hepsi bu.


0

İşte bir şey üzerinde çalışırken (React kullanarak) bu sorunla karşılaştım. Temel olarak, veritabanındaki belge tablomuza kaydettiğimiz ve ardından Belgeler veri kümesindeyken belirli koşullar altında sayfaya eklediğimiz bazı harici html içeriğine sahibiz.

Bu nedenle, dış html içerebilecek satır içi nsatırlar göz önüne alındığında n, içerik her birine tam olarak yüklendiğinde her satır içi iframe'i otomatik olarak yeniden boyutlandırmak için bir sistem tasarlamamız gerekiyordu. Tekerleklerimi bir süre döndürdükten sonra, bunu böyle yaptım:

  1. messageReact uygulamamızın dizininde, gönderici iframe'inden ayarlayacağımız belirli bir anahtarı kontrol eden bir olay dinleyicisi ayarlayın .
  2. Iframe'leri gerçekten oluşturan bileşende, dış html'yi içine ekledikten sonra, iframe'lerin tetiklenmesini <script>bekleyecek bir etiket ekliyorum window.onload. Bu tetiklendiğinde, postMessageüst pencereye iframe kimliği, hesaplanan yükseklik vb. Hakkında bilgi içeren bir mesaj göndermek için kullanırız .
  3. Kaynak eşleşirse ve anahtar dizin dinleyicide karşılanırsa id, MessageEventnesnede ilettiğimiz iframe'in DOM'unu alın
  4. Sahip olduktan sonra iframe, yüksekliği iframe'den aktarılan değerden ayarlayın 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"
                )
            }
        }
    }}
/>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.