Redimensionnement d'une iframe basée sur le contenu

je travaille sur une application de type iGoogle. Le contenu d'autres applications (sur d'autres domaines) est affiché en utilisant iframes.

comment redimensionner les iframes en fonction de la hauteur du contenu des iframes?

j'ai essayé de déchiffrer le javascript que Google utilise, mais il 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, ainsi, la Politique de même origine s'applique.

487
demandé sur robsch 2008-09-30 18:05:11

20 réponses

nous avons eu ce type de problème, mais légèrement à l'inverse de votre situation - nous fournissons le contenu iframed à des sites sur d'autres domaines, de sorte que la même politique d'origine était également un problème. Après de nombreuses heures passées à traquer google, nous avons finalement trouvé un (quelque peu..) solution réalisable, que vous pourriez être en mesure d'adapter à vos besoins.

il y a un moyen de contourner la même politique d'origine, mais il nécessite des changements à la fois sur le contenu iframed et la page de cadrage, donc si vous n'avez pas la possibilité de demander des changements des deux côtés, cette méthode ne vous sera pas très utile, j'en ai bien peur.

il y a une bizarrerie de navigateur qui nous permet de contourner la même politique d'origine-javascript peut communiquer soit avec des pages sur son propre domaine, ou avec des pages qu'il a iframed, mais jamais des pages dans lesquelles il est encadré, par exemple si vous avez:

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

