jquery ottiene l'altezza del contenuto dell'iframe quando viene caricato


85

Ho una pagina di aiuto, help.php che sto caricando all'interno di un iframe in main.php Come posso ottenere l'altezza di questa pagina una volta caricata nell'iframe?

Lo chiedo perché non riesco a definire lo stile dell'altezza di iframe su 100% o automatico. Ecco perché penso di aver bisogno di usare javascript .. Sto usando jQuery

CSS:

body {
    margin: 0;
    padding: 0;
}
.container {
    width: 900px;
    height: 100%;
    margin: 0 auto;
    background: silver;
}
.help-div {
    display: none;
    width: 850px;
    height: 100%;
    position: absolute;
    top: 100px;
    background: orange;
}
#help-frame {
    width: 100%;
    height: auto;
    margin:0;
    padding:0;
}

JS:

$(document).ready(function () {
    $("a.open-help").click(function () {
        $(".help-div").show();
        return false;
    })
})

HTML:

<div class='container'>
    <!-- -->
    <div class='help-div'>
        <p>This is a div with an iframe loading the help page</p>
        <iframe id="help-frame" src="../help.php" width="100%" height="100%" frameborder="1"></iframe>
    </div>  <a class="open-help" href="#">open Help in iFrame</a>

    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
</div>

Il contenuto dell'iFrame proviene dallo stesso dominio della pagina in cui si trova?
Andrew

sì, è andrew, voglio usare un iFrame perché uso gli ancoraggi nella pagina di aiuto
FFish

Risposte:


102

ok finalmente ho trovato una buona soluzione:

$('iframe').load(function() {
    this.style.height =
    this.contentWindow.document.body.offsetHeight + 'px';
});

Poiché alcuni browser (i vecchi Safari e Opera) segnalano che il caricamento è stato completato prima del rendering CSS, è necessario impostare un micro Timeout, cancellare e riassegnare l'src dell'iframe.

$('iframe').load(function() {
    setTimeout(iResize, 50);
    // Safari and Opera need a kick-start.
    var iSource = document.getElementById('your-iframe-id').src;
    document.getElementById('your-iframe-id').src = '';
    document.getElementById('your-iframe-id').src = iSource;
});
function iResize() {
    document.getElementById('your-iframe-id').style.height = 
    document.getElementById('your-iframe-id').contentWindow.document.body.offsetHeight + 'px';
}

questa soluzione funziona alla grande in quanto quanto sopra ottiene solo la dimensione dall'iframe contenuto all'interno del contenitore mentre questa ottiene la realdimensione
rickyduck

2
Credo che l'evento di caricamento si inneschi sullo stesso ciclo di eventi, quindi un setTimout di 1 millisecondo funzionerà altrettanto bene
George Mauer

hhmmm Chiunque sa come ottenere l'altezza di un iframe nascosto al momento del caricamento del genitore. Questo metodo riporta 0.
JT ...

1
Potresti volere l' documentaltezza, non l' bodyaltezza. Usando jQuery puoi prenderlo con $(this.contentWindow.document).height().
vpiTriumph

Ad esempio, iframe.contentDocument.body.offsetHeight funzionerà. stackoverflow.com/questions/2684693/...
user1087079

50

La risposta meno complicata è usare .contents()per arrivare all'iframe. È interessante notare, tuttavia, che restituisce un valore diverso da quello che ottengo usando il codice nella mia risposta originale, a causa dell'imbottitura sul corpo, credo.

$('iframe').contents().height() + 'is the height'

È così che ho fatto per la comunicazione tra domini, quindi temo che sia forse inutilmente complicato. Per prima cosa, metterei jQuery nel documento dell'iFrame; questo consumerà più memoria, ma non dovrebbe aumentare il tempo di caricamento poiché lo script deve essere caricato solo una volta.

Usa jQuery di iFrame per misurare l'altezza del corpo del tuo iframe il prima possibile (onDOMReady) e quindi imposta l'hash dell'URL a quell'altezza. E nel documento principale, aggiungi un onloadevento al tag iFrame che esaminerà la posizione dell'iframe ed estrarrà il valore di cui hai bisogno. Poiché onDOMReady si verificherà sempre prima dell'evento di caricamento del documento, puoi essere abbastanza certo che il valore verrà comunicato correttamente senza che una race condition complichi le cose.

In altre parole:

... in Help.php:

var getDocumentHeight = function() {
    if (location.hash === '') { // EDIT: this should prevent the retriggering of onDOMReady
        location.hash = $('body').height(); 
        // at this point the document address will be something like help.php#1552
    }
};
$(getDocumentHeight);

... e nel documento genitore:

var getIFrameHeight = function() {
    var iFrame = $('iframe')[0]; // this will return the DOM element
    var strHash = iFrame.contentDocument.location.hash;
    alert(strHash); // will return something like '#1552'
};
$('iframe').bind('load', getIFrameHeight );

Ciao Andrew, finora un ottimo aiuto qui. content () funziona alla grande, ma ho ancora bisogno di testarlo con un limitatore di larghezza di banda. Forse puoi usare la proprietà innerHeight (). Ho un problema in FF (OSX) usando la tua soluzione mettendo l'altezza nell'hash. FF sembra continuare a caricare la funzione getDocumentHeight () in un ciclo infinito? Safari va bene ..
FFish

