Так это ответ?
«Если вам нужно что-то вычислить, но не показывать, установите для элемента значение visibility:hidden
и position:absolute
, добавьте его в дерево DOM, получите offsetHeight и удалите его (это то, что библиотека прототипов делает за строкой в прошлый раз, когда я проверял)».
У меня та же проблема по ряду элементов. На сайте нет ни jQuery, ни прототипов, но я полностью поддерживаю заимствование техники, если она работает. В качестве примера некоторых вещей, которые не сработали, после чего я приведу следующий код:
// Layout Height Get
function fnElementHeightMaxGet(DoScroll, DoBase, elementPassed, elementHeightDefault)
{
var DoOffset = true;
if (!elementPassed) { return 0; }
if (!elementPassed.style) { return 0; }
var thisHeight = 0;
var heightBase = parseInt(elementPassed.style.height);
var heightOffset = parseInt(elementPassed.offsetHeight);
var heightScroll = parseInt(elementPassed.scrollHeight);
var heightClient = parseInt(elementPassed.clientHeight);
var heightNode = 0;
var heightRects = 0;
//
if (DoBase) {
if (heightBase > thisHeight) { thisHeight = heightBase; }
}
if (DoOffset) {
if (heightOffset > thisHeight) { thisHeight = heightOffset; }
}
if (DoScroll) {
if (heightScroll > thisHeight) { thisHeight = heightScroll; }
}
//
if (thisHeight == 0) { thisHeight = heightClient; }
//
if (thisHeight == 0) {
// Dom Add:
// all else failed so use the protype approach...
var elBodyTempContainer = document.getElementById('BodyTempContainer');
elBodyTempContainer.appendChild(elementPassed);
heightNode = elBodyTempContainer.childNodes[0].offsetHeight;
elBodyTempContainer.removeChild(elementPassed);
if (heightNode > thisHeight) { thisHeight = heightNode; }
//
// Bounding Rect:
// Or this approach...
var clientRects = elementPassed.getClientRects();
heightRects = clientRects.height;
if (heightRects > thisHeight) { thisHeight = heightRects; }
}
//
// Default height not appropriate here
// if (thisHeight == 0) { thisHeight = elementHeightDefault; }
if (thisHeight > 3000) {
// ERROR
thisHeight = 3000;
}
return thisHeight;
}
который в основном пытается что-нибудь и все, только чтобы получить нулевой результат. ClientHeight без каких-либо последствий. С проблемными элементами я обычно получаю NaN в базе и ноль в высотах смещения и прокрутки. Затем я попытался добавить решение DOM и clientRects, чтобы увидеть, работает ли оно здесь.
29 июня 2011 года я действительно обновил код, чтобы попытаться добавить DOM и clientHeight с лучшими результатами, чем я ожидал.
1) clientHeight также был 0.
2) Дом на самом деле дал мне рост, который был отличным.
3) ClientRects возвращает результат, почти идентичный методу DOM.
Поскольку добавленные элементы являются текучими по своей природе, при добавлении их в пустой элемент Temp DOM в противном случае они отображаются в соответствии с шириной этого контейнера. Это странно, потому что это на 30px короче, чем в итоге получается.
Я добавил несколько снимков, чтобы проиллюстрировать, как высота рассчитывается по-разному.
Разница в высоте очевидна. Я, конечно, мог бы добавить абсолютное позиционирование и скрытое, но я уверен, что это не будет иметь никакого эффекта. Я продолжал убеждаться, что это не сработает!
(Я отвлекаюсь дальше) Высота получается (отображается) ниже, чем истинная отображаемая высота. Эту проблему можно решить, установив ширину элемента DOM Temp в соответствии с существующим родителем, и теоретически это можно сделать довольно точно. Я также не знаю, что произойдет, если удалить их и добавить обратно в их существующее местоположение. Когда они пришли через метод innerHTML, я буду искать, используя этот другой подход.
* ОДНАКО * Ничего из этого не было необходимо. Фактически это работало как рекламируется и возвратило правильную высоту !!!
Когда я смог снова увидеть меню, DOM вернул правильную высоту в соответствии с макетом жидкости в верхней части страницы (279 пикселей). Приведенный выше код также использует getClientRects, которые возвращают 280px.
Это показано на следующем снимке (взятом из Chrome после работы.)
Теперь у меня нет идеи, почему этот трюк с прототипом работает, но, похоже, это так. Кроме того, getClientRects также работает.
Я подозреваю, что причиной всех этих проблем с этими конкретными элементами было использование innerHTML вместо appendChild, но на данный момент это чистое предположение.