Quindi questa è la risposta?
"Se devi calcolare qualcosa ma non mostrarlo, imposta l'elemento su visibility:hidden
e position:absolute
, aggiungilo all'albero DOM, ottieni offsetHeight e rimuovilo. (Ecco cosa fa la libreria dei prototipi dietro le righe l'ultima volta che ho controllato)."
Ho lo stesso problema su un numero di elementi. Non c'è jQuery o Prototype da utilizzare sul sito, ma sono tutti a favore di prendere in prestito la tecnica se funziona. Come esempio di alcune cose che non hanno funzionato, seguito da quello che ho fatto, ho il seguente codice:
// 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;
}
che fondamentalmente cerca di tutto e di tutto solo per ottenere un risultato zero. ClientHeight senza alcun effetto. Con gli elementi problematici ottengo normalmente NaN nella Base e zero nelle altezze di Scostamento e Scorrimento. Ho quindi provato la soluzione Aggiungi DOM e clientRects per vedere se funziona qui.
29 giu 2011, ho effettivamente aggiornato il codice per provare sia ad aggiungere a DOM che a clientHeight con risultati migliori di quanto mi aspettassi.
1) clientHeight era anche 0.
2) Dom in realtà mi ha dato un'altezza che è stata grandiosa.
3) ClientRects restituisce un risultato quasi identico alla tecnica DOM.
Poiché gli elementi aggiunti sono di natura fluida, quando vengono aggiunti a un elemento DOM DOM altrimenti vuoto vengono renderizzati in base alla larghezza di quel contenitore. Questo diventa strano, perché è 30px più corto di quello che alla fine finisce.
Ho aggiunto alcune istantanee per illustrare come l'altezza viene calcolata in modo diverso.
Le differenze di altezza sono evidenti. Potrei sicuramente aggiungere un posizionamento assoluto e nascosto, ma sono sicuro che non avrà alcun effetto. Ho continuato a essere convinto che non avrebbe funzionato!
(Sto divagando ulteriormente) L'altezza viene fuori (rendering) inferiore alla vera altezza di rendering. Questo potrebbe essere risolto impostando la larghezza dell'elemento DOM DOM in modo che corrisponda al genitore esistente e potrebbe essere fatto in modo abbastanza accurato in teoria. Inoltre, non so cosa sarebbe il risultato della loro rimozione e dell'aggiunta di nuovo nella loro posizione esistente. Come sono arrivati attraverso una tecnica innerHTML, cercherò di utilizzare questo approccio diverso.
* TUTTAVIA * Niente di tutto ciò era necessario. In effetti ha funzionato come pubblicizzato e ha restituito l'altezza corretta !!!
Quando sono stato in grado di rendere nuovamente visibili i menu, DOM ha restituito l'altezza corretta per il layout fluido nella parte superiore della pagina (279 px). Il codice sopra usa anche getClientRects che restituisce 280px.
Questo è illustrato nella seguente istantanea (presa da Chrome una volta che funziona).
Ora non ho idea del perché quel trucco prototipo funzioni, ma sembra. In alternativa, anche getClientRects funziona.
Sospetto che la causa di tutti questi problemi con questi elementi particolari sia stata l'uso di innerHTML invece di appendChild, ma a questo punto è pura speculazione.