Ridimensionamento di un iframe basato sul contenuto

Sto lavorando a un’applicazione simile a iGoogle. Il contenuto di altre applicazioni (su altri domini) viene mostrato usando iframe.

Come ridimensiono gli iframe per adattarli all’altezza del contenuto degli iframe?

Ho provato a decifrare il javascript di Google, ma è stato offuscato e la ricerca sul Web è stata finora infruttuosa.

Aggiornamento: si prega di notare che il contenuto è caricato da altri domini, quindi si applica la politica dell’origine stessa .

Avevamo questo tipo di problema, ma leggermente al contrario della tua situazione: stavamo fornendo il contenuto iframed ai siti su altri domini, quindi anche la stessa politica di origine era un problema. Dopo molte ore trascorse a navigare su google, alla fine abbiamo trovato una soluzione (alquanto ..) praticabile, che potresti essere in grado di adattare alle tue esigenze.

C’è un modo per aggirare lo stesso criterio di origine, ma richiede modifiche sia sul contenuto ifram che sulla pagina di framing, quindi se non hai la possibilità di richiedere modifiche su entrambi i lati, questo metodo non ti sarà molto utile, Ho paura.

C’è una stranezza del browser che ci consente di ignorare la stessa politica di origine: javascript può comunicare sia con pagine del proprio dominio, sia con pagine con iframed, ma mai pagine in cui è incorniciato, ad esempio se si dispone di:

www.foo.com/home.html, which iframes |-> www.bar.net/framed.html, which iframes |-> www.foo.com/helper.html 

quindi home.html può comunicare con framed.html (iframed) e helper.html (stesso dominio).

  Communication options for each page: +-------------------------+-----------+-------------+-------------+ | | home.html | framed.html | helper.html | +-------------------------+-----------+-------------+-------------+ | www.foo.com/home.html | N/A | YES | YES | | www.bar.net/framed.html | NO | N/A | YES | | www.foo.com/helper.html | YES | YES | N/A | +-------------------------+-----------+-------------+-------------+ 

framed.html può inviare messaggi a helper.html (iframed) ma non a home.html (il bambino non può comunicare tra domini con il genitore).

La chiave qui è che helper.html può ricevere messaggi da framed.html e può anche comunicare con home.html .

Quindi, essenzialmente, quando framed.html caricato framed.html , framed.html la sua altezza, dice helper.html , che passa il messaggio a home.html , che può quindi ridimensionare l’iframe in cui framed.html trova framed.html .

Il modo più semplice con cui abbiamo trovato di passare i messaggi da framed.html a helper.html era attraverso un argomento URL. Per fare ciò, framed.html ha un iframe con src='' specificato. Quando il suo onload si onload , valuta la propria altezza e imposta la src dell’iframe a questo punto su helper.html?height=N

C’è una spiegazione qui su come gestirlo da Facebook, che potrebbe essere leggermente più chiaro del mio!


Codice

In www.foo.com/home.html , è richiesto il seguente codice javascript (che può essere caricato da un file .js su qualsiasi dominio, tra l’altro ..):

   

In www.bar.net/framed.html :

    

Contenuto di www.foo.com/helper.html :

       

Se non hai bisogno di gestire i contenuti iframe da un dominio diverso, prova questo codice, risolverà il problema completamente ed è semplice:

   

https://developer.mozilla.org/en/DOM/window.postMessage

window.postMessage ()

window.postMessage è un metodo per abilitare in sicurezza la comunicazione tra origini. Normalmente, gli script su pagine diverse possono accedere l’un l’altro solo se e solo se le pagine che li hanno eseguiti si trovano in posizioni con lo stesso protocollo (di solito entrambi http), numero di porta (80 è l’impostazione predefinita per http) e host (modulo document.domain viene impostato da entrambe le pagine sullo stesso valore). window.postMessage fornisce un meccanismo controllato per aggirare questa restrizione in un modo che è sicuro se usato correttamente.

Sommario

window.postMessage, quando chiamato, fa sì che un MessageEvent venga inviato alla finestra di destinazione quando viene completato uno script in sospeso che deve essere eseguito (ad esempio rimanenti gestori di eventi se viene chiamato window.postMessage da un gestore eventi, timeout in sospeso precedentemente impostati, ecc. ). MessageEvent ha il tipo message, una proprietà data che è impostata sul valore stringa del primo argomento fornito a window.postMessage, una proprietà di origine corrispondente all’origine del documento principale nella finestra che chiama window.postMessage nella finestra temporale. è stato chiamato postMessage e una proprietà di origine che è la finestra da cui viene chiamato window.postMessage. (Altre proprietà standard degli eventi sono presenti con i loro valori previsti).

La libreria iFrame-Resizer utilizza postMessage per mantenere un iFrame dimensionato per il suo contenuto, insieme a MutationObserver per rilevare le modifiche al contenuto e non dipende da jQuery.

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

jQuery: qualità di scripting cross-domain

