Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Правильное адаптивное меню (https://javascript.ru/forum/jquery/70436-pravilnoe-adaptivnoe-menyu.html)

Tipylja 05.09.2017 10:30

Правильное адаптивное меню
 
Здравствуйте подскажите пожалуйста. Мне уже ранее помогли на этом форуме с адаптивным меню, но оно не совсем правильно работает, вот код меню:
$('.menu__list').on('mouseleave mouseenter click', function (e) {
    if( e.relatedTarget === null && e.type !== 'click' ) return;
    $('.middleMenu__drop').slideToggle(100);
});

<ul class="wrap middleMenu">
<li class="menu__list first"><a>Каталог</a>
	<ul class="middleMenu__drop" style="display: block;">
		<li><a href="#">Туфли</a></li>
		<li><a href="#">Босоножки</a></li>
		<li><a href="#">Кеды</a></li>
		<li><a href="#">Кросcовки</a></li>
		<li><a href="#">Ботинки демисезон</a></li>
		<li><a href="#">Сапоги демисезон</a></li>
	</ul>
</li>
<li><a href="#">ОПЛАТА / ДОСТАВКА</a></li>
<li><a href="#">ОТЗЫВЫ О МАГАЗИНЕ</a></li>
<li class="last"><a href="#">НОВИНКИ</a></li>
</ul>

Но это меню выходит дерганым, если мышкой наводить и уводить, его можно сломать и заставить работать наоборот, так же как если при обновлении страницы курсор мышки навести на меню и заставить его выпасть.
Хотелось бы правильно реализовать меню вероятно это нужно делать через slideDown и slideUp, я нашел вот такой кусок когда:
$(document).ready(function () {
 
  $('.vert-nav li').hover(
    function() {
      $('ul', this).slideDown(110);
    },
    function() {
      $('ul', this).slideUp(110);
    }
  );
 
});

Но тут при неведение только работает, я так понимаю что неправильно вызывать для каждого события одну и туже функцию, хотелось бы передать список событий через .on, то в примере с .hover в качестве параметров передано две функции slideDown и slideUp, в .on не получается просто передать две функции после перечня событий, подскажите как правильно реализовать данный момент?

рони 05.09.2017 10:45

Tipylja,
другого выхода, как оставить только клик, не вижу.

j0hnik 05.09.2017 10:48

$('.menu__list').on('mouseenter', function (e) {
    $('.middleMenu__drop').slideDown(100);
});
$('.menu__list').on('mouseleave', function (e) {
    $('.middleMenu__drop').slideUp(100);
});

если разделить событие не сломается, а клик указан для тачей?

Tipylja 05.09.2017 10:48

Цитата:

Сообщение от рони (Сообщение 463720)
Tipylja,
другого выхода, как оставить только клик, не вижу.

Это адаптивное меню, оно должно срабатывать и при наведении и при клике, в том числе и с мобильных устройств=(

Tipylja 05.09.2017 10:49

Цитата:

Сообщение от j0hnik (Сообщение 463721)
если разделить событие не сломается, а клик указан для тачей?

Получается что да, для тачей, для мышки срабатывает hover

j0hnik 05.09.2017 11:03

Цитата:

Сообщение от Tipylja (Сообщение 463723)
Получается что да, для тачей, для мышки срабатывает hover

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

Tipylja 05.09.2017 11:03



Возможно как-то можно дополнить событием на клик(тап), что если меню раскрыто, то при клике slideUp а если закрыто, то slideDown?

Tipylja 05.09.2017 11:05

Цитата:

Сообщение от j0hnik (Сообщение 463729)
как я предложил на большинстве мобильных устройств работать будет по принципу, косящемся ссылки открывается, касаемся в пустоту закрывается. есть тачь события но они еще сырые.

Да, работает, но закрывается только по клику вне меню, а на мобильных устройствах это меню занимает весь экран по ширине, что бы его закрыть, нужно скролить и искать пустое место что бы при клике закрылось=( То есть нужно условие для клика по идее? Но как отследить, открыто ли меню сейчас, что бы понять стоит его закрыть или открыть

Tipylja 05.09.2017 11:20

В общем написал вот так и все работает вроде бы как нужно, буду тестировать. Всем спасибо за ответы
$('.menu__list').on('mouseenter', function (e) {
    $('.middleMenu__drop').slideDown(100).addClass('open');
});
$('.menu__list').on('mouseleave', function (e) {
    $('.middleMenu__drop').slideUp(100).removeClass('open');
});
$('.menu__list').on('click', function (e) {

    if($('.middleMenu__drop').hasClass('open')){        
        
        $('.middleMenu__drop').slideUp(100).removeClass('open');
    }else{
        
        $('.middleMenu__drop').slideDown(100).addClass('open');
    }
});

Tipylja 05.09.2017 11:33

UPD. Поспешил, не правильно работает на тачскрине, при первом нажатие меню раскрывается и тут же скрывается, после этого начинает работать нормально

Tipylja 05.09.2017 11:39

Вот так заработало
$(document).ready(function(){


$('.menu__list').on('mouseenter', function (e) {
    if( e.relatedTarget === null && e.type !== 'click' ) return;
    $('.middleMenu__drop').slideDown(100).addClass('open');
});
$('.menu__list').on('mouseleave', function (e) {
    $('.middleMenu__drop').slideUp(100).removeClass('open');
});
$('.menu__list').on('click', function (e) {

    if($('.middleMenu__drop').hasClass('open')){        
        
        $('.middleMenu__drop').slideUp(100).removeClass('open');
    }else{
        
        $('.middleMenu__drop').slideDown(100).addClass('open');
    }
})

});

Tipylja 05.09.2017 11:47

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

Tipylja 09.09.2017 10:14

Так и не удалось решить задачу=( Возможно все же, кто-нибудь все же укажет куда копать

Nexus 09.09.2017 10:32

Tipylja,
$(document).ready(function(){
	$('.menu__list').on('mouseenter',function(e){
		if(!e.relatedTarget) 
			return;
		
		$(this).find('.middleMenu__drop').slideDown(100).addClass('open');
	});
	$('.menu__list').on('mouseleave',function(e){
		$(this).find('.middleMenu__drop').slideUp(100).removeClass('open');
	});
	$('.menu__list').on('click',function(e){
		$(this).find('.middleMenu__drop').slideToggle(100).toggleClass('open');
	});
});

Tipylja 09.09.2017 11:05

Цитата:

Сообщение от Nexus (Сообщение 464156)
Tipylja,
$(document).ready(function(){
	$('.menu__list').on('mouseenter',function(e){
		if(!e.relatedTarget) 
			return;
		
		$(this).find('.middleMenu__drop').slideDown(100).addClass('open');
	});
	$('.menu__list').on('mouseleave',function(e){
		$(this).find('.middleMenu__drop').slideUp(100).removeClass('open');
	});
	$('.menu__list').on('click',function(e){
		$(this).find('.middleMenu__drop').slideToggle(100).toggleClass('open');
	});
});

Спасибо, работает адекватно, до того момента пока кликать "menu__list", если же раскрыть меню, кликнуть куда-нибудь вне него, меню закроется, а если вновь кликнуть после этого на "menu__list" меню откроется и тут же скроется, как и ранее - на мобильных экранах, на десктопе все работает отлично.
UPD. Более простая ситуация - открываем страницу на таскрине, тапаем куда угодно в пустое место вне меню, после чего тапаем на меню и получаем - меню раскрывается и тут же скрывается

Tipylja 10.09.2017 09:09

Извиняюсь, возможно кто-то что-нибудь еще подскажет?

j0hnik 10.09.2017 11:23

Цитата:

Сообщение от Tipylja (Сообщение 464218)
Извиняюсь, возможно кто-то что-нибудь еще подскажет?

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
<ul class="wrap middleMenu">
<li class="menu__list first"><a>Каталог</a>
	<ul class="middleMenu__drop" style="display: none;">
		<li><a href="#">Туфли</a></li>
		<li><a href="#">Босоножки</a></li>
		<li><a href="#">Кеды</a></li>
		<li><a href="#">Кросcовки</a></li>
		<li><a href="#">Ботинки демисезон</a></li>
		<li><a href="#">Сапоги демисезон</a></li>
	</ul>
</li>
<li><a href="#">ОПЛАТА / ДОСТАВКА</a></li>
<li><a href="#">ОТЗЫВЫ О МАГАЗИНЕ</a></li>
<li class="last"><a href="#">НОВИНКИ</a></li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>

function is_touch_device() {
 return (('ontouchstart' in window)
      || (navigator.MaxTouchPoints > 0)
      || (navigator.msMaxTouchPoints > 0));
}

if (!is_touch_device()) {
$('.menu__list').on('mouseenter', function (e) {
    $('.middleMenu__drop').slideDown(100);
});
$('.menu__list').on('mouseleave', function (e) {
   $('.middleMenu__drop').slideUp(100);
});
}
else {
	$('.menu__list').on('touchstart', function (e) {
    $('.middleMenu__drop').slideToggle(100);
});
}

</script>
</body>
</html>

Белый шум 10.09.2017 11:36

А если так?
<script src="//code.jquery.com/jquery-latest.min.js"></script>
<ul class="wrap middleMenu">
<li class="menu__list first"><a>Каталог</a>
	<ul class="middleMenu__drop" style="display: none;">
		<li><a href="#">Туфли</a></li>
		<li><a href="#">Босоножки</a></li>
		<li><a href="#">Кеды</a></li>
		<li><a href="#">Кросcовки</a></li>
		<li><a href="#">Ботинки демисезон</a></li>
		<li><a href="#">Сапоги демисезон</a></li>
	</ul>
</li>
<li><a href="#">ОПЛАТА / ДОСТАВКА</a></li>
<li><a href="#">ОТЗЫВЫ О МАГАЗИНЕ</a></li>
<li class="last"><a href="#">НОВИНКИ</a></li>
</ul>

<script>
$('.menu__list').on('mouseleave mouseenter click', function (e) {

console.log(e);

    if( e.relatedTarget === null && e.type !== 'click' ) return;
    switch( e.handleObj.origType ) {
        case 'mouseleave': $(this).find('.middleMenu__drop').slideUp(100); break;
        case 'mouseenter': $(this).find('.middleMenu__drop').slideDown(100); break;
        case 'click': $('.middleMenu__drop').slideToggle(100); break;
    }
});
</script>


P.S. вариант j0hnik работает лучше.

Tipylja 11.09.2017 10:36

Спасибо всем за помощь, вариант от j0hnik вроде бы работает хорошо!

Tipylja 11.09.2017 10:55

UPD. На тачскринах, при тапе меню разворачивается, но при тапе по пункту меню я попадаю сквозь него, и нажимаются ссылки которые остались под раскрытым меню:
<li><a href="#">ОПЛАТА / ДОСТАВКА</a></li>
<li><a href="#">ОТЗЫВЫ О МАГАЗИНЕ</a></li>
<li class="last"><a href="#">НОВИНКИ</a></li>

То есть опять меню прозрачно, как я описывал в самом начале этой темы, при тапе по нему, я попадаю тапом под выпадающее меню

Tipylja 11.09.2017 11:00

$('.menu__list').on('mouseleave mouseenter click', function (e) {

    if( e.relatedTarget === null && e.type !== 'click' ) return;
    switch( e.handleObj.origType ) {
        case 'mouseleave': $(this).find('.middleMenu__drop').slideUp(100); break;
        case 'mouseenter': $(this).find('.middleMenu__drop').slideDown(100); break;
        case 'click': $('.middleMenu__drop').slideToggle(100); break;
    }
});

Это работает как задумано.
UPD Нет, есть глюк со сворачиванием меню. Если открыть меню, а потом тапнуть куда-нибудь мимо, то меню свернется, а если повторно тапнуть, что бы меню развернулось, то оно развернется и тут же свернется

j0hnik 11.09.2017 19:20

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
<ul class="wrap middleMenu">
<li class="menu__list first"><a>Каталог</a>
	<ul class="middleMenu__drop" style="display: none;">
		<li><a href="https://google.com">Туфли</a></li>
		<li><a href="https://google.com">Босоножки</a></li>
		<li><a href="https://google.com">Кеды</a></li>
		<li><a href="https://google.com">Кросcовки</a></li>
		<li><a href="https://google.com">Ботинки демисезон</a></li>
		<li><a href="https://google.com">Сапоги демисезон</a></li>
	</ul>
</li>
<li><a href="https://yandex.ru">ОПЛАТА / ДОСТАВКА</a></li>
<li><a href="https://yandex.ru">ОТЗЫВЫ О МАГАЗИНЕ</a></li>
<li class="last"><a href="https://yandex.ru">НОВИНКИ</a></li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>

function is_touch_device() {
 return (('ontouchstart' in window)
      || (navigator.MaxTouchPoints > 0)
      || (navigator.msMaxTouchPoints > 0));
}

if (!is_touch_device()) {
$('.menu__list').on('mouseenter', function (e) {
    $('.middleMenu__drop').slideDown(100);
});
$('.menu__list').on('mouseleave', function (e) {
   $('.middleMenu__drop').slideUp(100);
});
}
else {
	$('.menu__list>a').on('touchstart', function (e) {
		e.stopPropagation();
     $('.middleMenu__drop').slideToggle(100);
});
}

</script>
</body>
</html>


немного изменил, поэксперементируйте

Tipylja 12.09.2017 09:40

Спасибо. Последнее работает пока что без глюков


Часовой пояс GMT +3, время: 13:54.