web-dev-qa-db-fra.com

Comment créer une table arborescente repliable en html / css / js?

J'ai quelques données à afficher qui sont à la fois tabulaires et hiérarchiques. Je voudrais permettre à l'utilisateur de développer et de réduire les nœuds.

Un peu comme ça, sauf fonctionnel:

http://www.maxdesign.com.au/articles/tree-table/

Quelle serait la meilleure façon d'aborder cela? Je ne suis pas opposé à l'utilisation d'un plugin standard.

35
justkevin

SlickGrid a cette fonctionnalité, voir démonstration d'arbre .

Si vous voulez construire le vôtre, voici un exemple ( démo jsFiddle ): Construisez votre table avec un data-depth attribut pour indiquer la profondeur de l'élément dans l'arborescence (les classes CSS levelX sont juste pour l'indentation de style):

<table id="mytable">
    <tr data-depth="0" class="collapse level0">
        <td><span class="toggle collapse"></span>Item 1</td>
        <td>123</td>
    </tr>
    <tr data-depth="1" class="collapse level1">
        <td><span class="toggle"></span>Item 2</td>
        <td>123</td>
    </tr>
</table>

Ensuite, quand un lien bascule est cliqué, utilisez Javascript pour masquer tout <tr> éléments jusqu'à ce que <tr> de profondeur égale ou inférieure est trouvée (à l'exclusion de celles déjà réduites):

$(function() {
    $('#mytable').on('click', '.toggle', function () {
        //Gets all <tr>'s  of greater depth below element in the table
        var findChildren = function (tr) {
            var depth = tr.data('depth');
            return tr.nextUntil($('tr').filter(function () {
                return $(this).data('depth') <= depth;
            }));
        };

        var el = $(this);
        var tr = el.closest('tr'); //Get <tr> parent of toggle button
        var children = findChildren(tr);

        //Remove already collapsed nodes from children so that we don't
        //make them visible. 
        //(Confused? Remove this code and close Item 2, close Item 1 
        //then open Item 1 again, then you will understand)
        var subnodes = children.filter('.expand');
        subnodes.each(function () {
            var subnode = $(this);
            var subnodeChildren = findChildren(subnode);
            children = children.not(subnodeChildren);
        });

        //Change icon and hide/show children
        if (tr.hasClass('collapse')) {
            tr.removeClass('collapse').addClass('expand');
            children.hide();
        } else {
            tr.removeClass('expand').addClass('collapse');
            children.show();
        }
        return children;
    });
});
36
bcoughlan

Dans les navigateurs modernes, vous n'avez besoin que de très peu de code pour créer une arborescence pliable:

var tree = document.querySelectorAll('ul.tree a:not(:last-child)');
for(var i = 0; i < tree.length; i++){
    tree[i].addEventListener('click', function(e) {
        var parent = e.target.parentElement;
        var classList = parent.classList;
        if(classList.contains("open")) {
            classList.remove('open');
            var opensubs = parent.querySelectorAll(':scope .open');
            for(var i = 0; i < opensubs.length; i++){
                opensubs[i].classList.remove('open');
            }
        } else {
            classList.add('open');
        }
        e.preventDefault();
    });
}
body {
    font-family: Arial;
}

ul.tree li {
    list-style-type: none;
    position: relative;
}

ul.tree li ul {
    display: none;
}

ul.tree li.open > ul {
    display: block;
}

ul.tree li a {
    color: black;
    text-decoration: none;
}

ul.tree li a:before {
    height: 1em;
    padding:0 .1em;
    font-size: .8em;
    display: block;
    position: absolute;
    left: -1.3em;
    top: .2em;
}

ul.tree li > a:not(:last-child):before {
    content: '+';
}

ul.tree li.open > a:not(:last-child):before {
    content: '-';
}
<ul class="tree">
  <li><a href="#">Part 1</a>
    <ul>
      <li><a href="#">Item A</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item B</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item C</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item D</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item E</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
    </ul>
  </li>

  <li><a href="#">Part 2</a>
    <ul>
      <li><a href="#">Item A</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item B</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item C</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item D</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item E</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
    </ul>
  </li>

  <li><a href="#">Part 3</a>
    <ul>
      <li><a href="#">Item A</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item B</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item C</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item D</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item E</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

(voir aussi ce violon )

25
John Slegers

jquery est votre ami ici.

http://docs.jquery.com/UI/Tree

