uaktywnij wysokość ramki iframe na podstawie zawartości wewnątrz - JQUERY / Javascript

202

Ładuję stronę internetową aspx w ramce iframe. Zawartość w ramce iframe może mieć większą wysokość niż wysokość ramki iframe. Ramka iframe nie powinna mieć pasków przewijania.

Mam divtag otoki wewnątrz iframe, który w zasadzie jest całą zawartością. Napisałem jQuery, aby zmienić rozmiar:

$("#TB_window", window.parent.document).height($("body").height() + 50);

gdzie TB_windowjest div, w którym Iframejest zawarty.

body - znacznik body aspx w ramce iframe.

Ten skrypt jest dołączony do treści iframe. Otrzymuję TB_windowelement ze strony nadrzędnej. Chociaż działa to dobrze w Chrome, ale TB_window zwija się w Firefox. Jestem naprawdę zdezorientowany / zagubiony, dlaczego tak się dzieje.

karry
źródło
ta strona iframe .aspx pochodzi z tej samej nazwy domeny?
AlexC
czy możesz sprawdzić $ („body”). wysokość () ma wartość w firefoxie?
Michael L Watson,
tak .. iframe jest w tej samej domenie co strona kontenera
karry
@MichaelLWatson Wygląda na to, że okno zegarka firebug ma wartość wysokości 0 dla wysokości ciała ... Chrome ma jednak wartość
karry
Przykład kątowej
Eduardo Cuomo

Odpowiedzi:

211

Możesz pobrać wysokość IFRAMEzawartości, używając: contentWindow.document.body.scrollHeight

Po IFRAMEzaładowaniu można zmienić wysokość, wykonując następujące czynności:

<script type="text/javascript">
  function iframeLoaded() {
      var iFrameID = document.getElementById('idIframe');
      if(iFrameID) {
            // here you can make the height, I delete it first, then I make it again
            iFrameID.height = "";
            iFrameID.height = iFrameID.contentWindow.document.body.scrollHeight + "px";
      }   
  }
</script>   

Następnie na IFRAMEtagu podłączasz moduł obsługi w następujący sposób:

<iframe id="idIframe" onload="iframeLoaded()" ...

Jakiś czas temu miałem sytuację, w której dodatkowo musiałem zadzwonić iframeLoadedod IFRAMEsiebie po złożeniu formularza. Możesz to zrobić, wykonując następujące czynności w IFRAMEskryptach treści:

parent.iframeLoaded();
Arystos
źródło
152
Nie obsługuje w wielu domenach.
Soumya
3
@Soumya Cross domain nie ma nic wspólnego z tym kodem. Występuje problem bezpieczeństwa, który można obejść za pomocą polecenia.
Aristos
9
@Soumya Poszukaj, X-FRAME-OPTIONSaby dodać linię jako: Response.AddHeader("X-FRAME-OPTIONS", "SAMEORIGIN");lubresponse.addHeader("X-FRAME-OPTIONS", "Allow-From https://some.othersite.com");
Aristos
15
To rozwiązuje problem zmiany
David Bradshaw
2
@deebs Możesz także spróbować zmienić iFrameID.height = "";na iFrameID.height = "20px";. Domyślna wysokość ramki iframe w przeglądarce wynosi 150 pikseli, co ""powoduje jej przywrócenie.
philfreo
112

Nieco ulepszona odpowiedź dla Aristosa ...

<script type="text/javascript">
  function resizeIframe(iframe) {
    iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
  }
</script>  

Następnie zadeklaruj w swoim ramce iframe w następujący sposób:

<iframe onload="resizeIframe(this)" ...

Istnieją dwie niewielkie poprawki:

  1. Nie musisz pobierać elementu za pośrednictwem document.getElementById - ponieważ już go masz w wywołaniu zwrotnym onload.
  2. Nie ma potrzeby ustawiania, iframe.height = ""jeśli zamierzasz zmienić przypisanie w następnej instrukcji. Takie postępowanie wiąże się z dodatkowymi kosztami związanymi z elementem DOM.

Edycja: Jeśli zawartość ramki zawsze się zmienia, to wywołaj:

parent.resizeIframe(this.frameElement); 

z poziomu elementu iframe po aktualizacji. Działa dla tego samego pochodzenia.

