Я пытался выяснить, как это сделать правильно, и, похоже, не может заставить его работать.
Я хочу использовать jQuery для выбора и выбора того, что я хочу показать на странице. Я посмотрел и попытался найти какой-то скрипт, какой-то работа, но не так, как я этого хотел.
Страница будет использовать флажки как «теги», скажем, искусство, компьютеры, здоровье, видеоигры
<div class="tags"> <label><input type="checkbox" class="arts" /> Arts </label> <label><input type="checkbox" class="computers" /> Computers </label> <label><input type="checkbox" class="health" /> Health </label> <label><input type="checkbox" class="video-games" /> Video Games </label> </div>
Затем на странице будут результаты, и каждый результат будет прикреплен к нему тегами.
<ul class="results"> <li class="arts computers"> Result 1 </li> <li class="video-games"> Result 2 </li> <li class="computers health video-games"> Result 3 </li> <li class="arts video-games"> Result 4 </li> </ul>
Я хочу иметь возможность нажимать на искусство и видеоигры и отображать все, что имеет как искусство, так и видео-игры, поэтому результат 4. Или иметь возможность просто выбирать компьютеры и возвращать результаты 1 и 3.
Я думал, что смогу сделать что-то вроде
$('.tags input').click( function() { $('.results > li').hide(); //For each one checked $('input').is(':checked').each( function() { //Display that result $('.results li').hasClass($(this).attr('class')).show(); }); });
но он не работает, он просто скрывает все, но потом не возвращается, чтобы показать остальное. Я знаю, что логика совершенно неправа, я не думаю, что я должен использовать каждого таким образом? Может быть, использовать его, чтобы захватить все классы в массиве, а затем показать li, которые имеют эти классы?
Есть идеи?
.change()
этого флажка. .hasClass()
возвращает логическое значение. class
, например rel
или атрибут data-*
. $('div.tags').delegate('input:checkbox', 'change', function() { var $lis = $('.results > li').hide(); $('input:checked').each(function() { $lis.filter('.' + $(this).attr('rel')).show(); }); }).find('input:checkbox').change();
@Justin спрашивает
Как бы вы изменили это, чтобы возвращать только lis, которые соответствуют всем отмеченным ячейкам вместо любого из них?
Stuff (любой атрибут, который вы используете) из каждого проверенного ввода в массив String.join('.')
Чтобы создать один большой селектор классов, а затем .filter()
<li>
s, как и раньше:
var selector = $('input:checked').map(function () { return $(this).attr('rel'); }).get().join('.'); $lis.filter(selector).doWhatever();
Я немного изменил решение Мэтта, чтобы он делал то, что вы просили. По крайней мере, как я это интерпретировал (показывая только те элементы, которые соответствуют всем выбранным категориям). Это ни в коем случае не столь элегантно, как решение Мэтта:
HTML:
<div class="tags"> <label><input type="checkbox" data-category="arts" /> Arts </label> <label><input type="checkbox" data-category="computers" /> Computers </label> <label><input type="checkbox" data-category="health" /> Health </label> <label><input type="checkbox" data-category="video-games" /> Video Games </label> </div> <ul class="results"> <li data-category="arts computers"> Result 1 </li> <li data-category="video-games"> Result 2 </li> <li data-category="computers health video-games"> Result 3 </li> <li data-category="arts video-games"> Result 4 </li> </ul>
И JS:
$('div.tags').delegate('input:checkbox', 'change', function() { $('.results > li').hide(); var selector = $('input:checked').map(function() { return $(this).attr('data-category'); }).get(); function matchesCategories(elem) { var elemCats = elem.attr('data-category'); if (elemCats) { elemCats = elemCats.split(' '); } else { elemCats = Array(); } for (var i = 0; i < selector.length; i++) { console.log("testing " + selector[i] + " in:"); console.log(elemCats); if (jQuery.inArray(selector[i], elemCats) == -1) { return false; } } return true; } $('.results > li').each(function(i, elem) { if (matchesCategories(jQuery(elem))) { $(elem).show(); } }); }).find('input:checkbox').change();
Если вы хотите попробовать, вот моя запись jsfiddle (раздвоенная от Мэтта)
Попробуйте функцию grep
. Pseudopseudocode:
$(yourstuff).grep(filter1).grep(filter2)...
Две проблемы.
.is
– это функция, а не селектор. hasClass
– также не селектор. Оба возвращают true
или false
поэтому вы не можете работать с их результатами, как объект jQuery.
$('.tags input').click( function() { $('.results > li').hide(); //For each one checked $('input:checked').each( function() { $('.'+$(this).attr('class')).show(); }); });
$('.tags') .on('update', function() { // Limit the selector(s) to search for: var $filters = $(this).find('input:checked'); // Get the class names of interest // Return null (rather than "") to keep them out of the result array var $classes = $filters.map(function(){ return this.className || null; }); // Use .replace() if your checkboxes might target multiple classes var selector = $classes.get().join('.').replace(/ /g,'.'); var $results = $('ul.results > li').hide(); if (selector) $results.filter('.'+selector).show(); }) // Relay any changes to the display-state container (.tags) .on('change','input[type="checkbox"]',function() { $(event.currentTarget).trigger('update'); }) // When first loaded, apply the server-supplied checkbox state(s) to the page: .trigger('update');
Мне нравится .on () много 🙂 [jQuery 1.7+]