ひさびさにツリーメニューを実装しようと思って
Treeview を設置してみたけど、動かない。。。
更新も止まっているようだし、他のプラグインを探してみたら良さそうなのがあった。 😯
採用するかどうかはわからないけど、使い方をメモ。
コード中に出てくる vakata って何かと思ってたけど
作者の HN でした。
GitHub:vakata
【環境】
jsTree:3.2.1
jQuery:1.11.3
DL
公式 の Download ボタンより DL。
2015-10-28 現在
vakata-jstree-3.2.1-0-g8ea6ce7.zip
ファイル配置
- DL したファイルを解凍
- 中身の dist ディレクトリを js ディレクトリへ配置
- 配置した dist ディレクトリを jstree にリネーム
中には CSS ファイルや画像ファイルもあるので、本来なら分けるべきかもしれないけど、ここで完結させる。
なぜなら、テーマ名を設定するだけで、テーマの変更をできるようになっているから。
でも、その割には CSS ファイルへの参照はちゃんと記述しないとダメ。。。
利用
前提
<link rel="stylesheet" type="text/css" href="./css/jstree.min.css">
<script type="text/javascript" src="./js/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="./js/jstree.min.js"></script>
リストタグ
<script>
$(document).ready(function(){
$('#tree').jstree();
});
</script>
<div id="tree">
<ul>
<li>階層1
<ul>
<li>階層2</li>
</ul>
</li>
</ul>
</div>
注意
階層リストの場合、書式に注意。
下記タイプA、タイプB、どちらでもリスト表示をできるけど
jsTree は、タイプB で記述しないと認識しない。
// タイプA
<ul>
<li>階層1</li>
<ul>
<li>階層2</li>
</ul>
</ul>
// タイプB
<ul>
<li>階層1
<ul>
<li>階層2</li>
</ul>
</li>
</ul>
私は今までタイプAで書くのが普通だったんだけど
もしかして、正式はタイプBなのかしら。。。汗
XML データ
JSON データ
注意
ツリー項目に a タグを付けてリンクを貼ろうとしたけど
どうも表示が変になる。
<li>Content <a href="#">Edit</a></li>
としても、Edit だけが表示される。
dnd の研究にノードオブジェクトの中身を覗いてみたけど
jsTree が表示用に a タグを利用しているようで
リンクを貼りたければ、click イベントで制御するしかなさそう。
設定書式
プラグインも含めた設定の例。
$(document).ready(function(){
$('#jstree').jstree({
// 基本設定
'core' : {
'themes' : {
'variant' : 'large'
}
},
// プラグイン毎の設定
'checkbox' : {
'keep_selected_style' : false
},
// 利用するプラグインを列挙?
'plugins' : [ 'wholerow', 'checkbox' ]
});
});
</script>
こんな感じ。
他のプラグインと同じ~。 😯
‘plugins’ で、On にしたいプラグインを列挙し
プラグイン毎の設定で、各プラグインの設定変更をする。
設定変更がなければ、プラグイン各個の設定は記述しなくて良い。
core(基本設定)
themes
$(document).ready(function(){
$('#jstree').jstree({
"core" : {
'themes' : {
// 独自テーマを利用したい場合は、当該ディレクトリ名文字列を指定?
'name' : false,
// 独自テーマを利用したくて、.js ファイルと別階層に置きたい場合に true を指定?
'url' : false,
// url を true にしたときだけ有効。テーマの場所を記述?
'dir' : false,
// ツリー罫線を表示するか否か
'dots' : true,
// ノード(フォルダ)アイコンを表示するか否か
'icons' : true,
// 1行おきに背景色を付けて縞々にするか否か
'stripes' : false,
// CSS クラス('large', 'small', 'responsive')があるっぽい
// false でデフォルトなんだろうけど、どれかわからない
'variant' : false,
// 小さい画面の時は ture って書いてある気がするけど、true にしてみても、違いがわからない
'responsive' : false,
}
}
});
});
check_callback
ユーザーによるツリーの変更を許可するか否か。
デフォルトは false。
$(document).ready(function(){
$('#jstree').jstree({
"core" : {
'check_callback' : false,
}
});
});
関数指定
true か false か、状況によって変化させるために
関数を指定することができる。
$(document).ready(function(){
$('#jstree').jstree({
"core" : {
'check_callback' : function (operation, node, node_parent, node_position, more) {
if ((operation === 'move_node' || operation === 'copy_node') && (node_parent.id === '#')) return false;
},
}
});
});
jstree.js
* __Examples__
*
* $('#tree').jstree({
* 'core' : {
* 'check_callback' : function (operation, node, node_parent, node_position, more) {
* // operation can be 'create_node', 'rename_node', 'delete_node', 'move_node' or 'copy_node'
* // in case of 'rename_node' node_position is filled with the new node name
* return operation === 'rename_node' ? true : false;
* }
* }
* });
引数
jstree.js
* @name check(chk, obj, par, pos)
* @param {String} chk the operation to check, can be "create_node", "rename_node", "delete_node", "copy_node" or "move_node"
* @param {mixed} obj the node
* @param {mixed} par the parent
* @param {mixed} pos the position to insert at, or if "rename_node" - the new name
* @param {mixed} more some various additional information, for example if a "move_node" operations is triggered by DND this will be the hovered node
* @return {Boolean}
- 引数
- operation(String)
- node(Object)
- node_parent(Object)
- node_position(integer)
- more(Object)
- core
- is_foreign
- is_multi
- origin(Object)
- 恐らく移動前のツリー全体の情報が格納されている
- 参考記事の more.ref.data.type の使い方不明
よくわからないオブジェクト連鎖
stackoverflow:JsTree v3.0 drag and drop plugin. Reference target node upon dropping
こちらに書かれている下記コードにおける
more.ref.data.type
が、何をどう辿っているのか不明。
if (more.ref.data.type === "folder") {
return true;
}
console.log(more.ref.data.type);
TypeError: more.ref is undefined
タイミング
チェックは常に行っているらしく
上記のように指定することで、ドラッグ中に
root 直下へは、移動先候補 ▶ のマークが出なくなった。
data(Ajax)
こちらを設定しておくことで、ページ読み込み時に
そちらを読みにいく。
$(document).ready(function(){
$('#jstree').jstree({
"core" : {
'data' : {
'url' : function (node){
if (node.id === '#') {
return "http://localhost:9000/getCourses/" ;
}
else
return "http://localhost:9000/getCourses/" + node.id;
}
},
'data' : function (node) {
return { 'id' : node.id };
}
}
}
});
});
こちらは下記サイトのコードをいただいてきたが
あちこちでこのような書き方がされている。
answer uxu:jstree html and json
どうもデフォルトでは、node.id がルートの # になっていて
ルートの情報を取得して表示。
後はノードを選択する度に、そのノードの ID を送り、その配下の情報を取得し表示。
という仕様になっているっぽい。
変更の通信ではない?
プラグイン
jsTree という名前の jQuery プラグインに実装されている
プラグイン(追加機能)。
一覧
公式:Plugins?
'plugins' : [
'checkbox',
'contextmenu',
'dnd',
'massload',
'search',
'sort',
'state',
'types',
'unique',
'wholerow',
'changed',
'conditionalselect'
]
checkbox
設定
$(document).ready(function(){
$('#jstree').jstree({
'checkbox' : {
// 選択された行に背景色をつけるか否か
'keep_selected_style' : true
}
'plugins' : [ 'checkbox' ]
});
});
contextmenu
contextmenu
dnd(Drag and Drop)
dnd(Drag and Drop)
search
設定
JSFIDDLE:http://jsfiddle.net/53cvtbv9/1/
$(document).ready(function(){
$('#jstree').jstree({
'plugins' : [ 'search' ]
});
});
<div><?php echo __('Search : '); ?><input type="text" class="search-input" /></div>
<script>
$(document).ready(function() {
$(".search-input").keyup(function() {
var searchString = $(this).val();
$(selectorTree).jstree('search', searchString);
});
});
<script>
unique
単一ノード直下の重複チェック。
設定
$(document).ready(function(){
$('#jstree').jstree({
'unique' : {
// 大文字小文字の区別をするか否か
'case_sensitive' : false,
// 重複した場合の名称を hoge -> hoge (2) のように変更する
'duplicate' : false,
}
'plugins' : [ 'unique' ]
});
});
イベントリスナー
イベントリスナー
メソッド
書式
複数あるっぽい。
$('#jstree').jstree('select_all'); // うまくいった
$('#jstree').select_all(true); // 未試行
一覧
// 選択系
$('#jstree').jstree('select_all'); // 全選択
$('#jstree').jstree('check_all'); // 全選択
$('#jstree').jstree('deselect_all'); // 全選択解除
$('#jstree').jstree('select_node', node.id); // 個別選択
$('#jstree').jstree('deselect_node', node.id); // 個別選択解除
// オープン系
$('#jstree').jstree('open_all'); // 全開く
$('#jstree').jstree('close_all'); // 全閉じる
// 後はパターンで考えてましょう。。。
本体解析
this
全部でないかもしれないけど、本体コード中に現れる this は
カスタマイズの際には $(selectorTree).jstree(true) に読みかえればよいかも?
Loading
本体の Ajax 通信を利用せずに、独自の通信ロジックにしたら
Loading 表示のやり方がわからなかった。
独自にした理由
どこの例を見ても、’data’ : のところが、{ “id” : node.id } となっていて、それ以外のデータの渡し方がわからなかったから
当該ノードだけを更新するわけでなくて、ツリー全体を更新しているから
本体解析
うまい例を見つけられなかったので、本体を見てみた。
jstree.js
refresh : function (skip_loading, forget_state) {
__snip__
if(!skip_loading) {
this.element.html("<"+"ul class='"+c+"' role='group'><"+"li class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='treeitem' id='j"+this._id+"_loading'><i class='jstree-icon jstree-ocl'></i><"+"a class='jstree-anchor' href='#'><i class='jstree-icon jstree-themeicon-hidden'></i>" + this.get_string("Loading ...") + "</a></li></ul>");
this.element.attr('aria-activedescendant','j'+this._id+'_loading');
}
__snip__
}
どうやら、ここで表示しているらしい。
本体の HTML を一旦 Loading 用に書き換えちゃってるのね~。
refresh
それで、いくつか refresh メソッドを試してみたけど表示されなかった。
$(selectorTree).jstree(true).trigger('refresh');
// create で試したけど、当該ノードが消えただけ
// refresh をかけたわけだから、create に前に戻るので当たり前
$(selectorTree).jstree(true).refresh();
Loading 表示
上記の HTML の内、わからないところとか、不必要と思われる箇所を少しだけ除いて
無理くり下記のようにしてみたら、ツリー全体を Loading 画像で置き換えることができた。
var htmlLoading = '<ul class="jstree-container-ul jstree-children" role="group">'
+ '<li class="jstree-initial-node jstree-loading jstree-leaf jstree-last" role="tree-item">'
+ '<i class="jstree-icon jstree-ocl"></i>'
+ '<a class="jstree-anchor" href="#">'
+ '<i class="jstree-icon jstree-themeicon-hidden"></i>Loading ...'
+ '</a>'
+ '</li>'
+ '</ul>';
$('#jstree').jstree(true).element.html(htmlLoading);
refresh
そのまんま。
読み込んだときの状態に戻す。
$(selectorTree).jstree(true).refresh();
$(selectorTree).jstree(true).refresh(false, false);
第1引数:skip_loading。Loading 表示をスキップするか否か
第2引数:forget_state。現状を記憶するか否か
参考サイト
株式会社アンフィニ 技術ブログ:【javascript】jQueryプラグイン jsTreeの紹介
海外製ライブラリ・Web API ドキュメントの翻訳ページ:jsTreeドキュメント日本語訳