jQueryのロードのフォールバックでHTML4やXHTML1.0準拠の書き方を考えてみた


  • 公開:
  • 更新:
  • 編集:
概要 ▶ 「jQueryをロードする際のナイス!と思った書き方」でコメントを頂いたので返信がてら記事を書いてみようと思います。シマダさんからコメントを頂きました。ありがとうございます。フォールバックの違う書き方をCSS-Tricksで見つけました。http://css-tricks.com/snippets/jquery/fallback-for-cdn-hosted-jquery/Initializrが書
20120406-jQueryのattrとprop-00

jQueryをロードする際のナイス!と思った書き方」でコメントを頂いたので返信がてら記事を書いてみようと思います。


シマダさんからコメントを頂きました。ありがとうございます。
フォールバックの違う書き方をCSS-Tricksで見つけました。
http://css-tricks.com/snippets/jquery/fallback-for-cdn-hosted-jquery/

Initializrが書き出すやつはHTML5用であり、HTML4やXHTML1.0ではHTMLの文法エラーを招くので、HTML4やXHTML1.0に書くのであればCSS-Tricksで紹介されているやつがいいでしょう。
jQueryをロードする際のナイス!と思った書き方

なるほど。まだ皆さんがHTML5になっているわけではないですから、重要な指摘ですね。


では文法エラーは何が出るのかから見てみましょう。

InitializrのHTMLとXHTML1.0の文法エラー

Another HTML-lint gatewayを利用させて頂いて確認します。ありがとうございます。

以下の部分に対して

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.2.min.js"><\/script>')</script>


次のエラーが表示されました。
  • (1) <script> の src 属性の URI `//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js` はうまく評価されないかも知れません。
  • (2) <script> には type 属性が必要です。
  • (3) メタ文字 `<` は `&lt;` と書かなければなりません。
  • (4) メタ文字 `>` は `&gt;` と書かなければなりません。
  • (5) <script> に対応する終了タグ </script> が見つかりません。

(1)は無視しても構わないエラーでしょう。
(2)はHTML5の場合、scriptのtypeは基本的にJavaScriptと決まっているので、<script type="text/javascript">とは書いていないからでしょう。
また、document.writeの中で呼び出しているscriptタグにもtype="text/javascript"がないためエラーになっています。
(3)(4)のメタ文字の制限は厳しいですね。&lt;・&gt;に書き直して正常に動くブラウザがどのくらいあるのか…。
(5)は仕方が無いです(笑)。scriptタグ内でscriptタグを使用しているので、閉じタグを使用すると問題があるためです。


CSS TricksのjQueryのフォールバックの書き方

コメントで頂いた「Fallback for CDN hosted jQuery | CSS-Tricks」に掲載されている書き方は以下の通りです。

<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
if (typeof jQuery == 'undefined') {
    document.write(unescape("%3Cscript src='/js/jquery-1.4.2.min.js' type='text/javascript'%3E%3C/script%3E"));
}
</script>


「if (typeof jQuery == 'undefined')」 の部分は「window.jQuery ||」でも同じ結果かな。


このCSS Tricksのフォールバックの勘所はunescape関数を使ってメタ文字を回避している点でしょうか。

おもしろいアイデアです。
この書き方だとLintでエラーは出ません。
HTML4やXHTML1.0を使っている人はこのような書き方もありでしょう。


Google Analyticsのコードを参考にしてみる

「document.write(unescape())」の書き方はどこかで見たことがあるな…と思って調べてみたらGoogle Analyticsの古いコードでした。

トラッキング コードの追加(従来のコード) - アナリティクス ヘルプ」のページには以下のコードが掲載されていました。(太字は筆者によるもの)

<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
</script>
try{
var pageTracker = _gat._getTracker("UA-xxxxxx-x");
pageTracker._trackPageview();
} catch(err) {}
</script>


現在はこのようなコードでないことはWeb制作者の方ならご存じのはずですね。
トラッキング コードの設定(非同期) - アナリティクス ヘルプ」のページによれば、現在は以下のコードになっています。(太字は筆者)

<script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXX-X']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

</script>

この書き方はLintでエラーは出ません。


結論:最終コード(Google Analytics的コードの場合)

ということは、HTML4やXHTML1.0に準拠したjQueryのフォールバックのコードは以下のコードで良いのではないでしょうか。

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
    (function() {
        window.jQuery ||
            var jq = document.createElement('script');
            jq.type = 'text/javascript';
            jq.async = true;
            jq.src = '/js/jquery-1.7.2.min.js';
            var s = document.getElementsByTagName('script')[0];
            s.parentNode.insertBefore(jq, s);
    })();
</script>

「jq.async=true;」で非同期で読み込む設定にしているのが微妙な感じもしますが大きな問題は発生しないと思います。(直後にjQueryの命令を使う場合は非同期読み込みはダメですが)


あと1行目は「うまく評価されないかも知れません」というLintのエラーが出ますが、実際の動作としてはほとんど問題は起きません。
しかし、どうしてもLintでエラーを出したくなければ「document.location.protocol」を使って回避するコードを書けば良いでしょう。または常にhttpsでロードするようにして「src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"」としても良いでしょう。



なにか間違っている点があればご指摘頂ければありがたいです。(スクリプトが長くなりすぎって以外(笑))
それでは。

カテゴリー:

このページをぜひシェアしてください