Hsan Hsan - 5 days ago 7
jQuery Question

Removing active class from specific a href

I have a one page layout with a navbar that changes active class on the scroll position. I had an issue where it wouldn't select the "Contact Us" navbar link when I scrolled to the contact section but I've fixed that by adding code to make the Contact Us link active when the user scrolls to the bottom of the page.

The problem now is that now the "Get A Quote" link doesn't go active after I've reached the bottom of the page until I've scrolled up past it and then back down again.

ie. Everything is fine scroll past each div and the links go active according to scroll. Get to the bottom of the page "Contact Us" goes active. Scroll up to the 'quote' div but "Get A Quote" doesn't go active. Scroll past it, all the others work, scroll back down and "Get A Quote" goes active again.

Here is my full code

Javascript

<script type='text/javascript'>//<![CDATA[
window.onload = function(){

// Cache selectors
var lastId,
topMenu = $("#top-menu"),
topMenuHeight = topMenu.outerHeight()+15,
// All list items
menuItems = topMenu.find("a"),
// Anchors corresponding to menu items
scrollItems = menuItems.map(function(){
var item = $($(this).attr("href"));
if (item.length) { return item; }
});

// Bind click handler to menu items
// so we can get a fancy scroll animation
menuItems.click(function(e){
var href = $(this).attr("href"),
offsetTop = href === "#" ? 0 : $(href).offset().top-topMenuHeight+1;
$('html, body').stop().animate({
scrollTop: offsetTop
}, 300);
e.preventDefault();
});

// Bind to scroll
$(window).scroll(function(){

// Get container scroll position
var fromTop = $(this).scrollTop()+topMenuHeight;

// Get id of current scroll item
var cur = scrollItems.map(function(){
if ($(this).offset().top < fromTop)
return this;
});

// Get the id of the current element
cur = cur[cur.length-1];
var id = cur && cur.length ? cur[0].id : "";

if (lastId !== id) {
lastId = id;
// Set/remove active class
menuItems
.parent().removeClass("active")
.end().filter("[href='#"+id+"']").parent().addClass("active");
}
});

$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()) {
$(".contactive").addClass('active');
$('a[href="#quote"]').parent('li').parent('li').removeClass('active');
}
else {
$(".contactive").removeClass('active');
}
});
}//]]>
</script>


HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="header">

<div id="navbar">
<div id="logo">
<img src="logosmall.png">
</div>
<ul id="top-menu">
<li class="active">
<a href="#home">Home</a>
</li>
<li>
<a href="#services">Services</a>
</li>
<li>
<a href="#moving">Moving Tips</a>
</li>
<li>
<a href="#quote">Get A Quote</a>
</li>
<li class="contactive">
<a href="#contact">Contact Us</a>
</li>
</ul>
</div>
</div>

<div id="home">
Content Here.
</div>

<div id="services">
<div id="servicesleft"></div>
<div id="servicesmain">
<div id="movessec">
Content Here.
</div>

<div id="movessec">
Content Here.
</div>

<div id="movessec">
Content Here.
</div>
</div>
<div id="servicesright"></div>
</div>


<div id="moving">Content here.</div>

<div id="quote">Quote form goes here.</div>

<div id="contact">
<div id="contactleft">Content Here</div>
<div id="contactmain">Content Here</div>
<div id="contactright">Content Here</div>
</div>


</body>

Answer

You are making a special case for the "quote" section by removing its "active" class when you hit the bottom of the page (to make the contact us form active, even though the scroll height hasn't reached it, and can't because it's the end of the page).

However, you aren't then making that section active again if the height isn't at the bottom. i.e. you've forgotten to do the opposite of your original special case.

Actually though, you can simplify the code a little bit and make it less of a special case (not relying on "quote" being the next-to-last item):

// Bind to scroll
$(window).scroll(function(){

    // Get container scroll position
    var fromTop = $(this).scrollTop()+topMenuHeight;

    // Get id of current scroll item
    var cur = scrollItems.map(function(){
        if ($(this).offset().top < fromTop)
            return this;
    });

    // Get the id of the current element
    cur = cur[cur.length-1];
    var id = cur && cur.length ? cur[0].id : "";

    if (lastId !== id) {
        menuItems.parent().removeClass('active');
        lastId = id;
    }

    //special case for "contact us" section at bottom of page
    if($(window).scrollTop() + $(window).height() == $(document).height()) {
        menuItems.parent().removeClass("active");
        $(".contactive").addClass('active');
    }
    else {
        $(".contactive").removeClass('active');
        $("[href='#"+id+"']").parent().addClass('active');
    }
});
Comments