Lub automatycznie wykryć:

  // on resize
  this.container = this.frameElement.contentWindow.document.body;

  this.watch = () => {
    cancelAnimationFrame(this.watcher);

    if (this.lastScrollHeight !== container.scrollHeight) {
      parent.resizeIframeToContentSize(this.frameElement);  
    }
    this.lastScrollHeight = container.scrollHeight;
    this.watcher = requestAnimationFrame(this.watch);
  };
  this.watcher = window.requestAnimationFrame(this.watch);
BlueFish
źródło
6
Co byś zrobił, gdyby zawartość ramki zawsze się zmieniała?
Kevin
Jeśli rozmiar zawartości ciągle się zmienia i / lub jeśli element iframe jest przeznaczony do umieszczania w domenach innych niż domena, z której element iframe pobiera stronę, musisz zrobić coś innego.
BlueFish
4
W tym celu ... rozwiązaniem jest użycie postMessage i receiveMessage. Rozwiązałem to za pomocą github.com/jeffomatic/nojquery-postmessage
BlueFish
Chodzi o to, aby obliczyć nową wysokość i wysłać wiadomość do ramki nadrzędnej, która musi ją odebrać, i odpowiednio dostosować wysokość ramki iframe.
BlueFish
Zawsze było dla mnie kilka pikseli, więc wymyśliłem to: function resizeIframe(iframe) { var size=iframe.contentWindow.document.body.scrollHeight; var size_new=size+20; iframe.height = size_new + "px"; }
Martin Mühl
56

Przekonałem się, że zaakceptowana odpowiedź nie była wystarczająca, ponieważ OPCJE X-FRAME: Allow-From nie jest obsługiwane w Safari ani Chrome . Zamiast tego zastosowano inne podejście, przedstawione w prezentacji Ben Vinegar z Disqus. Chodzi o to, aby dodać detektor zdarzeń do okna nadrzędnego, a następnie w elemencie iframe użyć window.postMessage, aby wysłać zdarzenie do elementu nadrzędnego z poleceniem, aby coś zrobił (zmiana rozmiaru elementu iframe).

Zatem w dokumencie nadrzędnym dodaj detektor zdarzeń:

window.addEventListener('message', function(e) {
  var $iframe = jQuery("#myIframe");
  var eventName = e.data[0];
  var data = e.data[1];
  switch(eventName) {
    case 'setHeight':
      $iframe.height(data);
      break;
  }
}, false);

Wewnątrz elementu iframe napisz funkcję, aby opublikować wiadomość:

function resize() {
  var height = document.getElementsByTagName("html")[0].scrollHeight;
  window.parent.postMessage(["setHeight", height], "*"); 
}

Na koniec wewnątrz elementu iframe dodaj tag onLoad do tagu body, aby uruchomić funkcję zmiany rozmiaru:

<body onLoad="resize();">
Marty Mulligan
źródło
1
Aby to zadziałało, musiałem zmienić „window.parent” na „rodzic”.
prograhammer,
Wspaniały! ale ładuje wysokość tylko raz. Jeśli chcesz, aby iframe naprawdę reagował, wolę wywoływać metodę zmiany rozmiaru co sekundę, w ten sposób:setInterval(resize, 1000);
Jules Colle
12

Dodaj to do iframe, to zadziałało dla mnie:

onload="this.height=this.contentWindow.document.body.scrollHeight;"

A jeśli używasz jQuery, wypróbuj ten kod:

onload="$(this).height($(this.contentWindow.document.body).find(\'div\').first().height());"
Mohit Aneja
źródło
6

Istnieją cztery różne właściwości, na które można spojrzeć, aby uzyskać wysokość zawartości w ramce iFrame.

document.documentElement.scrollHeight
document.documentElement.offsetHeight
document.body.scrollHeight
document.body.offsetHeight

Niestety wszyscy mogą udzielić różnych odpowiedzi, które są niespójne między przeglądarkami. Jeśli ustawisz margines ciała na 0, to document.body.offsetHeightdaje najlepszą odpowiedź. Aby uzyskać poprawną wartość, wypróbuj tę funkcję; który jest pobierany z biblioteki iframe-resizer, która również dba o utrzymanie iFrame właściwego rozmiaru przy zmianie zawartości lub zmianie rozmiaru przeglądarki.

