2015-03-25 1 views
0

Я создаю длинную страницу с навигацией с привязными ссылками. Когда вы прокрутите страницу вниз, соответствующая ссылка на навигаторе будет подсвечена, чтобы соответствовать разделу, в котором вы находитесь.Текущий раздел не правильно подсвечивается в навигаторе при прокрутке

Это нормально работает, однако у меня также есть раздел на странице, на которой нет якорной ссылки на nav. Проблема состоит в том, что, добавив этот раздел, он разрушает мой порядок раздела, который разрушает правильное выбранное состояние.

Вот код, чтобы показать вам пример. http://codepen.io/anon/pen/jEdKBp - Обратите внимание, что при прокрутке вниз до «нового раздела» ссылка «претензии» в навигаторе подсвечивается, что неверно!

Что мне нужно для того, чтобы подсвечивалась только текущая ссылка?

Вот мой код ...

HTML

<nav id="prod-menu"> 
    <div class="wrapper"> 
     <ul> 
     <li><a href="#features">Features</a></li> 
     <li><a href="#claims">Claims</a></li> 
     <li><a href="#guides">Guides</a></li> 
     <li><a href="#reviews">Reviews</a></li> 
     <li><a href="#faq">FAQs</a></li> 
     </ul> 
    </div> 
</nav> 


<section class="prod-hero"></section> 

<div class="wrapper"> 

    <section class="tile js-panel pad0">   

     <section id="features" class="prod-panels"> 
      <h2>Features</h2> 
     </section> 

    <section class="prod-panels"> 
      <h2>New section</h2> 
    <p>I do not want this section to appear in the nav</p> 
     </section> 

     <section id="claims" class="prod-panels"> 
      <h2>Claims</h2> 
     </section> 

     <section id="guides" class="prod-panels"> 
      <h2>Guides</h2> 
     </section> 

     <section id="reviews" class="prod-panels"> 
      <h2>Reviews</h2> 
     </section> 

     <section id="faq" class="prod-panels"> 
      <h2>FAQs</h2> 
     </section> 

    </section> 
</div> 

JQuery

var homeH = $(window).height(), 
    pH = []; 
pH.push("0"); 

// create array with panel heights 
for (var s=1; s<5; s++) { 
    var po = $(".js-panel section:nth-child("+s+")").position(); 
    pH.push(Math.round(po.top)); 
}; 

$(window).scroll(function() {  

    // toggle top menu selection 
    for (var i=0;i<6;i++) { 
    if ($(window).scrollTop() > pH[i]+900) { 
     $("#prod-menu ul li").removeClass("sel"); 
     $("#prod-menu ul li:nth-child("+(i+1)+")").addClass("sel"); 
    } 
    }; 

}); 

ответ

2

Я тоже решил взять удар. Мне нравится приближаться к подобным вещам с гибкостью в виду, удаляя жестко закодированные значения, где я могу, и принимая во внимание динамический поток страниц. В моей вилке вместо использования класса на панелях, которые вы хотите связать с верхней навигацией, я использую идентификаторы href и панели для использования ссылки, подразумеваемой этими сопоставлениями.

var navPanels = $(); 
$('#prod-menu a').each(function() { 
    navPanels = navPanels.add($(this.hash)); // easy array of nav panels according to nav items 
}); 

Используя этот подход, вы можете просто добавить или вычесть навигационные элементы и панели без дополнительных классов. Кроме того, если они меняют высоту или перемещаются, потому что другой элемент над ними в стеке вызывает изменение смещения, наличие массива offset(). Верхние значения с самого начала будут несовпадающими при прокрутке, поэтому это будет проверено на прокрутке. Проверка смещения становится:

navPanels.each(function() { 
    var $p = $(this) // current panel in loop 

    if ($(window).scrollTop() + $('#prod-menu').outerHeight() >= $p.offset().top) { 
     $("#prod-menu ul li").removeClass("sel"); 
     $('#prod-menu a').filter('[href="#'+$p.attr('id')+'"]').parent().addClass("sel"); 
    } 
}); 

Я также учет высоты птичьего полета нав по всему сценарию, так что будет выделен ваш пункт нав когда раздел свитка мимо видимую области, которая начинается под верхней навигационной панелью.

Этот подход не делает, это удаление выделения для раздела, который вы не хотите показывать в навигационном режиме. Вместо этого он просто покидает навигацию до ее выделения.

Это полный JS:

