Вопрос

Short Description: I want to use JS/JQuery to take precedence over the CSS :hover psuedo-class for specific brief moments without removing the CSS rule for the other majority of cases. Since the site is already script-heavy enough I'm trying to find a solution that doesn't require me to nuke the CSS interaction and rely on mouseover/mouseout events. In my case there's a marked performance difference between the two.

Details: I've created a CSS-based dropdown shopping cart viewer. I rigged up some JQuery to force the cart open when the user triggers certain page interactions like adding an item to the cart. When the cart is "programmatically opened" an 8 second timer is used to close it. All that works. The Problem: I also want to add a click handler to the cart so that when the user clicks on it it will be explicitly closed whether the 8second timeout has expired or not. However, when they click on the cart they are - by definition - hovering over it, kicking in the :hover state and keeping it from closing. Is there a way to temporarily disable the :hover rule and then once the cart has closed reinstate it.

HTML:

<span class="minicart-wrapper">
    <a class="minicart-anchor" href="...">Shopping Cart</a>
    <div id="minicart">
        ...
    </div>
</span>

CSS:

.minicart-wrapper #minicart { display: none; }
.minicart-wrapper:hover #minicart,
.minicart-wrapper #minicart.open { display: block; }

JQuery:

function openMinicart() {
    var minicart = jQuery('#minicart');
    minicart.addClass('open');
    minicart.bind('click', {}, closeMinicart);
    window.setTimeout(closeMinicart, 8000);
}

function closeMinicart() {
    var minicart = jQuery('#minicart');
    minicart.removeClass('open');
    minicart.unbind('click', closeMinicart);
}

I've tried: a few suggestions I found here like changing .minicart-wrapper:hover #minicart to .minicart-wrapper:hover #minicart.canhover. I then added removeClass(canhover) to the beginning of closeMinicart() and setTimeout(function(){jQuery('#minicart').addClass('canhover')},500); to the end of it. However it seems that this is too short a timeout for the browser to refresh it's hover-state and before it's done rendering the hover re-triggers and the cart stays put.

Thanks for any suggestions.

Edit: Thanks Jedison. Here's the JSFiddle: http://jsfiddle.net/WJS3h/ . Also fixed some bugs in the sample.

Edit 2: Turns out I had a code error (oops) and the can-not-hover class method is the way to go. Thanks to everyone who commented.

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

Решение

One way to do this would be to add a class to block the hover, and then remove it when you close the dropdown. You could then put some .css on the hover pseudo class for that class that would block the hover class.

Something like this:

#minicart {display: 'none'}
#minicart:hover {display: 'block'}
#minicart.noHoverCss:hover {display: ''}

Add the noHoverCss to the cart in openMinicart and remove it in closeMinicart.

You could also remove it with some delay after closeMinicart is done so the user has some time to move their mouse away without triggering the hover.

EDIT TWO:

The other thing you can do is take advantage of the fact that inline .css trumps .css from a style sheet. Instead of using a css class (open) to set display: block, do it inline. Similarly, when you exit, set the css to display : none to force the dropdown to hide, then, after a timeout, set the css to display : '' to restore your default hovering behavior.

Here's an updated fiddle: fiddle

Другие советы

So you want something that blocks the hover command when you click on it?

You could create an extra class to listen when you hover. The extra class can signal if the box should be opened or not:

It's a little ugly, but does the trick.

jsfiddle: http://jsfiddle.net/kychan/zH3x5/

//    add listener to minicart.
var anchor = $('.minicart-anchor');
var cart   = $('#minicart');

//    our functions that will be executed on the events.
var close  = function() {
    cart.slideUp(500);
},
    open   = function() {
    //    if it has class 'stayClosed' don't do anything.
    if (cart.hasClass('stayClosed')) return;
    //    else, slide!
    cart.slideDown(500);
};

//    bind to event: hover.
anchor.hover(open, close).click(function () {
    //    add or remove 'stayClosed' class on click.
    if (cart.hasClass('stayClosed'))
    {
        //    don't stay closed when the user clicks again.
        cart.removeClass('stayClosed');

        //    automatically open it again.
        open();
    }
    else
    {
        //    stay closed, even on hover.
        cart.addClass('stayClosed');

        //    automatically close it.
        close();
    }
});

//    initially hide it.
cart.hide();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top