Вопрос

I am designing a website with a header containing two rows of names. When the user hovers over one of the names, a specific div needs to appear below the names. This div will have other images and links contained within it so it is necessary for the user to be able to navigate the mouse from the name down into the div.

For simplicity sake, I will call the top row of names "top" with the associated div "top-reveal" and the bottom row of names "bottom" and "bottom-reveal." (See linked jsfiddle.)

"Top-reveal" and "bottom-reveal" need to appear in the same place and can't overlap the names above.

I first tried using straight CSS div:first-child, but I couldn't control the user "intent."

I then switched to a jQuery approach with the hoverIntent plugin:

var timeHover = 700;

$("[id^='top']").hoverIntent({
    over: topRevealer,
    timeout: timeHover,
    out: topHider
});
$("[id^='bottom']").hoverIntent({
    over: bottomRevealer,
    timeout: timeHover,
    out: bottomHider
});

function topRevealer() {
    setTimeout(function () {
        $('#bottom-reveal').hide(), $('#top-reveal').fadeIn();
    }, timeHover);
}

function bottomRevealer() {
    setTimeout(function () {
        $('#top-reveal').hide(), $('#bottom-reveal').fadeIn();
    }, timeHover);
}

function topHider() {
    $('#top-reveal').hide()
}

function bottomHider() {
    $('#bottom-reveal').hide()
}

I am using hoverIntent because I couldn't figure out how to do the timeout with .hover(). It works, except the reveal div fades out and then back in. I know this is because it is calling "TopHider" when the mouse moves from "Top" into "Top-Reveal" and then calling "TopRevealer" once it is into the "Top-Reveal" div but I don't want it to pop in and out. I also notice it can create a queue of fading in and out and I don't know how to create an error catcher of sorts.

Fiddle with where I am at: http://jsfiddle.net/UFZ6U/

As you can see, it is almost there, but I need some guidance for the final push, or even some tips on better JavaScript coding. I have only recently started to work with JavaScript outside of downloading standalone scripts and I have hit my head on the wall too many times now. I am looking for the most straight forward answer, it doesn't have to be jQuery or pure CSS, just a working solution which is lightweight. I am also not married to hoverIntent, but it helped get me this far.

I hope this made sense.

Thank you all potential answerers.

Это было полезно?

Решение

If you are already using timeouts, you can selectively store and clear the timeout IDs to create this effect. The following solution does not utilize the hoverIntent jQuery Plug-in.

HTML

<div id="hover-area">
    <div id="one" class="hoverable">One</div>
    <div id="two" class="hoverable">Two</div>
    <div id="three" class="hoverable">Three</div>
    <div id="four" class="hoverable">Four</div>
    <div id="one-reveal" class="revealable">One Reveal</div>
    <div id="two-reveal" class="revealable">Two Reveal</div>
    <div id="three-reveal" class="revealable">Three Reveal</div>
    <div id="four-reveal" class="revealable">Four Reveal</div>
</div>

JS

var timeHover = 700;

// Setup reveal and hide on hoverable items
$('.hoverable').on({
    'mouseenter': function() {
        // Get the hoverable ID
        var hoverableId = $(this).attr('id');
        // Generate the associated revealable ID
        var revealableId = hoverableId + '-reveal';
        // Show the associated revealable item (after timeout)
        showRevealable('#' + revealableId);
    },
    'mouseleave': function() {
        // Get the hoverable ID
        var hoverableId = $(this).attr('id');
        // Generate the associated revealable ID
        var revealableId = hoverableId + '-reveal';
        // Hide the associated revealable item (after timeout)
        hideRevealable('#' + revealableId);
    }
});

// Set up to maintain visibility and hide for the revealable items
$('.revealable').on({
    'mouseenter': function() {
        // Clear the timeout for this revealable item
        clearRevealableTimeout(this);
    },
    'mouseleave': function() {
        // Hide the revealable item (after timeout)
        hideRevealable(this);
    }
});

// Clears the timeout for the given revealable container
function clearRevealableTimeout(revealable) {
    // Get the associated timeout ID from the data attribute
    var timeout = $(revealable).data('timeout');
    // Clear the associated timeout
    clearTimeout(timeout);
}

// Shows the given revealable item (after a delay)
function showRevealable(revealable) {
    // Set a new timeout for the show and get the associated ID
    var timeout = setTimeout(function () {
        // Hide any existing revealables that are not this one
        $('.revealable').not(revealable).hide();
        $(revealable).stop().fadeIn();
    }, timeHover);
    // Store the timeout ID in the data attribute
    $(revealable).data('timeout', timeout);
}

// Hides the given revealable item (after a delay)
function hideRevealable(revealable) {
    // Clear the timeout to prevent any pending behavior
    clearRevealableTimeout(revealable);
    // Set a new timeout for the hide and get the associated ID
    var timeout = setTimeout(function () {
        $(revealable).hide();
    }, timeHover);
    // Store the timeout ID in the data attribute
    $(revealable).data('timeout', timeout);
}

DEMO

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top