Faulty toggle functionality within a JavaScript-created accordion panel

HTML

I'm looking to add a FAQ question within the div with the class "section-center"


<body>

    <section class="questions">
        <div class="title">
            <h2>FAQ SECTION</h2>
        </div>
        <div class="section-center">
<!-- dynamic data insert here -->
        </div>
    </section>
    <!-- script -->
    <script src="/script.js"></script>
</body>

</html>

CSS

With the use of JavaScript, we will be able to add or remove the "show-text" class. When the "show-text" class is added, the 'question-text' class will display block (making the answer visible), the 'minus-icon' class will display inline (revealing the minus icon which was initially hidden), and the 'plus-icon' class will have display none (the plus icon disappears).

.question-text {
    display: none;
}

.show-text .question-text {
    display: block;
}

.minus-icon {
    display: none;
}

.show-text .minus-icon {
    display: inline;
}

.show-text .plus-icon {
    display: none;
}

JS

This array holds questions and answers

const faq = [
  {
    ques: 'this is test question',
    answer: 'this is test answer ',
  },
  {
    ques: 'this is test question',
    answer: 'this is test answer ',
  },
]

We are traversing the DOM in order to insert the question/answer where needed.

const sectionCenter = document.querySelector('.section-center');

The function displayQuestion is called when the webpage loads to show the question and answer.

window.addEventListener('DOMContentLoaded', () => {
  displayQuestions(faq);
});

const questions = document.querySelectorAll('.question');

//console.log(questions);

This portion of code enables the feature of automatically closing an open question when another question is opened by clicking on a toggle button.

questions.forEach((question) => {
  const btn = question.querySelector('.question-btn');

  btn.addEventListener('click', () => {
    questions.forEach((curQuestion) => {
      if (curQuestion !== question) {
        curQuestion.classList.remove('show-text');
      }
    });
    question.classList.toggle('show-text');
  });
});

A function to display question and answer

// function to display questions

function displayQuestions(items) {
  let display = items.map(({ ques, answer }) => {
    return ` 
            <article class="question">
                <div class="question-title">
                    <P>${ques}</P>
                    <button type="button" class="question-btn">
                        <span class="plus-icon">
                            <i class="far fa-plus-square"></i>
                        </span>

                        <span class="minus-icon">
                            <i class="far fa-minus-square"></i>
                        </span>
                    </button>
                </div> 
                
                 <div class="question-text">
                    <p>${answer}</p>
                </div>
            </article>
          `;
  });
  display = display.join('');
  //   console.log(display);
  sectionCenter.innerHTML = display;
}

Answer №1

After restructuring the code, I created a function named addEventListenersToQuestions to handle adding event listeners to the question buttons. This function is now called after displayQuestions runs within the DOMContentLoaded event listener callback function.

The main reason for this change was that even though the code for adding event listeners came after the displayQuestions code in source order, it was actually executing before displayQuestions had completed its process. In JavaScript, event listener callbacks are only executed after the current section of code has finished execution.

const faq = [
  {
    ques: 'this is test question 1',
    answer: 'this is test answer 1',
  },
  {
    ques: 'this is test question 2',
    answer: 'this is test answer 2',
  },
];

const sectionCenter = document.querySelector('.section-center');

window.addEventListener('DOMContentLoaded', () => {
  displayQuestions(faq);
  addEventListenersToQuestions();
});


function addEventListenersToQuestions() {
  const questions = document.querySelectorAll('.question');

  questions.forEach((question) => {
    const btn = question.querySelector('.question-btn');

    btn.addEventListener('click', () => {
      questions.forEach((curQuestion) => {
        if (curQuestion !== question) {
          curQuestion.classList.remove('show-text');
        }
      });
      question.classList.toggle('show-text');
    });
  });
}

// function to display questions

function displayQuestions(items) {
  let display = items.map(({ ques, answer }) => {
    return ` 
            <article class="question">
                <div class="question-title">
                    <P>${ques}</P>
                    <button type="button" class="question-btn">
                        <span class="plus-icon">
                            +
                        </span>

                        <span class="minus-icon">
                            -
                        </span>
                    </button>
                </div> 
                
                 <div class="question-text">
                    <p>${answer}</p>
                </div>
            </article>
          `;
  });
  display = display.join('');
  //   console.log(display);
  sectionCenter.innerHTML = display;
}
.question-text {
    display: none;
}

.show-text .question-text {
    display: block;
}

.minus-icon {
    display: none;
}

.show-text .minus-icon {
    display: inline;
}

.show-text .plus-icon {
    display: none;
}
<section class="questions">
    <div class="title">
        <h2>FAQ SECTION</h2>
    </div>
    <div class="section-center">
<!-- dynamic data insert here -->
    </div>
</section>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Show the day of the week

I'm seeking a solution to display the upcoming Friday of each week within Wordpress. We were able to achieve this in the past using the code below on non-Wordpress platforms, but it seems outdated and no longer functional. For example: This week&apos ...