function getIFrameHeight(){
    function getComputedBodyStyle(prop) {
        function getPixelValue(value) {
            var PIXEL = /^\d+(px)?$/i;

            if (PIXEL.test(value)) {
                return parseInt(value,base);
            }

            var 
                style = el.style.left,
                runtimeStyle = el.runtimeStyle.left;

            el.runtimeStyle.left = el.currentStyle.left;
            el.style.left = value || 0;
            value = el.style.pixelLeft;
            el.style.left = style;
            el.runtimeStyle.left = runtimeStyle;

            return value;
        }

        var 
            el = document.body,
            retVal = 0;

        if (document.defaultView && document.defaultView.getComputedStyle) {
            retVal =  document.defaultView.getComputedStyle(el, null)[prop];
        } else {//IE8 & below
            retVal =  getPixelValue(el.currentStyle[prop]);
        } 

        return parseInt(retVal,10);
    }

    return document.body.offsetHeight +
        getComputedBodyStyle('marginTop') +
        getComputedBodyStyle('marginBottom');
}
David Bradshaw
źródło
Nie działa to z elementami, które „zwijają”, np. Dane lub pływające div. Wysokość zależy od normalnej wysokości rozwiniętej, a nie od wysokości końcowej.
djack109
@ djack109 najprawdopodobniej coś w twoim CSS zatrzymuje element kurczący się na twojej stronie
David Bradshaw,
3

Inne odpowiedzi nie działały dla mnie, więc wprowadziłem pewne zmiany. Mam nadzieję, że to pomoże

$('#iframe').on("load", function() {
    var iframe = $(window.top.document).find("#iframe");
    iframe.height(iframe[0].ownerDocument.body.scrollHeight+'px' );
});
Ravi
źródło
2

Zamiast używać javscript / jquery najłatwiej znalazłem:

<iframe style="min-height:98vh" src="http://yourdomain.com" width="100%"></iframe>

Tutaj 1vh = 1% wysokości okna przeglądarki. Więc teoretyczna wartość wysokości, którą należy ustawić, to 100vh, ale praktycznie 98vh zrobiło magię.

Binod
źródło
9
Nie uwzględnia to wysokości treści elementu iframe.
Adrian Pauly,
Jest to wystarczająco blisko, gdy nie masz prostego sposobu obejścia dramatu między domenami ...
dsghi 18.09.19
2

Na wszelki wypadek pomaga to każdemu. Wyciągałem włosy, próbując sprawić, żeby to zadziałało, a potem zauważyłem, że iframe ma klasę o wysokości: 100%. Kiedy to usunąłem, wszystko działało zgodnie z oczekiwaniami. Więc sprawdź, czy nie ma żadnych konfliktów css.

użytkownik8640976
źródło
2

możesz również dodać powtarzające się żądanieAnimationFrame do ramki resizeIframe (np. z odpowiedzi @ BlueFish), które zawsze będzie wywoływane, zanim przeglądarka maluje układ, i możesz zaktualizować wysokość ramki iframe, gdy jej zawartość zmieni wysokość. np. formularze wejściowe, leniwie ładowana treść itp.

<script type="text/javascript">
  function resizeIframe(iframe) {
    iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
    window.requestAnimationFrame(() => resizeIframe(iframe));
  }
</script>  

<iframe onload="resizeIframe(this)" ...

oddzwanianie powinno być wystarczająco szybkie, aby nie miało większego wpływu na ogólną wydajność

użytkownik2520818
źródło
1
jest to bardzo sprytne rozwiązanie, które od wstępnych testów działa bardzo dobrze. Byłbym zainteresowany implikacjami związanymi z wydajnością korzystania z tego.
KFE
Właśnie natknąłem się na skrzynkę, Uncaught TypeError: Cannot read property 'scrollHeight' of nullponieważ bodyjest null, jednak zwykle działa.
caot
1

Możesz odnieść się do pokrewnego pytania tutaj - Jak sprawić, aby szerokość i wysokość elementu iframe była taka sama jak elementu div rodzica?

Aby ustawić dynamiczną wysokość -

  1. Musimy komunikować się z ramkami iFrames między domenami i nadrzędnymi
  2. Następnie możemy wysłać wysokość przewijania / wysokość zawartości elementu iframe do okna nadrzędnego

I kody - https://gist.github.com/mohandere/a2e67971858ee2c3999d62e3843889a8

Mohan Dere
źródło
1

Korzystam z jQuery i poniższy kod działa dla mnie,

var iframe = $(window.top.document).find("#iframe_id_here");
iframe.height(iframe.contents().height()+'px' );
śrijiszki
źródło
0

Odkryłem, że odpowiedź Troya nie zadziałała. To jest ten sam kod przerobiony dla ajax:

