Как я могу отфильтровать мои загрузочные 4 навигационные ссылки с помощью панели поиска?
Я перехожу на свой старый сайт с помощью Bootstrap 4, поэтому он определенно был процессом обучения.
У меня хорошо работает макет сайта, но я понимаю, что в левой вертикальной навигационной панели есть много ссылок. Многие из них сгруппированы в рухнувших гнездах.
Я думаю, было бы неплохо добавить панель поиска наверху моего навигатора, чтобы я мог фильтровать ссылки на основе частичных строк, введенных в строку поиска. Это работает для ссылок, которые не скрываются внутри скрытого div (или class=collapsed
boostrap 4 ul).
Я был бы признателен за помощь в модификации моего кода, чтобы показать отфильтрованные результаты, содержащие любые ссылки, скрывающиеся внутри сложенной ul?
Здесь скрипка
$('.search-filter').on('keyup', function() {
var input = $('.search-filter').val();
var filter = input.toLowerCase();
if (filter.length == 0) { // show all if filter is empty
$('a').each(function() {
$(this).show(); // show links
});
return;
} else {
$('a').removeClass('collapsed');
$('a').each(function() {
$(this).hide(); // hide all links once search is begun
});
$('a:contains("' + filter + '")').each(function() {
$(this).removeClass('collapsed'); // remove bootstrap 4 collapsed class designation
$(this).show(); // show only matched links to search string?
});
}
});
@import url('https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css');
.navbar-nav.sidebar-nav {
position: absolute;
left: 0;
top: 0;
margin-top: 56px;
padding-bottom: 56px;
height: 100vh;
background: #292b2c;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
overflow: auto;
}
.navbar-brand {
display: inline-block;
padding-top: .25rem;
padding-bottom: .25rem;
margin-right: 1rem;
font-size: 1.25rem;
line-height: inherit;
white-space: nowrap;
color: #fff;
}
.navbar-nav .nav-link {
color: rgba(255, 255, 255, .5);
}
<div id="link-content">
<ul class="sidebar-nav navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#"><i class="fa fa-fw fa-home"></i> Home</a>
</li>
<li class="nav-item">
<label for="nav-search" class="col-2 col-form-label sr-only">Search links</label>
<div class="col p-2">
<input class="form-control form-control-sm search-filter" type="search" id="nav-search" placeholder="Search for tools">
</div>
</li>
<li class="nav-item">
<span class="navbar-brand">Popular tools</span>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="fa fa-fw fa-calculator"></i> Calculator</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="fa fa-fw fa-battery-3"></i> Battery </a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="fa fa-fw fa-database"></i> Pancake Batter</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="fa fa-fw fa-clock-o"></i> Marzipan</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="fa fa-fw fa-tags"></i> Cakes and Muffins</a>
</li>
<li class="nav-item">
<span class="navbar-brand">Categories</span>
</li>
<li class="nav-item">
<a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#collapseComponents"><i class="fa fa-fw fa-flask"></i> Cars</a>
<ul class="sidebar-second-level collapse" id="collapseComponents">
<li>
<a class="nav-link-collapse collapsed" data-toggle="collapse" href="#collapseMulti2">American</a>
<ul class="sidebar-third-level collapse" id="collapseMulti2">
<li>
<a href="#">Ford</a>
</li>
<li>
<a href="#">GMC</a>
</li>
</ul>
</li>
<li>
<a class="nav-link-collapse collapsed" data-toggle="collapse" href="#collapseMulti3">European</a>
<ul class="sidebar-third-level collapse" id="collapseMulti3">
<li>
<a href="#">BMW</a>
</li>
<li>
<a href="#">Audi</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
Ответы
Ответ 1
Хорошо, я думаю, что сам понял это (с небольшой помощью этого сообщения для без учета регистра filter).
1) Я обновил ссылки, обернув их в div with id #link-content
, чтобы отделить мой фильтр от дома и поиска.
2) Я добавил нечувствительный к регистру метод, упомянутый выше
Мой HTML:
<ul class="sidebar-nav navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#"><i class="fa fa-fw fa-home"></i> Home</a>
</li>
<li class="nav-item">
<label for="nav-search" class="col-2 col-form-label sr-only">Search links</label>
<div class="col p-2">
<input class="form-control form-control-sm search-filter" type="search" id="nav-search" placeholder="Search for tools">
</div>
</li>
<div id="link-content"><!-- added this to wrap the links-->
<li class="nav-item">
<span class="navbar-brand">Popular tools</span>
</li>
<li class="nav-item filter">
<a class="nav-link" href="#"><i class="fa fa-fw fa-calculator"></i> Calculator</a>
</li>
<li class="nav-item filter">
<a class="nav-link" href="#"><i class="fa fa-fw fa-battery-3"></i> Battery </a>
</li>
<li class="nav-item filter">
<a class="nav-link" href="#"><i class="fa fa-fw fa-database"></i> Pancake Batter</a>
</li>
<li class="nav-item filter">
<a class="nav-link" href="#"><i class="fa fa-fw fa-clock-o"></i> Marzipan</a>
</li>
<li class="nav-item filter">
<a class="nav-link" href="#"><i class="fa fa-fw fa-tags"></i> Cakes and Muffins</a>
</li>
<li class="nav-item filter">
<span class="navbar-brand">Categories</span>
</li>
<li class="nav-item ">
<a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#collapseComponents"><i class="fa fa-fw fa-flask"></i> Cars</a>
<ul class="sidebar-second-level collapse" id="collapseComponents">
<li>
<a class="nav-link-collapse collapsed" data-toggle="collapse" href="#collapseMulti2">American</a>
<ul class="sidebar-third-level collapse" id="collapseMulti2">
<li>
<a href="#">Ford</a>
</li>
<li>
<a href="#">GMC</a>
</li>
</ul>
</li>
<li>
<a class="nav-link-collapse collapsed" data-toggle="collapse" href="#collapseMulti3">European</a>
<ul class="sidebar-third-level collapse" id="collapseMulti3">
<li>
<a href="#">BMW</a>
</li>
<li>
<a href="#">Audi</a>
</li>
</ul>
</li>
</ul>
</li>
</div>
</ul>
Мой обновленный код:
// Case insensitive method for filter
jQuery.expr[':'].casecontains = (a, b, c) => jQuery(a).text().toUpperCase().indexOf(c[3].toUpperCase()) >= 0;
$('.search-filter').on('keyup', function () {
var input = $('.search-filter').val();
console.log('input: '+input);
if (input.length != 0) {
// first hide the div #link-content lists from view
$('#link-content li').hide();
// but secretly unhide the collapsed links
// using .show, so the nested uls can be viewed
$('#link-content li.nav-item ul').show();
// then filter in the matching links only
$('#link-content li:casecontains("'+input+'")').show();
} else {
// secretly unhide the collapsed links
$('#link-content li.nav-item ul').hide();
// if search is empty, show the div and reset columns
$('#link-content li').show();
}
});
Вот fiddle с рабочим примером, который открывает любые скрытые ссылки (свернутый класс в boostrap 4).
Ответ 2
Подход, который я использовал, - это запомнить, какие элементы совпадают, а затем использовать этот список, чтобы скрыть родителей.
Обновлен скрипт: https://jsfiddle.net/j2gpann3/1/
Преимущество этого подхода в том, что скрытые элементы подменю (например, "BMW" и т.д.) теперь будут отображаться в поиске и не будут иметь огромных пробелов над ними из других скрытых предметов. Поиск в регулярном выражении ищет вхождения каждого слова, поэтому, даже если они не соответствуют тексту пункта меню, он все равно будет соответствовать.
$('.search-filter').on('keyup', function() {
var matches = [];
var input = $.trim($('.search-filter').val());
var val = '^(?=.*\\b' + input.split(/\s+/).join('\\b)(?=.*\\b') + ').*$'; // using individual word matching filter from http://stackoverflow.com/a/9127872/1544886
var filter = RegExp(val, 'i');
if (input.length === 0) { // show all if filter is empty
$('.collapse').removeClass('show').addClass('collapsed'); // hide collapsable items fast.
$('.hide').removeClass('hide'); // remove any hidden elements from previous searches
} else {
$('.collapse').addClass('show'); // show all collapsed items
$('ul.sidebar-nav a:not(".home")').filter(function() { // skip home <li> so it shows permanently
$this = $(this);
// test for a match to search string
text = $this.text().replace(/\s+/g, ' ');
var isMatch = filter.test(text);
// store match so we can unhide parents of this item
if (isMatch) matches.push($this);
return !isMatch;
}).parent().addClass('hide'); // this hides any <li> that doesn't match search terms. Hiding <a> results in large gaps in the output
$.each(matches, function() { // unhide parents of our matches
this.parentsUntil(".sidebar-nav", ".hide").removeClass('hide');
});
}
});
Для демонстрации требуется, чтобы класс home
добавлялся к главной ссылке, чтобы предотвратить ее скрытие при поиске:
<a class="nav-link home" href="#"><i class="fa fa-fw fa-home"></i> Home</a>
и добавлен класс CSS для hide
:
.hide {
display: none;
}
Ответ 3
Если вы удалите:
toLowerCase();
Все отлично сочетается, если вы ввели его отлично. Проблема заключается в том, что вы делаете запрос в нижнем регистре, но он не соответствует строчным словам. Поэтому, когда вы вводите калькулятор, это не соответствует, потому что фактический элемент навигации отображается как Калькулятор с капиталом c.
Таким образом, вы можете либо сделать нижний регистр навигационных элементов, либо через HTML или JavaScript, либо по-другому, например, используя идентификаторы, но это может вызвать проблемы, если сайт динамический.
Немного странная работа может заключаться в том, чтобы заглавные буквы первых букв каждого слова, чтобы они соответствовали HTML. Взгляните на Как загладить первую букву каждого слова, например, город с двумя словами?
Ответ 4
Отфильтровать от чего именно? Я все еще пытаюсь понять