jQuery は、軽量 (縮小化して gzip で圧縮すると約 25KB) で CSS3 に準拠したクロス・ブラウザーのライブラリーで、ブラウザーの種類によらず動作します。jQuery ライブラリーは HTML の DOM (Document Object Model) のトラバースと操作、イベント処理などを行うための豊富な API セットを提供しています。また jQuery ライブラリーの Ajax (Asynchronous JavaScript and XML) リクエスト API を使用すると、サーバーと通信することができます。さらに jQuery ライブラリーには、Web ページのためのアニメーション効果や画像効果、そして強力なプラグイン・アーキテクチャーも用意されています。
この記事では jQuery のデータ・ストレージ機能の使い方として、特定の DOM 要素とデータとを関連付け、カスタムの非表示データを Web ページに埋め込む方法を学びます。そのために、この機能をアプリケーションの中で使用する方法を詳細な例によって示します。また jQuery を使用したアプリケーションで HTML5 の data-* 属性を活用する方法を学びましょう。
この記事を読み進める上で内容を理解するには、以下のことが要求されます。
- HTML の使用経験
- JavaScript に関する基礎知識
- jQuery に関する基礎知識
この記事で使用しているソース・コードとサンプルはダウンロードすることができます。
作業をしている中で、Web ページの特定要素に関連付けられた隠し情報やメタデータを格納しなければならない場合があります。こうした情報を、別途取得しなくても利用できる状態にしておくと、Web ページや関連するコードを単純化することができます。こうした隠し情報は、スタイル設定をするためや、ユーザーが特定の UI 要素を選択した際に計算をするため、そしてユーザーに対して表示する結果をフィルタリングするためなど、さまざまな用途に使用することができます。
通常、隠し情報を Web ページ内に含めるためには創造的な方法が必要でした。例えば以下のような方法があります。
- HTML 要素の属性 (
id、class、rel、titleなど) の中に情報を格納し、その属性本来の目的を変えてしまう方法。 <span>ブロックまたは<div>ブロックを使用して隠し情報を含める一方、それらのブロックをスタイル設定 (style="display: none;") によってユーザーに対して非表示にする方法。- Web ページに JavaScript コードを追加し、HTML の ID 要素にマッピングされるデータ構造を定義する方法。
- 独自の属性を既存の HTML 要素に追加する (HTML 標準自体に違反させ、HTML ブラウザーに依存することによって構文エラーを無視する) 方法。
上記の他にも方法はあり、あとは開発者の創造的な力次第です。
上記の方法はスマートではなく、適切なコーディング方法とは言えません。しかし幸いなことに、ブラウザーに依存しないすっきりとした方法で DOM 要素にデータを簡単に関連付けられる機能が jQuery に用意されています。
jQuery の data() API を利用すると、特定の DOM
要素に関連付けられたデータを格納、取得することができます。しかもさらに強力なことに、JavaScript
オブジェクトを始めとする、さまざまなデータ型がサポートされています。jQuery の data() メソッドにより、データを非表示のまま特定の DOM 要素に関連付けられるため、HTML ビューとデータとを完全に分離することができます。この方法により、HTML 自体を簡潔に保つことができ、必要な静的情報を追加で取得するために Ajax 呼び出しを行う必要がありません。
jQuery JavaScript ライブラリーには 2 つのデータ・メソッドが定義されています (表 1)。
表 1. jQuery のデータ・メソッド
| 一般的な形式 | 説明 | フォーマット |
|---|---|---|
jQuery.data (または $.data) | 指定された要素に関連付けられた任意のデータを格納します | jQuery.data(element, key, value)
jQuery.data(element, key)
jQuery.data(element) |
jQuery.fn.data (または $.fn.data) | 一致した要素に関連付けられた任意のデータを格納します | .data(key, value)
.data(obj)
.data(key)
.data() |
jQuery.data() の場合、データは特定の DOM
要素と関連付けられます。この形式では、開発者自らが対象とする要素を選択して追跡しなければならないため、jQuery.fn.data() ほど実用的ではありません。この data() 形式は fn.data() 形式よりも動作は高速ですが、本来、jQuery フレームワークの下位レベルで使用するためのものです。
jQuery.fn.data() の場合、データは指定された jQuery 選択基準と一致する DOM
要素と関連付けられます。この形式では、渡された選択基準に基づいて、jQuery が自動的に要素を選択してくれるため、fn.data() 形式の方が実用的です。$.fn.data は要素選択機能を実行するため、$.data よりも動作は低速です。
jQuery 1.4.3 からは、$fn.data() は HTML の DOM から HTML5 の data 属性を返すはずです。HTML5 のデータ・ストレージおよび jQuery に関するドキュメントは、この点について詳細に説明されています。
この記事のこれから先では、主に jQuery.fn.data() に焦点を絞って説明します。
jQuery を使用して DOM に基づいてデータを格納、取得する
まず、いくつかの基本事項を説明しましょう。ブラウザーによって Web ページ (または XML 文書) がロードされると、その Web ページは構文解析され、その Web ページの DOM 表現が作成されます。リスト 1 は単純な HTML ファイルの例を示しています。
リスト 1. 単純な HTML ファイル
<table>
<tbody>
<tr>
<td>Shady Grove</td>
<td>Aeolian</td>
</tr>
<tr>
<td>Over the River, Charlie</td>
<td>Dorian</td>
</tr>
</tbody>
</table>
|
図 1 は、この HTML に関連付けられた DOM を示しています。この DOM は W3C の仕様書に記載されている例を基に作成したものです (「参考文献」のリンクを参照)。
図 1. リスト 1 の HTML をグラフィカルに表現した DOM
DOM を利用することにより、HTML 文書や XML 文書の中にあるすべて (各要素およびコンテンツ) に対し、プログラムによってアクセスしたり、追加、削除、変更などを行ったりすることができます。
jQuery を利用することにより、JavaScript のデータ型 (文字列、数値、オブジェクト、配列、イベント、関数) を特定の DOM
要素と関連付けることができます。データは内部の索引付けされた jQuery キャッシュの JavaScript オブジェクトに格納されます。名前が付けられたデータと DOM
要素とが関連付けられるため、jQuery では DOM を基にデータを格納したり取得したりすることができます。リスト 2に は、このキャッシュと jQuery.data() メソッドの定義を示しています。
リスト 2. jQuery.cache と下位レベルの
jQuery.data() メソッドの定義
(function( jQuery ) {
jQuery.extend({
cache: {},
// Please use with caution
uuid: 0,
// Unique for each copy of jQuery on the page
expando: "jQuery" + jQuery.now(),
:
:
data: function( elem, name, data ) {
if ( !jQuery.acceptData( elem ) ) {
return;
}
elem = elem == window ?
windowData :
elem;
var isNode = elem.nodeType,
id = isNode ? elem[ jQuery.expando ] : null,
cache = jQuery.cache, thisCache;
if ( isNode && !id && typeof name === "string"
&& data === undefined ) {
return;
}
// Get the data from the object directly
if ( !isNode ) {
cache = elem;
// Compute a unique ID for the element
} else if ( !id ) {
elem[ jQuery.expando ] = id = ++jQuery.uuid;
}
// Avoid generating a new cache unless none exists and we
// want to manipulate it.
if ( typeof name === "object" ) {
if ( isNode ) {
cache[ id ] = jQuery.extend(cache[ id ], name);
} else {
jQuery.extend( cache, name );
}
} else if ( isNode && !cache[ id ] ) {
cache[ id ] = {};
}
thisCache = isNode ? cache[ id ] : cache;
// Prevent overriding the named cache with undefined values
if ( data !== undefined ) {
thisCache[ name ] = data;
}
return typeof name === "string" ? thisCache[ name ] : thisCache;
},
:
:
|
jQuery.fn.data() メソッドの定義も同様なので、この記事とは別の演習として
jQuery.fn.data() メソッドの定義方法を考えてみてください。その場合、Github にある data.js が役立ちます (「参考文献」のリンクを参照)。
以下のセクションでは、指定の DOM 要素に関連付けられているデータを、索引付けされた jQuery のデータ・キャッシュに格納する方法、およびそのデータを取得する方法を学びます。
先ほど触れたように、jQuery を利用すると、JavaScript の任意のデータ型 (文字列、数値、オブジェクト、配列、イベント、関数) のデータを DOM に基づいて格納、取得することができます。これらのデータは内部の索引付けされた jQuery キャッシュの JavaScript オブジェクトに格納されます。
jQuery の data メソッドを使ってデータを格納、および取得する方法を示すために、CSS ベースの表とフィルター関数を使用する Web ページの例を説明します。このフィルター関数は、特定の行の DOM 要素と関連付けられたデータに基づいて行をフィルタリングします。図 2 はこの例を示しています。
図 2. DOM を基にデータを格納、取得する方法を示す Web ページの例
このサンプル Web ページのコンテンツとしては、レストランの名前、提供される料理の種類、場所、そのレストランのランキングが表で表示されています。Web
ページの本体はいくつかの <div> セクションで構成されており、これらのセクションによってサイドバーと、テーブルまたはグリッド自体を定義しています (リスト 3)。
リスト 3. HTML の内容
<body>
<div id="sidebar">
Filter by type, location or rating:
<input type="text" />
<button id="filter">Filter</button>
<button id="clear">Clear</button>
<p>
To keep the sample code simple, the search terms are "ORed". Example
"seafood 2 stars downtown" which returns all rows that match seafood OR 2+ stars
OR in downtown.
</p>
</div>
<div id="rows">
<p>
This sample web page shows how to use the <code>jQuery.data()</code>
method. It uses a CSS-based table and a filter function that filters rows based on the
data associated with the particular row DOM-element.
</p>
<div class="row" id="row1">
<div class="cell"><b>Restaurant</b></div>
<div class="cell"><b>Type of Food</b></div>
<div class="cell"><b>Location</b></div>
<div class="cell"><b>Rating</b></div>
</div>
<div class="row" id="row2">
<div class="cell">Manuel's</div>
<div class="cell">Mexican</div>
<div class="cell">Arboretum Area, Downtown</div>
<div class="cell">3 Stars</div>
</div>
<div class="row" id="row3">
<div class="cell">NoRTH</div>
<div class="cell">Italian</div>
<div class="cell">North Austin</div>
<div class="cell">4 Stars</div>
</div>
<div class="row" id="row4">
<div class="cell">Perlas Seafood</div>
<div class="cell">Seafood</div>
<div class="cell">Downtown</div>
<div class="cell">5 Stars</div>
</div>
<div class="row" id="row5">
<div class="cell">Rudys</div>
<div class="cell">BBQ</div>
<div class="cell">North Austin, Downtown, South Austin, Round Rock,
Dallas</div>
<div class="cell">3 Stars</div>
</div>
<div class="row" id="row6">
<div class="cell">Chuys</div>
<div class="cell">Tex Mex</div>
<div class="cell">North Austin, Downtown, South Austin</div>
<div class="cell">2 Star</div>
</div>
<div class="row" id="row7" data-id="7" data-type="Sushi" data-stars="3"
data-area="downtown">
<div class="cell">Midoro</div>
<div class="cell">Sushi</div>
<div class="cell">Downtown</div>
<div class="cell">4 Star</div>
</div>
</div>
</body>
|
各行は class 行であり、一意の ID を持っています。この ID を使用して DOM 要素を指定し、その DOM 要素とデータとを関連付けます。リスト 4 はその例を示しています。
リスト 4. CSS のテーブルの行と一意の ID
<div class="row" id="row6">
<div class="cell">Chuys</div>
<div class="cell">Tex Mex</div>
<div class="cell">North Austin, Downtown, South Austin</div>
<div class="cell">2 Star</div>
</div>
|
リスト 4 はサンプル Web ページの静的な部分です。この Web ページの他の部分は JavaScript で作成されており、jQuery を使用することにより、特定の DOM 要素に関連付けられたデータの格納や、格納したデータの取得、そしてフィルタリング条件に基づく動的な情報のフィルタリングを行います。
JavaScript の中ではまず、ready() イベント・ハンドラーにクリック・ハンドラーを追加します (リスト 5)。
リスト 5.
ready() イベント・ハンドラー
<script type="text/javascript">
/* Ready */
$(document).ready(function() {
$('#filter').click(function () {
filterRows($('input').val());
});
$('#clear').click(function () {
$('input').val('')
clearRows($('input').val());
});
});
:
:
|
このコードは「Filter (フィルター)」ボタンと「Clear (クリア)」ボタン用のクリック・ハンドラーを追加します。「Filter (フィルター)」ボタンによってテーブルのビューのコンテンツのフィルタリングが開始され、一方「Clear (クリア)」ボタンによって表が元のビューの状態に戻ります。
次のステップでは、図 2 の例に従い、jQuery コードによって非表示のメタデータを特定の DOM 要素に関連付けます。そのためには、そのメタデータを保持する
JavaScript オブジェクトを関連付ける必要があります。この例では、ID、料理の種類 (type)、評価 (stars)、場所 (area)
といった属性を表の各行に関連付けます。リスト 6 は jQuery のセレクターを使って特定の DOM 要素を選択する方法と、選択された要素の .data() を呼び出して、その DOM 要素に JavaScript オブジェクトを追加する例を示しています。JavaScript オブジェクトの場合と同様に、他のメンバーのデータ型としては、整数型、文字列型、そしてもっと複雑な型 (配列型、関数型、その他のオブジェクト型など) を指定することが可能です。
リスト 6. 特定の DOM 要素にデータを関連付ける (jQuery)
:
:
/* Associate data to specific DOM-elements */
$('#row1').data({ id:1, type:'rowheader'});
$('#row2').data({ id:2, type:'mexican', stars:3, area:'north'});
$('#row3').data({ id:3, type:'italian', stars:4, area:'north'});
$('#row4').data({ id:4, type:'seafood', stars:5, area:'downtown'});
$('#row5').data({ id:5, type:'bbq', stars:3, area:'west'});
$('#row6').data({ id:6, type:'tex mex', stars:2, area:'south'});
:
:
|
リスト 7 は、リスト 5 で説明した $(document).ready()
関数に追加したクリック・ハンドラーの実装方法を示しています。clearRows()
関数を使って表のビューを元の状態にリセットし、filterRows() を使って表のビューをフィルタリングします。フィルタリングの基準は、格納されている DOM
データとの比較に基づいて行われます。
リスト 7. クリック・ハンドラー
:
:
/* Clear Rows */
function clearRows(filterString) {
// For each row, that is, div in #rows of class .row
$.each($('#rows .row'), function(i, row) {
$(row).show();
});
}
/* Filter Rows */
function filterRows(filterString) {
// For each row, that is, div in #rows of class .row
$.each($('#rows .row'), function(i, row) {
var $row = $(row); // Get the row div element
var rowData = $row.data(); // Get the data associated with the row
div element
var id = rowData.id; // Get the row id
var type = rowData.type;
if (filterString.length == 0) {
$row.show();
} else {
if (type.toLowerCase().search("rowheader") != -1) {
$row.show();
} else {
if (filterByType(filterString, rowData.type) ||
filterByRating(filterString, rowData.stars) ||
filterByLocation(filterString, rowData.area)) {
$row.show();
} else {
$row.hide();
}
}
}
});
}
:
:
|
では、表の各行に対して jQuery のセレクターがどのように実行されるのか、コードの $.each($('#rows
.row'), function(i, row) のブロックをもう少し詳しく見てみましょう。このブロックでは、選択された各行に対して、その行の要素と、その要素に関連付けられたデータを抽出しています (リスト 8)。
リスト 8. DOM 要素データを取得する
var $row = $(row); // Get the row div element var rowData = $row.data(); // Get the data associated with the row div element |
その後の関数では、料理の種類 (type)、評価 (stars)、場所 (area) に基づいて実際のフィルタリングを行っています。リスト 9 に、その一例を示しています。
リスト 9. DOM 要素のデータに基づいてコンテンツをフィルタリングする
:
:
/* Filter Rows by Type */
function filterByType(filterString, type) {
var p1 = RegExp(type);
if (p1.test(filterString)) {
return true;
} else {
return false;
}
}
/* Filter Rows by Rating */
function filterByRating(filterString, stars) {
if (filterString.toLowerCase().search('star') != -1) {
var value = filterString.replace(/[^0-9]/g,'');
if (stars >= value) {
return true;
} else {
return false;
}
}
}
/* Filter Rows by Location */
function filterByLocation(filterString, area) {
var p1 = RegExp(area);
if (p1.test(filterString)) {
return true;
} else {
return false;
}
}
</script>
|
リスト 9 のコードを変更または改善するためには、他のフィルター・ロジックや関数を追加します。
この「ダウンロード」セクションにある dom-based-data-sample.html ファイルには、上記の HTML コンテンツ、関連する JavaScript、jQuery コードがすべて含まれており、皆さんが自由に使用することができます。
HTML5 にはカスタム data 属性が新たに導入されており、カスタムの非表示データを Web ページに埋め込むために活用することができます。W3C の定義によれば、「これらの新しいカスタム data 属性は、他に適切な属性や要素がない、ページまたはアプリケーション独自のカスタム・データを格納するためのものです。」
jQuery の観点から見ると、HTML5 の新しいカスタム data 属性が対象としている問題は、jQuery の data() メソッドが対処する問題と同じです。HTML5 の data 属性は文字列データにしか対応することができません。jQuery
の data() を利用する場合には、格納できる JavaScript のデータ型は整数型や文字列型から配列型、関数型、さらには他のオブジェクト型に至るまで、あらゆる種類が可能です。
jQuery 1.4.3 以降では、.data() によって、HTML の DOM から HTML5 の data 属性が自動的に抽出され、(キャッシュに) 格納されて、返されます。
HTML5 の data 属性は data-* という形式で定義されます。data- は属性名の接頭辞として必ず必要であり、* は W3C によって定義される任意の文字シーケンスです。カスタムの data 属性は、どの名前空間にも属さず、名前は「data-」という文字列で始まり、ハイフンの後に少なくとも 1 文字続きます。この属性は、XML の標準に準拠しており、U+0041 から U+005A まで (ラテン語大文字 A からラテン語大文字 Z まで) の文字を含みません。
リスト 10 の HTML コード・スニペットに含まれる行の定義では、上記で .data() という補助機能を使って追加したものと同じメタデータを追加していますが、この場合は
HTML5 のカスタム属性を使用して追加しています。
リスト 10. DOM ベースのデータに HTML5 を使用する
<div class="row" id="row7"
data-id="7"
data-type="Sushi"
data-stars="3"
data-area="downtown">
<div class="cell">Midoro</div>
<div class="cell">Sushi</div>
<div class="cell">Downtown</div>
<div class="cell">4 Star</div>
</div>
|
この方法の優れた点は、HTML5 をサポートするためにコードを変更する必要がない点です。jQuery の data() では、自動的にカスタムの data 属性を検出して構文解析し、キャッシュにロードし、要求に応じて返送しました。
この記事では jQuery の data() メソッドについて、jQuery.fn.data() に焦点を当てて学びました。この記事で説明した jQuery のデータ格納機能を利用すると、カスタムの非表示データを特定の DOM 要素に関連付け、Web ページに埋め込むことができるため、DOM を基にデータを格納、取得することができます。これで、すっきりとした方法で任意の JavaScript データ型を格納できるようになりました。
| 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|---|---|---|
| Article source code | dom.based.data.sample.zip | 3KB | HTTP |
学ぶために
- Mozilla Developer Center の JavaScript Guide には、JavaScript を使うために必要なすべてが解説されています。
- Mozilla
Developer Network は Web 開発者にとって素晴らしいリソースです。
- Rebecca Murphey 著の「jQuery Fundamentals」は jQuery JavaScript ライブラリーの全体的な概要を解説しています。
- DOM についての詳細は、W3C 仕様の「What is the Document
Object Model?」を読んでください。
- チュートリアル、「DOM objects and
methods」には、W3C DOM のすべてのプロパティー、コレクション、メソッドが解説されています。
- jQuery のドキュメントを調べてみてください。
- 「JavaScript and the
Document Object Model」(developerWorks、2002年7月) は JavaScript によって DOM を処理する方法を解説し、またユーザーがメモを追加でき、メモの内容を編集できる Web ページの作成方法について順を追って解説しています。
- チュートリアル、「Understanding DOM」(developerWorks、2007年5月) では DOM 文書の構造を学ぶことができます。
- jQuery.data() メソッドと .data() メソッドについて学んでください。
- jQuery のソース・コードを見てください。
- W3C の仕様、「HTML5, A vocabulary and associated
APIs for HTML and XHTML」を読んでください。
- developerWorks の Web development ゾーンには、Web ベースの多様なソリューションを解説した記事が豊富に用意されています。
- developerWorks
podcasts ではソフトウェア開発者のための興味深いインタビューや議論を聞くことができます。
- developerWorks
の Technical events and webcasts で最新情報を入手してください。
製品や技術を入手するために
- jQuery JavaScript ライブラリーをダウンロードしてください。jQuery ライブラリーは MIT
ライセンスまたは GNU Public License の下で入手することができます。jQuery
ライブラリーをダウンロードしてローカルで利用することも、アプリケーションに含め、Google CDN から直接提供することもできます。
- 皆さんの次期開発プロジェクトを IBM ソフトウェアの試用版を使って革新してください。
議論するために
- 今すぐ My
developerWorks プロフィールを作成し、jQuery に関するウォッチ・リストを設定してください。My
developerWorks とずっとつながっていられます。
- Web
開発に関心を持つ他の developerWorks メンバーを見つけてください。
- Web
の話題に焦点を絞った developerWorks のグループの 1 つに参加し、皆さんの知識を共有してください。
- Roland Barcia が彼のブログの中で Web
2.0 とミドルウェアについて語っています。
- developerWorks のメンバーが Web
のトピックに関して共有するブックマークを調べてみてください。
- 即座に答えを得るために、Web 2.0 Apps
フォーラムを訪れてください。
C. Enrique Ortiz はモバイルの技術者、開発者、著作者として長年活躍しています。彼は「About Mobility」というブログを書いており、また MobileMonday の Austin 支部の設立者でもあります。