jsTree で下のツリー階層を開く時にもAJAX通信で読み込む方法

jsTree配布デモを見ても、ツリー全体JSONAJAXで読み込む方法はあるが、
静的に書いたJSON から下の階層を開く時や、AJAX読込み後さらに下の階層を読み込む方法が、
なかなか解らなかった。massload とかプラグインあるみたいだが、どうもできない。。。
f:id:posturan:20180929112809j:plain
クリックしたら
f:id:posturan:20180929112848j:plain
読込み終わったら自動的に、、
f:id:posturan:20180929112937j:plain
ということがしたい。巨大なツリーやあるノードにぶら下がる下が大量に子が存在すると、
これができない場合、ツリーデータ全てを読込みサーバから送信が終わるまで表示できないなんて
とてもつらいだろう。。
でもなんとか、AJAX読込み後さらに下の階層を読み込む方法が判った。
後から読み込ませるノードの id に任意のキーを設定し、初期状態を "state": "closed"
子ノードがあることだけを示すように、"children":[ ] を書かないで、"children": true を書く。
AJAX読込みの url は、url : function(node){ } を書いて、対象ノードIDで JSON取得先を変えて
ツリー全体か、設定した任意のキーに沿った JSON を取得するようなURL、
どちらかを返すようにする。

上の画像のサンプル
ツリー全体のJSONデータ (root.json

[
   {
      "id":1, "icon":"jstree-folder", "text":"Root 1", "title":"This is Root 1",
      "children":[{
         "id":2, "icon":"jstree-file", "text":"Child 2", "title":"This is Child 2"
      }]
   },{
       "id" : "submore",
       "icon": "jstree-folder",
        "text": "Root 2", "title":"open more ...",
        "state": "closed",
        "children": true
   }
]

↑"id" : "submore" のノードを開いた時の JSONデータ(sub.json

[{
   "id":21, "icon":"jstree-file", "text":"A001", "title":"This is A001"
},{
   "id":22, "icon":"jstree-file", "text":"A002", "title":"This is A002"
},{
   "id":23, "icon":"jstree-file", "text":"A003", "title":"This is A003"
},{
   "id":24, "icon":"jstree-file", "text":"A004", "title":"This is A004"
}]

ブラウザで表示させる jQuery

$.jstree.defaults.core.themes.variant = "large";
$.jstree.defaults.core.themes.responsive = true;

$('#tree').jstree({
   "core": {
      "multiple": false,
      "data": {
         "url" : function(node){
            var url = "/mycontext/treeview?req=#";
            if (node.id === "submore") url = "/mycontext/treeview?req=sub";
            return url;
         },
         "dataType" : "json"
      }
   }
}).on("hover_node.jstree", function(e, data){
   $("#"+data.node.id).prop('title', data.node.original.title);
});

サーバ側、別に Wicket でなくても要求に従って上のJSONを送るのが振り分けさえ
できてればよいのですが、参考として。。
Wicket での例です。
URLと WebPage クラスの紐付け、WebApplication の init でマウント

mountPage("/treeview", TreeAjaxJsonRes.class);

WebPage (TreeAjaxJsonRes) で

 getRequestCycle().getRequest().getQueryParameters().getParameterValue("req").toString();

でパラメータ受け取り

File file = // URLパラメータ"req" の結果で、root.json か sub.json のどちらかを読み込むファイル

getRequestCycle().scheduleRequestHandlerAfterCurrent(
   cycle->{
      try(InputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream()){
         in.transferTo(out);
         text = out.toString();
         cycle.getResponse().getOutputStream().write(text.getBytes());
      }catch(IOException ex){
         logger.error(ex.getMessage(), ex);
      }
   }
);