2013-04-08 16 views
23

Ho bisogno di misurare con precisione le dimensioni del testo all'interno della mia app Web, che sto ottenendo creando un elemento (con classi CSS pertinenti), impostandolo come innerHTML e aggiungendolo al contenitore utilizzando appendChild.Come sapere quando un elemento creato dinamicamente ha eseguito il rendering

Dopo aver eseguito questa operazione, c'è un'attesa prima che l'elemento sia stato sottoposto a rendering e il suo offsetWidth può essere letto per scoprire quanto è ampio il testo.

Attualmente sto utilizzando setTimeout(processText, 100) per attendere il completamento del rendering.

C'è una richiamata che posso ascoltare o un modo più affidabile di dire quando un elemento che ho creato è stato reso?

+1

Nel caso in cui qualcuno trovi questa domanda, è possibile trovare buone risposte qui http://stackoverflow.com/a/5629730/697388 e qui http://stackoverflow.com/a/850995/697388 –

+0

possibile duplicato di [Come per verificare se l'elemento esiste nel DOM visibile?] (http://stackoverflow.com/questions/5629684/how-to-check-if-element-exists-in-the-visible-dom) – iConnor

+0

possibile duplicato di [Is è possibile determinare quando un elemento è stato reso utilizzando JavaScript?] (http://stackoverflow.com/questions/3667991/is-is-possible-to-determine-when-an-element-has-been-rendered-using -javascript) – Purefan

risposta

29

Attualmente non ci sono eventi DOM che indicano che un elemento è stato completamente renderizzato (ad esempio, il CSS allegato applicato e disegnato). Questo può far sì che alcuni codici di manipolazione DOM restituiscano risultati errati o casuali (come ottenere l'altezza di un elemento).

Utilizzare setTimeout per assegnare al browser un sovraccarico per il rendering è il modo più semplice. Utilizzando

setTimeout(function(){}, 0) 

è forse la pratica accurata più, come si mette il codice alla fine della coda degli eventi del browser attiva senza più ritardi - in altre parole, il codice è in coda subito dopo l'operazione di rendering (e tutti gli altri operazioni in corso al momento).

+1

vale la pena sottolineare che a volte è necessario passare in un certo tempo. Ho avuto un problema con il tentativo di ottenere l'altezza di scorrimento di un contenitore e la proprietà era talvolta 0 e talvolta corretta. L'aggiunta di un ritardo di 500 millisecondi per l'acquisizione di questa proprietà ha risolto il problema. – markthewizard1234

+0

Sembra che tu stia facendo più di un semplice rifacimento, @ markthewizard1234. – mystrdat

5

This blog post Di Swizec Teller, suggerisce di utilizzare requestAnimationFrame e di verificare l'elemento size.

function try() { 
    if (!$("#element").size()) { 
     window.requestAnimationFrame(try); 
    } else { 
     $("#element").do_some_stuff(); 
    } 
}; 

in pratica è sempre e solo una volta ritenta. Perché non importa cosa, dal prossimo fotogramma di rendering, se arriva in un 60esimo di secondo o in un minuto, l'elemento sarà stato renderizzato.

0

quando si effettua ad esempio

var clonedForm = $('#empty_form_to_clone').clone(true)[0]; 

var newForm = $(clonedForm).html().replace(/__prefix__/g, next_index_id_form); 

// next_index_id_form is just a integer 

Che ci faccio qui?
Clona un elemento già sottoposto a rendering e modifica il codice HTML da sottoporre a rendering.

Successivamente aggiungo il testo a un contenitore.

$('#container_id').append(newForm); 

Il problema nasce quando voglio aggiungere un gestore di eventi a un pulsante all'interno Newform, BENE, basta usare pronto evento.

$(clonedForm).ready(function(event){ 
    addEventHandlerToFormButton(); 
}) 

Spero che questo ti aiuti.

PS: Ci scusiamo per il mio inglese.

3

La risposta accettata è del 2014 ed è obsoleta. Un setTimeout potrebbe funzionare, ma non è il più pulito e non garantisce necessariamente che l'elemento sia stato aggiunto al DOM.

Oggi, uno MutationObserver è ciò che è necessario utilizzare per rilevare quando un elemento è stato aggiunto al DOM. MutationObservers ora è ampiamente supportato da tutti i browser moderni (Chrome 26+, Firefox 14+, IE11, Edge, Opera 15+, ecc.).

Quando un elemento è stato aggiunto al DOM, sarà possibile recuperare le sue dimensioni effettive.

Ecco un semplice esempio di come è possibile utilizzare un MutationObserver da ascoltare quando un elemento viene aggiunto al DOM.

Per brevità, sto usando la sintassi jQuery per creare il nodo e inserirlo nel DOM.

var myElement = $("<div>hello world</div>")[0]; 

var observer = new MutationObserver(function(mutations) { 
    if (document.contains(myElement)) { 
     console.log("It's in the DOM!"); 
     observer.disconnect(); 
    } 
}); 

observer.observe(document, {attributes: false, childList: true, characterData: false, subtree:true}); 

$("body").append(myElement); // console.log: It's in the DOM! 

Il gestore eventi observer attiverà ogni volta che viene aggiunto o rimosso dal document qualsiasi nodo. All'interno del gestore, eseguiamo quindi un controllo contains per determinare se myElement è ora nello document.

Non è necessario iterare su ciascuna MutationRecord memorizzata in mutations perché è possibile eseguire il controllo document.contains direttamente su myElement.

Per migliorare le prestazioni, sostituire document con l'elemento specifico che conterrà myElement nel DOM.

+0

Questo non funziona nel caso di rendering di testo. –

+0

@ErikGrosskurth document.contains funziona anche con 'TextNode'. Ecco un esempio: jsfiddle.net/ef9yub3y Ma secondo l'MDN, potrebbe non funzionare con IE più vecchi. Se hai qualche problema con la tua implementazione, sentiti libero di pubblicare su SO e sarei felice di dare un'occhiata. –

+0

La cosa con testo è il rendering dell'elemento dom e quindi il testo muta ulteriormente l'osservatore che è già entrato nell'istruzione if, così l'osservatore conserva l'istantanea iniziale. Potrebbe essere solo una cosa cromata. Non sono sicuro –

Problemi correlati