もっと実際的な例
ここで具体例として示すASP.NETページでは、クライアントサイドでjQueryを使ってページを調整して、jQueryの一部の機能を強調します。このページには、データから読み込んだ単純なテーブルを表示するためのGridViewが含まれています。このページを操作するために、jQueryと若干のコードを追加したいと思います。自分でも試してみたい方は、本稿のサンプルコードをダウンロードしてご利用ください。リスト1に、省略版のASP.NETページを示しておきます(サンプルコードにはHTMLファイルも含まれています)。
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>jQuery 101</title>
<link href="Standard.css" rel="stylesheet"
type="text/css" />
<link href="jQuery101.css" rel="stylesheet"
type="text/css" />
<script src="scripts/jquery.js"
type="text/javascript"></script>
</head>
<body>
...
<asp:GridView ID="gdEntries" runat="server"
AutoGenerateColumns="false"
cssClass="blackborder"
CellPadding="4">
<HeaderStyle CssClass="gridheader" />
<PagerStyle CssClass="gridpager" HorizontalAlign="Right"/>
<RowStyle CssClass="griddatarow" />
<Columns>
<asp:BoundField DataField="TimeIn" HeaderText="Time in"
DataFormatString="{0:MMM dd hh:mm tt}"
ItemStyle-CssClass="timeinField"/>
<asp:TemplateField ItemStyle-CssClass="descriptionField">
<ItemTemplate>
<div id="entrytitle"><%# Eval("Title") %></div>
<div id="entrydescription"><%# Eval("Description"))%>
</div>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ItemTotal"
HeaderText="Total" />
</Columns>
</asp:GridView>
</form>
</body>
</html>
この例ではGridViewに最小限の書式を適用するので、このページを実行すると、図1のような白黒の単純なグリッド(格子)が表示されます。
次にjQueryを使って要素を選択し、テーブルの見映えを少しよくすると共に、ある種の対話機能を追加します。まずテーブルの行に対して1行おきに処理するエフェクトを適用します。そのために、最後のページの</form>タグのすぐ上に次のようなスクリプトタグを追加します。
<script type="text/javascript">
$(document).ready( function() {
$("#gdEntries tbody tr:even")
.addClass("gridalternate");
.css("border","solid 1px lightgrey");
});
</script>
図2に1行おきのストライプのエフェクトを示します。
jQuery()/$()オブジェクト
上記のスクリプトブロックの$記号に注目してください。これはjQueryオブジェクトの別名です。この2つを互換的に使用することができます。従って、コード中でjQuery(document)やjQuery("#gdEntries")と書いても、$(document)や$("#gdEntries")と書いても同じことです。jQueryオブジェクトはパラメータとしてセレクタを受け取ります。セレクタは文字列で表現するのが普通ですが、DOM要素や別のjQueryオブジェクトを渡すこともできます。
例えば、$(document)はドキュメントにDOM要素を渡し、結果としてドキュメントオブジェクトが含まれる単一の要素ラップセットが生じます。$("#gdEntries")はページ上のgdEntriesテーブルを選択します。ただし、#はID識別子で、これはCSSの場合と同じです。
$(document).ready()ハンドラ
$(document).ready()ハンドラの使用に注意してください。.ready()はjQueryのイベントハンドラです。このイベントハンドラが呼び出されるのは、ドキュメントにアクセスできるときとスクリプトがロードを完了したときです。これをコードに含めると、コードからページのすべてのDOM要素とスクリプトコードに確実にアクセスできるようになります。.ready()ハンドラはページのどこにでも挿入できます。同じページに複数の.ready()ハンドラを配置することさえできます。
.ready()ハンドラの使用は必須ではありませんが、すべてのブラウザで一貫した動作が行われるようにするために、必ず「スタートアップコード」のスクリプトをラップして.ready()ハンドラに入れることをお勧めします。
jQueryは無名関数を使ってこのハンドラを実装しています。つまり、.ready()関数呼び出しと共にインラインでハンドラを宣言しているということです。
$(document).ready( function {...} );
これはjQueryでよく見られるやり方です。なぜなら、インライン関数はJavaScriptでよく使われる短いハンドラコードを書くための簡単な方法だからです。インライン関数には他にも利点がありますが、さしあたり、インライン無名関数がイベントハンドラを書くための一般的なやり方だという点だけ覚えておいてください。無名関数の代わりに関数ポインタを渡すこともできます。
$(document).ready( onLoaded );
... more script here
function onLoaded(e) { ... }
セレクタについて
行の選択を行っているグリッドのコードをもう一度見てください。$("#gdEntries tbody tr:even")は、グリッドのテーブル出力の偶数番目の行をすべて選択します。ここでのセレクタの意味は「gdEntries要素(#)を選択し、子tbody要素(スペース=子)を探し、それらの下にあるtr要素を探し、偶数番目の要素だけが含まれたフィルタ処理済みのセット(:even=フィルタ)を返す」ということです。
このセレクタの結果はテーブル内の偶数番目の全行から成るラップセットです。.addClass("gridalternate")関数はマッチした各要素に.gridalternate CSSスタイルを適用し、それによって強調表示にします。最後に.css関数がマッチした各要素にある種のカスタムスタイルを適用します。.addClass()も.cssも、それぞれの操作を、マッチした全要素に対して同時に適用します。
セレクタでありがちな過剰選択
サンプルコードを実行すると、偶数番目の行が強調される一方で、テーブル内におかしな副作用が生じることにも気づくでしょう。ASP.NETがテーブルとしてレンダリングしているページャを見ると、1行おきに.gridalternateクラスでマークアップされていることが分かります。問題は、ASP.NETのGridViewレンダリングがあまり正確でないことです。テーブルのヘッダーとフッターの輪郭を描く適切なtbodyタグとtfootタグがレンダリングされないので、セレクタクエリの範囲が広くなりすぎ、子要素にもマッチし、フッターに子ページャテーブルが含まれます。
この問題を修正する方法はいくつかあります。その1つとして、ある特定の要素を除外することで選択にフィルタを適用する方法があります。
$("#gdEntries tbody tr")
.not(":first,:last")
.filter(":even")
.addClass("gridalternate")
.css("border","solid 1px lightgrey");
このコードでは、奇数番目の全行にフィルタをかける代わりに、まず行をフィルタ処理して最初と最後の行(ヘッダーとフッター)を省きます。そして残りの行から偶数番目のアイテムのみを取り出します。もう1つの(もっと簡単な)方法は、すべての子を選択するスペースを使わずに、大なり(>)演算子を使って直接の子だけを選択するというものです。
$("#gdEntries>tbody>tr:even")
この他に、要素のフィルタリングを柔軟に行うための一般的かつ効果的な方法は、CSSクラスマッチングを利用することです。マークアップ内の要素には、CSSクラス(またはマッチするCSSクラスのない単なる「マーカー」クラス)を追加することができます。
GridViewの行がレンダリングされる方法をもう一度見てください。
<RowStyle CssClass="griddatarow" />
この例では、HTMLでレンダリングされる各行にCSSクラスgriddatarowを追加しています。griddatarowというCSSクラスは実際には存在しませんが、jQueryはセレクタ式でこのクラスとのマッチングを行うことができます。従って、次のコードは正しく機能します。
$("#gdEntries tr.griddatarow:odd")
もっと単純にすると、次のようになります。
$(".griddatarow:odd")
この単純な方も機能しますが、冗長であっても先に挙げた方が望ましいでしょう。対象をできるだけ限定することでドキュメントでのjQuery選択を最適化するのが肝要です。前者の場合はgdEntriesテーブルを探し、その中でのみ子を探しますが、後者の場合はドキュメント全体を解析しなければなりません。最初のセレクタでマッチする要素が少ないほど、反復処理すべき要素が少なくなります。
グリッド内の3番目の行の2番目のセルを選択するなら次のようにします。
$("#gdEntries>tbody>tr:nth-child(3)" +
">td:nth-child(2)")
.addClass("gridalternate");
2番目の列のすべてのセルを選択するなら次のようにします。
$("#gdEntries>tbody>tr>td:nth-child(2)")
.addClass("gridalternate")
とても簡単ですね! これをスクリプトコードで実現しようとしたらかなり複雑な作業になってしまいますが、セレクタを使えば1行で済み、簡単に書くことができます。しかも、より重要なのは、一目で理解できることです。