http://benalman.com/projects/jquery-postmessage-plugin/

Ha una demo di ridimensionamento della finestra iframe …

http://benalman.com/code/projects/jquery-postmessage/examples/iframe/

Questo articolo mostra come rimuovere la dipendenza da jQuery … Inoltre ha molte informazioni utili e collegamenti ad altre soluzioni.

http://www.onlineaspect.com/2010/01/15/backwards-compatible-postmessage/

Esempio di Barebones …

http://onlineaspect.com/uploads/postmessage/parent.html

HTML 5 bozza di lavoro su window.postMessage

http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages

John Resig su Cross-Window Messaging

http://ejohn.org/blog/cross-window-messaging/

Il modo più semplice con jQuery:

 $("iframe") .attr({"scrolling": "no", "src":"http://www.someotherlink.com/"}) .load(function() { $(this).css("height", $(this).contents().height() + "px"); }); 

La soluzione su http://www.phinesolutions.com/use-jquery-to-adjust-the-iframe-height.html funziona alla grande (usa jQuery):

  

Non so che è necessario aggiungere 30 alla lunghezza … 1 ha funzionato per me.

A proposito : se hai già un attributo “altezza” sul tuo iFrame, questo aggiunge semplicemente style = “height: xxx”. Questo potrebbe non essere quello che vuoi.

potrebbe essere un po ‘tardi, visto che tutte le altre risposte sono più vecchie 🙂 ma … ecco la mia soluzione. Testato in FF, Chrome e Safari 5.0.

css:

 iframe {border:0; overflow:hidden;} 

javascript:

 $(document).ready(function(){ $("iframe").load( function () { var c = (this.contentWindow || this.contentDocument); if (c.document) d = c.document; var ih = $(d).outerHeight(); var iw = $(d).outerWidth(); $(this).css({ height: ih, width: iw }); }); }); 

Spero che questo possa aiutare chiunque.

Ecco una soluzione semplice che utilizza un foglio di stile generato dynamicmente servito dallo stesso server del contenuto iframe. Molto semplicemente il foglio di stile “sa” cosa c’è nell’iframe e conosce le dimensioni da usare per disegnare l’iframe. Questo aggira le stesse restrizioni sulle politiche di origine.

http://www.8degrees.co.nz/2010/06/09/dynamically-resize-an-iframe-depending-on-its-content/

Quindi il codice iframe fornito avrebbe un foglio di stile di accompagnamento come quello …

Ciò richiede che la logica lato server sia in grado di calcolare le dimensioni del contenuto reso dell’iframe.

Finalmente ho trovato qualche altra soluzione per l’invio di dati al sito web principale da iframe usando window.postMessage(message, targetOrigin); . Qui spiego come ho fatto.

Sito A = http://foo.com Sito B = http://bar.com

Il sito B sta caricando all’interno del sito web

Il sito Web SiteB ha questa linea

 window.parent.postMessage("Hello From IFrame", "*"); 

o

 window.parent.postMessage("Hello From IFrame", "http://foo.com"); 

Quindi sitoA avere questo seguente codice

 // Here "addEventListener" is for standards-compliant web browsers and "attachEvent" is for IE Browsers. var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; var eventer = window[eventMethod]; var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message"; // Listen to message from child IFrame window eventer(messageEvent, function (e) { alert(e.data); // Do whatever you want to do with the data got from IFrame in Parent form. }, false); 

