Закрытие одного элемента при открытии другого в том же цикле с использованием Javascript - PullRequest
0 голосов
/ 07 ноября 2018

здесь впервые, поэтому я постараюсь объяснить, что я спрашиваю.

Итак, у меня есть 3 элемента списка с одинаковым именем класса. Я поместил их в функцию зацикливания, чтобы при нажатии на нее отображался поднабор элементов списка для этого конкретного элемента списка. У меня также есть они внутри оператора if, который добавляет новое имя класса к определенному элементу списка, по которому щелкнули. Это позволяет открывать и закрывать элементы подсписка при нажатии на соответствующий родительский элемент.

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

Это то, что я придумал, но он не знает, что такое кнопка [i], когда я включаю ее в функцию «щелчка». То, что я пытался сделать с этим кодом, это взять любой элемент списка, по которому щелкнули, а затем проверить предыдущую и следующую итерации имени «кнопки» имени класса, чтобы увидеть, содержит ли какой-либо из них также имя класса «нажал».

HTML

  <div class="main">
    <ul>                
      <li><a href="#" class="button">One</a>
           <ul>
             <li><a href="#">One-1</a></li>
             <li><a href="#">One-2</a></li>
          </ul>
      </li>
       <li><a href="#" class="button">Two</a>
           <ul>
             <li><a href="#">Two-1</a></li>
             <li><a href="#">Two-2</a></li>
          </ul>
      </li>
           <li><a href="#" class="button">Three</a>
           <ul>
             <li><a href="#">Three-1</a></li>
             <li><a href="#">Three-2</a></li>
          </ul>
      </li>
    </ul>
  </div>

CSS

.main ul ul {
    display: none;
}

.main ul ul li {
    display: block;
}

Javascript

var button = document.getElementsByClassName("button");

for (i = 0; i < button.length; i++) {

    button[i].addEventListener("click", function() {

        var prevItem = button[i - 1];
        var nextItem = button[i + 1];

        if (prevItem.className !== "button") {
            prevItem.className = "button";
            prevItem.nextElementSibling.style.display = "none";
        }

        if (nextItem.className !== "button") {
            nextItem.className = "button";
            nextItem.nextElementSibling.style.display = "none";
        }

        if (this.className === "button") {
            this.className += " clicked";
            this.nextElementSibling.style.display = "block";
        }
    });
}

Я хочу, чтобы этот код можно было использовать независимо от того, сколько элементов списка вы добавили. Так что проверять в точности кнопку [0], кнопку [1] и кнопку [2] на самом деле не вариант, но я вижу, как кнопка [i + 1] может проверять не каждый элемент списка после него, а только следующий. Я попытался добавить еще один цикл, но столкнулся с похожими проблемами. во всяком случае, поэтому я здесь. Спасибо за любую помощь заранее.

1 Ответ

0 голосов
/ 07 ноября 2018

Поскольку я не уверен, правильно ли я понял ваш вопрос, я быстро перефразирую его своими словами.

Вопрос: «У меня есть произвольное количество элементов списка, каждый из которых содержит кнопку и вложенный список. Кнопка всегда отображается, вложенный список по умолчанию скрыт. Когда пользователь нажимает на кнопку, соответствующий должен быть показан вложенный список. В то же время все остальные показанные вложенные списки должны быть снова скрыты. Как мне этого добиться? "

Оригинальный HTML выглядит нормально:

<div class="main">
  <ul>                
    <li><a href="#" class="button">One</a>
      <ul>
        <li><a href="#">One-1</a></li>
        <li><a href="#">One-2</a></li>
      </ul>
    </li>
    <li><a href="#" class="button">Two</a>
      <ul>
        <li><a href="#">Two-1</a></li>
        <li><a href="#">Two-2</a></li>
      </ul>
    </li>
    <li><a href="#" class="button">Three</a>
      <ul>
        <li><a href="#">Three-1</a></li>
        <li><a href="#">Three-2</a></li>
      </ul>
    </li>
  </ul>
</div>

CSS я не до конца понял, но предлагаю следующее:

.main ul ul {
  display: none;
}

.main li.is-active ul {
  display: block;
}

.main ul ul li {
  display: block;
}

При добавлении класса is-active к элементу LI он отображается. Таким образом, CSS контролирует видимость.

Для части JavaScript я предлагаю следующее:

const buttonElements = Array.from(document.querySelectorAll('.button'));
buttonElements.forEach(buttonElement => {
  buttonElement.addEventListener('click', () => { 
    const activeElements = Array.from(document.querySelectorAll('.is-active'));
    activeElements.forEach(activeElement => {
      activeElement.classList.remove('is-active');
    });
    buttonElement.parentElement.classList.add('is-active');
  });
});

В этом решении предполагается, что вы можете использовать более новые версии JavaScript / ECMAScript. В целом, он использует функции const и arrow.

Во-первых, мы получаем все элементы с классом «кнопка» с помощью document.querySelectorAll () . Поскольку в результате получается NodeList без массива, мы конвертируем его с помощью Array.from () . После этого мы перебираем массив с помощью Array.prototpye.forEach () . Мы добавляем прослушиватель событий для события «click». Когда кнопка нажата, мы ищем все элементы с классом is-active и для каждого удаляем ее. Наконец, мы добавляем класс is-active к родительскому элементу нажатой кнопки, используя Node.prototype.parentElement () .

Вот еще одно решение, которое работает в старых браузерах:

var buttonElements = document.getElementsByClassName('button');
for (var i = 0; i < buttonElements.length; i++) {
  buttonElements[i].addEventListener('click', function(event) { 
    var activeListElements = document.getElementsByClassName('is-active');
    for (var i = 0; i < activeListElements.length; i++) {
      activeListElements[i].setAttribute('class', '');
    }
    event.target.parentNode.setAttribute('class', 'is-active');
  });
}

Это почти то же самое, что и другой подход, но работает со старыми версиями JavaScript.

Как правило, идея состоит в том, чтобы сосредоточиться на произвольной сумме элементов вместо массива с определенной длиной. На естественном языке что-то вроде: «Дайте мне все кнопки. Для каждой кнопки добавьте прослушиватель событий. Когда нажата кнопка, дайте мне все активные элементы списка и удалите их активный статус. Затем отметьте элемент списка над кнопкой как активный ».

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...