PythonCoder1981
PythonCoder1981

Reputation: 463

Change CSS attribute with several Buttons Javascript

I have an FAQ project in which it has several question that can be answered when the users clicks the arrow button on each questions line. I am using javascript to change the css element but it only works with the firts arrow on not the rest.

I want to be able to click any arrow to show each answer. I was thinking add an differnt ID to each arrow per line but that may not be the best approach.

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)";
}

FAQ List

Upvotes: 0

Views: 99

Answers (2)

Miu
Miu

Reputation: 844

  1. ID should be unique. You can't use an ID multiple times in a HTML file, which means .getElementById() only retrieves one element which includes its children/grandchildren elements.
  2. You have to retrieve multiple elements by using .querySelectorAll() instead of .getElementById().
  3. You can't apply .addEventListener() to multiple elements (technically called node list in this case). You need to apply it one bye one by using .forEach()

Here is an example:

// 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>

Upvotes: 1

Jon P
Jon P

Reputation: 19787

I'd change this a little and toggle a class when the question is clicked, then let CSS do the work.

Note that I've removed IDs entirely replacing them with classes. Elements can have more than one class.

I've provided an alternate if you want to stick to just clicking the arrow.

//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>

Upvotes: 1

Related Questions