2011-11-09 9 views
11

私はJavaScriptのスタイルシートルールを動的に追加しようとしています。例2のようになります。 hereスタイルシートがdocument.styleSheetsに追加されるのはいつですか?

これは、ほとんどの時間の作品が、それは(少なくとも)クロム(15.0.874及び17.0.933)に時々失敗します競合状態があるように思われます。キャッシュが空の場合(またはクリアされた場合)は、まれにしか発生しません。

ここで私はそれを絞り込むことができました。最初に外部スタイルシートを<head>に追加してロードしてから、新しいスタイルシートを作成します(ここではルールを追加します)。私はdocument.styleSheetsの長さを印刷します(直ちに1秒後)。それはスタイルのいずれかを追加していないという意味

$(function() { 
    // it doesn't happen if this line is missing. 
    $("head").append('<link rel="stylesheet" type="text/css"'+ 
        'href="/css/normalize.css" />'); 

    var stylesheet = document.createElement("style"); 
    stylesheet.setAttribute("type", "text/css"); 
    document.getElementsByTagName('head')[0].appendChild(stylesheet); 

    var b = $('body'); 
    b.append(document.styleSheets.length).append('<br/>'); 
    setTimeout(function() { 
     b.append(document.styleSheets.length).append('<br/>'); 
    }, 1000); 
}); 

http://jsfiddle.net/amirshim/gAYzY/13/でそれで遊ぶ)

キャッシュがクリアされている場合、それは時々、その後24を印刷します(jsfiddleは、それ自身の2つのCSSファイルを追加します)、シートはすぐにdocument.styleSheetsになりますが、おそらく外部ファイルが読み込まれるのを待つでしょう。

これは予想されますか?

、(そこにおよび多くの他)Example 2 on MDNですもしそうなら壊れましたか?ライン27以来:

var s = document.styleSheets[document.styleSheets.length - 1]; 

私が最初に外部CSSファイルをロードしない場合にこれが起こらないことをdocument.styleSheets.length == 0

注意して評価することがあります。

+1

ご希望の最終結果は何ですか?どのような状況下でCSSファイルにルールを '注入'したいのですが、最初にCSSファイルの中に書かなければなりませんか? – Sotkra

+0

私はスタイルシートを動的に追加していますが、$(document).readyが起動した後でなければなりません... –

+1

@Kees:私が与えたコードは '$(document).ready'ですべてを行います。それは '$(function(){...});'がすることです。 – Amir

答えて

4

JavaScriptがページの下にある場合(ほとんどの場合)、HTMLパーサーは、JSとCSSが完全に読み込まれ、解析されるまでJSの実行を待たなければなりませんスクリプトが実際にこれを行うときだけそうする)。 これは事実上ほとんどの場合、外部CSSの読み込みを効果的にブロックします。 JavaScriptを使用して後で挿入するか、ページにJS 'がない(JSが非ブロッキングでロードされている)場合、CSSは非同期にロードされ、DOMの解析をブロックせずにロードされ、解析されます。 したがって、シートがDOMの中に入った後にdocument.stylesheetsのカウントが更新されるのは、シートが完全に読み込まれて解析された後にのみ発生します。

この場合、タイミングに差異が生じることがあります。 ほとんどのブラウザでは、データをロードするパイプの数が限られていることを考慮すると(いくつかはIE6のように2つしかなく、ほとんどが6で、12のものでもIE9のように)、スタイルシートの読み込みはキューの最後に追加されますロードされる。 DOMReadyで関数を呼び出すため、ブラウザはまだロード中です。 1秒後にスタイルシートが完全に読み込まれて解析されないため、document.stylesheets.lengthには影響しません。

と私はウェブ上に実行したすべてのスタイルシートの例は、DOMが完全に解析され、ロードされているとします。 OffDOMスタイルシートでは、ルールが@importルールを持つことができ、外部からロードする必要があるため、ルールを挿入またはチェックすることさえできないため、ブラウザではシートとのやりとりが安全でないと判断するのはかなり困難です。それらは完全に読み込まれ、解析されます。 OffDOMスタイルシートは、空のシートプロパティを公開しますが、シートがDOMに追加されるまで、そのシートプロパティと対話することはできません。

スタイルシートを動的に挿入し、すべての変更をその1枚のシートで実行し、document.stylesheetsだけを残しておく方が良いとわかっています。 これは、同じ特異性のスタイルを無効にすると、間違ったシートに挿入されるために問題に遭わないという大きな利点があります。 document.stylesheetsはライブnodeListなので、document.stylesheets [2]は関数を呼び出すたびに(varに格納されていない限り)別のシートを指すことができます。 私は動的に挿入されたシートを使い、そのシート上でのみ動作する傾向があります。

1

これは役立つはずです。 'When is a stylesheet really loaded' '例2' のよう

。 addStylesheetRules()を呼び出すときにスタイルシートが読み込まれると、それは壊れてしまいます(もちろんChromeにあります)。

+1

を見てください。そのため、例2は必ずしも機能しません。すなわち、I(または別のjsライブラリ)が 'addStylesheetRules()'を呼び出す前に外部スタイルシートを追加したばかりです。 – Amir

関連する問題