Подтвердить что ты не робот

Вычисление высоты перекрестного браузера iframe

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

В случае вычисления height мое лучшее решение заключается в следующем (с помощью 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)? Некоторые подсказки или подсказки?

4b9b3361

Ответ 1

Хотя мне нравится ваше решение, я всегда обнаружил, что IFRAME - это больше проблем, чем они того стоят.

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

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

Вместо < IFRAME... > использовать < DIV id = "mystuff" / >

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

Ответ 2

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

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

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

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

// executes when a message is received from the iframe, to adjust 
// the iframe 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 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.;)

Ответ 3

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

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

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

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

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

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

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

Ответ 4

Вот решение, которое, похоже, работает. В принципе, 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;
}

Ответ 5

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

// 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. Надеюсь, что это поможет.

Ответ 6

Здесь script, который изменяет размер iFrame в зависимости от тела внутри его высоты.