web-dev-qa-db-fra.com

Redimensionnement d'un iframe en fonction du contenu

Je travaille sur une application de type iGoogle. Le contenu d'autres applications (sur d'autres domaines) est affiché à l'aide d'iframes.

Comment redimensionner les iframes pour les adapter à la hauteur du contenu des iframes?

J'ai essayé de déchiffrer le code javascript utilisé par Google, mais celui-ci est obscurci et la recherche sur le Web a été infructueuse jusqu'à présent.

Mise à jour: Veuillez noter que le contenu est chargé à partir d'autres domaines. Par conséquent, la politique de même origine s'applique.

492
larssg

Si vous n'avez pas besoin de gérer du contenu iframe provenant d'un autre domaine, essayez ce code, il résoudra complètement le problème et c'est simple:

<script language="JavaScript">
<!--
function autoResize(id){
    var newheight;
    var newwidth;

    if(document.getElementById){
        newheight=document.getElementById(id).contentWindow.document .body.scrollHeight;
        newwidth=document.getElementById(id).contentWindow.document .body.scrollWidth;
    }

    document.getElementById(id).height= (newheight) + "px";
    document.getElementById(id).width= (newwidth) + "px";
}
//-->
</script>

<iframe src="usagelogs/default.aspx" width="100%" height="200px" id="iframe1" marginheight="0" frameborder="0" onLoad="autoResize('iframe1');"></iframe>
80
Ahmy

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

window.postMessage ()

window.postMessage est une méthode permettant d'activer en toute sécurité la communication entre origines. Normalement, les scripts de différentes pages ne sont autorisés à accéder les uns aux autres que si et seulement si les pages qui les ont exécutées se trouvent à des emplacements dotés du même protocole (généralement les deux: http), numéro de port (80 étant la valeur par défaut pour http) et Host (modulo). document.domain étant défini par les deux pages sur la même valeur). window.postMessage fournit un mécanisme contrôlé pour contourner cette restriction de manière sécurisée lorsqu'il est utilisé correctement.

Résumé

window.postMessage, lorsqu'il est appelé, provoque la distribution d'un MessageEvent dans la fenêtre cible lorsqu'un script en attente à exécuter est terminé (par exemple, les gestionnaires d'événement restants si window.postMessage est appelé à partir d'un gestionnaire d'événement, des délais d'attente définis auparavant, etc. ). MessageEvent a le type message, une propriété data définie sur la valeur de chaîne du premier argument fourni à window.postMessage, une propriété Origin correspondant à l'origine du document principal dans la fenêtre appelant window.postMessage à la fenêtre horaire. postMessage a été appelé et une propriété source qui est la fenêtre à partir de laquelle window.postMessage est appelé. (D'autres propriétés standard d'événements sont présentes avec leurs valeurs attendues.)

La bibliothèque iFrame-Resizer utilise postMessage pour conserver une image iFrame adaptée à son contenu, avec MutationObserver pour détecter les modifications apportées au contenu. et ne dépend pas de jQuery.

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

jQuery: bonté des scripts interdomaines

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

A une démo de redimensionnement iframe fenêtre ...

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

Cet article explique comment supprimer la dépendance à jQuery ... Plus contient de nombreuses informations utiles et des liens vers d'autres solutions.

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

Exemple de barebones ...

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

HTML 5 version préliminaire sur window.postMessage

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

John Resig sur la messagerie entre fenêtres

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

40
Chris Jacob

Le moyen le plus simple d'utiliser jQuery:

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

La solution sur http://www.phinesolutions.com/use-jquery-to-adjust-the-iframe-height.html fonctionne très bien (utilise jQuery):

<script type=”text/javascript”>
  $(document).ready(function() {
    var theFrame = $(”#iFrameToAdjust”, parent.document.body);
    theFrame.height($(document.body).height() + 30);
  });
</script>

Je ne sais pas si vous devez ajouter 30 à la longueur ... 1 a fonctionné pour moi.

FYI: Si vous avez déjà un attribut "height" sur votre iFrame, cela ajoute simplement style = "height: xxx". Ce n'est peut-être pas ce que vous voulez.

6
Macho Matt

peut-être un peu tard, car toutes les autres réponses sont plus anciennes :-) mais ... voici ma solution. Testé dans les versions FF, Chrome et 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
        });
    });
});

J'espère que cela aidera n'importe qui.

4
ddlab

Enfin, j'ai trouvé une autre solution pour envoyer des données d'iframe au site Web parent à l'aide de window.postMessage(message, targetOrigin);. Ici, j'explique comment j'ai fait.

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

SiteB se charge dans le site Web de siteA

SiteB SiteB ont cette ligne

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

ou

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

Alors siteA a ce code suivant

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

Si vous souhaitez ajouter une connexion de sécurité, vous pouvez utiliser cette condition si dans 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.
}

Pour IE

Dans IFrame:

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

À l'extérieur:

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

Cette réponse ne concerne que les sites Web utilisant Bootstrap. La fonction d'intégration réactive du Bootstrap fait le travail. Il est basé sur la largeur (pas la hauteur) du contenu.

<!-- 16:9 aspect ratio -->
<div class="embed-responsive embed-responsive-16by9">
  <iframe class="embed-responsive-item" src="http://www.youtube.com/embed/WsFWhL4Y84Y"></iframe>
</div>

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

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

2
Razan Paul

Voici une solution simple utilisant une feuille de style générée dynamiquement et servie par le même serveur que le contenu iframe. Tout simplement, la feuille de style "connaît" le contenu de l'iframe et connaît les dimensions à utiliser pour styler l'iframe. Cela permet de contourner les mêmes restrictions de stratégie d'origine.

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

