2013-04-08 13 views
23

Webアプリケーション内のテキストの寸法を正確に測定する必要があります。関連するCSSクラスを使用して要素を作成し、innerHTMLを設定します。容器はappendChildを使用しています。動的に作成された要素がレンダリングされたときの通知方法

これを実行すると、要素がレンダリングされるまで待機し、offsetWidthを読み取ってテキストの幅を調べることができます。

現在、私はsetTimeout(processText, 100)を使用してレンダリングが完了するまで待っています。

私が聞くことができるコールバックがありますか、または私が作成した要素がいつレンダリングされたかをより確実に伝える方法はありますか?

+1

誰かがこの質問を見つけた場合は、良い回答がここにありますhttp://stackoverflow.com/a/5629730/697388ここでhttp://stackoverflow.com/a/850995/697388 –

+0

[表示されているDOMに要素が存在するかどうかを確認しますか?](http://stackoverflow.com/questions/5629684/how-to-check-if-element-exists-in-the-visible-dom) – iConnor

+0

[Is JavaScriptを使用して要素がレンダリングされた時期を判断することはできますか?](http://stackoverflow.com/questions/3667991/is-is-possible-to-determine-when-an-element-has-been-rendered-using -javascript) – Purefan

答えて

29

現在、要素が完全にレンダリングされたことを示すDOMイベントはありません(たとえば、CSSが適用され、描画されているなど)。これは、いくつかのDOM操作コードが間違った結果(要素の高さの取得など)を返すことがあります。

ブラウザにレンダリングのオーバーヘッドを与えるためにsetTimeoutを使用するのが最も簡単な方法です。言い換えれば、あなたのコードは、右のレンダリング操作の後にキューに入れられた(および他のすべてのさ - これ以上遅れることなくアクティブブラウザのイベントキューの最後にあなたのコードを置くよう

setTimeout(function(){}, 0) 

を使用することで、おそらく最も実用的に正確ですその時に起こっている操作)。

+1

は時々あなたが時間を過ごす必要があることを指摘する価値があります。私はコンテナのスクロールの高さを取得しようとすることに問題があり、そのプロパティは時には0で、時には正しいものでした。このプロパティを取得するために500ミリ秒の遅延を追加することで問題が解決されました。 – markthewizard1234

+0

あなたは1つの再塗装に収まる以上のことをしているように思えます。@ markthewizard1234 – mystrdat

5

This blog post Swizec Tellerは、​​を使用し、要素のsizeを確認してください。実際に

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

それは今まで一度再試行します。次のレンダリングフレームによって、60分の1秒か1分かにかかわらず、要素がレンダリングされているためです。

0

あなたは一例

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 

のために作るとき、私はここで何をしているのですか?
すでにレンダリングされた要素を複製し、レンダリングするhtmlを変更します。

次に、そのテキストをコンテナに追加します。私はちょうど準備イベントを使用し、NEWFORM、WELL内部のボタンにイベントハンドラを追加したいとき

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

問題が来ます。

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

私はこれが役に立ちます。

PS:私の英語は申し訳ありません。

3

受け入れられる回答は2014年からのもので、現在は古くなっています。 A setTimeoutが機能するかもしれませんが、最もクリーンではなく、要素がDOMに追加されたことを必ずしも保証するものではありません。

今日、MutationObserverは、要素がDOMに追加されたことを検出するために使用する必要があります。 MutationObserversは現代のすべてのブラウザ(Chrome 26+、Firefox 14+、IE11、Edge、Opera 15+など)で広くサポートされるようになりました。

要素がDOMに追加されると、その実際の寸法を取得できます。

ここでは、MutationObserverを使用して要素がDOMに追加されたときをリッスンする方法の簡単な例を示します。

簡潔にするために、私はノードを構築してDOMに挿入するためにjQuery構文を使用しています。任意のノードが追加またはdocumentから除去されるたびに

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! 

observerイベントハンドラがトリガされます。ハンドラ内でcontainsのチェックを実行してmyElementdocumentにあるかどうかを確認します。

mutationsに格納されている各MutationRecordを反復処理する必要はありません。myElementに直接document.containsのチェックを行うことができます。

パフォーマンスを向上させるには、documentを、DOMにmyElementを含む特定の要素に置き換えます。

+0

テキストレンダリングの場合、これは機能しません。 –

+0

@ErikGrosskurth document.containsも 'TextNode'で動作します。ここに例があります:jsfiddle.net/ef9yub3yしかし、MDNによると、それは古いIEでは動作しないかもしれません。あなたの実装にいくつかの問題がある場合は、すぐに投稿してください。よろしくお願いします。 –

+0

テキストを持つものはdom要素であり、オブザーバが初期のスナップショットを保持するように、オブザーバがすでにif文に入力した文字列がさらに変化します。それはちょうどクロムの事かもしれない。わからない –

関連する問題