问题
I have a list I want a filter, I have the checkboxes working as shown in this question.
On my page I already had the tabs at the top of the page working as shown in the below code and in this fiddle.
However they conflict with each other, so currently if you click on xtr1 while the checkbox for col 1 is clicked it removes all col 1 and shows all xtr1. I want it to be to show all of xtra1 that have col 1 ticked for example. I tried to handle this by adding the variable addchosen as shown below, but can't get it working, how can this best be achieved?
<div id="nav">
<a rel="all" id="all">All</a>
<a rel="xtr1" id="xtr1">xtr1</a>
<a rel="xtr2" id="xtr2">xtr2</a>
<a rel="xtr3" id="xtr3">xtr3</a>
</div>
<form id="refine-cat">
<span><input type="checkbox" value="1" name="filtercol">cat 1</span>
<span><input type="checkbox" value="2" name="filtercol">cat 2</span>
<span><input type="checkbox" value="3" name="filtercol">cat 3</span>
</form>
<form id="refine-col">
<span><input type="checkbox" value="1" name="filtercat">col 1</span>
<span><input type="checkbox" value="2" name="filtercat">col 2</span>
<span><input type="checkbox" value="3" name="filtercat">col 3</span>
<span><input type="checkbox" value="4" name="filtercat">col 4</span>
</form>
<ul>
<li class="xtr3 all item cat-3 col-1">col 1 - cat 3 - xtra 3</li>
<li class="xtr1 all item cat-3 col-1">col 1 - cat 3 - xtra 1</li>
<li class="xtr1 all item cat-3 col-1">col 1 - cat 3 - xtra 1</li>
</ul>
(the list has more items in the fiddle)
JS
var chosen = "";
jQuery("#nav a").on("click", function (event) {
jQuery("#nav a").removeClass("current");
jQuery(this).addClass("current");
chosen = jQuery(this).attr("rel");
jQuery(".item").not("." + chosen).hide();
jQuery("." + chosen).show();
});
var $items = jQuery('.item');
var $cats = jQuery('#refine-cat input[type=checkbox]');
var $cols = jQuery('#refine-col input[type=checkbox]');
$cols.add($cats).on('change', function (e) {
var cats = $cats.filter(':checked').map(function(){
return 'cat-' + (this.value || '')
}).get();
var cols = $cols.filter(':checked').map(function(){
return 'col-' + (this.value || '')
}).get();
if(cats.length || cols.length){
var $fitems = $items;
var addchosen = "";
if (chosen) {
addchosen =', .' + chosen;
}
if(cats.length){
$fitems = $fitems.filter('.' + cats.join(', .') + addchosen );
}
if(cols.length){
$fitems = $fitems.filter('.' + cols.join(', .'));
}
$fitems.show();
$items.not($fitems).hide();
} else {
$items.show();
}
});
回答1:
I've modified your code a little bit. There is a cleaner way of doing this but I didn't wanted to change your line of thinking.
So, I've created a function named refine()
and basically isolated this part of your code and added a filter for chosen also:
if(cats.length){
$fitems = $fitems.filter('.' + cats.join(', .') + addchosen );
}
if(cols.length){
$fitems = $fitems.filter('.' + cols.join(', .'));
}
So this function will be called both on nav
click and cols/cats
change, like this:
var cats=[], cols=[], $fitems;
var $items = jQuery('.item');
var chosen = "";
function refine() {
$items.show();
$fitems = $items;
if(chosen.length && chosen != 'all') {
$fitems = $items.filter('.' + chosen);
}
if(cats.length){
$fitems = $fitems.filter('.' + cats.join(', .'));
}
if(cols.length){
$fitems = $fitems.filter('.' + cols.join(', .'));
}
$fitems.show();
$items.not($fitems).hide();
}
jQuery("#nav a").on("click", function (event) {
jQuery("#nav a").removeClass("current");
jQuery(this).addClass("current");
chosen = jQuery(this).attr("rel");
refine();
});
var $cats = jQuery('#refine-cat input[type=checkbox]');
var $cols = jQuery('#refine-col input[type=checkbox]');
$cols.add($cats).on('change', function (e) {
cats = $cats.filter(':checked').map(function(){
return 'cat-' + (this.value || '')
}).get();
cols = $cols.filter(':checked').map(function(){
return 'col-' + (this.value || '')
}).get();
refine();
});
Here is your fiddle
回答2:
I would n't probably complicate it this much. Here is one way.
jQuery("#nav a").on("click", function (event) {
jQuery("#nav a").removeClass("current");
jQuery(this).addClass("current").attr("rel");
if(this.id == 'all') $cats.add($cols).prop('checked', false);
updateResult();
});
var $items = jQuery('.item');
var $cats = jQuery('#refine-cat input[type=checkbox]');
var $cols = jQuery('#refine-col input[type=checkbox]');
$cols.add($cats).on('change', function () {
//Do something....
updateResult();
});
function updateResult() {
$('ul > li').hide();
var consArray = [];
consArray = consArray.concat($('#nav > a.current').map(function () {
return this.rel;
}).get());
consArray = consArray.concat($cats.filter(':checked').map(function () {
return 'cat-' + this.value;
}).get());
consArray = consArray.concat($cols.filter(':checked').map(function () {
return 'col-' + this.value;
}).get());
if(consArray.length)
$('.' + consArray.join('.')).show();
}
Fiddle
and a simpler version:
function updateResult() {
$('ul > li').hide();
var consArray = $('#nav > a.current').add(
$cats.filter(':checked')).add(
$cols.filter(':checked'))
.map(function(){
if(this.nodeName === 'A') return this.rel;
return this.name.replace(/filter/,'') + '-' + this.value;
}).get();
if(consArray.length)
$('.' + consArray.join('.')).show();
}
Fiddle
来源:https://stackoverflow.com/questions/18776842/jquery-filter-items-with-both-a-checkbox-and-click