Вычисление высоты перекрестного браузера 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)? Некоторые подсказки или подсказки?
Ответы
Ответ 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 в зависимости от тела внутри его высоты.