简体   繁体   中英

Menu open by hover on desktop, click on mobile

I am trying to create a menu button that when hovered, reveals a drop down set of links on desktop. However, obviously users can't hover on mobiles etc. so have been trying to work out how to make the button reveal the menu on click too.

I have so far managed to come up with adding and removing the .show-nav class on mouse enter and leave using jquery. I tried adding the following code block but it obviously also affects desktop, which makes the menu kinda screwy if someone clicks the button (as the class is applied on the hover and then added and removed permanently using the click).

Thanks to cesare everything is working as it should, apart from in Chrome on iOS. djtwigg's solution is working in Chrome but not safari. Is it possible to merge the two solutions together?

<nav>
    <ul>
        <li id="nav-button">
            <a id="nav-click" href="#">Menu <i class="fa fa-bars"></i></a>
            <ul class="sub-nav">
                <li><a href="#">Link1</a></li>
                <li><a href="#">Link2</a></li>
                <li><a href="#">Link3</a></li>
                <li><a href="#">Link4</a></li>
            </ul>
        </li>
    </ul>
</nav>

var flag = false;
container.bind('touchstart', function(){
if (!flag) {
   flag = true;
   setTimeout(function(){ flag = false; }, 260);
   list.toggleClass('show-nav');
}
return false
});

container.hover(function(){
   list.addClass('show-nav');
}, function(){
   list.removeClass('show-nav');    
});
});

You can use "hover" for desktop and bind "touchstart" for mobile.

var flag = false;
container.bind('touchstart', function(){
if (!flag) {
   flag = true;
   setTimeout(function(){ flag = false; }, 260);
   list.toggleClass('show-nav');
}
return false
});

container.hover(function(){
   list.addClass('show-nav');
}, function(){
   list.removeClass('show-nav');    
});

try this fiddle: https://jsfiddle.net/62cvsvvc/6/

This solution is inspired from this question: How to bind 'touchstart' and 'click' events but not respond to both?

EDIT I checked on my server and works properly. I guess that this issue with iOS is related with jsFiddle enviroment.

Please try on: http://cesare.heliohost.org/test/

Use the touchstart event:

$('#nav-button').on('touchstart', function(){
     $('.sub-nav').toggleClass('show-nav');
});

It is possible to do this by checking whether the event was a touch or click. I found a plugin that helps: Gist of plugin

Simply check for a click and if it was a touch-click then toggle the menu. Use preventDefault() as shown in the fiddle. Add or remove the class on mouseenter and mouseleave by checking if it was a mouse instead of touch.

    // Bind mouse events to links.
  container
    .click(myClickCallback)
    .mouseenter(myMouseenterCallback)
    .mouseleave(myMouseleaveCallback);

  // Click callback.
  function myClickCallback(e) {
    var touchOrMouse = $body.touchOrMouse('get', e);

    // If mouse event has been invoked by touch.
    if (touchOrMouse === 'touch') {
      // Toggle .hovered class.
      list.toggleClass('show-nav');
    }

    // Do not follow the link.
    e.preventDefault();
  }

  // Mouse enter callback.
  function myMouseenterCallback(e) {
    var touchOrMouse = $body.touchOrMouse('get', e);

    // If mouse event has not been invoked by touch.
    if (touchOrMouse === 'mouse') {
      // Add .hovered class.
      list.addClass('show-nav');
    }
  }

  // Mouse leave callback.
  function myMouseleaveCallback(e) {
    var touchOrMouse = $body.touchOrMouse('get', e);

    // If mouse event has not been invoked by touch.
    if (touchOrMouse === 'mouse') {
      // Remove .hovered class.
      list.removeClass('show-nav');
    }
  }

Here is a fiddle with a working example on an iPhone: Fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM