bmcculley
bmcculley

Reputation: 2088

mouseenter mouseleave not working the way I think it should

I am relatively new to jQuery, and I seem to be stuck with this mouseenter/mouseleave problem. I would like to setup a menu that "hides" when the page isn't at the top, which seems to be working fine, when it's hidden I would like to make it so when a user hovers over it the class switches and the menu comes back out. However, I don't want this when it gets scrolled back to the top. It works fine when the page first loads (in firefox and chrome) and I haven't scrolled yet, but after scrolling down and back to the top the menu will hide on mouseleave.

Here is a jsFiddle of my current code setup.

I've been trying to solve this for awhile now, and have tried a few other methods.

I tried just using hover like this

$("#access").hover(function() {
            $(this).removeClass("scroll").addClass("normal");
        }, function() {
            $(this).removeClass("normal").addClass("scroll");
        });

but that did the same thing as the code I have right now.

Some of the other methods I tried was to pass the b variable to another function, create a seperate div and track it's position to determine whether or not to use the mouseenter/mouseleave, and finally to bind them, but none of this seemed to work as I thought it should.

I can't think of anything else to try, so I am not sure if it's something I'm doing wrong or if this isn't even possible to accomplish like this.

This is my first question I tried to include as much information as I could think of hopefully it's enough information.

Upvotes: 0

Views: 650

Answers (4)

wirey00
wirey00

Reputation: 33661

Try this

$(document).ready(function() {
    $(window).scroll(function() {
        var b = $(window).scrollTop();
        $("#access").toggleClass("normal", b == 0)
        $("#access").toggleClass("scroll", b > 0)
    });
    $("#access").hover(function() {           
        if($(window).scrollTop() > 0){
            $("#access").toggleClass("normal scroll");
        }
    });
});​

http://jsfiddle.net/bJquD/6/

Upvotes: 2

orhanhenrik
orhanhenrik

Reputation: 1415

Here you simply add the variable isOnTop and the mouseenter and mouseleave handlers check it before they do anything

$(document).ready(function() {
var isOnTop=1;
    $(window).scroll(function() {
        var b = $(window).scrollTop();

        if (b > 0) {
            isOnTop=0;            
            $("#access").removeClass("normal").addClass("scroll");
        }

        else if (b == 0) {
            isOnTop=1;
            $("#access").removeClass("scroll").addClass("normal");
        }

    });

    $("#access").mouseenter(function() {
        if(isOnTop){return;}
        $(this).removeClass("scroll").addClass("normal");
    });

    $("#access").mouseleave(function() {
        if(isOnTop){return;}
        $(this).removeClass("normal").addClass("scroll");
    });
});​

Upvotes: 0

Kyle Ross
Kyle Ross

Reputation: 2160

Yea, you are adding a bunch of event handlers to that element which will ultimately slow down the page incredibly. You want to refrain from doing that. Alternatively, you can bind the events and then remove them when scrolled to the top of the page. The best way to do that is with the code below.

$(document).ready(function() {
    $(window).scroll(function() {
        if ($(this).scrollTop() > 0) {
            $("#access").removeClass("normal").addClass("scroll").on('mouseenter', function() {
                $(this).removeClass("scroll").addClass("normal");
            }).on('mouseleave', function() {
                $(this).removeClass("normal").addClass("scroll");
            });
        } else {
            $("#access").removeClass("scroll").addClass("normal").off('mouseenter mouseleave');
        }
    });
});​

You can also give it a try here.

Hopefully that helps you out :)

Upvotes: 0

David Thomas
David Thomas

Reputation: 253506

You weren't accounting for the scrolled status of the page, so the mouseenter/mouseleave events were, regardless of whether the page was scrolled, resetting the class-names without regard. Which, predictably, didn't gel with what you wanted.

The obvious resolution to this is to use a global variable (albeit within the scope of the jQuery document-ready) to keep track of this and, then check that in the hover() functions, leading to the following:

var scrolled = false;

$(window).scroll(
    function(){
        var b = $(window).scrollTop();
        if (b == 0) {
            $('#access').removeClass('scroll').addClass('normal');
            scrolled = false;
        }
        else if (b > 0) {
            $('#access').removeClass('normal').addClass('scroll');
            scrolled = true;
        }
    });

$('#access').hover(
    function(){
        if (scrolled) {
            // window scrolled, hence access class should be 'scroll'
            $('#access').removeClass('scroll').addClass('normal');
        }
    },
    function(){
        if (scrolled) {
            // window scrolled, hence access class should be 'normal' (from mouseenter)
            $('#access').removeClass('normal').addClass('scroll');
        }
    });​

JS Fiddle demo.

The result of this is that if the page is un-scrolled the mouseenter/mouseleave events do nothing (because they shouldn't, the normal class-name is correct in this case), whereas if the page is scrolled, they remove the scroll class-name on mouseenter and restore it on mouseleave.

Upvotes: 0

Related Questions