Актуализиране на хеша на прозореца на адресната лента със scrollspy

Имам меню със scrollspy (с помощта на twitter boostrap). Искам да актуализирам window.location.hash, когато потребителят превърти надолу до следващия раздел.

Следният код работи, когато потребителят превърта надолу:

$(window).on('activate.bs.scrollspy', function (e) {
  location.hash = $("a[href^='#']", e.target).attr("href") || location.hash;
});

Въпреки това не работи много добре, когато потребителят превърта нагоре.

Причината за това е, че задаването на нов location.hash задейства браузъра да навигира към съответната котва. Това предизвиква верижна реакция, при която потребителят моментално ще се озове в горната част на страницата.

Демонстрация в js-fiddle

Какъв би бил най-простият начин за решаване на този проблем?


person d_inevitable    schedule 14.04.2014    source източник


Отговори (3)


Възможно е да промените състоянието на URL адреса с HTML5 история, без да задействате браузъра да следва новото състояние. Това не се поддържа от всички браузъри.

Използването на history.replaceState() има допълнителното предимство, че когато потребителят използва бутона за връщане назад на браузъра, той няма просто да превърти първо нагоре.

$(window).on('activate.bs.scrollspy', function (e) {
    history.replaceState({}, "", $("a[href^='#']", e.target).attr("href"));
});

Вижте работещия js-fiddle.

person d_inevitable    schedule 15.04.2014

За повече актуализация на хеша за различни браузъри можете да използвате този JS:

$(window).on('activate.bs.scrollspy', function(e) {
  var $hash, $node;
  $hash = $("a[href^='#']", e.target).attr("href").replace(/^#/, '');
  $node = $('#' + $hash);
  if ($node.length) {
    $node.attr('id', '');
  }
  document.location.hash = $hash;
  if ($node.length) {
    return $node.attr('id', $hash);
  }
});

Той премахва временно търсения хеш, след което го добавя чрез window.location и след това възстановява въпросния хеш. За съжаление не знам точния диапазон на съвместимост за това решение, но IE9 се поддържа със сигурност и вероятно всички по-стари версии на IE също (не ме интересуват по-старите браузъри в моите проекти, така че не съм тествал това решение).

person jmarceli    schedule 09.01.2015
comment
Бих подобрил това, като използвам location.replace, така че да не спамите историята на потребителите с това. - person Nemo64; 22.09.2015
comment
Доколкото знам location.replace ще презареди страницата, което не е желателно поведение. - person jmarceli; 28.01.2017
comment
Поведението е идентично с това при щракване върху връзка. Но можем просто да опитаме ;). Просто изпълнете location.replace('#foo') и URL адресът ще се промени, докато страницата няма да се презареди. - person Nemo64; 13.02.2017

Използвам това за Bootstrap v4:

$(window).on('activate.bs.scrollspy', function(e) {
    history.replaceState({}, "", $('.nav-item .active').attr("href"));
});
person Someone    schedule 17.01.2018