Constantモジュール
まずは、名前空間を定義するところから始めます (リスト3を参照)。このサンプルTodoアプリケーションで使用する名前空間には、「TD」という名前を付けます。名前空間は基本的に、アプリケーションに関係する他のすべてのオブジェクトを保持するオブジェクトです。アプリケーションの拡大に備え、TDをグローバル名前空間に定義しておくことも可能です。TDオブジェクトがまだ用意されていない場合は、「single var pattern」を使用してTDオブジェクトを作成してください。メソッド呼び出しの一貫性を確実にするのは、名前空間関数です。TD.namespace(TD.module1) を呼び出すと、module1という名前のオブジェクトがTDに追加されます。以下のリストを見ると、TD名前空間を宣言して、必要に応じてこのTD名前空間の下にオブジェクトを足していく方法がわかります。
/********************************************************************************** * TD NAMESPACE **********************************************************************************/ var TD = TD || {}; TD.namespace = function (ns_string) { var parts = ns_string.split('.'), parent = TD, i; // strip redundant leading global if (parts[0] === "TD") { parts = parts.slice(1); } for (i = 0; i < parts.length; i += 1) { // create a property if it doesn't exist if (typeof parent[parts[i]] === "undefined") { parent[parts[i]] = {}; } parent = parent[parts[i]]; } return parent; };
Worklight user documentationに記されているEncrypted Cache(暗号化キャッシュ)についての情報や「Worklight Developer's Reference Guide」も参照してください。
図3に示されているように、TD.Constant(このサンプル・アプリケーションのConstantモジュール)にはプライベート・メンバーがありません。このモジュールは、Public APIと名付けられたAPI(オブジェクト・リテラルを使用して作成された、単なるキーと値のペア) を介して値を返すだけです。同様に、Todo items keyは暗号化オフライン・キャッシュ機能に使用されます。encryptとdecryptの値は、単純なブール値です。これらの値によって、Vaultモジュールに暗号化または復号のどちらを行うかを指示します。
![図3. 各モジュールの要素](http://cz-cdn.shoeisha.jp/static/images/article/6818/6818_figure03.gif)
Listモジュール
図1とリスト4に示されているように、基本的にアプリケーションのメイン・ページとなるのは、このサンプル・アプリケーションの2番目のパネルです。このパネルには、以下の要素があります。
- ヘッダーに表示されるロゴ
- 新規項目を追加するときに使用するテキスト・フィールド(id="new-todo")
- 新規項目を追加するためのボタン(id="add")
- 完了マークが付けられたすべての項目を削除するためのボタン(id="delete")
- 項目リストを追加するための順不同リスト(id="todo-list")
- リストが空になっているときにテキストを表示するための div タグ (id="no_items")
また、data-filter=’true’ プロパティーを <ul> タグに追加すれば (「参考文献」を参照)、データをフィルタリングできることにも注意してください (http://jquerymobile.com/demos/1.1.0/docs/lists/index.html)。
<!-------------------------- MAIN PAGE --------------------------> <div data-role="page" id="main" > <!-- <div data-role="header"><h1>Todo App</h1></div> --> <img class="centerimg" src="images/logonobg.png"/> <div data-role="content" > <input type="text" name="new-todo" id="new-todo" placeholder="Write your tasks here..." /> <div class="controls" data-role="controlgroup" data-type="horizontal"> <a href="#" id="add" data-role="button" data-icon="plus">Add New</a> <a href="#" id="delete" data-role="button" data-icon="delete">Delete Done</a> </div> <ul id="todo-list" data-role="listview" data-filter="true" data-inset="true" > </ul><!-- /todo-list --> <div class="center" id="no_items"></div> </div> <!-- /content --> </div> <!-- /page -->
タスク・リストの項目は、以下の例に示すように、リスト配列に格納します。
[{content: “myTodo Item 1", done: false}, {content: “myTodo Item 2", done: true}].
これはキーと値のペアによる JavaScript オブジェクトで構成される単純な配列で、項目の名前を表す文字列と完了項目であるかどうかを追跡するためのブール値が値として設定されているものです。
図3に示されているように、TD.List(このサンプル・アプリケーションのListモジュール)には、_encrypt()というプライベート・メソッドが定義されています。このメソッドは Public APIからVaultモジュールのencrypt() メソッドを呼び出して、リスト(list という名前のプライベート配列)を暗号化します。TD.Listには、HTML文書内に定義された項目を表示するために、テンプレートから生成される_item_template()という関数もあります。この関数には、itemというキーと値としてリスト配列を持つオブジェクトを渡す必要があります。
演習として、より複雑な型チェック(例えば、item.doneがブール値を返すかどうかのチェック、nullに対するチェックなど) を実行することもできます。
プライベート関数_add()は、item.contentが空でないことや、’undefined’でないこと、そしてitem.doneを呼び出すと何らかの結果が返されることをチェックします。値が割り当てられていない変数は、デフォルトで‘undefined’を返すことに注意してください。
_add = function (item) { if (item.content !== 'undefined' && item.done !== 'undefined' && item.content.length > 0) { list.push(item); } },// add item
_refresh_list()関数は、リスト配列で動的にmap関数を実行して、その配列に格納されているすべてのオブジェクトに新しい要素を追加します。この関数の残りの部分では、リストをクリアし、リストを基に生成されたテンプレートの結果をHTML内の順不同リスト (ul) に追加した後、ビューを最新の表示に更新します。この最後のメソッド呼び出しは、リストのスタイルを最新の状態に更新するためのjQuery Mobile特有の呼び出しです。
_refresh_list = function () { $.map(list, function (item, i) { item.index = i; }); list_ul.empty(); list_ul.append(_item_template({item : list})); list_ul.listview('refresh'); if (list.length < 1) { no_items.text('No items.'); } else { no_items.text(''); } }; // refresh list
この手法を変更して、異なるデータ構造と異なるアルゴリズムを使用してIDの生成と追跡を行うようにすることもできます。その目標は、map関数を使用してリスト全体を繰り返し処理してIDを生成する必要をなくすこと、そして項目を追加または削除するたびに、リスト全体をクリアしてすべてを追加し直す必要をなくすことです。
次に、アクションをイベントにアタッチします。jQueryを使い慣れているとしたら、bind()、live()、delegate()などの呼び出しを見慣れていたり、使い慣れていたりすると思いますが、この例ではon()だけを使用します。jQuery1.7.0以降、これらの bind()、live()、delegate()といったメソッドは、単なる on() のラッパーになっているためです。また、$(this)は、$thisという名前のローカル変数に「キャッシュ」されます。これは、DOMの操作には非常にコストがかかるため、理想的には前述のjQuery関数はできるだけ使用しないようにして、DOM(Document Object Module)に入り込む時間を制限することが望まれるからです。この例では、完了項目であるかどうかを記述するブール値をトグルして、スタイルシート(.cssファイル)に定義されているdoneクラスを追加または削除していることに注意してください。最後に、項目をクリックして完了マークを付けた直後にアプリケーションを閉じる場合であっても、リストを encrypt()で暗号化してから永続化します。
add_btn.on('click', function () { _add({content : new_item.val(), done: false }); new_item.val(''); _refresh_list(); _encrypt(); }); // add btn list_ul.on('click', 'li', function () { var $this = $(this), $item = $this.find('a'), index = $item.attr('id'), current_item = list[index]; current_item.done = !(current_item.done); if (current_item.done) { $item.addClass('done'); } else { $item.removeClass('done'); } _encrypt(); }); // list item delete_btn.on('click', function () { var i = list.length; while (i--) { if (list[i].done) { list.remove(i); } } _refresh_list(); _encrypt(); });// delete btn
削除ボタンにも同様の処理が適用されます。そのためのコードは、Worklight Studioで表示することができます。
ListモジュールのPublic APIは極めて単純です。このAPIでは、これから作業する対象の最新のリストを取得するためのget()、新しいリストを設定して操作するためのset()、現在設定されているリストを最新の表示に更新するためのrefresh()を使用することができます。これらのメソッドを呼び出すには、TD名前空間の後にモジュールの名前を続け、最後にモジュールから返されるオブジェクトのキーのいずれかを追加して呼び出します。
以下の例を見てください。
TD.List.get(), TD.List.set([]), TD.List.refresh()
上記はすべて有効な関数です。次に、以下の例を見てください。
TD.List._refresh_list(), TD.List._add()
上記の関数は有効ではありません。これらの関数を呼び出せるのは、モジュール内から呼び出す場合(関数がスコープを作成することを思い出してください)、または特権メンバー(モジュール内で返されるオブジェクトなど)が呼び出す場合のみです。
//public API return { get : function () { return list; }, set : function (new_list) { list = new_list; }, refresh : function () { _refresh_list(); } };