如何只使用特定的表行构建简单的手风琴

How to build simple accordion using only specific table rows?

本文关键字:简单 手风琴 构建      更新时间:2023-09-26

我有一个HTML表,列出了各种项目。每个<tr>都有一个唯一的title元素,但有些项目是相关的,并且这些行共享相同的标题。我正在尝试编写jQuery代码,解析这个表,只将具有相同标题的项目转换为一个简单的手风琴,然后在它们的正上方注入一个新的可点击行,将该共享标题用作内容,并在点击时切换这些相关项目。

这是一个示例表,在转换之前,"橙色"项目是相关的:

<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>

这就是我试图将此表转换为的内容。基本上,我隐藏相关项目,并在它们上面使用新创建的行来显示/隐藏:

<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>

注意1:标题可以是任何内容。我只是用"橙色"作为例子,但实际上标题甚至可以是多个单词。

注意2:相关项目将依次堆叠。

实现这一点最简单的方法是什么?

您可以从这里开始

$(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>

注意:如果后面有相同的tr标题,则此代码将正常工作彼此如果随机排列的

如果我可以假设相同类型的所有项目都分组在一起:

// 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>')
    }
});

我添加了一个额外的行来仔细检查它是否正常工作。

我希望这些评论能起到足够的作用。

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>