作成日: 2007年12月28日
作成者: フリーランスエンジニア 中垣 茂
最終更新日: 2007年12月28日
「CFTREE」も「CFGRID」と同様に CF8 以前のバージョンからあり、「format」属性を「Flash」にしたFlex 1.5 ベースの「CFTREE」が使用されていたかもしれません。CF8 から使用できる「format」属性に「html」が追加され Ajax ベースの「CFTREE」が使用できるようになりました。正直なところ Flex 2 の「Tree」クラスよりも良いかもしれません。Flex 2 の「Tree」は「アニメーションなどよりももっと Tree としての機能の完成度を高めるべきだったのでは?」と思われるところがあり、使おうとすると"帯に短し、たすきに長し..."と不満を漏らすことがあります。CF8の「CFTREE」はなかなか軽快に動いてくれます。
難点というか、「CFGRID」同様でとにかくヘルプが見辛い。「CFTREE」にはYahoo! User Interface Library(YUI)の YAHOO.widget.TreeView がベースとして使用されているのですが、YUIにあるメソッドやイベントが「CFTREE」ではほとんどサポートされていません。「ColdFusion.Tree.getTreeObject」というCF8で提供されているJavaScript関数でYAHOO.widget.TreeView オブジェクトを取得できるのですが、「そこからは御自分で」ということになります。もう一つ、「ColdFusion.Tree.refresh」というのがありますがこれはその名の通り"リフレッシュ"しかできません。
YUI の TreeView よりも Ext.JS の Tree の方が良かったと思うのですが、おそらく構造上 CFとしては YUI の TreeView の方が扱いやすかったのでしょう。ちょっと残念ですね。
まずはべたにツリーの各ノードをハードコーディングする方法です(図1)。
図1:使用例1のサンプルコード
※クリックすると大きな画像が表示されます
見ての通り「CFTREE」タグの中に「CFTREEITEM」タグを階層化させるだけで、「ブランチノード」や「リーフノード」といった概念もコード上はありません。子ノードがあれば自動的に"展開表示"を表すイメージが表示されます。実際のサンプルがこちらです。
使用例1のサンプル
各ノードをクリックするとツリーの下のテキスト入力欄に選択したノードに関連したデータがデバッグ用に表示されます。実はこれ、「CFTREE」タグ自体ではできないので工夫する必要があります(図2)。
図2:「CFTREE」の選択ノードの変更を検知する工夫
※クリックすると大きな画像が表示されます
24行目の"eventDummy"は"tree01″の「path」/「node」値の変更を検知すると、自身の変更イベントを発行し、「bind」で指定された
JavaScript をキックします。そのJavaScript の中で値を加工し、テキスト入力欄にデバッグ情報を表示しているわけです。ちょっと回りくどい方法ですが、「ColdFusion.Tree.getTreeObject」関数を使用して、「YAHOO.widget.TreeView」を取得し自前でイベントハンドリングJavaScriptを実装するよりは良いと思います。
jSON形式データから各ノードを生成する方法です(図3)。
図3:使用例2のサンプルコード
※クリックすると大きな画像が表示されます
「CFTREEITEM」タグの「bind」属性に「URL:」という接頭語を付け、続けて実行するCFMファイルのURLを指定します。こうすることで最初の実行時と各ノードをクリックしたときに指定したURLが引数付きで実行されます。とっても簡単すぎてかえって思いつかないかもしれません。おまけに、親切なヘルプには書いていませんし。サーバーサイドですがjSONデータを構築する為にちょっと手間なことをしているので、簡単なフローだけ説明しますと、
1.ノード情報を格納した構造体の配列を生成
2.「SerializeJSON」というCFの関数を使用して配列をjSON形式のデータに変換します。
3.「CFCONTENT」タグの「type」属性を「application/x-javascript」にしてjSON形式のデータを出力します。
実際のサンプルはこちらです。
使用例2のサンプル
サーバーサイドにjSON系の資産や自前のライブラリがある場合は、こちらのやり方の方が簡単かもしれません。
CFCからデータを取得する方法です(図4)。
図4:使用例3のサンプルコード
※クリックすると大きな画像が表示されます
「使用例2」とほぼ同じで、「bind」属性用の接頭語には「CFC:」で、ドットシンタックス表記でCFCのパスを記述します。パスの最後は「load」というCFC内で定義した関数名を記述しています。このようにRPC形式でコールできるのは便利かと思います。CFC側の記述はというと先ほどと似ています。簡単なフローは下記のようになります。
1.ノード情報を格納した構造体の配列を生成
2.「1」で生成した配列をリターンする
先ほどよりも簡単ですね。実際のサンプルはこちらです。
使用例3のサンプル
使用例2と3、どちらの場合もツリー用の構造体を生成する為に否応無しにサーバーサイドでループを回さないといけません。しかしながら、表示するノード分だけのデータなのでたいしたことは無いかもしれません。つまり、初回表示時はルートノードの一覧だけ、ノードをクリックした場合はその子ノードの数だけ、と一度に扱うデータ量が少なくてすみます。もちろん、子ノードに200〜300とかデータがあった場合はサーバーサイドもクライアントサイドもそれなりにパフォーマンスを必要とします。が、そのような場合はそもそも「ツリー」という表示方法をやめるべきです。100以上あるデータからユーザーが目見で選択対象を探すなどというのはユーザビリティ的にあり得ないと思います。
使用例1〜3は見た目がちょっとさびしいかもしれません。しかし、「CFTREE」ではイメージを各ノードに表示することが可能です。ちょっと便利だと思ったのですが、すべてのノードにそれぞれ違うイメージを簡単に指定することができるのです。ノード用の構造体に「閉じている状態のイメージ」(IMG)、「開いている状態のイメージ」(IMGOPEN)があり、その値にイメージのURLを指定するだけで簡単に表示できます。実際のサンプルはこちらです。
使用例3のサンプル
このようにデータの構築がちょっと面倒ですが「CFTREE」そのものは非常に簡単に利用できます。Ext.JS の Tree はドラッグ&ドロップでツリーアイテムの移動までできますが、「CFTREE」はこれはこれでコンパクトにまとまっていて扱いやすいと思います。
以上、【ツリーレイアウト+Ajaxを簡単に実現できる「CFTREE」】は終了です。