Interessante. Ho aggiunto un controllo che impedisce l'impostazione dell'hash se c'è già un valore lì. Potrebbe essere necessario modificare questo se stai caricando Help.php con un valore hash (ad esempio <iframe src="../Help.php#introduction" />)
Andrew

A proposito, supponendo che tu possa regolare la differenza di altezza, probabilmente non è necessario utilizzare l'hash per comunicare fuori dall'iframe. Se usi il metodo hash, anche inserire un file sleep(5)Help.php dovrebbe essere un buon modo per testare qualsiasi condizione di gara. Se l'iframe si attiva in qualche modo onLoadprima onDOMReady, dovrebbe essere visualizzato qui.
Andrew

24

Ho riscontrato che quanto segue funziona su Chrome, Firefox e IE11:

$('iframe').load(function () {
    $('iframe').height($('iframe').contents().height());
});

Al termine del caricamento del contenuto degli iframe, l'evento si attiverà e imposterà l'altezza degli iframe su quella del suo contenuto. Funzionerà solo per le pagine all'interno dello stesso dominio di quello dell'IFrame.


funziona bene ma per la larghezza devo farlo in questo modo o il contenuto viene tagliato $ ('iframe'). width ($ ('iframe'). contents (). width () + 30);
Geomorillo

@AminGhaderi Funziona bene per me in Firefox 40.0.3
mixkat

@mixkat carico un sito Web in iframe tramite questa soluzione e tutte le soluzioni in questo argomento ma per me non funzionano! Penso che queste soluzioni funzionino per una pagina e non funzionino quando carichiamo un sito web completo nell'iframe. il mio inglese è pessimo, spero che capirai.
Amin Ghaderi

@AminGhaderi, se ho capito bene, ti aspetti che funzioni per ogni pagina del tuo sito, ma ovviamente non funzionerà per tutte le pagine poiché viene eseguito solo una volta quando carichi il frame. Quindi funzionerà bene per la prima pagina ma poi se vuoi che funzioni per pagine più lunghe dovrai farlo di nuovo caricando di nuovo il frame con la nuova pagina o chiamando il contenuto.height in qualche altro punto in il tuo flusso
mixkat

9

Il codice per farlo senza jQuery è banale al giorno d'oggi:

const frame = document.querySelector('iframe')
function syncHeight() {
  this.style.height = `${this.contentWindow.document.body.offsetHeight}px`
}
frame.addEventListener('load', syncHeight)

Per sganciare l'evento:

frame.removeEventListener('load', syncHeight)

3
Bello e semplice! Purtroppo non funziona per iframe interdominio :(
TimoSolo

3
Sì, per fortuna lì. Sfrutterei la libreria iframe-resizer per questo. Ovviamente è necessario avere il controllo di entrambi i domini affinché funzioni.
cchamberlain

6

Non hai bisogno di jquery all'interno dell'iframe per farlo, ma lo uso perché il codice è molto più semplice ...

Inseriscilo nel documento all'interno del tuo iframe.

$(document).ready(function() {
  parent.set_size(this.body.offsetHeight + 5 + "px");  
});

aggiunti cinque sopra per eliminare la barra di scorrimento su finestre piccole, non è mai perfetto per le dimensioni.

E questo nel documento del tuo genitore.

function set_size(ht)
{
$("#iframeId").css('height',ht);
}

Anche questo non funzionerà se stai visualizzando un PDF all'interno dell'iframe.
Jason Foglia

Siamo spiacenti ma il tuo esempio "all'interno del frame" è chiaramente basato su jQuery.
T-moty

4

questa è la risposta corretta che ha funzionato per me

$(document).ready(function () {
        function resizeIframe() {
            if ($('iframe').contents().find('html').height() > 100) {
                $('iframe').height(($('iframe').contents().find('html').height()) + 'px')
            } else {
                setTimeout(function (e) {
                    resizeIframe();
                }, 50);
            }
        }
        resizeIframe();
    });

4

la riga semplice inizia con un'altezza minima predefinita e aumenta fino alla dimensione del contenuto.

<iframe src="http://url.html" onload='javascript:(function(o){o.style.height=o.contentWindow.document.body.scrollHeight+"px";}(this));' style="height:200px;width:100%;border:none;overflow:hidden;"></iframe>



1

Questa è una soluzione gratuita jQuery che può funzionare con SPA all'interno dell'iframe

document.getElementById('iframe-id').addEventListener('load', function () {
  let that = this;
  setTimeout(function () {
    that.style.height = that.contentWindow.document.body.offsetHeight + 'px';
  }, 2000) // if you're having SPA framework (angularjs for example) inside the iframe, some delay is needed for the content to populate
});

1

Questa è la mia versione amichevole di ES6 no-jquery

document.querySelector('iframe').addEventListener('load', function() {
    const iframeBody = this.contentWindow.document.body;
    const height = Math.max(iframeBody.scrollHeight, iframeBody.offsetHeight);
    this.style.height = `${height}px`;
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.