$(function() { 
    var homeH = $(window).height(), 
     navPanels = $(); 

    $('#prod-menu a').each(function() { 
     navPanels = navPanels.add($(this.hash)); // easy array of nav panels according to nav items 
    }); 

    $(window).scroll(function() { 
     // toggle top menu 
     if ($(window).scrollTop() < homeH/2) { 
      $("#prod-menu ul li").removeClass("sel"); 
      $("#prod-menu").css("top", ($('#prod-menu').outerHeight()*-1)); 
     } 
     else { 
      $("#prod-menu").css("top", "0"); 
     }; 

     // toggle top menu selection 
     navPanels.each(function() { 
      var $p = $(this) // current panel in loop 

      if ($(window).scrollTop() + $('#prod-menu').outerHeight() >= $p.offset().top) { 
       $("#prod-menu ul li").removeClass("sel"); 
       $('#prod-menu a').filter('[href="#'+$p.attr('id')+'"]').parent().addClass("sel"); 
      } 
     }); 
    }); 

    // animating anchor link scrolling 
    // snippet from css-tricks 
    // css-tricks.com/snippets/jquery/smooth-scrolling 
    $("a[href*=#]:not([href=#])").click(function() { 
     if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) { 
      var target = $(this.hash); 
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']'); 
      if (target.length) { 
       $('html,body').animate({ 
        scrollTop: target.offset().top-$('#prod-menu').outerHeight() 
       }, 700); 
       return false; 
      } 
     } 
    }); 
}); 

полное фирменное перо здесь: http://codepen.io/anon/pen/MYNmbb

EDIT: Мне скучно, поэтому я решил остановиться на этом. Если вы хотите, чтобы навигатор не высвечивался, когда вы переходите в раздел, который не находится на навигационной панели, вы можете изменить функцию «выбрать верхний экран меню» на следующее, которое проверяет нижнюю часть панели относительно области просмотра:

// toggle top menu selection 
navPanels.each(function() { 
    var $p = $(this) // current panel in loop 
    var viewTop = $(window).scrollTop() + $('#prod-menu').outerHeight(); 
    if (viewTop >= $p.offset().top) { 
     $("#prod-menu ul li").removeClass("sel"); 
     if ($p.offset().top + $p.outerHeight() > viewTop) { 
      $('#prod-menu a').filter('[href="#'+$p.attr('id')+'"]').parent().addClass("sel"); 
     } 
    } 
}); 

Затем, когда вы переходите в раздел, не находящийся на nav, ничто не подсвечивается до тех пор, пока вы не нажмете другой раздел на nav.

Опять же, полная ручка видна здесь: http://codepen.io/anon/pen/emqWEW

+0

Спасибо за это. Я проголосовал за это как лучший ответ, так как это был наименьший код, и вам также удалось снять подсветку с раздела, который не находится на борту. Я даже не спрашивал об этом, но думал об этом! – Adam

+0

Это было веселое отвлечение. Мне было скучно прошлой ночью, и мне хотелось что-то сделать, спасибо за сообщение вопроса. – Daved

4

Я изменил некоторые биты в коде, и я надеюсь, что это: http://codepen.io/anon/pen/pvmXgK является то, что вы хотите иметь.

Во-первых, я изменил эту строку:

var po = $(".js-panel section:nth-child("+s+")").position();

к

var po = $(".js-panel section.nav-section:eq("+s+")").offset();

и добавил класс nav-section ко всем HTML разделов, которые должны являются частью навигации ,

Функциональность переключения теперь разделена на два для петель, но это может быть необязательно. ;)

Весь код (без CSS части) HTML:

<nav id="prod-menu"> 
    <div class="wrapper"> 
    <ul> 
     <li><a href="#features">Features</a></li> 
     <li><a href="#claims">Claims</a></li> 
     <li><a href="#guides">Guides</a></li> 
     <li><a href="#reviews">Reviews</a></li> 
     <li><a href="#faq">FAQs</a></li> 
    </ul> 
</div> 
</nav> 


<section class="prod-hero"></section> 
<div class="wrapper"> 
    <section class="tile js-panel pad0">   
     <section id="features" class="nav-section prod-panels"> 
     <h2>Features</h2> 
     </section> 
     <section class="prod-panels"> 
      <h2>New section</h2> 
      <p>I do not want this section to appear in the nav</p> 
     </section> 

     <section id="claims" class="nav-section prod-panels"> 
      <h2>Claims</h2> 
     </section> 
     ....  

    </section> 
</div> 

JS:

