如何使用搜索栏过滤Bootstrap 4导航栏链接?

18

我正在使用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>

3个回答

9
我所使用的方法是记住哪些项目匹配,然后使用该列表取消隐藏父项。
更新的代码片段: 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 https://dev59.com/xWox5IYBdhLWcg3wkk-E#9127872
  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>

并添加了一个名为hide的CSS类:

.hide {
  display: none;
}

8

好的,我认为我已经自己解决了问题(在这篇与不区分大小写过滤器有关的帖子的一些帮助下)。

1)我通过将它们包装在具有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();
            }
        });

这里有一个演示,展示了如何打开任何隐藏的链接(在Bootstrap 4中使用collapsed类)。


你的fiddle有问题。 - Jarad
抱歉,现在应该已经修复了。 - user1837608

1

If you remove the:

toLowerCase();

如果您输入完全正确,那么所有内容都可以完美匹配。问题在于您将搜索词变为小写,但它不会与小写单词匹配。因此,当您键入计算器时,它不匹配,因为实际的导航项显示为 Calculator,其中 c 是大写的。
因此,您可以通过 HTML 或 JavaScript 使导航项也变为小写,或者以不同的方式进行操作,例如使用 ID,但这可能会导致网站动态化出现问题。
一个有点奇怪的解决方法是将每个单词的首字母大写,以便与 HTML 匹配。请看如何使每个单词的首字母大写,比如一个由两个单词组成的城市?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接