Наведение на пункты меню bootstrap 3

163
01 декабря 2019, 11:50

Стандартное меню Bootstrap 3:

var $window = $(window); 
 
$window.on('load resize', function(){ 
  if($(window).width() > 768){ 
    $('.dropdown').on('mouseenter mouseleave click tap', function() { 
      $(this).toggleClass("open"); 
    }); 
  } else { 
    $(".dropdown").unbind("mouseenter mouseleave"); 
  } 
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> 
	<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> 
  
<nav class="navbar navbar-default"> 
  <div class="container-fluid"> 
    <!-- Brand and toggle get grouped for better mobile display --> 
    <div class="navbar-header"> 
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> 
        <span class="sr-only">Toggle navigation</span> 
        <span class="icon-bar"></span> 
        <span class="icon-bar"></span> 
        <span class="icon-bar"></span> 
      </button> 
      <a class="navbar-brand" href="#">Brand</a> 
    </div> 
 
    <!-- Collect the nav links, forms, and other content for toggling --> 
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> 
      <ul class="nav navbar-nav"> 
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li> 
        <li><a href="#">Link</a></li> 
        <li class="dropdown"> 
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> 
          <ul class="dropdown-menu"> 
            <li><a href="#">Action</a></li> 
            <li><a href="#">Another action</a></li> 
            <li><a href="#">Something else here</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">Separated link</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">One more separated link</a></li> 
          </ul> 
        </li> 
        <li class="dropdown"> 
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> 
          <ul class="dropdown-menu"> 
            <li><a href="#">Action</a></li> 
            <li><a href="#">Another action</a></li> 
            <li><a href="#">Something else here</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">Separated link</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">One more separated link</a></li> 
          </ul> 
        </li> 
        <li class="dropdown"> 
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> 
          <ul class="dropdown-menu"> 
            <li><a href="#">Action</a></li> 
            <li><a href="#">Another action</a></li> 
            <li><a href="#">Something else here</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">Separated link</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">One more separated link</a></li> 
          </ul> 
        </li> 
      </ul> 
    </div> 
  </div> 
</nav>

На десктопе (больше 768px) подменю должно появляться по наведению, а на мобильных девайсах по клику как обычно.

Вопрос: как правильно реализовать возможность раскрытия подменю по наведению только на десктопах?

!Важно. Решение нужно только с jQuery или js, полная имитация добавления класса open.

Answer 1

В приведенном коде есть несколько недочетов

  1. на каждый обработчик resize, в случае если ширина больше 768 будет добавлять отдельный обработчик для указанных событий, это приводит к тому, что в случае четного количества обработчиков класс open будет добавляться и сразу убираться, таким образом будет казаться, что ничего не происходит.

  2. так как обработчик click ставит сам бутстрап не нужно ставить его дополнительно вручную

  3. кроме класса open, при открытии dropdown выполняются еще несколько действий, чтобы не переносить их вручную в свой код, можно воспользоваться методом, который предоставляет bootstrap api: toggle

Для того, чтобы не добавлялось несколько обработчиков сразу - можно перед навешиванием нового обработчика удалять старые, чтобы не зацепить обработчики установленные не нами, можно воспользоваться механизмом namespace, например:

.off('.my-hover') // удалим все обработчики с namespace `.my-hover`
.on('mouseenter.my-hover', function() { // добавим обработчик mouseenter с namespace `.my-hover`

Из-за скудного api, понять открыт dropdown или нет можно только по наличию класса open у родительского элемента (в данном случае li). Понимать это нужно для того, чтобы не пытаться открыть dropdown если он уже открыт, так как в данном случае выполнится метод toggle - и меню закроется либо наоборот откроется тогда, когда не надо.

В связи с этим придется разделить обработчики mouseenter и mouseleave добавив в каждый проверку:

если dropdown открыт и происходит mouseenter - то ничего не делать

.on('mouseenter.my-hover', function() {
    if ($(this).hasClass('open')) return;

если dropdown закрыт и происходит mouseleave - то ничего не делать

.on('mouseleave.my-hover', function() {
    if (!$(this).hasClass('open')) return;

Далее в обработчике останется только получить объект dropdown, взять его можно с помощью одноименной функции на элементе с атрибутом data-toggle="dropdown" и выполнить функцию toggle

$(this).find('[data-toggle="dropdown"]').dropdown('toggle');

Пример в сборе:

var $window = $(window); 
 
$window.on('load resize', function() { 
  var dd = $('.dropdown') 
    .off('.my-hover'); 
  if ($(window).width() > 768) { 
    dd.on('mouseenter.my-hover', function() { 
        if ($(this).hasClass('open')) return; 
        $(this).find('[data-toggle="dropdown"]').dropdown('toggle'); 
      }) 
      .on('mouseleave.my-hover', function() { 
        if (!$(this).hasClass('open')) return; 
        $(this).find('[data-toggle="dropdown"]').dropdown('toggle'); 
      }); 
  } 
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> 
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> 
 
<nav class="navbar navbar-default"> 
  <div class="container-fluid"> 
    <!-- Brand and toggle get grouped for better mobile display --> 
    <div class="navbar-header"> 
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> 
        <span class="sr-only">Toggle navigation</span> 
        <span class="icon-bar"></span> 
        <span class="icon-bar"></span> 
        <span class="icon-bar"></span> 
      </button> 
      <a class="navbar-brand" href="#">Brand</a> 
    </div> 
 
    <!-- Collect the nav links, forms, and other content for toggling --> 
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> 
      <ul class="nav navbar-nav"> 
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li> 
        <li><a href="#">Link</a></li> 
        <li class="dropdown"> 
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> 
          <ul class="dropdown-menu"> 
            <li><a href="#">Action</a></li> 
            <li><a href="#">Another action</a></li> 
            <li><a href="#">Something else here</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">Separated link</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">One more separated link</a></li> 
          </ul> 
        </li> 
        <li class="dropdown"> 
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> 
          <ul class="dropdown-menu"> 
            <li><a href="#">Action</a></li> 
            <li><a href="#">Another action</a></li> 
            <li><a href="#">Something else here</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">Separated link</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">One more separated link</a></li> 
          </ul> 
        </li> 
        <li class="dropdown"> 
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> 
          <ul class="dropdown-menu"> 
            <li><a href="#">Action</a></li> 
            <li><a href="#">Another action</a></li> 
            <li><a href="#">Something else here</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">Separated link</a></li> 
            <li role="separator" class="divider"></li> 
            <li><a href="#">One more separated link</a></li> 
          </ul> 
        </li> 
      </ul> 
    </div> 
  </div> 
</nav>

READ ALSO
Добавление заголовков в метод CONNECT

Добавление заголовков в метод CONNECT

Всем привет! У меня имеется клиент и прокси сервер на С#Клиент для соединения с сайтом через прокси сервер использует метод CONNECT

121
Как создать автоматически таблицы для SQLite?

Как создать автоматически таблицы для SQLite?

После создания создаёся пустая база данных

143
Как сравнить суму выдачи результатов на странице с числом total, если таких результатов может быть сколько угодно

Как сравнить суму выдачи результатов на странице с числом total, если таких результатов может быть сколько угодно

Суть в следующем: в строку поиска вводится строка, после сабмита получаем некоторое количество разделов, в которых найдена наша строкаВ зависимости...

158
Не могу добавить команду разработчика VisualStudio IOS

Не могу добавить команду разработчика VisualStudio IOS

Пытаюсь залить приложение на свой IPhoneЮзаю Visual Studio

169