牧羊人nacy
在我添加我的解决方案之前,我必须感谢@ffriend和他的函数来找出两个或多个数组中的所有组合(为此给他+1 ;)):Finding All Combinations (Cartesian product) of JavaScript array values这个功能非常有用,我在我的解决方案中使用了。这是针对您的问题的不同方法,因此我当然必须更改您的 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>...我创建了与所有导航列表的关系(也使用dot)<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>在您的 CSS 中,我只删除了.disabled该类,因为我使用 jQuery 来做到这一点。现在是javascript。我已经评论了我认为重要的部分,以试图澄清所有步骤:/* 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; }}而已。工作中的所有代码:var results = { series:[], body:[], style:[]};var container=$(".results");$(".nav li").on('click', function(){ var $this=$(this); var parent=$this.parent(); var parentObj=$this.parent().data("obj"); var myClass=$this.data("el"); var control=[]; if(myClass==="*") { if (!$this.hasClass("selected")) { $("li", parent).removeClass("selected"); $this.addClass("selected"); results[parentObj]=[]; } } else { $("li[data-el='*']", parent).removeClass("selected"); if ($this.hasClass("selected")) { $this.removeClass("selected"); results[parentObj]=$.grep(results[parentObj], function(value) { return value != myClass; }); } else { $this.addClass("selected"); results[parentObj].push(myClass) } } var entries = Object.entries(results); for (const [key, value] of entries) { if (value.length>0) control.push(value); else $(".nav[data-obj='"+key+"'] li[data-el='*']").addClass("selected"); } $(".results > div").css({"opacity":".5"}); if(control.length>0){ var c=allPossibleCases(control).toString(); $(c, container).removeAttr("style"); } else { $(".results > div").removeAttr("style"); }});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; }}ul { border-bottom: 1px solid black; padding-bottom: 10px;}li { display: inline-block;}.selected { background-color: red;}.results { display: flex;}.results > div { width: 100px; height: 100px; background: black; color: white; display: flex; justify-content: center; align-items: center; margin: 10px;}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><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><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>