Как я могу пройти вверх по дереву, чтобы добавить «активный» класс к моему меню на кнопках в зависимости от местоположения сайта пользователя?

Я пытаюсь сделать кнопки «меню на», которые выделяют, когда пользователь находится в определенной папке. Примеры есть на S.O. это помогло мне, но мне нужно пройти вверх по дереву, чтобы установить «активный» класс.

var current = location.pathname;

$('nav dl dt a').each(function(){
   var $this = $(this);
   // if the current path is like this link, make it active
   if($this.attr('href').indexOf(current) !== -1){
       ($this).parents('nav dl dt').addClass('menuOn');
   }
});

Мне нужно пройти из-за моей структуры HTML:

var current = location.pathname;

$('nav dl dt a').each(function() {
  var $this = $(this);
  // if the current path is like this link, make it active
  // Commenting following condition for testing.
  //if($this.attr('href').indexOf(current) !== -1){
  ($this).parents('nav dl dt').addClass('menuOn');
  //}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<div id="menuWrapper">
  <nav id="nav">
    <div id="menuArea">
      <dl class="menuAreas">
        <dt class="menuButtonHolder" id="menu0">
            <a class="menuButton" href='/'>
                <span class="menuTitleWrapper home">
                    <span class="menuTitle"><i class="fa fa-home" aria-hidden="true"></i>Home</span>
                </span>
            </a>
        </dt>
        <dt class="menuButtonHolder" id="menu1">
            <a class="menuButton" href='/books'>
                <span class="menuTitleWrapper">
                    <span class="menuTitle"><i class="fa fa-book" aria-hidden="true"></i>Books</span>
                </span>
            </a>
        </dt>
        <dt class="menuButtonHolder" id="menu2">
            <a class="menuButton" href='/resources'>
                <span class="menuTitleWrapper">
                    <span class="menuTitle"><i class="fa fa-book" aria-hidden="true"></i>Resources</span>
                </span>
            </a>
        </dt>
      </dl>
    </div>
  </nav>
</div>

У меня забавное ощущение, что именно эта строка ему не нравится, хотя в моей консоли нет ошибок.

($this).parents('nav dl dt').addClass('menuOn');

.parents(.selector-here).addClass. . . - правильный способ сделать это, не так ли?

В вашем DOM вы пишете div, но в jquery ваш селектор в первой строке начинается с nav, преднамеренно или по ошибке?

Sujit Agarwal 10.08.2018 14:42

@SujitAgarwal Он завернут в nav, да. Я обновил свой код. :-)

cmp 10.08.2018 14:45

Ответил. Пожалуйста, попробуйте.

Sujit Agarwal 10.08.2018 14:47

Если вы запустите рассматриваемый код, он работает нормально. Для проверки логики ($this).parents('nav dl dt').addClass('menuOn'); прокомментировал состояние if и проверил. он работает, как ожидалось. Вы можете проверить это с помощью элемента проверки из браузера.

Karan 10.08.2018 17:37
0
4
38
2

Ответы 2

Вы можете использовать closest, чтобы найти ближайший dt -

var current = location.pathname;

$('nav dl dt a').each(function(){
   var $this = $(this);
   // if the current path is like this link, make it active
   if($this.attr('href') == ('/' + current)){
       $(this).closest('dt').addClass('menuOn');
   }
});

Спасибо! Когда я нахожусь на домашней странице /, все они имеют menuOn, но когда я нахожусь на отдельных страницах, /books/, /resources/ и т. д. menuOn не применяется? Есть ли причина, по которой это может быть так?

cmp 10.08.2018 14:55

Я добавил небольшое изменение в условие if. пожалуйста, проверьте

Sujit Agarwal 10.08.2018 14:56

Это хороший вариант использования filter().

Обратите внимание, что элементы <a> также имеют свойство pathname, такое же, как и location, что позволяет проводить сравнение на предмет равенства.

Затем найдите closest('dt') в отфильтрованной коллекции.

$('nav dl dt a').filter(function(){
   return this.pathname === location.pathname;  
}).closest('dt').addClass('menuOn');

Демо с использованием жесткого кода переменная location.pathname

Разве это не должно быть return this.href === current?

Sujit Agarwal 10.08.2018 14:57

@SujitAgarwal нет, потому что сейчас это pathname, а не href. <a> имеет те же свойства, что и местоположение

charlietfl 10.08.2018 14:58

но функция фильтра установит this на текущий отображаемый тег привязки из селектора? Я что-то здесь неправильно понимаю?

Sujit Agarwal 10.08.2018 14:59

если это верно, то текущее значение this является тегом привязки, поэтому нам нужно получить доступ к значению href привязки, а не к имени пути, я прав?

Sujit Agarwal 10.08.2018 15:02

Понятно. Я совершенно забыл, что теги привязки также имеют свойство pathname. : D моя плохая

Sujit Agarwal 10.08.2018 15:05

@SujitAgarwal Правильно ... я уже говорил, что <a> имеет те же свойства, что и location. Многие люди не осознают этого, потому что вы используете их не очень часто и можете делать другие вещи для выполнения той же задачи.

charlietfl 10.08.2018 15:07

Большое спасибо @charlietfl. Есть ли простой способ применить это правило к первой папке. Например, если у меня был /books/best-sellers.aspx, на кнопке не отображается menuOn, могу ли я использовать .split("/")[1] или аналогичный? Еще раз спасибо!

cmp 10.08.2018 15:18

@cmp Может добавлять любую логику внутрь фильтра и возвращать логическое значение. Текущий подход, безусловно, самый простой случай. Так могло бы быть что-то вроде if(this.pathname.includes('best-sellers')){ return false;}else(return this.pathname === location.pathname;}

charlietfl 10.08.2018 15:19

Другие вопросы по теме