Измените атрибут CSS с помощью нескольких кнопок Javascript

#javascript #html #css

#javascript #HTML #css

Вопрос:

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

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

HTML

 <article class="questions">
            How many team members can I invite?
            <img src="images/icon-arrow-down.svg" alt="arrow" class="arrow" id="down-arrow">
            <hr>
            <detail id="answer">
              You can invite up to 2 additional users on the Free plan. There is no limit on 
              team members for the Premium plan.
            </detail>
          </article>  

          <article class="questions">
            What is the maximum file upload size?
            <img src="images/icon-arrow-down.svg" alt="arrow" class="arrow" id="down-arrow">
            <hr>
            <detail id="answer">
              No more than 2GB. All files in your account must fit your allotted storage space.
            </detail>
          </article>  

          <article class="questions">
            How do I reset my password?
            <img src="images/icon-arrow-down.svg" alt="arrow" class="arrow" id="down-arrow">
            <hr>
            <detail id="answer">
              Click “Forgot password” from the login page or “Change password” from your profile page.
              A reset link will be emailed to you.
            </detail>
          </article> 

          <article class="questions">
            Can I cancel my subscription?
            <img src="images/icon-arrow-down.svg" alt="arrow" class="arrow" id="down-arrow">
            <hr>
            <detail id="answer">
              Yes! Send us a message and we’ll process your request no questions asked.
            </detail>
          </article>

          <article class="questions">
            Do you provide additional support?
            <img src="images/icon-arrow-down.svg" alt="arrow" class="arrow" id="down-arrow">
            <hr>
            <detail id="answer">
              Chat and email support is available 24/7. Phone lines are open during normal business hours.
            </detail>
 

CSS — код

 #answer{
   display: none; 
}
 

Javascript

 document.getElementById('down-arrow').addEventListener("click", toggleAnswers);
const arrow = document.getElementById('down-arrow')
const current = document.getElementById("answer");
function toggleAnswers(){
    current.style.display = "inline";
    arrow.style.transform = "scaleY(-1)";
}
 

Список часто задаваемых вопросов

Комментарии:

1. НЕ используйте повторяющиеся идентификаторы. Как только происходит умножение одного идентификатора, они больше не являются идентификаторами и document.getElementById('down-arrow') больше не будут работать должным образом

Ответ №1:

Я бы немного изменил это и переключил класс при нажатии на вопрос, а затем позволил CSS выполнить всю работу.

Обратите внимание, что я полностью удалил идентификаторы, заменив их классами. Элементы могут иметь более одного класса.

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

 //Get the questions
let questions = document.querySelectorAll(".questions");
for (var i = 0; i < questions.length; i  ) {
  questions[i].addEventListener("click", function(event) {
    //Toggle active class when clicked
    this.classList.toggle("active");
  });
}


/*If you want to only toggle on clicking the arrow use the following loop instead*/
/*for(var i = 0; i < questions.length; i  ) {  
  questions[i].addEventListener("click", function(event){
    //Only toggle if arrow clicked
    if(event.target.matches(".arrow")){
      //Toggle active class when clicked
      this.classList.toggle("active");
    }
  });
}*/ 
 .answer {
  display: none;
}


/*Display answer when active*/

.questions.active .answer {
  display: initial;
}


/*Change arrow when active*/

.questions.active .arrow {
  transform: scale(-1);
} 
 <article class="questions">
  How many team members can I invite?
  <img src="images/icon-arrow-down.svg" alt="arrow" class="arrow">
  <hr>
  <detail class="answer display">
    You can invite up to 2 additional users on the Free plan. There is no limit on team members for the Premium plan.
  </detail>
</article>

<article class="questions">
  What is the maximum file upload size?
  <img src="images/icon-arrow-down.svg" alt="arrow" class="arrow">
  <hr>
  <detail class="answer">
    No more than 2GB. All files in your account must fit your allotted storage space.
  </detail>
</article>

<article class="questions">
  How do I reset my password?
  <img src="images/icon-arrow-down.svg" alt="arrow" class="arrow">
  <hr>
  <detail class="answer">
    Click “Forgot password” from the login page or “Change password” from your profile page. A reset link will be emailed to you.
  </detail>
</article>

<article class="questions">
  Can I cancel my subscription?
  <img src="images/icon-arrow-down.svg" alt="arrow" class="arrow">
  <hr>
  <detail class="answer">
    Yes! Send us a message and we’ll process your request no questions asked.
  </detail>
</article>

<article class="questions">
  Do you provide additional support?
  <img src="images/icon-arrow-down.svg" alt="arrow" class="arrow">
  <hr>
  <detail class="answer">
    Chat and email support is available 24/7. Phone lines are open during normal business hours.
  </detail>
</article> 

Ответ №2:

  1. Идентификатор должен быть уникальным. Вы не можете использовать идентификатор несколько раз в HTML-файле, что означает .getElementById() , что извлекается только один элемент, который включает его дочерние / внучатые элементы.
  2. Вы должны извлечь несколько элементов, используя .querySelectorAll() вместо .getElementById() .
  3. Вы не можете применить .addEventListener() к нескольким элементам (в данном случае технически называемым списком узлов). Вам нужно применить его один за другим, используя .forEach()

Вот один из примеров:

 // Get all of the arrows
const arrows = document.querySelectorAll('#faq-container .faq-question__arrow');

// Apply .addEventListener() to each arrow one by one
arrows.forEach(arrow => arrow.addEventListener('click', () => {
  // Get each arrow's parent's parent element
    const faqItem = arrow.closest(".faq-item");
    faqItem.classList.toggle('active');
})); 
 .faq-question__arrow {
  display: inline-block;
  cursor: pointer;
}

.faq-answer {
  display: none;
}

.faq-item.active .faq-question__arrow {
  transform: scaleY(-1)
}

.faq-item.active .faq-answer {
  display: initial;
} 
 <dl id="faq-container">
  <div class="faq-item">
    <dt class="faq-question">
      How old are you?
      <span class="faq-question__arrow">🔻</span>
    </dt>
    <dd class="faq-answer">I'm 20 years old.</dd>
  </div>
  
  <div class="faq-item">
    <dt class="faq-question">
      How are you?
      <span class="faq-question__arrow">🔻</span>
    </dt>
    <dd class="faq-answer">I'm ok.</dd>
  </div>
  
  <div class="faq-item">
    <dt class="faq-question">
      What's your name?
      <span class="faq-question__arrow">🔻</span>
    </dt>
    <dd class="faq-answer">I don't know</dd>
  </div>
</dl>