Изменение размера фрейма в зависимости от содержимого - PullRequest
490 голосов
/ 30 сентября 2008

Я работаю над iGoogle-подобным приложением. Контент из других приложений (в других доменах) показывается с помощью iframes.

Как изменить размеры фреймов, чтобы они соответствовали высоте содержимого фреймов?

Я пытался расшифровать javascript, который использует Google, но он запутан, и поиск в Интернете до сих пор был бесплодным.

Обновление: Обратите внимание, что контент загружается из других доменов, поэтому применяется политика с тем же происхождением .

Ответы [ 20 ]

576 голосов
/ 12 декабря 2008

У нас была проблема такого типа, но немного обратная вашей ситуации - мы предоставляли контент iframed для сайтов в других доменах, поэтому такая же политика происхождения также была проблемой. После долгих часов траления в Google мы нашли (несколько ..) работоспособное решение, которое вы можете адаптировать к вашим потребностям.

Существует способ обойти одну и ту же политику происхождения, но она требует изменений как для содержимого iframed, так и для страницы с кадрами, поэтому, если у вас нет возможности запрашивать изменения с обеих сторон, этот метод не будет очень полезен боюсь тебе.

Существует особенность браузера, которая позволяет нам обходить ту же политику происхождения - javascript может взаимодействовать либо со страницами в своем собственном домене, либо со страницами, на которые он встроен, но никогда со страницами, в которых он создан, например, если у вас есть:

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

затем home.html может связываться с framed.html (iframed) и helper.html (тот же домен).

 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 может отправлять сообщения на helper.html (iframed), но не home.html (дочерний элемент не может общаться между доменами с родителем).

Ключ в том, что helper.html может получать сообщения от framed.html, а также может связывать с home.html.

Таким образом, по существу, когда framed.html загружается, он вырабатывает собственную высоту, сообщает helper.html, который передает сообщение в home.html, который может затем изменить размер фрейма, в котором находится framed.html.

Самый простой способ передачи сообщений от framed.html до helper.html был через URL-аргумент. Для этого framed.html имеет iframe с указанным src=''. Когда стреляет onload, он оценивает свою собственную высоту и устанавливает в этом месте источник iframe равным helper.html?height=N

Здесь есть объяснение того, как Facebook справляется с этим, что может быть немного яснее, чем мое выше!

<ч /> Код

В www.foo.com/home.html требуется следующий код JavaScript (его можно загрузить из файла .js в любом домене, между прочим ..):

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

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

Содержимое 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>
80 голосов
/ 31 марта 2009

Если вам не нужно обрабатывать содержимое iframe из другого домена, попробуйте этот код, он полностью решит проблему и прост:

<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>
40 голосов
/ 10 июля 2010

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

window.postMessage ()

window.postMessage - это метод безопасного включения связи между источниками. Как правило, скрипты на разных страницах могут получать доступ друг к другу только тогда и только тогда, когда страницы, которые их выполняли, находятся в местах с одинаковым протоколом (обычно с http), номером порта (по умолчанию для http используется 80) и хостом (по модулю). document.domain устанавливается обеими страницами на одно и то же значение). window.postMessage предоставляет управляемый механизм, позволяющий обойти это ограничение безопасным способом при правильном использовании.

Резюме

window.postMessage, когда вызывается, заставляет MessageEvent отправляться в целевое окно, когда завершается любой ожидающий сценарий, который должен быть выполнен (например, оставшиеся обработчики событий, если window.postMessage вызывается из обработчика событий, предварительно установленных тайм-аутов ожидания , так далее.). MessageEvent имеет тип сообщения, свойство data, для которого задано строковое значение первого аргумента, предоставленного window.postMessage, свойство origin, соответствующее источнику основного документа в окне, вызывающем window.postMessage во временном окне. Был вызван postMessage и свойство источника, которое является окном, из которого вызывается window.postMessage. (Другие стандартные свойства событий присутствуют с их ожидаемыми значениями.)

Библиотека iFrame-Resizer использует postMessage для сохранения размера iFrame в своем содержимом, наряду с MutationObserver для обнаружения изменений в контенте и не зависит от jQuery.

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

jQuery: совершенство междоменных сценариев

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

Имеет демонстрацию изменения размера окна iframe ...

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

В этой статье показано, как удалить зависимость от jQuery ... Plus содержит много полезной информации и ссылок на другие решения.

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

Пример Barebones ...

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

HTML 5 рабочий проект для window.postMessage

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

Джон Ресиг о кросс-оконном обмене сообщениями

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

9 голосов
/ 30 августа 2012

Самый простой способ использования jQuery:

$("iframe")
.attr({"scrolling": "no", "src":"http://www.someotherlink.com/"})
.load(function() {
    $(this).css("height", $(this).contents().height() + "px");
});
6 голосов
/ 30 октября 2008

Решение на http://www.phinesolutions.com/use-jquery-to-adjust-the-iframe-height.html отлично работает (использует jQuery):

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

Я не знаю, что вам нужно добавить 30 к длине ... 1 работал для меня.

FYI : Если у вас уже есть атрибут "height" в вашем iFrame, это просто добавляет style = "height: xxx" Это может быть не то, что вы хотите.

4 голосов
/ 26 декабря 2013

может быть немного поздно, так как все остальные ответы старше :-) но ... вот мое решение. Протестировано в реальных FF, Chrome и 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
        });
    });
});

Надеюсь, это кому-нибудь поможет.

3 голосов
/ 12 июня 2014

Наконец-то я нашел другое решение для отправки данных на родительский сайт из iframe с помощью window.postMessage(message, targetOrigin);. Здесь я объясняю, как я это сделал.

Сайт А = http://foo.com Сайт B = http://bar.com

СайтB загружается внутри сайта Сайт

Сайт SiteB имеет эту строку

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

или

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

Тогда siteA имеет следующий код

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

Если вы хотите добавить безопасное соединение, вы можете использовать это, если условие в 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.
}

для IE

Внутри IFrame:

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

Снаружи:

 eventer(messageEvent, function (e) {
   var data = jQuery.parseJSON(e.data);
   doSomething(data.key);
 }, false);
2 голосов
/ 03 февраля 2015

Этот ответ применим только для веб-сайтов, которые используют Bootstrap. Функция адаптивного встраивания Bootstrap делает свою работу. Он основан на ширине (а не высоте) содержимого.

<!-- 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 голосов
/ 09 июня 2010

Вот простое решение, использующее динамически генерируемую таблицу стилей, обслуживаемую тем же сервером, что и содержимое iframe. Проще говоря, таблица стилей «знает», что находится в iframe, и знает размеры, используемые для стилизации iframe. Это обходит те же ограничения политики происхождения.

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

Таким образом, поставляемый код iframe будет иметь прилагаемую таблицу стилей, например ...

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

Для этого требуется, чтобы логика на стороне сервера могла рассчитывать размеры визуализированного содержимого iframe.

1 голос
/ 20 августа 2013
<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...