var homeH = $(window).height(), 
pH = []; 
var clicked = false; 
// create array with panel heights 
for (var s=0; s<5; s++) { 
    var po = $(".js-panel section.nav-section:eq("+s+")").offset(); 
    pH.push(Math.round(po.top)); 
}; 
$(window).scroll(function() { 
if (clicked === true) { 
    return; 
} else if (clicked == "fuzzy") { 
    clicked = false; 
    return; 
} 
// toggle top menu 
if ($(window).scrollTop() < homeH/2) { 
    $("#prod-menu ul li").removeClass("sel"); 
    $("#prod-menu").css("top", "-55px"); 
} else { 
    $("#prod-menu").css("top", "0"); 
}; 
$("#prod-menu ul li").removeClass("sel"); 

// toggle top menu selection 
var st = $(window).scrollTop(); 
for (var i=4;i>=0;i--) { 
    if (st > pH[i]) { 
    $("#prod-menu ul li:eq("+i+")").addClass("sel"); 
    break; 
    } 
}; 

}); 

// animating anchor link scrolling 
// snippet from css-tricks 
// css-tricks.com/snippets/jquery/smooth-scrolling 

$("a[href*=#]:not([href=#])").click(function() { 
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) { 
    var liEle = $(this).parent("li"); 
    var target = $(this.hash); 

    target = target.length ? target : $('[name=' + this.hash.slice(1) +']'); 
    if (target.length) { 
     clicked = true; 
     $('body').animate({ 
     scrollTop: target.offset().top-50 
     }, 700, function() { 
     clicked = "fuzzy"; 
     $("#prod-menu ul li").removeClass("sel"); 
     liEle.addClass("sel"); 
     }); 

    return false; 
    } 
} 
}); 
+0

Благодаря Wikunia это очень близко. Он отлично работает при прокрутке, однако, когда вы нажимаете на привязные ссылки, выбирается предыдущая ссылка. Например, если я нажму «обзоры», тогда «проводники» будут показаны как выбранное состояние. Есть ли способ исправить это? – Adam

+0

Hi @Adam действительно не любимое решение, но это нужно исправлять прямо сейчас! Не знаю, как сделать это лучше, но должен быть лучший способ: D – Wikunia

+1

Попробуйте следующее: http://codepen.io/anon/pen/OPeMEq. Я немного изменил код Викунии. – Romeo

2

я раздвоенный свой код ручку, пытался использовать другой подход

http://codepen.io/anon/pen/myNRzR

var homeH = $(window).height(), 
    pH = new Array(); 

// create array with panel heights 

    $(".js-panel section").each(function(){ 
     var elm = $(this); 
     var po = elm.position(); 
     pH.push({ 
     top : Math.round(po.top), 
     element : elm 
     }); 
    }); 


pH.sort(function(a, b) { 
    if (a.top > b.top) 
     return -1; 
    if (a.top < b.top) 
     return 1; 
    // a doit être égale à b 
    return 0; 
}); 
var ord = { 
    hasScrolled : true, 
    locked : false 
}; 
var ticker = function(){ 

    if(ord.hasScrolled){ 
    var menu = $("#prod-menu"),   
    actTop = $(window).scrollTop(), 
    level = actTop + menu.height(); 
    ord.locked = true; 
    ord.hasScrolled = false; 
    for(var i in pH){ 
     var o = pH[i]; 

     if(level > o.top && level < (o.top + o.element.height())){ 
     menu.css("top", "0"); 
     $("#prod-menu ul li").removeClass("sel"); 
     $("#prod-menu").find("a[href='#"+ o.element.attr("id") +"']").parent().addClass("sel"); 
     break; 
     } 
    } 





    ord.locked = false; 
    } 
} 

setInterval(ticker, 250); 

$(window).scroll(function() { 
ord.hasScrolled = true && !ord.locked; 
    // toggle top menu 


}); 

// animating anchor link scrolling 
// snippet from css-tricks 
// css-tricks.com/snippets/jquery/smooth-scrolling 

$("a[href*=#]:not([href=#])").click(function() { 
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) { 
     var target = $(this.hash); 
     target = target.length ? target : $('[name=' + this.hash.slice(1) +']'); 
     if (target.length) { 
     $('html,body').animate({ 
      scrollTop: target.offset().top-50 
     }, 700); 
     return false; 
     } 
    } 
    }); 

с помощью тикера вместо onScrollEvent: он работает нормально.

Было бы лучше, если вы обернете все это в плагине.

Смежные вопросы