首页 > 解决方案 > Javascript:在列表中查找特定的先前元素并添加类

问题描述

我有一个这样的清单。

在此处输入图像描述

在每个 .list 项中都有一个 html 按钮:

<div class="list">
<button>.list</button>
</div>

此外,每个项目都可以在一个.bloc元素内

在此处输入图像描述

  <div class="list"><button>.list</button></div>
  <div class=bloc>
    <div class="list"><button>.list</button></div>
  </div>

当我单击按钮时,我希望前一个 .list 项具有 .active 类,如下所示:

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

嗯,用 jquery 很容易,我已经做到了,它工作得很好:

$('.list button').on('click', function() {
    $(this).closest('.list').prev('.list').addClass('active');
});

我有一些具体情况:有时列表项可以隐藏,隐藏类的列表不能有 .active 类:

在此处输入图像描述

在此处输入图像描述

或者更复杂。您必须逐个增加每个项目,并将活动类放在没有隐藏类的第一个:

在此处输入图像描述

在此处输入图像描述

我为没有隐藏类的物品做了机制,但我担心我走错了方向,因为案例的数量越来越多。没有更聪明的方法吗?:o

  $('.list button').on('click', function() {
    if ($(this).closest('.list').prev().length === 0) {
      if ($(this).closest('.bloc').length) {
        $(this).closest('.bloc').prev('.list').addClass('active');
        $(this).closest('.bloc').prev('.bloc').find('.list:last-child').addClass('active');
      } else {
        $(this).closest('.list').next('.list').addClass('active');
      }
    }

    if ($(this).closest('.list').prev('.bloc').length) {
      $(this).closest('.list').prev('.bloc').find('.list:last-child').addClass('active');
    }
    $(this).closest('.list').prev('.list').addClass('active'); 
  }

标签: javascriptjqueryalgorithm

解决方案


而不是使用.closest .prev.next您可以使用重载.index为您提供现有集合中的索引。

var idx = collection.index(element);
  • 将所有 .list 项选择到 jquery 对象/集合中
  • 单击获取该集合中的索引时
  • 减 1 以获取该集合中的前一个 .list 项

基本场景包括$(".list")

// collate the list first
var list = $(".list");

// add click handler
list.click(function() {
    // confirm there are no duplicates
    // comapred with $(this).index() which is the index within the parent
    console.log(list.index(this), $(this).index())
    
    $(".active").removeClass("active");
    
    var idx = list.index(this);
    if (idx > 0)
        list.eq(idx-1).addClass("active");
});
.list { border:1px solid #CCC; height: 20px; }
.bloc { border:1px solid #444; padding: 5px; }
.active { border:1px solid red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='wrapper'>

  <div class='bloc'>
    <div class='list'></div>
    <div class='list'></div>
  </div>
  <div class='list'></div>
  <div class='list'></div>

</div>

然后,所有其他用例只是预先提供正确选择器的情况,否则代码完全相同

var list = $(".wrapper>.bloc:not(.hidden)>.list:not(.hidden),.wrapper>.list:not(.hidden)");

我试图重新创建您的一些场景,但如果缺少一个,请发表评论,我会确保它适合(在问题的范围内)。

给予:

var list = $(".wrapper>.bloc:not(.hidden)>.list:not(.hidden),.wrapper>.list:not(.hidden)")
list.click(function() {
    $(".active").removeClass("active");
    var idx = list.index(this);
    if (idx > 0)
        list.eq(idx-1).addClass("active");
});
.list { border:1px solid #CCC; height: 20px; }
.bloc { border:1px solid #444; padding: 5px; }
.active { border:1px solid red; }
.hidden { background-color: #ccc; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='wrapper'>
  <div class='bloc'>
    <div class='list'></div>
    <div class='list'></div>
  </div>
  <div class='list hidden'></div>
  <div class='bloc'>
    <div class='list hidden'></div>
    <div class='list hidden'></div>
  </div>
  <div class='list'></div>
  <div class='bloc'>
    <div class='list hidden'></div>
    <div class='list'></div>
  </div>
  <div class='list'></div>
  <div class='list'></div>
  <div class='bloc hidden'>
    <div class='list'></div>
    <div class='list'></div>
  </div>
  <div class='list'></div>
  <div class='list'></div>
</div>


推荐阅读