Javascript 使用三层菜单筛选结果列表

Javascript 使用三层菜单筛选结果列表,javascript,jquery,Javascript,Jquery,$('series nav li')。在('click',handleSeriesClick)上; $('body nav li')。在('click',手柄上); $('style nav li')。在('click',handlestyle click)上; 系列=[]; 正文=[]; 风格=[]; 功能手柄手柄(el){ 选定常数=$(el.currentTarget).data('系列'); 如果(所选===“全部”){ 系列=[]; }否则{ 常量索引=SERIES.indexOf(选

$('series nav li')。在('click',handleSeriesClick)上;
$('body nav li')。在('click',手柄上);
$('style nav li')。在('click',handlestyle click)上;
系列=[];
正文=[];
风格=[];
功能手柄手柄(el){
选定常数=$(el.currentTarget).data('系列');
如果(所选===“全部”){
系列=[];
}否则{
常量索引=SERIES.indexOf(选定);
如果(索引!=-1){
系列。拼接(索引,1);
}否则{
系列。推送(选定);
}
}
updateNav(“系列”);
}
功能把手手推车(el){
所选常量=$(el.currentTarget).data('body');
如果(所选===“全部”){
正文=[];
}否则{
常量索引=BODY.indexOf(选定);
如果(索引!=-1){
主体拼接(索引1);
}否则{
BODY.push(已选择);
}
}
updateNav(“主体”);
}
功能手柄样式点击(el){
所选常量=$(el.currentTarget).data('style');
如果(所选===“全部”){
风格=[];
}否则{
常量索引=STYLE.indexOf(选定);
如果(索引!=-1){
样式拼接(索引,1);
}否则{
样式。推送(选定);
}
}
updateNav(“风格”);
}
函数更新nav(导航){
让项目=“”;
让列表=“”;
如果(导航==“系列”){
项目=$('系列资产净值');
列表=系列;
}否则如果(导航==“主体”){
项目=$('body nav li');
列表=主体;
}否则如果(导航==“样式”){
项目=$('.style nav li');
列表=样式;
}否则{
返回false;
}
美元。每个(项目,(i,el)=>{
常数项=$(el);
const val=项目数据(nav);
const index=LIST.indexOf(val);
如果(LIST.length==0){
items.removeClass(“选定”);
items.first().addClass('selected');
}否则{
如果(索引==-1){
item.removeClass(“选定”);
}否则{
item.addClass('selected');
}
}
});
updateResults();
}
函数updateResults(){
常量结果=$('.results.result');
$。每个(结果(i,el)=>{
常数$el=$(el);
常数系列=$el.data(‘系列’);
const body=$el.data('body');
常量样式=$el.data('style');
常量系列索引=系列索引(系列);
const bodyIndex=BODY.indexOf(BODY);
const styleIndex=STYLE.indexOf(STYLE);
让启用=真;
如果(SERIES.length==0){
如果(BODY.length==0){
if(styleIndex==-1){
启用=错误;
}否则{
启用=真;
}
}else if(STYLE.length==0){
如果(bodyIndex=-1){
启用=错误;
}否则{
启用=真;
}
}否则{
如果(bodyIndex=-1 | | styleIndex=-1){
启用=错误;
}否则{
启用=真;
}
}
}else if(BODY.length==0){
如果(SERIES.length==0){
if(styleIndex==-1){
启用=错误;
}否则{
启用=真;
}
}else if(STYLE.length==0){
如果(序列索引==-1){
启用=错误;
}否则{
启用=真;
}
}否则{
如果(序列索引==-1 | |样式索引==-1){
启用=错误;
}否则{
启用=真;
}
}
}else if(STYLE.length==0){
如果(SERIES.length==0){
如果(bodyIndex=-1){
启用=错误;
}否则{
启用=真;
}
}else if(BODY.length==0){
如果(序列索引==-1){
启用=错误;
}否则{
启用=真;
}
}否则{
如果(序列索引==-1 | |体索引==-1){
启用=错误;
}否则{
启用=真;
}
}
}否则{
如果(seriesIndex=-1 | | bodyIndex==-1 | | styleIndex==-1){
启用=错误;
}否则{
启用=真;
}
}
if(SERIES.length==0&&BODY.length==0&&STYLE.length==0){
启用=真;
}
如果(!已启用){
$el.addClass('disabled');
}否则{
$el.removeClass(“禁用”);
}
});
}
ul{
边框底部:1px纯黑;
垫底:10px;
}
李{
显示:内联块;
}
.选定{
背景色:红色;
}
.残疾人{
不透明度:0.5;
}
.结果{
显示器:flex;
}
.结果{
宽度:100px;
高度:100px;
背景:黑色;
颜色:白色;
显示器:flex;
证明内容:中心;
对齐项目:居中;
利润率:10px;
}

  • 全部
  • 系列1
  • 系列2
  • 系列3
  • 全部
  • 正文1 正文2 正文3
  • 全部
  • 样式1
  • 样式2
  • 样式3
结果1 结果2 结果3 结果4 结果5 结果6 结果7 结果8
在添加我的解决方案之前,我必须感谢@ffriend和他的函数来找出两个或多个数组中的所有组合(这一点给他+1;):

这个函数非常有用,我在解决方案中使用了它

这是解决问题的另一种方法,因此我不得不更改您的HTML&当然是jQuery

首先是HTML。 为了创建与您相同的筛选系统,我决定只使用没有任何特定属性的类:

<div class="results">
   <div class="Series-1 Body-1 Style-1">Result 1</div>
   <div class="Series-1 Body-1 Style-1">Result 2</div>
   <div class="Series-2 Body-2 Style-2">Result 3</div>
   <div class="Series-2 Body-1 Style-2">Result 4</div>
   <div class="Series-3 Body-1 Style-1">Result 5</div>
   <div class="Series-3 Body-1 Style-1">Result 6</div>
   <div class="Series-3 Body-2 Style-2">Result 7</div>
   <div class="Series-2 Body-1 Style-3">Result 8</div>
</div>
就这样。工作中的所有代码:

var结果={
系列:[],
正文:[],
样式:[]
};
var容器=$(“.results”);
$(“.nav li”)。在('click',function()上{
var$this=$(this);
var parent=$this.parent();
var parentObj=$this.parent()
<ul class="nav" data-obj="series">
  <li data-el="*" class="selected">All</li>
  <li data-el=".Series-1">Series 1</li>
  <li data-el=".Series-2">Series 2</li>
  <li data-el=".Series-3">Series 3</li>
</ul>

<ul class="nav" data-obj="body">
  <li data-el="*" class="selected">All</li>
  <li data-el=".Body-1">Body 1</li>
  <li data-el=".Body-2">Body 2</li>
  <li data-el=".Body-3">Body 3</li>
</ul>

<ul class="nav" data-obj="style">
  <li data-el="*" class="selected">All</li>
  <li data-el=".Style-1">Style 1</li>
  <li data-el=".Style-2">Style 2</li>
  <li data-el=".Style-3">Style 3</li>
</ul>
/* I created one js object instead of 3 arrays, 'cause it is more simple to handle after in one general function */
var results = {
  series:[],
  body:[],
  style:[]
};

/* put the results containet in a variable */
var container=$(".results");

$(".nav li").on('click', function(){
  /*this is the general function that works for all your clicks */  

  /*set a few of variables */
  var $this=$(this);
  var parent=$this.parent();
  var parentObj=$this.parent().data("obj");
  var myClass=$this.data("el");
  var control=[]; /*this is an empty array that will set with your different classes*/

  if(myClass==="*") {
    /*click on first li*/
    if (!$this.hasClass("selected")) {
        /*do something if it didin't have the selected class*/
      $("li", parent).removeClass("selected"); /*remove selected classes from all li in my parent ul*/
      $this.addClass("selected");
      results[parentObj]=[];/* empty my associative object: series, body or style */
    }
  } else {
    /*click on the others li*/
    $("li[data-el='*']", parent).removeClass("selected"); 

    if ($this.hasClass("selected")) {
        /*click on li with selected class */
      $this.removeClass("selected");

      results[parentObj]=$.grep(results[parentObj], function(value) {
        return value != myClass; /* I used $.grep() to filter the contents of my object. This function remove a class that I previous added (remember that <li> was selected so this class is still in this obj) */
      });
    } else {
      $this.addClass("selected");
      results[parentObj].push(myClass) /* add a class on associative object */
    }
  }
 /* Here I use a EC6 technique to loop through my object => https://zellwk.com/blog/looping-through-js-objects/*/
  var entries = Object.entries(results);

  for (const [key, value] of entries) {
    if (value.length>0)
        /* add ONLY array with classes in it */
      control.push(value);
    else
    /* Here I know that if the array is empty all my child li have no selected class, so I can add "selected" class to the first li (i.e. <li> with data-el='*' as attribute)*/
      $(".nav[data-obj='"+key+"'] li[data-el='*']").addClass("selected");
  }


  /* Set all div in results to opacity:.5*/
  $(".results > div").css({"opacity":".5"});

  if(control.length>0){
    var c=allPossibleCases(control).toString(); /* use that function to find all combinations in control (that it is an array without empty associative objects. I transform it in string to use it as group classes to remove the opacity rule */
    $(c, container).removeAttr("style"); /* remove the opacity:.5 to all group class that I found in control array*/
  } else {
    $(".results > div").removeAttr("style"); /*if control is empty I set the initial state removing the opacity */
  }
});

function allPossibleCases(arr) {
  if (arr.length == 1) {
    return arr[0];
  } else {
    var result = [];
    var allCasesOfRest = allPossibleCases(arr.slice(1));
    for (var i = 0; i < allCasesOfRest.length; i++) {
      for (var j = 0; j < arr[0].length; j++) {
        result.push(arr[0][j] + allCasesOfRest[i]);
      }
    }
    return result;
  }
}