Se si desidera aggiungere una connessione di sicurezza, è ansible utilizzare questa condizione if in eventer(messageEvent, function (e) {})

 if (e.origin == 'http://iframe.example.com') { alert(e.data); // Do whatever you want to do with the data got from IFrame in Parent form. } 

Per IE

All’interno di IFrame:

  window.parent.postMessage('{"key":"value"}','*'); 

Al di fuori:

  eventer(messageEvent, function (e) { var data = jQuery.parseJSON(e.data); doSomething(data.key); }, false); 

Questa risposta è valida solo per i siti Web che utilizzano Bootstrap. La funzionalità di incorporamento reattivo di Bootstrap fa il lavoro. È basato sulla larghezza (non sull’altezza) del contenuto.

  

jsfiddle: http://jsfiddle.net/00qggsjj/2/

http://getbootstrap.com/components/#responsive-embed

Sto implementando la soluzione frame-in-frame di ConroyP per sostituire una soluzione basata sull’impostazione di document.domain, ma trovo che sia piuttosto difficile determinare correttamente l’altezza del contenuto dell’iframe in diversi browser (testando con FF11, Ch17 e IE9 in questo momento ).

ConroyP utilizza:

 var height = document.body.scrollHeight; 

Ma questo funziona solo sul caricamento iniziale della pagina. La mia iframe ha contenuti dinamici e ho bisogno di ridimensionare l’iframe su determinati eventi.

Quello che ho finito è stato usare diverse proprietà JS per i diversi browser.

 function getDim () { var body = document.body, html = document.documentElement; var bc = body.clientHeight; var bo = body.offsetHeight; var bs = body.scrollHeight; var hc = html.clientHeight; var ho = html.offsetHeight; var hs = html.scrollHeight; var h = Math.max(bc, bo, bs, hc, hs, ho); var bd = getBrowserData(); // Select height property to use depending on browser if (bd.isGecko) { // FF 11 h = hc; } else if (bd.isChrome) { // CH 17 h = hc; } else if (bd.isIE) { // IE 9 h = bs; } return h; } 

getBrowserData () è la funzione di rilevamento del browser “ispirata” da http://docs.sencha.com/core/source/Ext.html#method-Ext-apply di Ext Core

Questo ha funzionato bene per FF e IE ma poi ci sono stati problemi con Chrome. Uno dei problemi era il timing, a quanto pare Chrome impiega un po ‘di tempo per impostare / rilevare l’altezza dell’iframe. E poi Chrome non ha mai restituito correttamente l’altezza del contenuto nell’iframe se l’iframe era superiore al contenuto. Questo non funzionerebbe con il contenuto dinamico quando l’altezza è ridotta.

Per risolvere questo problema, ho sempre impostato l’iframe a un’altezza ridotta prima di rilevare l’altezza del contenuto e quindi di impostare l’altezza dell’iframe sul valore corretto.

 function resize () { // Reset the iframes height to a low value. // Otherwise Chrome won't detect the content height of the iframe. setIframeHeight(150); // Delay getting the dimensions because Chrome needs // a few moments to get the correct height. setTimeout("getDimAndResize()", 100); } 

Il codice non è ottimizzato, è dal mio test di sviluppo 🙂

Spero che qualcuno lo trovi utile!

        

I gadget di iGoogle devono implementare triggersmente il ridimensionamento, quindi la mia ipotesi è in un modello interdominio che non è ansible fare senza che il contenuto remoto partecipi in qualche modo. Se i tuoi contenuti possono inviare un messaggio con le nuove dimensioni alla pagina del contenitore utilizzando le tipiche tecniche di comunicazione tra domini, il resto è semplice.

Quando si desidera ridurre una pagina Web per adattarla alla dimensione iframe:

  1. Dovresti ridimensionare l’ iframe per adattarlo al contenuto
  2. Quindi devi ridurre l’intera iframe con il contenuto della pagina web caricata

Ecco un esempio:

 

  

Ecco un approccio jQuery che aggiunge le informazioni in json tramite l’attributo src dell’iframe. Ecco una demo, ridimensiona e scorri questa finestra .. l’url risultante con json è simile a questo … http://fiddle.jshell.net/zippyskippy/RJN3G/show/#{docHeight:5124,windowHeight:1019,scrollHeight: 571} #

Ecco il codice sorgente fiddle http://jsfiddle.net/zippyskippy/RJN3G/

 function updateLocation(){ var loc = window.location.href; window.location.href = loc.replace(/#{.*}#/,"") + "#{docHeight:"+$(document).height() + ",windowHeight:"+$(window).height() + ",scrollHeight:"+$(window).scrollTop() +"}#"; }; //setInterval(updateLocation,500); $(window).resize(updateLocation); $(window).scroll(updateLocation); 

ottenere l’altezza del contenuto iframe quindi assegnarlo a questo iframe

  var iframes = document.getElementsByTagName("iframe"); for(var i = 0, len = iframes.length; i 

Lavora con jquery sul caricamento (cross browser):

   function loaderIframe(){ var heightIframe = $('#containiframe').contents().find('body').height(); $('#frame').css("height", heightFrame); } 

sul ridimensionamento in una pagina retriggers:

 $(window).resize(function(){ if($('#containiframe').length !== 0) { var heightIframe = $('#containiframe').contents().find('body').height(); $('#frame').css("height", heightFrame); } }); 

Usando jQuery:

Parent.html

       

child.html

     

Questo è un po ‘complicato in quanto devi sapere quando la pagina iframe è stata caricata, il che è difficile quando non hai il controllo del suo contenuto. È ansible aggiungere un gestore onload all’iframe, ma l’ho provato in passato e ha un comportamento molto diverso tra i vari browser (non indovinate chi è il più fastidioso …). Probabilmente dovresti aggiungere una funzione alla pagina iframe che esegue il ridimensionamento e iniettare alcuni script nel contenuto che ascolta per caricare eventi o ridimensionare gli eventi, che quindi chiama la funzione precedente. Sto pensando di aggiungere una funzione alla pagina poiché vuoi assicurarti che sia sicura, ma non ho idea di quanto sarà facile da fare.

Qualcosa sulle linee di questo credo dovrebbe funzionare.

 parent.document.getElementById(iFrameID).style.height=framedPage.scrollHeight; 

Carica questo con il carico del tuo corpo sul contenuto dell’iframe.

Ho una soluzione semplice e ho bisogno di determinare la larghezza e l’altezza del link, per favore prova (Funziona con la maggior parte dei browser):

 500x400