Question Redimensionnement d'un iframe basé sur le contenu


Je travaille sur une application similaire à iGoogle. Le contenu d'autres applications (sur d'autres domaines) est montré en utilisant des iframes.

Comment redimensionner les iframes pour correspondre à 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.

Mettre à jour: S'il vous plaît noter que le contenu est chargé à partir d'autres domaines, de sorte que le politique de même origine s'applique.


485
2017-09-30 14:05


origine


Réponses:


Nous avons eu ce type de problème, mais légèrement en sens inverse de votre situation - nous fournissions le contenu iframed aux sites sur d'autres domaines, de sorte que le même politique d'origine était aussi un problème. Après de nombreuses heures passées à traquer Google, nous avons finalement trouvé une solution (quelque peu ..) réalisable, que vous pourrez peut-être adapter à vos besoins.

Il existe un moyen de contourner la même politique d'origine, mais cela nécessite des modifications à la fois sur le contenu iframed et sur la page de cadrage, donc si vous n'êtes pas en mesure de demander des modifications des deux côtés, cette méthode ne vous sera pas très utile. J'ai 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, soit avec des pages qu'il a iframed, mais jamais des pages dans lesquelles il est encadré, par ex. si tu as:

 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 ne pas  home.html (l'enfant ne peut pas communiquer entre domaines 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, cela fonctionne sur sa propre hauteur, dit helper.html, qui transmet le message à home.html, qui peut ensuite redimensionner l'iframe dans lequel framed.html se trouve

La façon la plus simple de transmettre des messages framed.html à helper.html était à travers un argument d'URL. Pour faire ça, framed.html a un iframe avec src='' spécifié. Quand il est onload incendies, il évalue sa propre hauteur, et définit le src de l'iframe à ce point de helper.html?height=N

Il y a une explication ici de la façon dont facebook gérer, qui peut être légèrement plus clair que le mien ci-dessus!


Code

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

<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
2017-12-12 12:04



Si vous n'avez pas besoin de gérer le contenu iframe d'un domaine différent, essayez ce code, cela 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>

78
2018-03-31 15:15



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

window.postMessage ()

window.postMessage est une méthode permettant de sécuriser la communication d'origine croisée en toute sécurité. Normalement, les scripts sur différentes pages ne sont autorisés à accéder les uns aux autres que si les pages qui les ont exécutées sont à des emplacements avec le même protocole (habituellement les deux http), le numéro de port (80 étant le http par défaut) 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 d'une manière sécurisée lorsqu'elle est correctement utilisée.

Résumé

window.postMessage, lorsqu'il est appelé, provoque l'envoi d'un MessageEvent dans la fenêtre cible lorsqu'un script en attente doit être exécuté (par exemple, des gestionnaires d'événements restants si window.postMessage est appelé depuis un gestionnaire d'événements, timeouts en attente précédemment définis, etc. ). Le MessageEvent a le message de type, une propriété de données qui est définie sur 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 appelant window.postMessage à la fenêtre de temps. postMessage a été appelé, et une propriété source qui est la fenêtre à partir de laquelle window.postMessage est appelée. (D'autres propriétés standard des événements sont présentes avec leurs valeurs attendues.)

le iFrame-Resizer La bibliothèque utilise postMessage pour garder un iFrame dimensionné à 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 de la fenêtre iframe ...

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

Cet article montre comment supprimer la dépendance sur jQuery ... Plus a beaucoup d'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 travail de rédaction sur window.postMessage

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

John Resig sur la messagerie cross-window

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


40
2017-07-10 16:24



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
2017-08-30 17:50



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 qu'il faut ajouter 30 à la longueur ... J'ai travaillé 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
2017-10-30 14:07



peut être un peu en retard, car toutes les autres réponses sont plus anciennes :-) mais ... voici ma solution. Testé dans 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
2017-12-25 23:55



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 «sait» ce qui se trouve dans l'iframe et connaît les dimensions à utiliser pour styliser l'iframe. Cela contourne les mêmes restrictions de politique d'origine.

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

Donc, le code iframe fourni aurait une feuille de style d'accompagnement comme ça ...

<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 rendu de l'iframe.


2
2018-06-09 03:10



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

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

SiteB est en cours de chargement dans le site Web de siteA

Site Web SiteB a cette ligne

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

ou

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

Alors le site 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 voulez ajouter une 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 IFrame:

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

À l'extérieur:

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

2
2018-06-12 07:54