2015-04-29 2 views
3

Я пытаюсь реализовать навигацию по документу, аналогичную той, что находится на сайте Bootstrap для их документации. У меня это работает в целом, но есть один маленький аспект этого, который подслушивает меня.event.preventDefault() Причинение: hover pseudo class to stick

Как и в Bootstrap, я использую комбинацию affix.js и scrollSpy.js, и это работает. См. Следующее: JSFiddle.

 $('#doc_nav').on("click", "a", function(e){ 
//   e.preventDefault(); 
      var target = this.hash; 
      var $target = $(target); 
      var offset = $target.offset().top; 
      console.log(offset); 
      offset = offset - 100; 
      console.log(offset); 

      $('html, body').scrollTop(offset); 


     }); 

С e.preventDefault() закомментированного, поведение навигации меню, как и ожидалось. Прокрутка окна приводит к тому, что отображаемый div выделяется в меню. Нажав на элемент в списке меню, вы перейдете непосредственно к соответствующему div на странице, а затем, когда вы прокрутите прочь от этого раздела на странице, меню обновится соответствующим образом.

На моей «реальной» странице у меня есть фиксированный заголовок высотой 100 пикселей. Так что в настоящее время, когда я нажимаю ссылку на меню, страницы перескакивают в требуемый раздел и помещают его в верхнюю часть страницы, где заголовок слегка скрывает его. Часть scrollTop вышеприведенного кода не работает, если я не использую e.preventDefault(). Если вы раскомментируете эту строку на скрипке и запустите ее снова, нажмите ссылку «Заголовок 3» в меню, и вы увидите, что теперь она помещает содержимое заголовка 3 в страницу смещения на 100 пикселей сверху. Отлично.

Однако теперь прокрутите страницу назад вверх. Вы увидите, что элемент списка «Заголовок 3» остается в состоянии «зависания», даже когда мышь не находится рядом с ним. Как будто e.preventDefault() помешало браузеру обнаружить, что мышь больше не зависает над элементом.

Взаимодействие в любом месте за окном браузера устраняет проблему.

Может ли кто-нибудь пролить свет на то, что я делаю неправильно здесь? Как я могу предотвратить поведение по умолчанию для привязки, чтобы я мог контролировать размещение прокрутки страницы, не останавливая правильную рисование CSS в этом процессе?

Проблема возникает из-за того, что я предотвращаю поведение браузеров по умолчанию, используя e.preventDefault(), так как я хочу управлять прокруткой к привязанному элементу.

Я тестировал это в Firefox и IE10.

ответ

4

Вопрос не о состоянии :hover, а состоянии :focus.

Когда вы нажимаете на ссылку, эта ссылка получает фокус, поэтому вы применяете стиль :focus (то же самое, что и стиль :hover в вашем коде). Предотвращая поведение по умолчанию, эта ссылка остается активной и не теряет фокуса.

Одним быстрым решением было бы сфокусировать/размыть элемент, используя: $(this).blur().

В вашем коде будет выглядеть следующим образом:

$('#doc_nav').on("click", "a", function(e){ 
     e.preventDefault(); 
     var target = this.hash; 
     var $target = $(target); 
     var offset = $target.offset().top; 
     console.log(offset); 
     offset = offset - 100; 
     console.log(offset); 
     $(this).blur(); 
     $('html, body').scrollTop(offset); 
    }); 

Вы можете посмотреть демо здесь: https://jsfiddle.net/z32rpe3b/30/


Почему это работает отлично с e.preventDefault() но неправильно без него?

Ответ на этот вопрос связан с порядком исполнения. onclick событие происходит до того, как href Перенаправление происходит в браузере:

  • Без e.preventDefault(), код выполняется, а браузер корректно прокручиваются в целевое положение offset - 100onclick), но затем он выполнил ссылку href и прокручивается до цели offset. Это происходит так быстро, что кажется, что он переходит непосредственно в целевую позицию.
  • С e.preventDefault() код выполнен (прокрутка до offset - 100), и браузер не выполняет действие href (поэтому он остается в offset - 100).
+0

Hi Alvaro. Благодарю. Я пинаю себя так просто! Я был зациклен на том, что это псевдо-класс: hover, я пропустил: фокус. Можете ли вы ответить на другую часть головоломки, почему scrollTop() не работал, если я не использовал e.preventDefault()? – Boidy

+1

Это связано с порядком выполнения событий. Я обновил свой ответ и объяснил, почему это произошло. –