目次


基礎から学ぶ Dojo

第 1 回 Dojo 開発入門

Comments

コンテンツシリーズ

このコンテンツは全#シリーズのパート#です: 基礎から学ぶ Dojo

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:基礎から学ぶ Dojo

このシリーズの続きに乞うご期待。

Dojo Toolkit の紹介

2004年に作成された Dojo の目的は、DHTML および JavaScript Web アプリケーションの開発プロセスを容易にするために、近年の Web ブラウザーに広がっているブラウザー間の違いの大半を隠すことです。そうすることによって、開発の焦点を、すべてのブラウザーで機能するようにコードを調整する作業ではなく、関数の実装へと移すことができます。Dojo を所有しているのは、2005年に Alex Russell と Dylan Schiemann によって設立された Dojo Foundation です。Dojo はオープンソース・ソフトウェア (OSS) であり、AFL (Academic Free License) と修正版の BSD ライセンスのデュアル・ライセンスで配布されています (どちらのライセンスに従うかを選択できます)。

機能の概略

Dojo Toolkit の機能は、以下の 4 つに分けられています。これにより、開発者は 1 つの重たい JavaScript ライブラリーをダウンロードしてアプリケーションのパフォーマンスに負担をかけることなく、ライブラリーのサイズを最小限に抑えることができます。例えば、Ajax をサポートする関数だけが必要な場合には、Base パッケージだけを組み込み、広範にわたる Dijit UI コンポーネントは組み込まないようにすることができます。Dojo が異なるモジュールをどのようにロードするかについては、連載の後のほうで詳しく説明します。

Base
Base パッケージは Dojo Toolkit の基本機能を提供します。このパッケージには、DOM ユーティリティー関数、CSS3 セレクターによる DOM ベースのクエリー機能、イベント処理機能、Ajax、基本的なアニメーション機能、Dojo のクラス・ベースのオブジェクト指向の機能などが含まれます。この記事では主に、Base パッケージを焦点とします。
Core
Core パッケージには、Base には含まれていない関数が含まれています。一般に、これらの機能は Base パッケージが提供する関数ほどには多用されていません。そのため、Base パッケージの負担を軽くする目的で、必要に応じて別途ロードできるようになっています。そうは言っても、Core パッケージが提供するコンポーネントは、例えば高度なアニメーション、ドラッグ・アンド・ドロップ、I/O、データ管理、国際化対応 (i8n)、ブラウザーの履歴管理など、実に有用なものばかりです。Core パッケージについては、この記事では取り上げません。
Dijit
Dijit パッケージには、Dojo の広範なウィジェットとコンポーネントからなる UI ライブラリーが含まれています。ウィジェットの例をいくつか挙げると、ダイアログ・ボックス、カレンダー、カラー・パレット、ツールチップ、そしてツリーがあります。さらに、標準の HTML フォームのコントロールに比べ、遥かに充実した機能を提供する一連のフォーム用コントロールや、完全なレイアウト管理オプションもあります。Dijit については、この連載の第 3 回で詳しく説明します。
DojoX
DojoX (Dojo eXtensions) は、このツールキットのさまざまなサブプロジェクトを集めたライブラリーです。DojoX には Dojo の実験的機能のほとんどが含まれているだけでなく、多数の安定したコンポーネントと機能も含まれています。DojoX については、連載の第 3 回で簡単に説明します。

開始手順

Dojo についての説明はこれくらいにして、早速このツールキットを実際に使ってみましょう。このセクションでは、皆さんのプロジェクトで考えられるさまざまな Dojo の利用方法、Firefox と Firebug プラグインを使って開発環境を構築する方法、そして Dojo コードを作成して、すべてが期待通りに機能することを確認する方法を説明します。

Dojo をセットアップする

Dojo をセットアップする最も簡単な方法は、CDN (Content Delivery Network) から Dojo を提供し、皆さんのサーバーからではなく、訪問者の近くのサーバーから Dojo JavaScript ファイルが配布されるようにすることです。この方法を使えば、スクリプトをロードする時間を短縮できるだけでなく、ユーザーが別の Web サイトから Dojo ファイルをすでにロードしてある場合には、キャッシュからファイルをロードできるため、さらにロード時間が短縮される可能性が高くなります。

