Czy to jest odpowiedź?
„Jeśli musisz coś obliczyć, ale nie chcesz tego pokazać, ustaw element na visibility:hidden
iposition:absolute
dodaj go do drzewa DOM, uzyskaj offsetHeight i usuń go. (To właśnie robi biblioteka prototypowa za liniami podczas ostatniego sprawdzania)”.
Mam ten sam problem z wieloma elementami. Na stronie nie ma jQuery ani prototypu, ale jestem zwolennikiem pożyczenia tej techniki, jeśli działa. Jako przykład niektórych rzeczy, które nie działały, a następnie tego, co zrobiłem, mam następujący kod:
// 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;
}
który w zasadzie próbuje wszystkiego i tylko po to, aby uzyskać zerowy wynik. ClientHeight bez wpływu. Z elementami problemowymi zwykle dostaję NaN w Bazie i zero w wysokości Przesunięcia i Przewijania. Następnie spróbowałem dodać rozwiązanie DOM i clientRects, aby sprawdzić, czy to działa tutaj.
29 czerwca 2011 r. Rzeczywiście zaktualizowałem kod, aby spróbować zarówno dodać do DOM, jak i clientHeight z lepszymi wynikami niż się spodziewałem.
1) clientHeight było również 0.
2) Dom rzeczywiście dał mi wzrost, który był świetny.
3) ClientRects zwraca wynik prawie identyczny z techniką DOM.
Ponieważ dodane elementy mają płynny charakter, po dodaniu do innego pustego elementu DOM Temp są renderowane zgodnie z szerokością tego kontenera. Dziwnie się to robi, bo jest o 30 pikseli krótsze niż ostatecznie.
Dodałem kilka migawek, aby zilustrować, w jaki sposób wysokość jest obliczana inaczej.
Różnice wysokości są oczywiste. Z pewnością mógłbym dodać pozycjonowanie bezwzględne i ukryte, ale jestem pewien, że to nie przyniesie efektu. Nadal byłem przekonany, że to nie zadziała!
(I dygresuję dalej) Wysokość wychodzi (renderuje) poniżej rzeczywistej renderowanej wysokości. Można temu zaradzić, ustawiając szerokość elementu DOM Temp w celu dopasowania do istniejącego elementu nadrzędnego i teoretycznie można to zrobić dość dokładnie. Nie wiem też, co by się stało z ich usunięcia i dodania z powrotem do ich istniejącej lokalizacji. Gdy dotarli za pomocą techniki innerHTML, będę szukał tego innego podejścia.
* JEDNAK * Nie było to konieczne. W rzeczywistości działał zgodnie z reklamą i zwrócił prawidłową wysokość !!!
Kiedy udało mi się ponownie wyświetlić menu, zadziwiająco DOM zwrócił prawidłową wysokość dla układu płynu na górze strony (279 pikseli). Powyższy kod używa również getClientRects, które zwracają 280px.
Ilustruje to poniższa migawka (pobrana z Chrome po uruchomieniu).
Teraz nie mam pojęcia, dlaczego ta prototypowa sztuczka działa, ale wydaje się, że tak. Alternatywnie działa również getClientRects.
Podejrzewam, że przyczyną wszystkich problemów z tymi konkretnymi elementami było użycie innerHTML zamiast appendChild, ale w tym momencie jest to czysta spekulacja.