首页 > 解决方案 > 按数据属性中匹配的关键字对列表进行排序

问题描述

我有一长串基本的 JavaScript 搜索。搜索功能使用正则表达式来测试是否满足某些条件,并隐藏不满足的条件。我正在尝试对列表进行排序并优先考虑在属性 1 中找到的那些,然后是在属性 2 中匹配关键字的项目。场景描述如下。

我的列表

目前-当我搜索时egg,它返回如下列表

Aiming for -这是我正在寻找的结果


从列表中我们可以看到,它的产品标题Garlic Mayonnaise中没有,但是搜索返回true,因为在data属性中找到,如下图所示。Eggegg

<li productname="Garlic Mayonnaise" data-desc="Contains egg">Garlic Mayonnaise</li>

有什么方法可以按在标题中找到的关键字对列表进行排序,然后是在数据属性中找到的那些关键字?

我的搜索功能如下

let productList = $('#productListUL li');
$.each(productList, function(_index, product){
    let self                        = $(product),
        productId                   = self.attr('productid'),
        productName                 = self.attr('productname'),
        productDesc                 = self.attr('data-desc');

        if (
            regex.test(productId) ||
            regex.test(productName) ||
            regex.test(productDesc)
        )
        {                        
            self.removeClass('hidden');
        }  
        else{
            self.addClass('hidden');
        }

});

标签: javascriptjquerysorting

解决方案


您可以简单地使用操作顺序。这意味着在列表中通过两次,它会给你你想要的结果。

$(function() {
  function sortList(d, lObj) {
    var c = [];
    $.each(d, function(k, p) {
      c.push($("li", lObj).eq(p.index).detach());
    });
    lObj.append(c);
  }

  function filterList(q, lObj, s) {
    q = q.toLowerCase();
    // Optional perimeter
    if (s == undefined) {
      s = false;
    }
    // Get List Items
    var ls = lObj.children();
    // Hide them all
    ls.addClass("hidden");
    // Array for Filtered/Sorted results
    var results = [];
    // First Pass, Filter by Name
    ls.each(function(i, p) {
      if ($(p).data("name").toLowerCase().indexOf(q) > -1) {
        results.push({
          index: $(p).index(),
          name: $(p).data("name"),
          desc: $(p).data("desc"),
        });
        $(p).removeClass("hidden");
      }
    });
    console.log("P1", results);
    // Second Pass, filter by Desc
    // Skip any already unfiltered
    ls.each(function(i, p) {
      if ($(p).hasClass("hidden") && $(p).data("desc").toLowerCase().indexOf(q) > -1) {
        results.push({
          index: $(p).index(),
          name: $(p).data("name"),
          desc: $(p).data("desc"),
        });
        $(p).removeClass("hidden");
      }
    });
    console.log("P2", results);
    // Array is built with desired filter and sort due to order of operations
    // Check if Element Sort is required
    if (s) {
      sortList(results, lObj);
    }
    // Return Filtered/Sorted Array
    return results;
  }

  $(".filter").keyup(function() {
    $(".hidden").removeClass("hidden");
    if ($(this).val().length > 2) {
      filterList($(this).val(), $(".productList"), true);
    }
  });
});
.hidden {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Search: <input type="text" class="filter">
<ul class="productList">
  <li data-name="Chocolate Caramels" data-desc="Contains dairy">Chocolate Caramels</li>
  <li data-name="Garlic Mayonnaise" data-desc="Contains egg">Garlic Mayonnaise</li>
  <li data-name="Tomato Egg" data-desc="Contains egg">Tomato Egg</li>
  <li data-name="Scrambled egg" data-desc="Contains egg">Scrambled egg</li>
</ul>

过滤本身不会对列表中的元素进行排序,因此请根据我们构建的数组创建另一个函数来执行此操作。这会将它们分离并将它们按顺序放置在列表的末尾,并且所有其他项目都被隐藏。


推荐阅读