TreeView Control: Custom TreeView with Check Boxes
このExample(Exampleのページへのリンク)は、「Custom TreeView with Check Boxes」というタイトルになっているが、TextNodeを拡張したTaskNode.jsというノードが紹介されている。
Taskという名前が示す通り、Tree上にWBS(Work Breakdown Structure)をそのまま表現して、タスクが終了したらチェックをいれる、ということを想定しているように思われる。
各ノードは、「終了(チェックマーク)」、「仕掛(-)」、「未着手(マークなし)」の3種類のステータスをプロパティーとして保持している。
チェックするというイベントが発生すると、その親のノードへそれが伝播し、
- 親ノードの全てのchildrenがチェック済みなら、その親ノードもチェックとする。
- 上記以外は仕掛りとする。
という仕組みで、ノードの状態(state)がchangeする。
これは、チェックが外されたときも同様。
このリカーシブな処理も、TaskNodeの中で行われている。
(TaskNode.jsはこちらからダウンロードできる)
ここでは、これをカスタマイズすることはせず、YUIモジュールのひとつとして使ったサンプリングを行う。
以下に示すサンプルは、Exampleのページにあるものに若干の修正を加えたものである。
初期画面は以下。Exampleでは、画面トップに「Log array of checked nodes(チェック済みのノードの配列をログに書き出す)」というリンクがあるが、これは割愛した(必要な場合には、Exampleのソースコードを参照)。
上で述べた、ノードの状態遷移を示したものが以下である。
以下にJavascriptを含む、HTMLの全文を示す。多くの処理をTaskNode.jsに移譲することで、利用時のスクリプトは簡潔なものとなっていることがわかる。Scriptの配置位置を変えるにあたって、module patternに書き直しをおこなった。
<残課題>
このタスクノードを外部から読み込んだデータから生成したり、編集・保管できるように拡張することで、立派なWBSのツールができる。
<HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=UTF-8"> <TITLE>Ajax_Sampling</TITLE> <style type="text/css"> body { margin:0; padding:0; } </style> <link rel="stylesheet" type="text/css" href="scripts/yui/fonts/fonts-min.css" /> <link rel="stylesheet" type="text/css" href="scripts/yui/treeview/assets/skins/sam/treeview.css" /> <style type="text/css" id="defaultstyle"> #container { margin: 2px; padding: 3px; width: 300px; height: auto; border:1px dashed #999999; } #expandcontractdiv { border:1px solid #336600; background-color:#FFFFCC; margin:0 0 .5em 0; padding:0.2em; } #treeDiv1 { background: #fff } /*チェックボックス(この例ではCSS Spritesは行っていない)*/ .ygtvcheck0 { background: url(scripts/yui/treeview/assets/img/check/check0.gif) 0 0 no-repeat; width:16px; cursor:pointer } .ygtvcheck1 { background: url(scripts/yui/treeview/assets/img/check/check1.gif) 0 0 no-repeat; width:16px; cursor:pointer } .ygtvcheck2 { background: url(scripts/yui/treeview/assets/img/check/check2.gif) 0 0 no-repeat; width:16px; cursor:pointer } </style> <!-- 読み込むjs --> <script type="text/javascript" src="scripts/yui/yahoo-dom-event/yahoo-dom-event.js" > </script> <script type="text/javascript" src="scripts/yui/treeview/treeview-min.js" > </script> <!-- http://developer.yahoo.com/yui/examples/treeview/assets/js/TaskNode.js よりダウンロードして保管 --> <script type="text/javascript" src="scripts/yui/treeview/TaskNode.js"></script> <script type="text/javascript"> // //モジュールパターンで、サンプルのソースを書き直した。 // (注) Tree上でのステータスの伝播は、TaskNodeオブジェクトが行っているため // 以下に示すコードでは、Treeの生成と、画面上部のリンクの処理のみ // を行っている。 // YAHOO.namespace("EGP"); YAHOO.EGP.CheckTree = function() { var tree; var nodes = []; var nodeIndex; var buildTextNodeTree = function() { //TreeViewオブジェクトのインスタンス化。 tree = new YAHOO.widget.TreeView("treeDiv1"); //トップノードとして、0から7個のノードを作る。 for (var i = 0; i < Math.floor((Math.random()*4) + 3); i++) { var tmpNode = new YAHOO.widget.TaskNode("label-" + i, tree.getRoot(), false); buildRandomTaskBranch(tmpNode); } tree.draw(); }; function buildRandomTaskBranch(node) { // 階層の深さが5になるまで、リカーシブにノードの階層を構成する。 // 1つのノードには、0から5個の子ノードがつく。 if (node.depth < 5) { for ( var i = 0; i < Math.floor(Math.random() * 4) ; i++ ) { var tmpNode = new YAHOO.widget.TaskNode(node.label + "-" + i, node, false); buildRandomTaskBranch(tmpNode); } } }; function checkAll() { var topNodes = tree.getRoot().children; for(var i=0; i<topNodes.length; ++i) { topNodes[i].check(); } }; function uncheckAll() { var topNodes = tree.getRoot().children; for(var i=0; i<topNodes.length; ++i) { topNodes[i].uncheck(); } }; return{ init: function() { //「全て開く」のハンドラ YAHOO.util.Event.on("expand", "click", function(e) { YAHOO.util.Event.preventDefault(e); tree.expandAll(); }); //「全て閉じる」のハンドラ YAHOO.util.Event.on("collapse", "click", function(e) { YAHOO.util.Event.preventDefault(e); tree.collapseAll(); }); //「全てチェックする」のハンドラ YAHOO.util.Event.on("check", "click", function(e) { YAHOO.util.Event.preventDefault(e); checkAll(); }); //「全てのチェックを外す」のハンドラ YAHOO.util.Event.on("uncheck", "click", function(e) { YAHOO.util.Event.preventDefault(e); uncheckAll(); }); buildTextNodeTree(); } }; }(); //DOMが完全にloadされたら、サンプルを初期化する。 YAHOO.util.Event.onDOMReady( //DomReadyイベントで発火するハンドラ YAHOO.EGP.CheckTree.init, //ハンドラに渡すオブジェクト(関数) YAHOO.EGP.CheckTree, //ハンドラは、上記のオブジェクトのスコープをもつ。 true ); </script> </HEAD> <!-- class=" yui-skin-sam"の指定が必要 --> <BODY class=" yui-skin-sam"> <div id="container"> <p> チェックボックス付のテキストノードのサンプルです。 </p> <div id="expandcontractdiv"> <a id="expand" href="#">全て展開</a> <a id="collapse" href="#">全て閉じる</a> <a id="check" href="#">全てチェック</a> <a id="uncheck" href="#"全て>チェックを外す</a> <!-- <a id="getchecked" href="#">Log array of checked nodes</a> --> </div> <div id="treeDiv1"></div> </div> </BODY> </HTML>