knockout.jsというJavaScriptフレームワークがあります。フレームワークというより、HTMLで
<p>First name: <input data-bind="value: firstName" /></p>
と書いて、JavaScriptで
function AppViewModel() {
this.firstName = ko.observable("Bert");
}
ko.applyBindings(new AppViewModel());
とバインディングするライブラリで、PHPのSmartyあたりが近いんじゃないかと思います。個人的に、チェックボックスでdivタグのid属性を生成して、jQueryとかでchangeをbindするのとか嫌いなので、knockout.jsが勝手にバインディングしてくれると嬉しいなぁ、と試してみました。
はじめに
どういうのを習作とするか考えてたら、知り合いが「とある業界」の方から、ジョーの出勤状況を選ぶと、ジョーをお気に入りにしている客のメールアドレスが抽出される(ということをExcelでやりたい)という相談を受けているらしく、それにWebインタフェースで答えるイメージで書いてます。
1時間目
Knockout.jsの公式チュートリアルはバインドするデータもJavaScript内でセットされてますが、実際は外部で生成されたJSONを読み込むケースが多いんじゃなかろうかと。ただ、jQueryの$.ajaxでJSONを読み込もうとして、うまくいかなくてはまりました。
ポイントとしては、
- 空の配列をグローバルで用意する
- $.ajaxでJSONを読み込む場合、async:falseと設定する(そうしないとデータが同期されてない状態でデータバインドしようとして何も表示されない)
- $.ajaxのコールバックで空の配列にJSONの要素を追加する
- Knockout.jsでバインディングする予定の値に$.ajaxで要素を追加した配列を代入する
- 最後にapplyBindingsする
「習作」では、index.phpに、この手法を使っています。
https://github.com/usopyon/fu/blob/master/index.php
2時間目
と言いつつ、こんな感じでJavaScriptを動的に生成しちゃった方が楽だというケースもあります。
viewModel.members = <?php echo json_encode($members)?>;
スクリプトを動的生成することにアレルギーのある人には無理そうですね。
「習作」では、獲物の一覧を表示するところで試しています。
https://github.com/usopyon/fu/blob/master/member.php
3時間目
チェックボックスが100個ぐらい並んでいて、チェックしたり外したりするごとに、裏でデータベースへの追加とか削除が走るという実装を試してみます。
knockout.jsでは、observableArrayにチェックされた要素が格納されます。そこで最初は、チェックしたり外したりするごとに、全削除して、チェックされた状態のものをすべて追加する処理を実装していましたが、追加・削除が完了する前にウィンドウを閉じるとデータが不整合になったりします。
そこで、初期状態の配列とobservableArrayを比較し、
- 初期状態に含まれていた要素がobservableArrayに含まれていない場合は削除処理
- observableArrayに含まれていた要素が初期状態に含まれていない場合は追加処理
- 初期状態とobservableArrayを同期
として、チェックされたもの、チェックが外されたものだけ処理するように書いてみました。
「習作」では獲物の編集画面でジョーを選択するところで試しています。
https://github.com/usopyon/fu/blob/master/edit.php
サンプル
こちらのサイトでサンプルを動かしています。
http://barcelona.sakura.ne.jp/fu/index.php
githubに置いているコードは、PHP+SQLiteが使える環境にコピーし、最初にsetup.phpを起動すれば使えるようになっています。
https://github.com/usopyon/fu