Entonces, ¿es esta la respuesta?
"Si necesita calcular algo pero no mostrarlo, establezca el elemento en visibility:hidden
yposition:absolute
, agréguelo al árbol DOM, obtenga el offsetHeight y elimínelo (eso es lo que hace la biblioteca prototipo detrás de las líneas la última vez que lo verifiqué)".
Tengo el mismo problema en varios elementos. No hay jQuery o Prototype para usar en el sitio, pero estoy a favor de tomar prestada la técnica si funciona. Como ejemplo de algunas cosas que no funcionaron, seguido de lo que hizo, tengo el siguiente código:
// 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;
}
que básicamente intenta cualquier cosa y todo solo para obtener un resultado cero. ClientHeight sin afectar. Con los elementos del problema, normalmente obtengo NaN en la Base y cero en las alturas de Desplazamiento y Desplazamiento. Luego probé la solución Agregar DOM y clientRects para ver si funciona aquí.
El 29 de junio de 2011, de hecho, actualicé el código para intentar agregar a DOM y clientHeight con mejores resultados de lo que esperaba.
1) clientHeight también fue 0.
2) Dom realmente me dio una altura que fue genial.
3) ClientRects devuelve un resultado casi idéntico a la técnica DOM.
Debido a que los elementos agregados son de naturaleza fluida, cuando se agregan a un elemento DOM Temp vacío, se representan de acuerdo con el ancho de ese contenedor. Esto se vuelve extraño, porque es 30px más corto de lo que finalmente termina.
Agregué algunas instantáneas para ilustrar cómo la altura se calcula de manera diferente.
Las diferencias de altura son obvias. Ciertamente podría agregar posicionamiento absoluto y oculto, pero estoy seguro de que no tendrá ningún efecto. ¡Seguí convencido de que esto no funcionaría!
(Me desvío más) La altura sale (se renderiza) más baja que la altura real renderizada. Esto podría abordarse estableciendo el ancho del elemento DOM Temp para que coincida con el padre existente y podría hacerse con bastante precisión en teoría. Tampoco sé qué resultaría de eliminarlos y agregarlos nuevamente a su ubicación actual. Cuando llegaron a través de una técnica innerHTML, buscaré usando este enfoque diferente.
* SIN EMBARGO * Nada de eso era necesario. De hecho, funcionó según lo anunciado y devolvió la altura correcta.
Cuando pude volver a ver los menús de manera sorprendente, DOM había devuelto la altura correcta según el diseño fluido en la parte superior de la página (279 px). El código anterior también usa getClientRects que devuelve 280px.
Esto se ilustra en la siguiente instantánea (tomada de Chrome una vez que funciona).
Ahora no tengo ni idea de por qué funciona ese truco prototipo, pero parece que sí. Alternativamente, getClientRects también funciona.
Sospecho que la causa de todos estos problemas con estos elementos en particular fue el uso de innerHTML en lugar de appendChild, pero eso es pura especulación en este momento.