この連載では、読者が Dojo 1.5 を使用していることを前提としますが、バージョン 1.x であれば互換するはずです。HTML ページに以下の <script> タグを含めると、Google の CDN から Dojo 1.5 がロードされます。

<script src="//ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"></script>

あるいは、Dojo を皆さんのサーバーにダウンロードして、そこからロードするという方法もあります。私が好む方法は CDN からロードする方法ですが、CDN サーバーに問題が発生した場合に備えてローカルに代替を用意するようにします。そのためには、Dojo をダウンロードして、Web コンテンツの格納予定場所に対する適切な相対位置に Dojo ファイルを配置してください。リスト 1 のコードは、Web コンテンツから Dojo スクリプト・ファイルへの相対パスが script/ であるという前提で、最初に CDN から Dojo のロードを試み、それに失敗した場合にはローカルの Dojo をロードします。

リスト 1. ローカルにも代替ファイルを用意した状態での CDN からの Dojo のロード
<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js">
</script>
<script>
typeof(dojo) === "undefined" && document.write(unescape('%3Cscript
src="js/libs/dojo-1.5.min.js"%3E%3C/script%3E'))
</script>

ここで重要な点は、typeof(dojo) で始まるコード全体を 1 行で記述することです。そうしなければ、代替システムは機能しません。代替システムが機能していることをテストするには、CDN からロードする行をコメントアウトして、この後すぐに作成する「Hello, World!」のサンプルでページをテストすればよいのです。

Firebug コンソールを使用する

Dojo を試すための Web ページをわざわざ作成しなくてもよいように、この記事のサンプル・コードの多くは、Firebug を使用して実行します。Firefox の優れたプラグインである Firebug を使えば、JavaScript 開発者はコンソールだけでロギング、デバッグ、ネットワークの監視を行えるため、JavaScript アプリケーションをテストして問題を修正するプロセスが大幅に簡易化されます。これらの機能が実際に含まれる Web ブラウザーは他にもありますが、記事のサンプルでは多種多様なプラットフォームで使用可能な Firefox とFirebug を使用します。

まずは、Firefox とFirebug をインストールする必要があります (ダウンロード情報については、「参考文献」を参照)。最初に Firefox をインストールして起動し、それから Firebug プラグインをダウンロードしてインストールしてください。Firebug のインストールが完了すると、Firefox のウィンドウの右下隅に図 1 のような虫のアイコンが表示されます。このアイコンをクリックすると、Firebug のウィンドウが開きます。

図 1. Firebug のアイコンとウィンドウ
Firebug のウィンドウ。ウィンドウの右下隅に虫のアイコンが表示されています。
Firebug のウィンドウ。ウィンドウの右下隅に虫のアイコンが表示されています。

Firebug のコンソールを使用するには、「Console (コンソール)」タブをクリックします。コンソールが無効な場合には、このタブの下矢印をクリックして「Enable (有効)」をクリックしてください。コンソールが有効になったら、そのウィンドウに「console.log("Test");」と入力します。

すると、図 2 に示すように、コンソールをサポートするために JavaScript デバッガーが有効になっていることを知らせるメッセージとともに、この入力の結果が表示されます。

図 2. Firebug コンソールを使用する
「enabling javascript debugger to support the console」というメッセージが表示されたウィンドウ
「enabling javascript debugger to support the console」というメッセージが表示されたウィンドウ

Hello, World!

次は、Dojo を試してみましょう。この「Hello, World!」サンプルには Dojo を使用して、DOM がロードを完了した時点で 1 つの関数をアタッチします (リスト 2 を参照)。この関数はページの最後に「Hello, World!」というメッセージを出力するだけの簡単なものです。もちろん、これは何の変哲もない Web アプリケーションの作成方法ですが、こうすることによって、Dojo がページ上で使用可能であることを確かなものにすることができます。また、記事では Firebug コンソールで Dojo の機能を探るために、一貫してこのページをロードします。

リスト 2. listing1.html: Dojo による「Hello World」アプリケーション
<html>
<head>
    <title>Exploring Dojo</title>
</head>
<body>
<h1>Exploring Dojo</h1>
<div id="message">This is a DIV element with id attribute message.</div>
<ul id="list">
    <li>This is the first item in a list</li>
    <li class="highlight">This is the second item in a list</li>
    <li>This is the third item in a list</li>
</ul>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js">
</script>
<script>
dojo.addOnLoad(function() {
    dojo.create(
        "div",
        {
            "innerHTML": "Hello, World!"
        },
        dojo.body()
    );
});
</script>
</body>
</html>

上記のスクリプトがアタッチする匿名関数は、DOM がロードを完了した時点で呼び出されます。この関数は dojo.create を使用して DOM の新規 <div> 要素を作成し、その要素の “innerHTML” プロパティーを “Hello, World!” に設定してから、ユーティリティー関数 dojo.body を使ってこの <div> 要素をページ本体に挿入します。図 3 に、このアプリケーションの実行結果を示します。図に示されているように、このスクリプトによって、ページ本体の終わりに「Hello, World!」というメッセージが追加されます。

図 3. 見事に表示された「Hello World」ページ
テキストと、その終わりに「Hello World!」というメッセージが表示された「Hello World」ページ
テキストと、その終わりに「Hello World!」というメッセージが表示された「Hello World」ページ

差し当たり、このページを削除したり、閉じたりしないでください。次のセクションでも、Dojo をロードするという目的だけのために、このページを使用し、さらに Firebug コンソールを使って Dojo のいくつかの側面を実際に試す予定です。

次のセクションに移る前に、重要な点として、ページ上での JavaScript の配置場所について指摘しておきます。お気付きかもしれませんが、私は Dojo とページの JavaScript を、HTML 文書の <head> セクションに組み込む代わりに、ページの終わりにある <body> 終了要素の直前に追加しました。このようにした理由は、JavaScript がこの位置に配置されていれば、ページの他の要素がブロックされることなくロードされるからです。ページ内で JavaScript ライブラリーを使用する際には、ページのパフォーマンスを最適化するために、そのライブラリーがページの他のパーツのロードをブロックしないようにする必要があります。詳細については、「参考文献」セクションを参照してください。

基礎

このセクションでは、DOM および配列の操作を容易にするために Dojo が提供している便利な関数をいくつか紹介します。このセクションに記載するサンプル・コードを試すには、前のセクションで作成したページを Firefox に表示した状態のまま、この記事に示すコードを Firebug のコンソール・ウィンドウに入力してください。

DOM ユーティリティー関数

DOM ユーティリティー関数は、DOM の要素を簡単に操作できるようにします。それは、これらの関数では、項目をその ID または CSS3 セレクターを使って見つけることができるからです。さらに、要素を作成、破棄するための関数、既存の要素の内容を操作するための関数もあります。

dojo.byId

dojo.byId 関数では、DOM ノードをその id 属性によって選択することができます。この関数は、JavaScript の標準関数 document.getElementById の別名ですが、明らかに、こちらのほうが書く手間が省けるだけでなく、ブラウザー間の違いもある程度処理してくれます。試しに、Firebug コンソールを使って、”message” という ID を持つ DOM 要素の内容をログに記録してみましょう。それには、「dojo.byId("message").innerHTML;」と入力します。

このコマンドを実行すると、コンソールの左側に、リスト 3 に記載するレスポンスが表示されるはずです。

リスト 3. レスポンス
>>> dojo.byId("message").innerHTML;
"This is a DIV element with id attribute message1."

リスト 3 の先頭行は、実行されたコマンドをエコー出力しているに過ぎません。2 番目の行が、コマンドの実行結果です。この例では、ID が “message” に設定された <h1> 要素の内容が表示されています。

次の話題に進む前に、もう少し興味深いデモを行ってみます。コンソールのエディター域に、リスト 4 のコマンドを入力してください。

リスト 4. dojo.fadeOut コマンド
dojo.fadeOut({
    node: dojo.byId("message"),
    duration: 600
}).play();

このコマンドを実行すると、要素がフェードアウトしてページから消えて行きます。要素を再びフェードインさせるには、コマンドの fadeOut 参照を fadeIn に変更してから、コマンドを再び実行します。ごく簡単な仕組みだと思いませんか?このデモが明らかにしているのは、Firebug コンソールを使用して、現在のページを動的に操作できることです。当然、これらの変更が適用されるのは、ロード済みの現在のページに対してだけなので、他のページにナビゲートしたり、ページを最新の表示に更新したりすると、変更は維持されません。

dojo.query

前のセクションでは、id 属性を使用して単一の DOM 要素の参照を取得する方法を学びました。この方法は役に立つものの、操作したいすべての要素にこの属性を追加するのは現実的ではありません。しかも、id は一意に決まるものでなければなりません。では、複数の要素を同時に参照したい場合はどうすればよいのでしょうか。そこで登場するのが、dojo.query 関数です。

例えば、”list” という ID の番号なしリストがあり、このリストに含まれるすべての <li> 子要素への参照を取得して、それぞれの要素の内容をコンソールに出力したいとします。この場合、dojo.query を使えば簡単に処理することができます (リスト 5 を参照)。

リスト 5. dojo.query コマンド
dojo.query("#list li").forEach(function(item) {
    console.log(item.innerHTML);
});

上記のコマンドによって、コンソールにはリスト 6 に記載する内容が出力されます。

リスト 6. コンソールの出力
>>> dojo.query("#list li").forEach(function(item) { console.log
                                                       (item.innerHTML); });
This is the first item in a list
This is the second item in a list
This is the third item in a list
[li, li.highlight, li]

dojo.query 関数は、選択したい要素への CSS3 セレクター参照を設定したストリングを引数に取ります。この特定の例では、”list” という ID が設定された要素の子となっているすべての li 要素を選択するように指定しています。すると、関数がこのクエリーと一致する要素の配列を返します。リスト 6 の例では、dojo.forEach 関数を使用してこの配列を繰り返し処理し、検出した要素ごとの innerHTML プロパティーをコンソールにログとして出力していますが、次のセクションでは、この関数と他の配列関数についても詳しく説明します。

次のセクションに移る前に、dojo.query を使用して、highlight という名前のクラスを持つすべての HTML 要素を検索し、見つかった要素にスタイルを適用して強調表示する方法を紹介します (リスト 7 を参照)。

リスト 7. dojo.query を使用して highlight という名前のクラスを持つ HTML 要素を検索する
dojo.query(".highlight").style({
    backgroundColor: "yellow",
    color: "red"
});

ページ上の番号なしリストに含まれる 2 番目の項目を見てください。項目の背景は黄色に変わり、テキストは赤色に変わっているはずです。お気付きかもしれませんが、この例では dojo.forEach 関数を使用していません。この関数が不要になった理由については、「配列と NodeList」のセクションで説明します。

その他の有用なユーティリティー関数

DOM ベースのクエリーと要素の選択を行うユーティリティーの他にも、Dojo には DOM の操作を大幅に簡易化する多数のユーティリティー関数が揃っています。そのうちのいくつかは、サンプルの「Hello, World」ですでに使用しました。1 つは dojo.body 関数で、この関数は単純に文書の <body> 要素への参照を返すことによって、文書オブジェクト自体を返します。サンプルでもう 1 つ使用されていたユーティリティー関数、dojo.create では、簡単に新規要素を作成し、その属性を定義して DOM に挿入することができます。

その他に使用できる関数には、既存の要素または新規要素を文書内の任意の場所に配置できる dojo.place、その名前のとおり、DOM 要素の中身を空にする dojo.empty、そしてノードとその子要素を一緒に除去する dojo.destroy もあります。これらの関数についての詳細は、「参考文献」にリンクが記載されている Dojo リファレンス・マニュアルを参照してください。

配列と NodeList

配列には、値のコレクションを保存することができます。配列は標準的な JavaScript でも使用することができますが、Dojo での配列は複数のヘルパー関数を組み込むように拡張されています。これらの拡張配列は、NodeList と呼ばれます。NodeList は標準の配列関数に加え、Dojo 固有の関数を使用することができます。前のセクションで説明した dojo.query 関数による戻り値は、NodeList (具体的には dojo.NodeList) オブジェクトです。ここからは、NodeList で使用できる関数をいくつか取り上げて説明します。

dojo.forEach

まず始めに取り上げるべき関数は、dojo.forEach 関数です。この関数は、記事の前のセクションに記載した dojo.query の例ですでに使用しました。この関数では、NodeList に対してイテレーターを定義して、NodeList に含まれる各項目に適用する関数を指定することができます。リスト 8 に記載する基本的な例を見てください。

リスト 8. 基本的な例
var list = ['My','name','is','Joe'];
dojo.forEach(list, function(item, i) {
    console.log((i+1)+'. '+item);
});

リスト 8 のコードは、リスト 9 に記載する内容を出力します。

リスト 9. 出力
>>> var list = ['My','name','is','Joe']; dojo.forEac...item, i)
                             { console.log((i+1)+'. '+item); });
