Вычисление кросс-браузерной высоты iframe - PullRequest
16 голосов
/ 16 октября 2008

Одной из самых сложных проблем в моем опыте работы с JavaScript было правильное (то есть "кросс-браузерное") вычисление высоты фрейма . В моих приложениях у меня много динамически генерируемого iframe, и я хочу, чтобы все они выполняли своего рода автоматическое изменение размера в конце события load, чтобы настроить их высоту и ширину.

В случае высота мои лучшие решения следующие (с помощью jQuery):

function getDocumentHeight(doc) {
  var mdoc = doc || document;
  if (mdoc.compatMode=='CSS1Compat') {       
      return mdoc.body.offsetHeight;
  }
  else {
    if ($.browser.msie)
      return mdoc.body.scrollHeight;
    else  
      return Math.max($(mdoc).height(), $(mdoc.body).height());
  }
}

Я безуспешно искал в интернете. Я также протестировал библиотеку Yahoo, в которой есть некоторые методы для измерений документа и области просмотра, но она не является удовлетворительной. Мое решение работает прилично, но иногда оно вычисляет более высокую высоту. Я изучил и протестировал множество свойств относительно высоты документа в Firefox / IE / Safari: documentElement.clientHeight, documentElement.offsetHeight, documentElement.scrollHeight, body.offsetHeight, body.scrollHeight, ... Также jQuery не имеет согласованного поведения в различных браузерах с вызовами $(document.body).height(), $('html', doc).height(), $(window).height()

Я вызываю вышеуказанную функцию не только в конце события загрузки, но и в случае динамически вставленных элементов DOM или скрытых или показанных элементов. Это случай, который иногда нарушает код, который работает только в событии загрузки.

Есть ли у кого-нибудь реальное кросс-браузерное (по крайней мере, Firefox / IE / Safari) решение? Некоторые советы или подсказки?

Ответы [ 6 ]

4 голосов
/ 16 октября 2008

Несмотря на то, что мне нравится ваше решение, я всегда находил, что IFRAME доставляют больше хлопот, чем стоят.

Почему? 1. Проблема с размерами. 2. у iframe есть этот атрибут src, о котором стоит беспокоиться. то есть абсолютный путь. 3. дополнительная сложность со страницами.

Мое решение - DIV, которые динамически загружаются через вызовы AJAX. DIVs будут автоматически по размеру. Хотя AJAX-код требует работы с JavaScript (что можно сделать с помощью фреймворков), он зависит от того, где находится сайт. 3 - мойка, вы торгуете сложностью на страницах до javascript.

Вместо

Выполните вызов ajax, чтобы заполнить div mystuff данными и позволить браузеру беспокоиться об этом.

2 голосов
/ 01 декабря 2011

Некоторое время этот ответ не принимался, поэтому я хотел предложить решение, с которым я столкнулся после некоторого исследования. Это кросс-браузер и междоменный домен (например, когда iframe указывает на контент из другого домена)

В итоге я использовал механизм передачи сообщений html5, включенный в jQuery pluging , что делает его совместимым со старыми браузерами с использованием различных методов (некоторые из них описаны в этой теме).

Конечное решение очень простое.

На странице хоста (родительской):

// executes when a message is received from the iframe, to adjust 
// the iframe's height
    $.receiveMessage(
        function( event ){
            $( 'my_iframe' ).css({
                height: event.data
            });
    });

// Please note this function could also verify event.origin and other security-related checks.

На странице iframe:

$(function(){

    // Sends a message to the parent window to tell it the height of the 
    // iframe's body

    var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);

    $.postMessage(
        $('body').outerHeight( true ) + 'px',
        '*',
        target
    );

});

Я тестировал это на Chrome 13+, Firefox 3.6+, IE7, 8 и 9 на XP и W7, сафари на OSX и W7. ;)

1 голос
/ 02 апреля 2011

Так как в вашем примере вы обращаетесь к документу внутри КАДРА Я полагаю, вы говорите о знании высоты документа, а не самого фрейма. Кроме того, это означает, что контент поступает с вашего собственного веб-сайта, и вы можете контролировать его содержимое.

Итак, почему бы вам просто не разместить DIV вокруг вашего контента, а затем использовать clientHeight этого DIV?

Код, который вы загружаете в свой IFRAME:

...
<body>
  <div id="content">
  ...
  </div>
</body>

Родительский документ:

 function getDocumentHeight(mdoc) {
    return mdoc.getElementById("content").clientHeight;
 }

Кстати, эта часть вашей примерной функции не имеет смысла, так как «документ» не ссылается на IFRAME: var mdoc = doc || document;

0 голосов
/ 04 апреля 2011

Вот скрипт , который изменяет размер iFrame в зависимости от тела внутри его высоты.

0 голосов
/ 14 августа 2009

Я нашел, что это решение работает в т.е 6+, ff 3.5+, сафари 4+. Я создаю и добавляю iframe к документу. Следующий код выполняется в конце события загрузки jQuery после некоторых других манипуляций с dom. Тайм-аут мне нужен из-за дополнительных манипуляций с dom, происходящих в событии load.

// sizing - slight delay for good scrollheight
setTimeout(function() {
   var intContentHeight = objContentDoc.body.scrollHeight;
   var $wrap = $("#divContentWrapper", objContentFrameDoc);
   var intMaxHeight = getMaxLayeredContentHeight($wrap);
   $this.height(intContentHeight > intMaxHeight ? intMaxHeight : intContentHeight);

   // animate
   fireLayeredContentAnimation($wrap);
}, 100);

У меня есть некоторые ограничения по размеру, которые я и проверяю при вызове getMaxLayeredContentHeight. Надеюсь, это поможет.

0 голосов
/ 15 апреля 2009

Вот решение, которое, кажется, работает. По сути, scrollHeight является правильным значением в большинстве случаев. Однако в IE (в частности, 6 и 7), если содержимое просто содержится в текстовых узлах, высота не рассчитывается, а просто устанавливается по умолчанию на высоту, заданную в CSS или на атрибут «height» в iframe. Это было найдено методом проб и ошибок, поэтому возьмите его за то, что оно стоит.

function getDocumentHeight(doc) {
  var mdoc = doc || document; 
  var docHeight = mdoc.body.scrollHeight;

  if ($.browser.msie) {
      // IE 6/7 don't report body height correctly.  
      // Instead, insert a temporary div containing the contents.

      var child = $("<div>" + mdoc.body.innerHTML + "</div>", mdoc);
      $("body", mdoc).prepend(child);
      docHeight = child.height();
      child.remove();
  }

  return docHeight;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...