Ainsi, le code iframe fourni aurait une feuille de style qui l'accompagnerait comme si ...

<link href="http://your.site/path/to/css?contents_id=1234&dom_id=iframe_widget" rel="stylesheet" type="text/css" />
 <iframe id="iframe_widget" src="http://your.site/path/to/content?content_id=1234" frameborder="0" width="100%" scrolling="no"></iframe>

Cela nécessite que la logique côté serveur puisse calculer les dimensions du contenu restitué de l'iframe.

2
Vaughan Rowsell
<html>
<head>
<script>
function frameSize(id){
var frameHeight;

document.getElementById(id).height=0 + "px";
if(document.getElementById){
    newheight=document.getElementById(id).contentWindow.document.body.scrollHeight;    
}

document.getElementById(id).height= (frameHeight) + "px";
}
</script>
</head>

<body>

<iframe id="frame"  src="startframe.html" frameborder="0" marginheight="0" hspace=20     width="100%" 

onload="javascript:frameSize('frame');">

<p>This will work, but you need to Host it on an http server, you can do it locally.    </p>
</body>
</html>
1
webd3sign

J'implémente la solution frame-in-frame de ConroyP pour remplacer une solution basée sur le paramètre document.domain, mais il a été assez difficile de déterminer correctement la hauteur du contenu de l'iframe dans différents navigateurs (tests avec FF11, Ch17 et IE9 actuellement). ).

ConroyP utilise:

var height = document.body.scrollHeight;

Mais cela ne fonctionne que lors du chargement initial de la page. Mon iframe a un contenu dynamique et je dois redimensionner l’iframe lors de certains événements.

J'ai fini par utiliser différentes propriétés JS pour les différents navigateurs.

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 () est une fonction de détection de navigateur "inspirée" par la technologie Ext Core http://docs.sencha.com/core/source/Ext.html#method-Ext-apply

Cela fonctionnait bien pour FF et IE, mais il y avait des problèmes avec Chrome. L’un des problèmes était un problème de synchronisation. Apparemment, il faut Chrome un certain temps pour définir/détecter la hauteur de l’iframe. Et puis Chrome n'a jamais non plus retourné correctement la hauteur du contenu dans l'iframe si l'iframe était supérieur au contenu. Cela ne fonctionnerait pas avec un contenu dynamique lorsque la hauteur est réduite.

Pour résoudre ce problème, définissez toujours l'iframe sur une hauteur faible avant de détecter la hauteur du contenu, puis définissez la hauteur de l'iframe sur sa valeur correcte.

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

Le code n'est pas optimisé, c'est de mon test de développement :)

J'espère que quelqu'un trouve cela utile!

1
Tor Olsson

Lorsque vous souhaitez effectuer un zoom arrière sur une page Web pour l'adapter à la taille de l'iframe:

  1. Vous devez redimensionner le iframe pour l'adapter au contenu
  2. Ensuite, vous devez effectuer un zoom arrière sur l'ensemble de l'iframe avec le contenu de la page Web chargée.

Voici un exemple:

<div id="wrap">
   <IFRAME ID="frame" name="Main" src ="http://www.google.com" />
</div>

<style type="text/css">
    #wrap { width: 130px; height: 130px; padding: 0; overflow: hidden; }
    #frame { width: 900px; height: 600px; border: 1px solid black; }
    #frame { zoom:0.15; -moz-transform:scale(0.15);-moz-transform-Origin: 0 0; }
</style>
0
kaw

Travailler avec jQuery au chargement (navigateur croisé):

 <iframe src="your_url" marginwidth="0"  marginheight="0" scrolling="No" frameborder="0"  hspace="0" vspace="0" id="containiframe" onload="loaderIframe();" height="100%"  width="100%"></iframe>

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

sur redimensionner dans la page sensible:

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

Voici une approche jQuery qui ajoute les informations dans JSON via l'attribut src de l'iframe. Voici une démo, redimensionnez et faites défiler cette fenêtre .. l'URL résultante avec json ressemble à ceci ... http://fiddle.jshell.net/zippyskippy/RJN3G/show/# {docHeight: 5124, windowHeight: 1019, scrollHeight: 571} #

Voici le violon du code source 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);
0
chad steele

Utilisation de jQuery:

parent.html

<body>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<style>
iframe {
    width: 100%;
    border: 1px solid black;
}
</style>
<script>
function foo(w, h) {
    $("iframe").css({width: w, height: h});
    return true;  // for debug purposes
}
</script>
<iframe src="child.html"></iframe>
</body>

child.html

<body>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
$(function() {
    var w = $("#container").css("width");
    var h = $("#container").css("height");

    var req = parent.foo(w, h);
    console.log(req); // for debug purposes
});
</script>
<style>
body, html {
    margin: 0;
}
#container {
    width: 500px;
    height: 500px;
    background-color: red;
}
</style>
<div id="container"></div>
</body>
0
Nino Škopac

obtenir la hauteur du contenu iframe puis le donner à cette iframe

 var iframes = document.getElementsByTagName("iframe");
 for(var i = 0, len = iframes.length; i<len; i++){
      window.frames[i].onload = function(_i){
           return function(){
                     iframes[_i].style.height = window.frames[_i].document.body.scrollHeight + "px";
                     }
      }(i);
 }
0
YellowGlue

les gadgets iGoogle doivent implémenter activement le redimensionnement. Par conséquent, je suppose que dans un modèle interdomaine, vous ne pouvez pas le faire sans le contenu distant pris en charge. Si votre contenu peut envoyer un message avec la nouvelle taille à la page conteneur à l'aide de techniques de communication inter-domaines classiques, le reste est simple.

0
Joeri Sebrechts