Question

I have this bit of HTML:

<div id="site-header-inner">
    <div id="header-logo">
    <?php echo wp_get_attachment_image(get_field('header_logo','options'),'full'); ?>
    </div>
    <div id="header-nav">
        <ul>
            <li class="header-nav-item">
            Articles 
            </li>
            <li class="header-nav-item">
            Art Space
            </li>
            <li class="header-nav-item">
            Job Board
            </li>
            <li class="header-nav-item">
            Calendar
            </li>
        </ul>
    </div>
</div>  
<div id="header-nav-dropdown"> 
    <div id="dropdown-inner">
    Dropdown Stuff
    </div>
</div>

When the <li class="header-nav-item"> is hovered, I want to show the <div id="header-nav-dropdown"> using javascript/jquery.

What is the simplest way to do that while also keep the <div id="header-nav-dropdown") visible as long as the mouse is over it or the <li>?

Was it helpful?

Solution

It would probably be easiest to maintain a small self-invoking function to manage this so it doesn't impact any other scripts.

All we're doing is binding mouseover events to the items we want to reveal the dropdown list to, and when we mouseout, we're giving the user 500ms (change the time

(function($){
    // Select the items you want to bind our mouse events to.
    var $hoverItems = $("#header-nav .header-nav-item, #header-nav-dropdown");
    // Dropdown list.
    var $dropdownList = $("#header-nav-dropdown");
    // This is a timeout variable so we can keep track of our mouse incomings/outgoings.
    var timeout;

    // Bind mouseover/mouseout events.
    $hoverItems.on("mouseover", function(){
        $dropdownList.show();
        clearTimeout(timeout);
    }).on("mouseout", function(){
        timeout = setTimeout(function(){
            $dropdownList.hide();
        }, 500);
    });
})(jQuery);

OTHER TIPS

Here is the vanilla way to do this. Add the CSS display:none to hide any element you want (in this case, your header elements that will be displayed when you hover the li).

Grab the li elements and give them an event.

var derp = document.getElementsByClassName("header-nav-item");
var herp = document.getElementsByClassName("header-nav-dropdown");
for (var i=0;i<derp.length;derp++) { //loop the array of dom elements
    derp[i].addEventListener('mouseover', function() {
        for (var x=0;x<herp.length;herp++) {
            herp[x].style.display = "block"; //or inline etc
        }
    });
    derp[i].addEventListener("mouseout", function() {
        for (var x=0;x<herp.length;herp++) {
            herp[x].style.display = "none"; //hide again
        }
    });
}

This loops the li elements, adds listeners for mouseout and mouseover and within them, hides/shows all elements with the header class. No need for jQuery!

I would use variables as flags and do something like this:

var liHover = false;
var dropdownHover = false;
$(document).ready(function() {

    $('.header-nav-item').mouseover(function() {
        liHover = true;
        $('#header-nav-dropdown").show();
    });
    $('#header-nav-dropdown').mouseover(function() {
        dropdownHover = true;
    });

    $('.header-nav-item').mouseout(function() {
        liHover = false;
    });
    $('#header-nav-dropdown').mouseout(function() {
        dropdownHover = false;
    });

    $('.header-nav-item, #header-nav-dropdown').mouseout(function() {
        if (!liHover && !dropdownHover) {
            $('#header-nav-dropdown").show();
        }
    });
});

Now I'll explain all the decisions there. The mouseovers are in separate method calls because it makes more sense than using an if statement and combining them. The li hover needs to show the dropdown and adjust its respective flag, while the dropdown hover only needs to adjust its flag. I chose to still separate the flag adjustments for the mouseouts, but you COULD put them both in the combined mouseout with an if statement. Then of course for the combined one, it is such because that is the functionality that will exist in either instance.

EDIT: Sorry, I had a typo, the last mouseout said mouseover. It's fixed.

I hope this is what you need!

Jquery:

$('#header-nav li.header-nav-item').hover(function () {
    $('#header-nav-dropdown').show(); 
}, function () {
    $('#header-nav-dropdown').hide();
});

css:

#header-nav-dropdown {
    display: none;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top