узел jsTree развернуть/свернуть

сегодня утром я столкнулся с отличным jstree jQuery UI plug. Одним словом - здорово! Он прост в использовании, прост в стиле и делает то, что он говорит на коробке. Единственное, что я еще не смог понять, это - в моем приложении я хочу убедиться, что только один узел расширяется в любой момент времени. т. е. когда пользователь нажимает на кнопку + и разворачивает узел, любой ранее развернутый узел должен быть молча свернут. Мне нужно сделать это частично, чтобы предотвратить контейнер div для довольно длинный вид дерева от создания уродливой полосы прокрутки при переполнении, а также во избежание "перегрузки выбора" для пользователя.

Я полагаю, что есть какой-то способ сделать это, но хорошая, но довольно лаконичная документация jstree не помогла мне определить правильный способ сделать это. Я был бы очень признателен за любую помощь.

4 ответов


jsTree, но документации достаточно плотная. В конце концов я понял это так вот решение для тех, кто работает в этой теме.

во-первых, вам нужно привязать событие open_node к рассматриваемому дереву. Что-то вроде

$("tree").jstree({"themes":objTheme,"plugins":arrPlugins,"core":objCore}).
bind("open_node.jstree",function(event,data){closeOld(data)}); 

т. е. вы настраиваете экземпляр treeview, а затем привязываете событие open_node. Здесь я вызываю функцию closeOld, чтобы выполнить требуемую работу - закрыть любой другой узел, который может быть открыт. Функция выглядит так

function closeOld(data)
{
    var nn = data.rslt.obj;
    var thisLvl = nn;
    var levels = new Array();
    var iex = 0;
    while (-1 != thisLvl)
    {
        levels.push(thisLvl);
        thisLvl = data.inst._get_parent(thisLvl);
        iex++;
    }

    if (0 < ignoreExp)
    {
        ignoreExp--;
        return;
    }

    $("#divElements").jstree("close_all");
    ignoreExp = iex;
    var len = levels.length - 1;
    for (var i=len;i >=0;i--) $('#divElements').jstree('open_node',levels[i]);
}

это будет правильно обрабатывать сворачивание всех других узлов независимо от уровня вложенности узла, который только что был расширен.

краткое объяснение действия

  • Сначала мы возвращаемся к treeview, пока не достигнем узла верхнего уровня (-1 в jstree speak), убедившись, что мы записываем каждый узел предка, встреченный в процессе в массиве уровень
  • Далее мы развалится все узлы в treeview
  • теперь мы собираемся повторно расширить все nodees в уровень массив. При этом мы не хотим, чтобы этот код выполнялся снова. Чтобы остановить это, мы установили global ignoreEx переменная к числу узлов в уровень
  • наконец, мы проходим через узлы в уровень и расширить каждый из них

приведенный выше ответ будет строить дерево снова и снова. Приведенный ниже код откроет узел и свернет, которые уже открыты, и он не построит дерево снова.

.bind("open_node.jstree",function(event,data){
        closeOld(data);
        });

и функция closeOld содержит:

function closeOld(data)
{
    if($.inArray(data.node.id, myArray)==-1){
            myArray.push(data.node.id);
            if(myArray.length!=1){
                var arr =data.node.id+","+data.node.parents;
                var res = arr.split(",");
                var parentArray = new Array();
                var len = myArray.length-1;
                for (i = 0; i < res.length; i++) {
                    parentArray.push(res[i]);
                }
                for (var i=len;i >=0;i--){
                    var index = $.inArray(myArray[i], parentArray);
                if(index==-1){
                    if(data.node.id!=myArray[i]){
                    $('#jstree').jstree('close_node',myArray[i]);
                        delete myArray[i];
                    }
                }
                }
        }
    }

еще один пример для jstree 3.3.2. Он использует подчеркивание lib, не стесняйтесь адаптировать решение к jquery или vanillla js.

$(function () {
    var tree = $('#tree');
    tree.on('before_open.jstree', function (e, data) {
        var remained_ids = _.union(data.node.id, data.node.parents);
        var $tree = $(this);
        _.each(
                $tree
                    .jstree()
                    .get_json($tree, {flat: true}),
                function (n) {
                    if (
                        n.state.opened &&
                        _.indexOf(remained_ids, n.id) == -1
                    ) {
                        grid.jstree('close_node', n.id);
                    }
                }
        );
    });
    tree.jstree();
});

Я достиг этого, просто используя событие "before_open" и закройте все узлы, мое дерево имело только один уровень tho, не уверен, что это то, что вам нужно.

$('#dtree').on('before_open.jstree', function(e, data){
    $("#dtree").jstree("close_all");
});