Hover Intent + Touch - Dropdown Menu
A touch-enabled jQuery dropdown menu with hover intent for mouse events.
by bizamajig
HTML
<!-- IF YOU WANT TO TRY THIS ON A TOUCH SCREEN DEVICE YOU WILL NEED TO VIEW WITHIN THE FULL SCREEN PREVIEW -->
<ul class="menu">
<li class="dropdown">
<a href="#" class="toplevel">This is a dropdown menu</a>
<ul class="submenu">
<li><a href="#">Lorem</a></li>
<li><a href="#">Ipsum</a></li>
<li><a href="#">Doler</a></li>
<li><a href="#">Sit amet</a></li>
</ul>
</li>
</ul>
CSS
.menu {
width:200px;
list-style-type:none;
}
.toplevel {
display:block;
padding:0 10px;
line-height:2;
color:#fff;
text-decoration:none;
background:#f00;
}
/* Dropdowns */
.dropdown {
position:relative;
z-index:200;
}
.submenu {
position:absolute;
top:0;
left:0;
display:none;
width:200px;
list-style-type:none;
padding-top:2em;
z-index:200;
}
.hover .submenu {
display:block;
}
.submenu a {
display:block;
padding:5px;
color:#fff;
text-decoration:none;
background:navy;
}
JavaScript
$(function()
{
var $dropdowns = $('li.dropdown'); // Specifying the element is faster for older browsers
/**
* Mouse events
*
* @description Mimic hoverIntent plugin by waiting for the mouse to 'settle' within the target before triggering
*/
$dropdowns
.on('mouseover', function() // Mouseenter (used with .hover()) does not trigger when user enters from outside document window
{
var $this = $(this);
if ($this.prop('hoverTimeout'))
{
$this.prop('hoverTimeout', clearTimeout($this.prop('hoverTimeout')));
}
$this.prop('hoverIntent', setTimeout(function()
{
$this.addClass('hover');
}, 250));
})
.on('mouseleave', function()
{
var $this = $(this);
if ($this.prop('hoverIntent'))
{
$this.prop('hoverIntent', clearTimeout($this.prop('hoverIntent')));
}
$this.prop('hoverTimeout', setTimeout(function()
{
$this.removeClass('hover');
}, 250));
});
/**
* Touch events
*
* @description Support click to open if we're dealing with a touchscreen
*/
if ('ontouchstart' in document.documentElement)
{
$dropdowns.each(function()
{
var $this = $(this);
this.addEventListener('touchstart', function(e)
{
if (e.touches.length === 1)
{
// Prevent touch events within dropdown bubbling down to document
e.stopPropagation();
// Toggle hover
if (!$this.hasClass('hover'))
{
// Prevent link on first touch
if (e.target === this || e.target.parentNode === this)
{
...