"Resolving the issue of Django request.FILE returning a null value

HTML Template: <form method="post" action="" enctype="multipart/form-data" class="form-group"> {% csrf_token %} <h1 class="m-3 text-center">New Post</h1> <div id="tui-image-e ...

Any modifications made to a copied object will result in changes to the original object

The original object is being affected when changes are made to the cloned object. const original = { "appList": [{ "appId": "app-1", "serviceList": [{ "service": "servic ...

Looking for assistance with a CSS selector in jQuery

I am working with a WordPress blog that has multiple pages with dropdown subpages on hover. However, I only want the main pages to have links, not the subpages. To achieve this, I am using some basic JavaScript. jQuery(document).ready(function(){ jQ ...

Tips on how to indicate a checkbox as selected within an Angular controller

I'm in the process of creating a form for entering new service requests, as well as displaying and editing existing ones. One part of this form includes a list of labeled check-boxes that represent different countries. When an existing request is disp ...

How can I update a Django webpage using AJAX without having to refresh it?

I'm currently in the process of developing a messaging application and I'd like to implement a feature that automatically reloads the page every minute so users can see new messages without having to manually refresh. While I have some knowledge ...

Struggling to resolve the issue while deploying a Next.js application on Netlify. The error seems to be stemming from the import of an image and its

I attempted to eliminate the code on line 4 and line 15 in index.js, then deployed it on Netlify. The functionality is working correctly, but the image is not displaying as desired. However, when I try to modify the code with just lines 4 and 15 included, ...

Cube area to be filled

I am struggling to fill a cube with colors as it is only getting half of the figure filled. I suspect there might be an issue with the cubeIndices, but I'm having trouble figuring out how to make it fill everything. While I know I could use a cylinder ...

From time to time, I may post files of substantial size

When moving to the next step in the form, I have implemented checks to prevent photos over 10mb and disallow .heic files from being uploaded. Most of the time it works as expected, but occasionally files slip through. If anyone has suggestions for a more ...

Using v-model with checkboxes in vue.js: A Step-by-Step Guide

How can I use a checkbox with a v-model in Vue2.js? <input type="checkbox" value="test" :checked="selected"/> I need the value of the checkbox to be test, and I also require two-way binding with the prop named selected, ...

transfer data from local array to global variable

Need help with returning array values using console.log(array);, currently it's displaying empty value []. Any tips or suggestions would be greatly appreciated. var array = []; var maxLength = 3; var delay = 250; //Shortened the delay var ticker = {}; ...

Is it advisable to employ jQuery(this) in this specific scenario?

My PHP script generates HTML a:link divs with different $linkname and $pageid values. It also creates corresponding jQuery scripts for each link: $output = '<a class="sig_lightbox_link" id="' . $pageid . '">' . ...

Ways To Obtain Trustworthy Dates Using JavaScript

Last week, I encountered an intriguing issue at my job. I needed to obtain a date accurately using JavaScript, but the code I was working with utilized new Date() which resulted in discrepancies due to some customers having incorrect system time settings. ...

I'm having some trouble with this search filter in Vue 2 - is it failing to display the items as expected

After struggling with this issue for over a week, I've hit a roadblock and need some assistance. I'm currently working on implementing a search filter in Vue 2 with Vuetify, but something isn't quite right. Here's a snippet of the sea ...

Switch off any other currently open divs

I'm currently exploring a way to automatically close other div's when I expand one. Check out my code snippet below: $( document ).ready(function() { $( ".faq-question" ).click(function() { $(this).toggleClass('open'); $(this ...

Issue encountered while generating REST API through Postman resulting in a 500 error

I am in the process of creating a Node.js API for a web application. The GET request is functioning properly, however, when attempting to execute a POST request, I encounter an error messageError Below is the code snippet: //User Schema const mongoose ...

How can we integrate this icon/font plugin in CSS/JavaScript?

Check out the live demonstration on Jsfiddle http://jsfiddle.net/hc046u9u/ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materializ ...

Retrieve information from a MongoDB document based on the specific month

If I have a user document with a createdAt field, how can I retrieve data by month in the condition? The format of the createdAt value is as follows: 2016-10-08T16:21:40.935Z Account.find({'what should be passed here?'}, function(err,response){ ...

Create a new button dynamically within an HTML table row using pure JavaScript programming techniques

Currently, I am retrieving JSON data from an API and then displaying this data in an HTML table using plain JavaScript. My goal is to dynamically add a button at the end of each row for additional functionality, but so far, I have been unable to figure out ...

I'm having trouble getting my Django for-loop to show the items

Having trouble displaying all the songs on my music streaming website homepage using a carousel. Even though I have around 10 songs in my database, nothing is showing up. How can I fix this issue? This is the HTML code I am using: <div id="All-song ...