1. My
2. name
3. is
4. Joe

ご覧のように、forEach 関数は配列に含まれる各要素を取得して、アタッチされた関数をその要素に対して実行します。上記では匿名関数を使用していますが、名前付き関数を使用することもできます (リスト 10 を参照)。

リスト 10. 名前付き関数を使用した dojo.forEach による配列の繰り返し処理
var list = ['My','name','is','Joe'];

var printArray = function(item, i) {
    console.log((i+1)+'. '+item);
}

dojo.forEach(list, printArray);

dojo.indexOf

特定の値が配列内のどの位置にあるかを調べるには、dojo.indexOf 関数を使用することができます。その方法を説明するのに最善の方法は、具体的な例を見てみることです。前のセクションで作成したリスト配列を例に、name という値が位置する配列のインデックスを調べるとすると、そのためのコマンドには dojo.indexOf(list, "name"); を使用します。

このコマンドを実行すると、リスト 11 の結果が返されます。

リスト 11. 結果
>>> dojo.indexOf(list, "name");
1

これで、name という値は、配列内のインデックス 1 に位置することがわかりました。JavaScript の配列のインデックスは 0 から始まるため、この値は配列内の 2 番目の項目ということになります。配列内に含まれていない値をこの関数に指定して実行すると、戻り値は -1 となります。

