2 votes

Comment construire un accordéon simple en utilisant uniquement des lignes de tableau spécifiques ?

J'ai un tableau HTML qui énumère divers articles. Chaque <tr> a un unique title mais certains éléments sont liés et ces rangées partagent le même titre. J'essaie d'écrire un code jQuery qui analyserait ce tableau et convertirait uniquement les éléments ayant le même titre en un simple accordéon, puis injecterait une nouvelle rangée cliquable juste au-dessus d'eux, qui utiliserait le titre partagé comme contenu et ferait basculer les éléments liés en cas de clic.

Voici un exemple de tableau, avant conversion, où les éléments "orange" sont liés :

<table>
    <tr title="Banana">
        <td>Document 1</td>
    </tr>
    <tr title="Apple">
        <td>Document 2</td>
    </tr>
    <tr title="Orange">
        <td>Document 3</td>
    </tr>
    <tr title="Orange">
        <td>Document 4</td>
    </tr>
    <tr title="Orange">
        <td>Document 5</td>
    </tr>
    <tr title="Lemon">
        <td>Document 6</td>
    </tr>
    <tr title="Cherry">
        <td>Document 7</td>
    </tr>
</table>

C'est ce que j'essaie de convertir en cette table. En fait, je cache les éléments liés et j'utilise une nouvelle ligne créée au-dessus d'eux pour les afficher ou les cacher :

<table>
    <tr title="Banana">
        <td>Document 1</td>
    </tr>
    <tr title="Apple">
        <td>Document 2</td>
    </tr>
    <tr title="Orange">
        <td>Orange (click to toggle)</td>
    </tr>
    <tr title="Orange" style="display:none;">
        <td>Document 3</td>
    </tr>
    <tr title="Orange" style="display:none;">
        <td>Document 4</td>
    </tr>
    <tr title="Orange" style="display:none;">
        <td>Document 5</td>
    </tr>
    <tr title="Lemon">
        <td>Document 6</td>
    </tr>
    <tr title="Cherry">
        <td>Document 7</td>
    </tr>
</table>

Note 1 : Le titre peut être n'importe quoi. J'utilise simplement "Orange" comme exemple ici, mais en réalité, le titre peut même être composé de plusieurs mots.

Note 2 : Les éléments connexes seront empilés les uns après les autres.

Quel serait le moyen le plus simple d'y parvenir ?

2voto

Mohamed-Yousef Points 11109

Vous pouvez commencer par ici

$(document).ready(function(){
    var titles_arr = [] , create_list = [];
  $('tr[title]').each(function(){
    var title = $(this).attr('title').trim();
    if($.inArray( title , titles_arr) > -1){
      if($.inArray( title , create_list) <= -1){
        create_list.push(title);
      }
    }else{
        titles_arr.push(title);
    }
  });
  //console.log(create_list[0]);
  for(var i = 0 ; i < create_list.length ; i++){
    var newtrTitle = create_list[i];
    var html = '<tr title="'+newtrTitle+'" class="clcToggle"><td>'+newtrTitle+' (Click To Toggle)</td></tr>';
    $(html).insertBefore('tr[title="'+newtrTitle+'"]:eq(0)').promise().done(function(){
        $('tr[title="'+newtrTitle+'"]').not(':eq(0)').hide();
    });

  }

  $('#MainTable').on('click', '.clcToggle',function(){
    var title = $(this).attr('title').trim();
    $('tr[title="'+title+'"]').not(':eq(0)').slideToggle();
  });
});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="MainTable">
    <tr title="Banana">
        <td>Document 1</td>
    </tr>
    <tr title="Apple">
        <td>Document 2</td>
    </tr>
    <tr title="Orange">
        <td>Document 3</td>
    </tr>
    <tr title="Orange">
        <td>Document 4</td>
    </tr>
    <tr title="Orange">
        <td>Document 5</td>
    </tr>
    <tr title="Lemon">
        <td>Document 6</td>
    </tr>
    <tr title="Lemon">
        <td>Document 6</td>
    </tr>
    <tr title="Cherry">
        <td>Document 7</td>
    </tr>
    <tr title="Cherry">
        <td>Document 8</td>
    </tr>
</table>

Note : ce code fonctionnera très bien si vous avez le même titre de tr derrière l'autre. l'un derrière l'autre il faut un peu de travail pour les arranger si c'est arrangé au hasard

1voto

blokeish Points 475

Si je peux supposer que tous les articles du même type sont regroupés :

// Step 1: Code to add an extra row if there are multiple occurrences of an item
// This is not dynamic yet
if($("tr[title='Orange']").length>1){ // if there is more than one occurance
   $("tr[title='Orange']").first().before('<tr title="Orange"><td>Orange (click to toggle)</td></tr>')
}

    // Step 2: Loop through the items to make the above code dynamic
var ftypes = [];
$("table tr").each(function(idx)){
// get one of each type of fruit
if(ftypes.indexOf($(this).attr('title'))<0) ftypes.push($(this).attr('title'));
});

ftypes.forEach(function(fruit){
// if each fruit have more than one occurrence then add a row above
   if($("tr[title='"+fruit+"']").length>1){
       $("tr[title='"+fruit+"']").first().before('<tr title="'+fruit+'"><td>Orange (click to toggle)</td></tr>')
    }
});

1voto

Jhecht Points 2924

En espérant que cela réponde à vos besoins, j'ai ajouté une ligne supplémentaire pour vérifier que cela fonctionnait correctement.

J'espère que ces commentaires vous aideront suffisamment, faites-moi savoir si quelque chose n'est pas clair.

function click_handler(e) {
  var $this = $(this);
  //I am too lazy to write $(this) over and over again
  $('tr[title="' + $this.prop('title') + '"]').not($this).toggle();
  //First Part: gets all TR elements with same title
  //Next Part: but not this element
  //Toggle their visibility;
}
$(document).ready(function() {
  var prev; //Previous Element.
  var prev_i = 0; //previous level.
  $('tr').each(function(i, el) {
    el = $(el);
    if (prev != null) {
      //So we are not at the first element.
      if (prev.prop('title') == el.prop('title')) {
        //The previous title and the current el title are the same.
        if (prev_i == 0) {
          prev.text(prev.text() + "(click to toggle)");
          //If we are at previous level 0, meaning we have not encountered this portion of the loop before, we need to add the "click to toggle" text.
          prev.on('click', click_handler.bind(prev));
          //Add the click_handler, bound to the previous element (first).
        }

        el.hide(); //Hide any not-first element with the same title

        ++prev_i;
      } else {
        prev_i = 0;
        //If the titles are different, we reset the previous level.
      }

    } //end prev!=null
    prev = el;
    //set previous element
  });
});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <tr title="Banana">
    <td>Document 1</td>
  </tr>
  <tr title="Apple">
    <td>Document 2</td>
  </tr>
  <tr title="Orange">
    <td>Orange</td>
  </tr>
  <tr title="Orange">
    <td>Document 3</td>
  </tr>
  <tr title="Orange">
    <td>Document 4</td>
  </tr>
  <tr title="Orange">
    <td>Document 5</td>
  </tr>
  <tr title="Lemon">
    <td>Document 6</td>
  </tr>
  <tr title="Lemon">
    <td>Document 7</td>
  </tr>
  <tr title="Cherry">
    <td>Document 8</td>
  </tr>
</table>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X