0

I got a question regarding the .hover() state. I have one navigation container id='search' and a other container called content (id='content') which is set to be hidden.

When I hover over the headline the content container shows up with links in it. But here's the question, is it possible to tell jQuery to not hide the content when I hover over it? Basically, I hover over the headline > the content shows up > so that I can click on the links and the content will disappear once I leave the headline or the content with my mouse.. Is that possible? ;/

Here's my HTML code.

<div class='navigation'>
        <ul>
            <li class='headline' id='search'>Search</li>
            <li class='headline' id='news'>News</li>
            <li class='headline' id='media'>Media</li>
            <li class='headline' id='miscellaneous'>Miscellaneous</li>
        </ul>

        <div id='content'>Hover over a headline to show its content.</div>
</div>

And JavaScript / jQuery

$('#content').hide(); /* Hide content container */
var contentSearch = '<ul>' +
                        '<li><img src=\'images/icons/youtube.png\' class=\'icon\'><a class=\'link\' href=\"#\">DuckDuckGo</a></li>' +
                        '<li><img src=\'images/icons/youtube.png\' class=\'icon\'><a class=\'link\' href=\"#\">Google</a></li>' +
                    '</ul>';
$('#search').hover(function () { /* Headline is hovered upon */
    var pos = $(this).position(); /* Get the position of the headline container relative to its parent */
    var headlineWdth = $(this).width(); /* Get the width of the headline container */
    $('#content').html(contentSearch); /* Content container gets its content filled in */
    var contentWdth = $('#content').width(); /* Get the width of the content container */
    var contentWdthRemaining = contentWdth - headlineWdth; /* Content width minus headline width equals the remaining width of the content container */
    var posSubtract = contentWdthRemaining / 2; /* Remaining content container width will be divided by 2, that way it can be later subtracted from the offset position
    in order for us to place the content container directly bellow the headline */
    $('#content').css({'left': pos.left - posSubtract}); /* Place content container right bellow the headline */
    $('#content').slideDown('fast'); /* Show content container with a fast slide down animation */
}, function () { /* The headline is not hovered upon anymore */
    $('#content').hide(); /* immediately hide the content container */
    $('#content').html(''); /* Clear previous html input so it won't be seen in the page inspector tool */
});
Dean
  • 301
  • 1
  • 3
  • 13

1 Answers1

0

Okay so you need to make a few changes:

HTML

You should wrap your navigation in an element denominating the entire block used for navigation - this will include main menu and sub menu.

You already had a div.navigation element, so I added a new one called div#nav:

<div class='navigation'>
    <div id="nav">
        <ul>
            <li class='headline' id='search'>Search</li>
            <li class='headline' id='news'>News</li>
            <li class='headline' id='media'>Media</li>
            <li class='headline' id='miscellaneous'>Miscellaneous</li>
        </ul>
        <div id='content'>Hover over a headline to show its content.</div>
    </div>
</div>

CSS

Not a lot of change here, the only change I made was to change the following rule from .navigation > ul to #nav > ul:

#nav > ul {
    margin: 0px;
    padding: 0px;
    text-align: center;
}

JS

I've drastically changed the Javascript (as you can see by this diff comparison). Here's a rundown of my changes:

  1. I added both var instances to the top, for organization.
  2. I've changed all events to .on() events. Check out the docs here.
  3. Another organization change I made was to chain together many functions. JQuery is designed so that each function returns the original jQuery object, so you can continue your series of functions from the original $() call. (e.g. $('#content').hide(); $('#content').html(''); becomes $('#content').hide().html('');.) This is actually not exclusive to jQuery, and this SO answer has a good way of illustrating this behavior.
  4. I'm using event delegation so that the event listeners don't have to be reinstantiated, as the events will be "bubbling up" the DOM, to the body which is always available.

The idea is the browser is waiting your mouse to be over the designated menu items (#search and #news). When you take your mouse out of the #nav object (which holds both the menu and submenu), your browser will wait a fraction of a second before removing the submenu.

When your mouse is over the submenu, it will get rid of the timer to remove the submenu. The point of this is that you won't accidentally take your mouse out and hide the submenu by accident.

Let me know if you need any further explanation!

JsFiddle available here.

Community
  • 1
  • 1
xyhhx
  • 6,384
  • 6
  • 41
  • 64
  • Oh my god, thank you so much! You deserve a medal for that :D – Dean Mar 28 '15 at 13:16
  • A medal for taking so long to answer? I think not :) – xyhhx Mar 28 '15 at 13:33
  • Doesn't matter how much time went by before you answered, I mean just look at that answer of yours, organized, structured and well written. I wouldn't have had found the solution without you - so I appreciate your help and effort, thank you Martin! :3 – Dean Mar 28 '15 at 21:00