1

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.

1
  • I'd suggest you make a JSFiddle so that we can try annd give you a solution. Commented Apr 24, 2014 at 15:36

2 Answers 2

2

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

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks @ckersch. I had already tried that and it didn't work. I just retried to make sure it wasn't an error on my end. While it works great in JSFiddle, it did not work on the actual site. Presumably this is because of the considerable difference in rendering time between our bloated (Magento) site and the fiddle ideal case. I even tried removing the noHoverCSS class after a 1sec delay, still didn't work.
See updated fiddle. I used inline css to override the styling for opening/closing, but you could just as easily only do this when you want to close. The idea is that the inline css will trump the style sheet, so you can use it to force the dropdown to close, then remove the inline css after it's closed to restore your default functionality.
Realized I had blocked some functionality. Fixed and updated the fiddle.
Thanks! It works now. Just realized I was messing up my setTimeout in the real environment by calling - not passing a callback - for my function (facepalm). Duh. That being said, I was able to use a no-hover class with display:none. Final working fiddle is: jsfiddle.net/WJS3h/5
0

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();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.