puis home.html peut communiquer avec framed.html (iframed) et helper.html (même domaine).

 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 peut envoyer des messages à helper.html (iframed) mais pas home.html (l'enfant ne peut pas communiquer de domaine croisé avec le parent).

la clé ici est que helper.html peut recevoir des messages de framed.html , et peut aussi communiquer avec home.html .

donc essentiellement, quand framed.html charges, il fonctionne de sa propre hauteur, dit helper.html , qui passe le message à home.html , qui peut alors redimensionner l'iframe dans laquelle framed.html se trouve.

le moyen le plus simple que nous ayons trouvé pour passer des messages de framed.html à helper.html était par un argument D'URL. Pour ce faire, framed.html a une iframe avec src='' spécifié. Lorsque son onload incendies, il évalue sa propre hauteur, et fixe le src de l'iframe à ce point à helper.html?height=N

Il ya une explication ici de la façon dont facebook Gérer, qui peut être un peu plus claire que la mienne ci-dessus!


Code

Dans www.foo.com/home.html , le code javascript suivant est nécessaire (cela peut être chargé à partir d'un .js fichiers sur n'importe quel domaine d'ailleurs..):

<script>
  // Resize iframe to full height
  function resizeIframe(height)
  {
    // "+60" is a general rule of thumb to allow for differences in
    // IE & and FF height reporting, can be adjusted as required..
    document.getElementById('frame_name_here').height = parseInt(height)+60;
  }
</script>
<iframe id='frame_name_here' src='http://www.bar.net/framed.html'></iframe>

Dans www.bar.net/framed.html :

<body onload="iframeResizePipe()">
<iframe id="helpframe" src='' height='0' width='0' frameborder='0'></iframe>

<script type="text/javascript">
  function iframeResizePipe()
  {
     // What's the page height?
     var height = document.body.scrollHeight;

     // Going to 'pipe' the data to the parent through the helpframe..
     var pipe = document.getElementById('helpframe');

     // Cachebuster a precaution here to stop browser caching interfering
     pipe.src = 'http://www.foo.com/helper.html?height='+height+'&cacheb='+Math.random();

  }
</script>

Contenu de www.foo.com/helper.html :

<html> 
<!-- 
This page is on the same domain as the parent, so can
communicate with it to order the iframe window resizing
to fit the content 
--> 
  <body onload="parentIframeResize()"> 
    <script> 
      // Tell the parent iframe what height the iframe needs to be
      function parentIframeResize()
      {
         var height = getParam('height');
         // This works as our parent's parent is on our domain..
         parent.parent.resizeIframe(height);
      }

      // Helper function, parse param from request string
      function getParam( name )
      {
        name = name.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");
        var regexS = "[\?&]"+name+"=([^&#]*)";
        var regex = new RegExp( regexS );
        var results = regex.exec( window.location.href );
        if( results == null )
          return "";
        else
          return results[1];
      }
    </script> 
  </body> 
</html>
573
répondu ConroyP 2013-10-30 17:33:44

si vous n'avez pas besoin de gérer le contenu iframe d'un autre domaine, essayez ce code, il résoudra le problème complètement 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>
79
répondu Ahmy 2012-08-28 08:59:30

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

de la fenêtre.postMessage ()

de la fenêtre.postMessage est une méthode permettant en toute sécurité la communication d'origine croisée. Normalement, les scripts sur des pages différentes ne sont autorisés à accéder les uns aux autres que si et seulement si les pages qui les ont exécutés sont à des endroits avec le même protocole (généralement les deux http), le numéro de port (80 étant la valeur par défaut pour http), et l'hôte (modulo document.domaine défini par les deux pages de la même valeur). fenêtre.postMessage fournit un mécanisme contrôlé pour contourner cette restriction d'une manière qui est Sécuritaire lorsqu'il est correctement utilisé.

résumé

de la fenêtre.postMessage, lorsqu'il est appelé, provoque l'envoi d'un message à la fenêtre cible lorsque n'importe quel script en attente qui doit être exécuté est terminé (e.g. l'événement restant les gestionnaires si la fenêtre.postMessage est appelé à partir d'un gestionnaire d'événements, de délais en attente définis précédemment, etc.). Le MessageEvent a le message de type, une propriété de données qui est définie à la valeur de chaîne du premier argument fourni à window.postMessage, une propriété d'origine correspondant à l'origine du document principal dans la fenêtre d'appel de fenêtre.postMessage à la fenêtre horaire.postMessage a été appelé, et une propriété source qui est la fenêtre à partir de laquelle fenêtre.postMessage est appelé. (D'autres standard propriétés des événements sont présents avec leurs valeurs attendues.)

la bibliothèque iFrame-Resizer utilise postMessage pour conserver une iFrame dimensionnée à son contenu, ainsi que MutationObserver pour détecter les changements au contenu et ne dépend pas de jQuery.

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

jQuery: cross-domain scripting bonté

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

a une démo pour redimensionner la fenêtre iframe...

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

cet article montre comment supprimer la dépendance à jQuery... Plus a beaucoup d'infos utiles et des liens vers d'autres solutions.

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

Barebones exemple...

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

HTML 5, document de travail de la fenêtre.postMessage

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

John Resig sur la Fenêtre de Messagerie

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

40
répondu Chris Jacob 2014-03-15 19:39:40

la manière la plus simple d'utiliser jQuery:

$("iframe")
.attr({"scrolling": "no", "src":"http://www.someotherlink.com/"})
.load(function() {
    $(this).css("height", $(this).contents().height() + "px");
});
8
répondu Omer Arshad 2012-08-30 18:26:26

La solution http://www.phinesolutions.com/use-jquery-to-adjust-the-iframe-height.html fonctionne à merveille (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". Cela pourrait ne pas être ce que vous voulez.

6
répondu Macho Matt 2016-03-30 12:16:47

peut-être un peu tard, comme toutes les autres réponses sont plus :-) mais... voilà ma solution. Testé en 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 ça aidera n'importe qui.

4
répondu ddlab 2013-12-25 23:55:41

Voici une solution simple utilisant une feuille de style générée dynamiquement servie par le même serveur que le contenu iframe. Tout simplement la feuille de style "sait" ce qui est dans l'iframe, et connaît les dimensions à utiliser pour le style de l'iframe. Cela va à l'encontre des mêmes restrictions de la Politique d'origine.

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

ainsi la fourniture iframe code aurait une feuille de style d'accompagnement comme cela...

<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 soit capable de calculer les dimensions du contenu rendu de l'iframe.

2
répondu Vaughan Rowsell 2010-06-09 03:10:32

finalement j'ai trouvé une autre solution pour envoyer des données sur le site parent à partir d'iframe en utilisant window.postMessage(message, targetOrigin); . Ici j'explique Comment j'ai fait.

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

SiteB charge à l'intérieur du site web de siteA

SiteB site Web ont cette ligne

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

ou

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

puis siteA ont le 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 voulez ajouter connexion de sécurité, Vous pouvez utiliser cette condition si 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

À L'Intérieur De L'IFrame:

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

à l'extérieur:

 eventer(messageEvent, function (e) {
   var data = jQuery.parseJSON(e.data);
   doSomething(data.key);
 }, false);
2
répondu Selvamani 2014-06-12 07:54:23

cette réponse ne s'applique qu'aux sites Web qui utilisent Bootstrap. La fonction d'embed responsive du Bootstrap fait le travail. Elle est basée 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
répondu Razan Paul 2015-02-03 03:47:14

J'implémente la solution frame-in-frame de ConroyP pour remplacer une solution basée sur le document de configuration.domaine, mais a trouvé assez difficile de déterminer la hauteur du contenu de l'iframe correctement dans différents navigateurs (test avec FF11, Ch17 et IE9 en ce moment).

ConroyP utilisations:

var height = document.body.scrollHeight;

mais cela ne fonctionne que sur la page de charge initiale. Mon iframe a un contenu dynamique et je dois redimensionner l'iframe sur certains événements.

ce que j'ai fini par faire était d'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 () is browser detect function "inspired" by Ext Core http://docs.sencha.com/core/source/Ext.html#method-Ext-apply

qui a bien fonctionné pour FF et IE mais il y avait des problèmes avec Chrome. Un des était un problème de timing, apparemment, il faut Chrome un certain temps pour set/détecter la hauteur de l'iframe. Et puis Chrome n'a jamais retourné la hauteur du contenu dans l'iframe correctement si l'iframe était plus élevé que le contenu. Cela ne fonctionnerait pas avec le contenu dynamique lorsque la hauteur est réduite.

pour résoudre ce problème, je règle toujours l'iframe à une faible hauteur avant de détecter la hauteur du contenu et ensuite de régler la hauteur de l'iframe à 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é, il est de mon développement test:)

Espère que quelqu'un trouve cette pratique!

1
répondu Tor Olsson 2012-03-20 22:49:54
<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
répondu webd3sign 2013-08-19 21:55:24

gadgets iGoogle doivent activement mettre en œuvre redimensionnement, donc mon avis est dans un modèle cross-domaine, vous ne pouvez pas le faire sans le contenu à distance prendre part d'une certaine manière. Si votre contenu peut envoyer un message avec la nouvelle taille à la page du conteneur en utilisant des techniques de communication inter-domaines typiques, alors le reste est simple.

0
répondu Joeri Sebrechts 2008-10-30 14:22:23

quand vous voulez zoomer sur une page web pour l'adapter à la taille iframe:

  1. vous devez redimensionner le iframe pour l'adapter au contenu
  2. ensuite, vous devriez zoomer 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
répondu kaw 2012-11-20 19:30:08

Voici une approche jQuery qui ajoute l'information 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 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
répondu chad steele 2013-01-23 18:37:39

obtenir le contenu de l'iframe hauteur puis de 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
répondu YellowGlue 2013-12-11 09:33:18

Travailler avec jquery en charge (de la croix-navigateur):

 <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 en responsive page:

$(window).resize(function(){
if($('#containiframe').length !== 0) {
var heightIframe = $('#containiframe').contents().find('body').height();
 $('#frame').css("height", heightFrame);
}
});
0
répondu Mario Gonzales Flores 2014-06-16 22:03:35

utilisant 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>

de l'enfant.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
répondu Nino Škopac 2015-09-17 02:36:30

c'est un peu délicat car vous devez savoir quand la page iframe a chargé, ce qui est difficile quand vous n'êtes pas en contrôle de son contenu. Il est possible d'ajouter un handler onload à l'iframe, mais j'ai essayé cela dans le passé et il a des comportements très différents parmi les navigateurs (ne pas deviner qui est le plus ennuyeux...). Vous devrez probablement ajouter une fonction à la page iframe qui exécute le redimensionnement et injecter du script dans le contenu qui soit écoute pour charger les événements ou redimensionner les événements, qui appelle la fonction précédente. Je pense ajouter une fonction à la page puisque vous voulez vous assurer de sa sécurité, mais je n'ai aucune idée de comment il sera facile à faire.

-2
répondu roryf 2008-09-30 14:12:16

quelque chose dans ce sens devrait marcher.

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

chargez ceci avec votre corps chargé sur le contenu iframe.

-2
répondu Ólafur Waage 2008-09-30 14:13:07

j'ai une solution facile et vous demande de déterminer la largeur et la hauteur dans le lien, s'il vous plaît essayer (il fonctionne avec la plupart des navigateurs):

<a href='#' onClick=" document.getElementById('myform').src='t2.htm';document.getElementById('myform').width='500px'; document.getElementById('myform').height='400px'; return false">500x400</a>
-4
répondu فيصل خلبوص 2012-02-20 06:05:39