Si vous souhaitez créer le vôtre, voici quelques conseils de haut niveau:

Affichez toutes vos données sous la forme <ul /> éléments avec les données internes imbriquées <ul />, puis utilisez la jquery:

$('.ulClass').click(function(){ $(this).children().toggle(); });

Je pense que c'est exact. Quelque chose comme ca.

MODIFIER:

Voici un exemple complet.

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
</head>
                                                                                                                                                                                <body>
<ul>
    <li><span class="Collapsable">item 1</span><ul>
        <li><span class="Collapsable">item 1</span></li>
        <li><span class="Collapsable">item 2</span><ul>
            <li><span class="Collapsable">item 1</span></li>
            <li><span class="Collapsable">item 2</span></li>
            <li><span class="Collapsable">item 3</span></li>
            <li><span class="Collapsable">item 4</span></li>
        </ul>
        </li>
        <li><span class="Collapsable">item 3</span></li>
        <li><span class="Collapsable">item 4</span><ul>
            <li><span class="Collapsable">item 1</span></li>
            <li><span class="Collapsable">item 2</span></li>
            <li><span class="Collapsable">item 3</span></li>
            <li><span class="Collapsable">item 4</span></li>
        </ul>
        </li>
    </ul>
    </li>
    <li><span class="Collapsable">item 2</span><ul>
        <li><span class="Collapsable">item 1</span></li>
        <li><span class="Collapsable">item 2</span></li>
        <li><span class="Collapsable">item 3</span></li>
        <li><span class="Collapsable">item 4</span></li>
    </ul>
    </li>
    <li><span class="Collapsable">item 3</span><ul>
        <li><span class="Collapsable">item 1</span></li>
        <li><span class="Collapsable">item 2</span></li>
        <li><span class="Collapsable">item 3</span></li>
        <li><span class="Collapsable">item 4</span></li>
    </ul>
    </li>
    <li><span class="Collapsable">item 4</span></li>
</ul>
<script type="text/javascript">
    $(".Collapsable").click(function () {

        $(this).parent().children().toggle();
        $(this).toggle();

    });

</script>
15
joe_coolish

Je jetterai aussi jsTree dans le ring. Je l'ai trouvé assez adaptable à votre situation particulière. Il est emballé comme un plugin jQuery.

Il peut s'exécuter à partir de diverses sources de données, mais mon préféré est une simple liste imbriquée, comme décrit par @joe_coolish ou ici:

<ul>
  <li>
    Item 1
    <ul>
      <li>Item 1.1</li>
      ...
    </ul>
  </li>
  ...
</ul>

Cette structure échoue gracieusement dans une arborescence statique lorsque JS n'est pas disponible dans le client et est assez facile à lire et à comprendre du point de vue du codage.

5
peteorpeter

Vous pouvez essayer jQuery treegrid ( http://maxazan.github.io/jquery-treegrid/ ) ou jQuery treetable ( http://ludo.cubicphuse.nl/jquery-treetable/ )

Les deux utilisent HTML <table> format de balise et stylisé l'arborescence as.

Le jQuery treetable utilise data-tt-id et data-tt-parent-id pour déterminer le parent et l'enfant de l'arbre. Exemple d'utilisation:

<table id="tree">
  <tr data-tt-id="1">
    <td>Parent</td>
  </tr>
  <tr data-tt-id="2" data-tt-parent-id="1">
    <td>Child</td>
  </tr>
</table>
$("#tree").treetable({ expandable: true });

Pendant ce temps, jQuery treegrid utilise uniquement la classe pour styliser l'arbre. Exemple d'utilisation:

<table class="tree">
    <tr class="treegrid-1">
        <td>Root node</td><td>Additional info</td>
    </tr>
    <tr class="treegrid-2 treegrid-parent-1">
        <td>Node 1-1</td><td>Additional info</td>
    </tr>
    <tr class="treegrid-3 treegrid-parent-1">
        <td>Node 1-2</td><td>Additional info</td>
    </tr>
    <tr class="treegrid-4 treegrid-parent-3">
        <td>Node 1-2-1</td><td>Additional info</td>
    </tr>
</table>
<script type="text/javascript">
  $('.tree').treegrid();
</script>
3
Tutompita

HTML 5 permet la balise de résumé, l'élément de détails. Cela peut être utilisé pour afficher ou masquer (réduire/développer) une section. Lien

3
rational