2

I am using http://jsfiddle.net/mekwall/up4nu/ for my scrolling on a one pager. How would I deactivate the current marking when a menu item is clicked? I want to keep it on scroll. But when I am on the first item and click the fourth one, I just want the fourth one to mark current, with no marking "sliding" through second and third item.

I also tried the onePageNav, but it breaks if I have a subpage that doesn't have content (section with id) on the landing page.

SliverNinja - MSFT
  • 31,051
  • 11
  • 110
  • 173
user980902
  • 43
  • 1
  • 8

1 Answers1

2

This should work :) I added a noScrollAction variable. I set it before the scrolling animation starts and disable it when it's ended. But the window scroll still fires after the animation is over (haven't figured out why yet). So I put an extra delay on it. And set the active class for the right anchor.

// 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; }
    }),
    noScrollAction = false;

// 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;
    noScrollAction = true;
    $('html, body').stop().animate({ 
        scrollTop: offsetTop
    },{
        duration: 300,
        complete: function() {
            menuItems
                .parent().removeClass("active")
                .end().filter("[href=" + href +"]").parent().addClass("active");
            setTimeout(function(){ noScrollAction = false; }, 10);
        }
    });
    e.preventDefault();
});

// Bind to scroll
$(window).scroll(function(){
   if(!noScrollAction){
       // 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");
       }
   }    
});​
VDP
  • 6,340
  • 4
  • 31
  • 53
  • Great! It works. Maybe just one more thing. Can the current be added to the menu item when it's clicked? So that during the scrolling the new current item would be marked and not the old one? Thank you very much!! – user980902 Sep 17 '12 at 12:14
  • So you wan't the active class set before the animation starts in staid of at the end? Just move that piece of code. Here is a [fiddle](http://jsfiddle.net/Vandeplas/up4nu/150/) (Btw: welcome to stackoverflow, if you think this answer is what you were looking for you can [accept](http://meta.stackexchange.com/a/5235) it ;)) – VDP Sep 17 '12 at 12:20