深くて広いDojo Toolkitの世界を紹介する、当連載は今回4回目だ。
前回は、Dijitプログラミングをこれから行っていく上で最低限必要な知識として、「属性」や「メソッド」、そして「拡張ポイント」についての説明を行った。今回は、マークアップを用いずにDijitプログラミングを行う方法について解説したい。
マークアップを用いないDijitプログラミングの概要
「マークアップを用いずに」と言うのは、つまり「JavaScriptコードのみを用いてウィジェットを生成する」と言うことだ。どういうことかを手っ取り早く知っていただくために、まずは軽くコードで説明しよう。
まずは、ボタンウィジェットをマークアップで記述する例をお見せする。
<div id="button" dojoType="dijit.form.Button" label="クリック!></div>
このコードを、マークアップを用いずに書くとすると以下のようになる。
// プレースホルダのDOMを取得
var elem = dojo.byId("button");
// label属性とプレースホルダのDOMを指定してボタンウィジェットを生成
var button = new dijit.form.Button({label:"クリック!"}, elem);
マークアップを用いる方法に比べて、多少見通しが悪くなった。なぜこんな方法を紹介するのであろうか。Dijitプログラミングの特徴はもちろん「マークアップを使用できる」ことである。しかし、JavaScriptによってウィジェットを生成・操作できるようになると、「任意のタイミングでウィジェットを生成できる」「ウィジェットの振る舞い(イベントハンドラなど)も、動的に差し替えることができる」などの利点があるのだ。「必要になるまでウィジェットの生成を遅らせ、リソースを節約したい」など、応用的なプログラミングを行うためには、プログラマティックなウィジェット操作が必ず必要になると言うことだ。
では、マークアップを用いずにDijitプログラミングを行う方法を本格的に学んでいこう。
マークアップを用いずにDijitプログラミングを行う手順
では、プログラマティックにウィジェットを生成するための手順をいかに示そう。
(1) ウィジェットを貼付けるDOMの確保
まずはウィジェットを貼付けたい場所に、プレースホルダ(目印)となるHTMLタグを書いておく。
<div id="button"></div>
(2) プレースホルダのDOMを取得
次に、プレースホルダとして指定した要素のDOMを取得する。もちろんdocument.getElementById()などを用いても良いが、せっかくDojoを使っているのだから「dojo.byId()」を使用しよう。
var elem = dojo.byId("button");
DOMにアクセスするので、当然のことながらこのコードはbody.onload()以降(ページのDOMが構築されて以降)に実行される必要がある。さらに言うと、body.onload()直後ではDojoによる各種セットアップが完了していないこともあるので、dojo.addOnLoad()メソッド以降にこの処理を行うのが無難だ(以下のサンプル参照)。
(3) ウィジェットの生成
最後にウィジェットを生成する。プレースホルダのDOMを取得した後、ボタンウィジェットのインスタンスを生成する。インスタンス生成の際、第1引数に指定するオブジェクトにより属性の指定を行うことができる。
var button = new dijit.form.Button({label:"クリック"}, elem);
前回のサンプルをプログラマティックに書き換える
では今回学んだ知識を使って、前回作成したサンプル(クリックされると、ボタンのラベルが「クリック!」から「こんにちは!」に変化する)を書き換えてみよう。詳細については、ソースコード中のコメントを参考にしてほしい。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<!-- 環境に合わせてDojoへのパスを書き換えてください -->
<script src="../dojo-release-1.1.0/dojo/dojo.js" djConfig="parseOnLoad: true">
</script>
<style type="text/css">
/* 環境に合わせてDojoへのパスを書き換えてください */
@import "../dojo-release-1.1.0/dojo/resources/dojo.css";
@import "../dojo-release-1.1.0/dijit/themes/tundra/tundra.css";
</style>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.Button");
// DOM生成後に呼び出される関数を登録
dojo.addOnLoad(function() {
// プレースホルダのDOMを取得
var elem = dojo.byId("button");
// ボタンウィジェットを生成
var button = new dijit.form.Button({label:"クリック"}, elem);
// ボタンの拡張ポイントonClickをオーバーライド
button.onClick = function() {
button.setLabel("こんにちは!");
};
});
</script>
</head>
<body class="tundra">
<div id="button"></div>
</body>
</html>
おまけ: その他のDijit基本知識
これで、Dijitに関する基本的な知識はだいたい習得したと言える。次回からは、Dijitが提供するUIウィジェットをどんどん紹介していく予定だ。
基本知識の締めくくりとして、知っておくと役に立つTIPSをあと少しだけ補足しておきたい。
マークアップで生成したウィジェットの参照方法
マークアップを用いて生成したウィジェットのインスタンスにアクセスしたい、という場合が多くある。前回のサンプルを一部抜き出してみよう。コメントの部分に注目してほしい。
<button id="button" dojoType="dijit.form.Button" label="クリック!">
<script type="dojo/method" event="onClick">
// dijit.byId()により、ウィジェットのインスタンスを取得
var button = dijit.byId("button");
button.setLabel("こんにちは!");
</script>
</button>
このように、前回のサンプルでは「dijit.byId("ID文字列")」を使用してウィジェットのインスタンスを取得していた。この他にも「jsId」という属性を用いて、ウィジェットのインスタンスをグローバルな変数に格納する方法も存在する。
<!-- jsId属性を用いて、グローバルな変数「button」にウィジェットのインスタンスを格納する -->
<button jsId="button" dojoType="dijit.form.Button" label="クリック!">
<script type="dojo/method" event="onClick">
button.setLabel("こんにちは!");
</script>
</button>
グローバルスコープに格納されるので、変数名の衝突が多少不安ではあるが、dijit.byId()を多用するよりもコードをコンパクトにすることができる。
拡張ポイントの実装にdojo/connectを用いる
上のコードでは、拡張ポイントの実装を行うために入れ子のscriptタグを使っている。そのtype属性には「dojo/method」という文字列が指定されているが、ここには「dojo/connect」を用いることもできる。
<!-- type属性に注目! -->
<script type="dojo/connect" event="onClick">
...略...
</script>
「dojo/method」と「dojo/connect」の違いは、前者は単なるメソッドのオーバーライドであるが、後者は「dojo.connect()」を用いると言うことである。これをコードで表すと以下のようになる。
// 「button」はボタンウィジェットのインスタンス
// dojo/methodと等価なコード
button.onClick = function() {...}
// dojo/connectと等価なコード
dojo.connect(button, "onClick", function(){...});
dojo.connect()は、「イベントに対して、イベントハンドラを『接続』する」ため、Dojoでは頻繁に用いられるメソッドだ。このメソッドを利用する利点は、1つのイベントに対して複数のイベントハンドラを接続できることだ。詳しく知りたい方は、こちらのページを参考にしていただきたい。