この dojo.indexOf 関数は、指定された値について検索を始め、最初に見つかったインデックスを返します。したがって、配列に同じ値を持つ要素が複数ある場合には、最初に当該要素が見つかった時点で実行を停止します。Dojo にはこれと同様の dojo.lastIndexOf という関数が用意されており、この関数の場合は、特定の値を持つ要素のうち最後に見つかったインデックスを返します。この dojo.lastIndexOf 関数は、dojo.indexOf とまったく同じように機能します。

dojo.filter

dojo.filter 関数では、別の配列をフィルタリングして新しい配列を作成することができます。例えば、前に作成したリスト配列から、値 is を持つ要素を除外して新しいリスト配列を作成する場合には、リスト 12 に記載するコードを使用します。

リスト 12. 配列のフィルタリングによる新規配列の作成
var filteredList = dojo.filter(list, function(item) {
    return item != "is";
});

dojo.forEach(filteredList, "console.log(item)");

This results in the following output:

>>> var filteredList = dojo.filter(list,
function(it...dojo.forEach(filteredList, "console.log(item)");
My
name
Joe

その他の NodeList 関数

Dojo には上記の他にも、配列を操作するときに役立つ NodeList 関数がいくつかあります。その 1 つ、dojo.map 関数では、既存の配列を変更して新しい配列を作成することができます。例えば、金額を表す数値からなる配列があるとします。その場合、map 関数を使用すれば、これらの値を通貨形式の配列で返すことができます。また、dojo.some 関数では、指定された基準を満たす要素が配列に 1 つ以上含まれているかどうかを調べることができます。同様に、dojo.every を使用して、配列内のすべての要素が指定された基準を満たすかどうかを調べることもできます。全 NodeList 関数を網羅したリストとそれぞれに関連する資料については、「参考文献」を参照してください。

Dojo でのイベント処理

大抵の JavaScript ライブラリーには、DOM イベントがトリガーされたときに呼び出す関数をアタッチできるように、JavaScript によるネイティブ・イベント処理のクロスブラウザー実装があります。この実装はそれだけでも有用でしょうが、Dojo ではこの概念をさらに発展させて、関数を別の関数に接続できるようにしています。接続できるのは、DOM イベント、オブジェクト・イベント、ユーザー定義関数、あるいはこのセクションの後のほうで説明する「トピック」です。

DOM イベント処理

関数を DOM イベントにアタッチする第 1 の方法は、dojo.connect 関数を使用することです。この仕組みを説明するには、例を用いるのが一番です。Firebug コンソールにリスト 13 のコードを入力してください。

リスト 13. dojo.connect を使用して関数を DOM イベントにアタッチする方法
var message = dojo.byId("message");
dojo.connect(message, "onclick", function() {
    alert(message.innerHTML);
});

上記のコマンドによって、コンソールにはリスト 14 に記載する出力が生成されます。

リスト 14. 出力
>>> var message = dojo.byId("message"); dojo.connect..., function()
                                              { alert(message.innerHTML); });
[div#message, "onclick", function(), 1]

これはこれで素晴らしい機能ですが、この関数は実際には何かを実行するはずではなかったのでしょうか?まったくその通りです。上記では、Dojo が関数を、”message” という ID を持つ要素の click イベント・ハンドラーにアタッチしています。試しに、画面上に表示された「This is a DIV element with id attribute message.」という内容のメッセージをクリックしてみてください。すると、JavaScript によるアラート・ボックスが表示されます (図 4 を参照)。

リスト 4. DOM イベントへの関数のアタッチ
「This is a DIV element with id attribute message.」と示されたメッセージ・ボックス
「This is a DIV element with id attribute message.」と示されたメッセージ・ボックス

簡単だと思いませんか?ここで、イベントを配列に含まれるすべての要素にアタッチする場合を考えてみてください。例えば、ページ上の番号なしリストの各項目をクリックすると、その項目が太字で強調表示されるようにしたいとします。それには、リスト 15 のコードで簡単に対処することができます。

リスト 15. 要素の配列へのイベントのアタッチ
dojo.query("#list li").forEach(function(item) {
    dojo.connect(item, "onclick", function() {
        dojo.style(item, {
            fontWeight: "bold"
        });
    });
});

このコードでも十分機能しますが、Dojo では、さらに簡潔なコードを作成することができます。それには、forEach で配列を繰り返し処理する代わりに、NodeList.connect ショートカット関数を使用します (リスト 16 を参照)。

リスト 16. 要素の配列へのイベントのアタッチ (改良後)
dojo.query("#list li").onclick(function(e) {
    dojo.style(e.target, {
        fontWeight: "bold"
    });
});

リストにはすでにイベントをアタッチしてあるので、リスト 16 のコードが機能することを確認するには、その前にページを最新の表示に更新する必要があります。引数 eEvent オブジェクトへの参照です。このオブジェクトの target プロパティーから、イベントを起動した要素を識別することができます。そしてこの情報を使用して、太字スタイルを適用する要素を特定します。3 つのリスト項目をクリックしてみてください。各項目をクリックすると、その項目が太字になるはずです。

関数を別の関数に接続する

前のセクションで用いた例では、関数を DOM イベントに接続しました。Dojo ではこれと同じようにして、関数を別の関数に接続することもできます。その一例として、ページ上の任意の場所にスピンする輪の画像を表示する関数を取り上げます。この例では、ユーザーが Ajax 関数を実行すると、スピンする輪の画像が表示されるようにしたいとします。同じように、関数がレスポンスを返した時点でこの画像を非表示にするには、dojo.connect を使用しない場合、リスト 17 に記載するようなコードが考えられます。

リスト 17. dojo.connect を使用せずに、関数を別の関数に接続する方法
function toggleImage() {
    //Code to show/hide loading image goes here
}

function callAjax() {
    toggleImage();
    //Code to call Ajax function goes here
}

function handleResponse() {
    //Code to handle Ajax response goes here
    toggleImage();
}

上記のコードには何も問題ありませんが、toggleImage 関数の呼び出しは、callAjax 関数と handleResponse 関数の両方に固定されています。そのため、別の関数呼び出しを追加するとしたら、これらの関数を再び変更して、追加の呼び出しを組み込まなければなりません。dojo.connect を使用すれば、関数呼び出しを関数自体に追加する代わりに、関数同士を結ぶリンクを確立することができます。リスト 18 に、dojo.connect メソッドの一例を記載します。

リスト 18. dojo.connect を使用して、関数を別の関数に接続する方法
function toggleImage() {
    //Code to show/hide loading image goes here
}

function callAjax() {
    //Code to call Ajax function goes here
}

function handleResponse() {
    //Code to handle Ajax response goes here
}

dojo.connect(callAjax, toggleImage);
dojo.connect(handleResponse, toggleImage);

このコーディング・スタイルは、すべての開発者に好まれるわけではないかもしれませんが、コードを遥かに読みやすく構成することができます。

トピックのパブリッシュとサブスクライブ

説明しておく価値のある Dojo イベント処理の最後の側面は、トピックのパブリッシュ/サブスクライブ機能です。この機能によって、Dojo コンポーネントは互いの存在を認識していないとしても、相互に対話することができます。例えば、個人の苗字と名前が含まれる message オブジェクトを要求する、printName という名前のトピックを定義しているとします。このトピックにサブスクライブするコンポーネントは、別のコンポーネントがこのトピックを個人の名前でパブリッシュするたびに、その名前をコンソールに出力するという設定です。リスト 19 に、このようなサブスクリプションの例を記載します (このコードを Firebug で試してみてください)。

リスト 19. サブスクリプション
dojo.subscribe("printName", function(msg) {
    console.log("The person's name is: "+msg.first_name+" "+msg.last_name);
});

このトピックをパブリッシュするには、トピックの API に従ったオブジェクトの配列を渡す必要があります (この例のオブジェクトには、苗字と名前が含まれている必要があります)。リスト 20 は、その一例です。

リスト 20. トピックへのパブリッシュ
dojo.publish("printName", [
    {
        first_name: "Joe",
        last_name: "Lennon"
    }
]);

これにより、リスト 21 の内容が出力されます。

リスト 21. 出力
>>> dojo.publish("printName", [ { first_name: "Joe", last_name: "Lennon" } ]);
The person's name is: Joe Lennon

このように、上記のオブジェクトを printName トピックにパブリッシュしたことによって、サブスクライブした関数が対応するメッセージをコンソールに出力したというわけです。

dojo.xhr* による Ajax の実現

通常、Ajax を使った Web アプリケーションを作成するには、特定の URL に対して HTTP リクエストを行ってリクエストのヘッダーと本体を渡す XmlHttpRequest (XHR) オブジェクトを作成し、成功または HTTP 失敗の内容が含まれるレスポンスが返されたときに実行すべき内容を規定するコールバック関数を定義します。クロスブラウザー対応の XHR を実装するのは控えめに言っても手間のかかる作業ですが、ありがたいことに、Dojo はこの手間を大幅に省いてくれます。その手段は、GETPOSTPUTDELETE リクエストを実行するために使用できる一連の dojo.xhr* 関数です。

これらの関数は、以下の 4 つの形で提供されています。

  • xhrGet
  • xhrPost
  • xhrPut
  • xhrDelete

この 4 つの関数はいずれも同じ構文に従い、単一のプロパティー構成オブジェクトを引数として取ります。このオブジェクトには、実行する Ajax リクエストのさまざまな側面を定義することができます。これらのオプションにしても、XHR 関数すべてに共通しています。

構成オプション

以下に、XHR 関数で使用できる構成オプションのうち、特に有用なものを抜粋します。

url
このオプションでは、HTTP リクエストの対象となる URL を指定します。この URL は、リクエストを行うページと同じドメイン、同じポートになければなりません。
handleAs
このオプションでは、レスポンスを扱う際のフォーマットを定義することができます。デフォルトは text ですが、jsonjavascriptxml、そしてその他いくつかのフォーマットを指定することができます。この後に記載する例で作成している Ajax リクエストは、JSON レスポンス・フォーマットを処理するコールバック関数を指定しています。
form
このオプションでは、<form> 要素への参照、またはこの <form> 要素のストリング ID を指定します。フォームの各フィールドの値が、リクエスト本体としてリクエストと一緒に送信されます。
content
このオプションでは、リクエスト本体でリソースに渡すパラメーターが含まれるオブジェクトを指定します。このオブジェクトは、form プロパティーから取得された値と一緒にされて送信されます (content オプションと form オプションの両方が指定されている場合)。

リスト 22 に、XHR 関数の一例を記載します。

リスト 22. XHR 関数呼び出しの例
dojo.xhrGet({
    url: "save_data.php",
    content: {
        id: "100",
        first_name: "Joe",
        last_name: "Lennon"
    }
});

上記のコードは、文書そのものが置かれているのと同じ場所にある save_data.php ファイルに対し、非同期 HTTP GET リクエストを行います。このコードは content オブジェクトのプロパティーをパラメーターとして PHP スクリプトに渡します。PHP では、これらの値を $_GET 変数で取得し、おそらくデータベースに保管することになります。

コールバック関数

前の例では、dojo.xhrGet を使用して Ajax リクエストを呼び出す方法を学びました。この例は、実際にリクエストを行うという目的を果たすものの、レスポンスを処理する機能はありません。レスポンスを処理するには、コールバック関数も構成オブジェクトに渡します。使用できる構成オプションは以下のとおりです。

load
このオプションで指定する関数は、Ajax リクエストが成功のレスポンス・メッセージを返すと実行されます。この関数には、レスポンス・データとリクエスト・オブジェクトが引数として渡されます。
error
このオプションで指定する関数は、Ajax リクエストに問題がある場合に実行されます。つまり、Ajax リクエストに指定された URL が無効な場合、リクエストがタイムアウトになった場合、あるいは何らかの HTTP エラーが発生した場合などです。この関数には、エラー・メッセージとリクエスト・オブジェクトが引数として渡されます。
handle
このオプションでは、load と error の 2 つのコールバック関数を 1 つに合成した関数を指定することができます (リクエストの結果が成功であるか、エラーであるかは問題でない場合に役立ちます)。

次の例で作成する Ajax 呼び出しでは、JSON ファイルからデータをロードしてページに出力する load コールバック関数を使用します。

JSON データを処理する

これから、より実際に近い例を作成して、dojo.xhr* 関数の真価を試してみましょう。まず、新しいファイルを作成し (このファイルは listing1.html ファイルと同じディレクトリーに配置します)、そこに JSON データを追加してください。リスト 23 に、ファイルの内容を記載します。

リスト 23. data.json — Ajax リクエストによって処理される JSON データ
{
    count: 4,
    people: [
        {
            first_name: "Joe",
            last_name: "Lennon",
            age: 25
        },{
            first_name: "Darragh",
            last_name: "Duffy",
            age: 33
        },{
            first_name: "Jonathan",
            last_name: "Reardon",
            age: 30
        },{
            first_name: "Finian",
            last_name: "O'Connor",
            age: 23
        }
    ]
}

次に、Firebug で Ajax リクエストを作成します (必ず listing1.html が Firefox にロードされるようにすることで、Dojo がロードされるようにしてください)。このリクエストは、load コールバック関数を使用して JSON レスポンスを処理し、ページに表を出力します (リスト 24 を参照)。

リスト 24. Ajax を使用した JSON データのロードと処理
dojo.xhrGet({
    url: "data.json",
    handleAs: "json",
    load: function(data) {
        var table = "<table border=\"1\">";
        table += "<tr><th>Name</th><th>Age</th>
</tr>";
        dojo.forEach(data.people, function(person) {
            table += "<tr><td>";
            table += person.first_name+" "+person.last_name;
            table += "</td><td>";
            table += person.age;
            table += "</td></tr>";
        });
        table += "</table>";
        dojo.place(table, dojo.body());
    }
});

リスト 24 のコードを Firebug で試してみると、動的に表がページに追加され、JSON ファイルからロードされたデータが表示されるはずです。結果を図 5 に示します。

図 5. JSON データから Ajax によってロードされた表
4 人の名前とそれぞれの年齢が掲載された表がページ上に表示されている様子
4 人の名前とそれぞれの年齢が掲載された表がページ上に表示されている様子

実際の例では、Ajax リクエストによって渡されたパラメーターをベースに、PHP、Python、ASP.NET、Java™ などのサーバー・サイドの言語を使用して JSON データを動的に生成することになるはずです。

まとめ

連載「基礎から学ぶ Dojo」の今回の記事では、Dojo とその基本的な使用方法について学びました。具体的に学んだ内容は、さまざまな DOM ユーティリティー関数、配列関数、イベント処理、そして XHR 機能です。次回の記事では、Dojo の Java™ ライクなクラス・ベースのオブジェクト指向機能を使用する方法を学びます。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=626443
ArticleTitle=基礎から学ぶ Dojo: 第 1 回 Dojo 開発入門
publish-date=01182011