2012-08-23 16 views
6

Mi sono imbattuto nell'eccellente interfaccia jstree jQuery UI in questa mattina. In una parola: fantastico! È facile da usare, facile da stile & fa ciò che dice sulla scatola. L'unica cosa che non sono ancora riuscito a capire è questa: nella mia app voglio assicurarmi che un solo nodo sia espanso in un dato momento. Ad esempio, quando l'utente fa clic sul pulsante + e espande un nodo, qualsiasi nodo precedentemente espanso dovrebbe essere collassato in modo silenzioso. Ho bisogno di farlo in parte per evitare che div contenitore per una vista ad albero piuttosto lunga da creare una brutta barra di scorrimento su overflow e anche per evitare "scelta sovraccarico" per l'utente.jsTree Node Espandi/comprimi

Immagino che ci sia un modo per farlo ma la buona ma piuttosto tersa documentazione di JSTree non mi ha aiutato a identificare il modo giusto per farlo. Apprezzerei molto qualsiasi aiuto.

risposta

5

jsTree è ottimo ma la sua documentazione è piuttosto densa. Alla fine ho capito e quindi ecco la soluzione per chiunque si imbattesse in questo thread.

In primo luogo, è necessario associare l'evento open_node all'albero in questione. Qualcosa sulla falsariga di

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

Ad esempio, si configura l'istanza di treeview e quindi si associa l'evento open_node. Qui sto chiamando la funzione closeOld per fare il lavoro che richiedo: chiudo qualsiasi altro nodo che potrebbe essere aperto. La funzione va come così

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]); 
} 

Ciò gestire correttamente la piegatura di tutti gli altri nodi indipendentemente dal livello di annidamento del nodo che è stato appena ampliato.

Una breve spiegazione delle fasi coinvolte

  • Prima facciamo un passo indietro la vista ad albero fino a raggiungere un nodo di livello superiore (-1 in jstree parlare) assicurandosi che registriamo ogni nodo antenato incontrate nel processo di nell'array livelli
  • Successivamente abbiamo comprimere tutti i nodi del treeview
  • ora andiamo a ri-expand tutti i nodees nelle livelli matrice. Mentre così facendo non vogliamo che questo codice venga eseguito di nuovo. Per impedire che accada abbiamo impostato il globale ignoreEx variabile al numero di nodi in livelli
  • Infine, ci passo attraverso i nodi in livelli ed espandere ciascuno di essi
2

che questo la risposta costruirà l'albero ancora e ancora. Il codice seguente aprirà il nodo e collasserà che sono già aperti e non costruisce di nuovo l'albero.

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

e funzione closeOld contiene:

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]; 
        } 
       } 
       } 
     } 
    } 
1

Ancora un altro esempio per jstree 3.3.2. Usa underscore lib, sentiti libero di adattare la soluzione a jquery o 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(); 
}); 
0

ho ottenuto che da solo utilizzando l'evento "before_open" e chiudere tutti i nodi, il mio albero aveva un solo tho livello, non so se questo è quello che vi serve.

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