Нажмите, чтобы закрыть раскрывающееся меню jQuery на мобильных устройствах, сохранив при этом другое поведение.

У меня есть довольно простое выпадающее меню jQuery со ссылками в обычном порядке списка ul/li. Код для раскрывающегося списка выглядит следующим образом:

$('body').ready(function() {
      if(screen.width <= 720) {
          $('.dropdown').hover(function() { $(this).find('.subMenu').toggle(); });
          $('.dropdown').click(function() { if( $('this').css('display') != 'none') {
              $('this').toggle();
              }
          });
      }
      else
      {
          $('.dropdown').hover(
              function() { $(this).stop(true,true).find('.subMenu').slideDown("fast"); },
              function() { $(this).stop(true,true).find('.subMenu').hide(); } 
          );
      }
  });

На мобильных устройствах (игнорируйте ширину 720, это только для тестирования прямо сейчас), я хотел бы добиться следующей функциональности:

  • Пользователь нажимает на ссылку с выпадающим меню> Если меню открыто, закройте его

  • Пользователь нажимает на ссылку, когда другое меню уже открыто> Закрыть предыдущее меню, открыть текущее меню

  • Пользователь нажимает в другом месте на странице> Закрыть все открытые меню

Я обнаружил, что функция наведения на самом деле обрабатывает #2 и #3, но я не могу понять, как заставить #1 работать. Я вполне уверен, что знаю, почему именно эта попытка

$('.dropdown').click(function() { if( $('this').css('display') != 'none') {
      $('this').toggle();
      }
});

выходит из строя. Я предполагаю, что щелчок (или касание, в данном случае) запускает событие наведения, которое, кажется, имеет приоритет и, следовательно, отображает меню, а не скрывает его.

Как я могу заставить это работать на мобильных устройствах?

Редактировать: я использую jQuery v1.7.2

Структура списка HTML выглядит следующим образом, в случае, если она кому-то помогает (сокращенная версия):

    <div id="navbar">
      <ul>
        <li class="dropdown"><a href="#">Link A</a></li>
        <li class="dropdown"><a href="#">Link B</a>
          <ul class="subMenu">
            <li><a href="#">Link 1</a></li>
            <li><a href="#">Link 2</a></li>
          </ul>
        </li>
      </ul>
    </div>

4 ответа

Решение

Если вы используете jq 1.7+, попробуйте это ДЕМО ЗДЕСЬ http://jsfiddle.net/SCN5T/3/

$(function(){
    $(document).mousedown(function(){
         $('.dropdown .active').removeClass('active').children('ul').hide();
    })
    $('.dropdown').on('mousedown','.subMenu', function(e){
        e.stopPropagation();
        var elem = $(this);
        if(elem.is('.active')) {
            elem.children('ul').slideUp(150);
            elem.removeClass('active');
        } else {
             $('.dropdown .active').removeClass('active').children('ul').hide();
            elem.addClass('active').children('ul').slideDown(150);
        }
    });
    $('.subMenu').on('mousedown','ul', function(e){
        e.stopPropagation();
        alert('menu item clicked');
    });       
})

if( $('this').css('display')!= 'none') можно заменить на if($('this').is(':hidden'))

Вы можете использовать.siblings(), чтобы закрыть другие меню... не могу увидеть HTML-код, чтобы сказать, как именно должен выглядеть селектор.

Как вариант, вы можете добавить некоторый класс, чтобы проверить, есть ли другие открытые меню...

  $('.dropdown').hover(function() { 
      $('.openedMenu .subMenu').hide().removeClass('openedMenu');
      $(this).find('.subMenu').toggle(); 
      $(this).addClass('openedMenu');
  });
  $('.dropdown').click(function() { 
      if( $('this').is(':hidden')) {
          $('this').toggle();
      }
  });

Я работал только в одном мобильном веб-проекте, но у меня тоже были проблемы с кликом. Я использовал мобильную среду jQuery. В качестве обходного пути использовалось событие "tap", включенное в jQm вместо click. Я полагаю, что вы не используете jQuery для мобильных устройств. Я обнаружил этот плагин, который помогает вам создавать события "касания": http://aanandprasad.com/articles/jquery-tappable/

Следующий фрагмент кода помог мне с конкретной проблемой:

$('html').mousedown(function() {
    $('.subMenu').hide();
    });

$('#navbar').mousedown(function(event) {
    event.stopPropagation();
    });

$('.dropdown').mousedown(function() {
    var ele = $(this).find('.subMenu');
    $('#navbar').find('.subMenu').each(function(index) { if(!$(this).is(ele)) $(this).hide(); } );
    ele.toggle();
    });

Основная идея, которой я следовал, состояла в том, чтобы найти подменю при получении события mousedown и скрыть их, если только элемент не был меню, по которому щелкнул пользователь. Переключатель либо показывает, либо скрывает меню. Часть распространения события и часть body/html hide от ответа acrashik и изменения к $('html') это из этого ответа.

Другие вопросы по тегам