$.ajax({                                      
    url: 'data.php',    
    dataType: 'json',                             

    success: function(data)
    {
        // Put the data onto the page

        // Resize the iframe
        var iframe = $(window.top.document).find("#iframe");
        iframe.height( iframe[0].contentDocument.body.scrollHeight+'px' );
    }
});
Martin Lester
źródło
0

Aby dodać do części okna, która wydaje się odcinać na dole, szczególnie gdy nie masz przewijania, użyłem:

function resizeIframe(iframe) {
    var addHeight = 20; //or whatever size is being cut off
    iframe.height = iframe.contentWindow.document.body.scrollHeight + addHeight + "px";
  }
Matt Stacey
źródło
0

Ten przydaje się, gdy potrzebujesz rozwiązania bez jquery. W takim przypadku powinieneś spróbować dodać pojemnik i ustawić wypełnienie w procentach

Przykładowy kod HTML:

<div class="iframecontainer">
    <iframe scrolling="no" src="..." class="iframeclass"width="999px" height="618px"></iframe>
</div>

Przykładowy kod CSS:

.iframeclass{
    position: absolute;
    top: 0;
    width: 100%;
}

.iframecontainer{
    position: relative;
    width: 100%;
    height: auto;
    padding-top: 61%;
}
Juan M.
źródło
0

Prostym rozwiązaniem jest zmierzenie szerokości i wysokości obszaru zawartości, a następnie użycie tych pomiarów do obliczenia procentu dolnego wypełnienia.

W tym przypadku wymiary wynoszą 1680 x 720 pikseli, więc wypełnienie na dole to 720/1680 = 0,43 * 100, co stanowi 43%.

.canvas-container {    
    position: relative;
    padding-bottom: 43%; // (720 ÷ 1680 = 0.4286 = 43%)
    height: 0;
    overflow: hidden;   
}

.canvas-container iframe {    
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;   
}
loek
źródło
0

Nieco ulepszona odpowiedź na BlueFish ...

function resizeIframe(iframe) {
    var padding = 50;
    if (iframe.contentWindow.document.body.scrollHeight < (window.innerHeight - padding))
        iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
    else
        iframe.height = (window.innerHeight - padding) + "px";
}

Bierze to pod uwagę wysokość ekranu systemu Windows (przeglądarki, telefonu), co jest dobre dla responsywnego projektu i ramek iframe o dużej wysokości. Wypełnienie reprezentuje dopełnienie, które chcesz powyżej i poniżej ramki iframe w przypadku, gdy przechodzi przez cały ekran.

Tadej Vengust
źródło
0
jQuery('.home_vidio_img1 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery(this).replaceWith(video);
});

jQuery('.home_vidio_img2 img').click(function(){
    video = <iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>;
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});

jQuery('.home_vidio_img3 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});

jQuery('.home_vidio_img4 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});
Keyur Savsani
źródło
0

Przykład za pomocą PHP htmlspecialchars () + sprawdź, czy wysokość istnieje i wynosi> 0:

$my_html_markup = ''; // Insert here HTML markup with CSS, JS... '<html><head></head><body>...</body></html>'
$iframe = '<iframe onload="if(this.contentWindow.document.body.scrollHeight) {this.height = this.contentWindow.document.body.scrollHeight;}" width="100%" src="javascript: \''. htmlspecialchars($my_html_markup) . '\'"></iframe>';
jteks
źródło
0

po prostu ustaw pozycję kontenera iframe: wartość bezwzględna, a iframe automatycznie zmieni wysokość zgodnie z zawartością

<style>
   .iframe-container {
       display: block;
       position: absolute;
       /*change position as you need*/
       bottom: 0;
       left: 0;
       right: 0;
       top: 0;
   }
   iframe {
       margin: 0;
       padding: 0;
       border: 0;
       width: 100%;
       background-color: #fff;
   }
 </style>
 <div class="iframe-container">
     <iframe src="http://iframesourcepage"></iframe>
 </div>
Hatem Badawi
źródło
-1
$(document).height() // - $('body').offset().top

i / lub

$(window).height()

Zobacz pytanie Przepełnienie stosu Jak uzyskać wysokość elementu nadwozia .

Spróbuj tego, aby znaleźć wysokość ciała w jQuery:

if $("body").height()

Nie ma wartości, jeśli Firebug . Być może to jest problem.

Michael L. Watson
źródło
Próbowałem zrobić obie rzeczy ... to wciąż dzieje się w przeglądarce Firefox. firefox jakoś nie dostaje window.height () w ramce iframe. Jak wspomniałem, skrypt jest dołączony do zawartości iframe i
wywołuję