What is the best way to reveal the following div while concealing the one before it?

Just starting out with Javascript, I'm currently developing a quiz solution that utilizes divs and buttons to navigate through the questions. I've written some JavaScript code for this functionality but I'm encountering an issue where it doesn't progress to the final question as expected. Any assistance on why the next button doesn't lead to the last question would be greatly appreciated.

var question = document.querySelectorAll('.question');
var next = document.getElementById("next");

next.addEventListener("click", function() {
  var question = document.querySelectorAll(".question");

  for (var i = 0; i < question.length; i++) {
    if (question[i].style.display != "none") {
      question[i].style.display = "none";
      //restores original questions
      if (i == question.length - 1) {
        question[0].style.display = "block";
      } else {
        question[i + 1].style.display = "block";
      }
      break;
    }
  }
});
.question {
  margin: 50px;
  width: 300px;
  height: 300px;
  border-radius: 10px;
  padding: 50px;
  text-align: center;
  color: white;
  background: #333;
  position: relative;
  display: none;
}

.visible {
  display: block;
}

.q-input,
.move {
  margin: 10px;
  border: none;
  padding: 10px;
}

.move {
  display: flex;
  justify-content: space-between;
}

.move button {
  padding: 5px;
  font-size: 16px;
  width: 60px;
  border-radius: 5px;
  border: none;
  cursor: pointer;
  transition: 0.4s;
}

.move button:hover {
  box-shadow: -2px -2px 20px #fff;
}

.move button:focus {
  outline: none;
}
<div class="question visible">
  <h1>Question <span class="one">1</span></h1>
  <p>What is your Name</p>
  <input type='text' class="q-input">
  <div class="move">
    <button id="prev">Prev</button>
    <button id="next">Next</button>
  </div>
</div>
<div class="question">
  <h1>Question 2</h1>
  <p>What is your Age</p>
  <input type="text" class="q-input">
  <div class="move">
    <button id="prev">Prev</button>
    <button id="next">Next</button>
  </div>
</div>
<div class="question">
  <h1>Question 3</h1>
  <p>What is your Sex</p>
  <input type="text" class="q-input">
  <div class="move">
    <button id="prev">Prev</button>
    <button id="next">Next</button>
  </div>
</div>

Answer №1

Utilizing

 document.getElementById("next")
will only target the first button with an ID of next, resulting in only that specific button having the click listener attached to it.

Since IDs are intended for singular unique elements, it is advisable to use classes instead - by modifying it to

<button class="next">Next</button>


In your JavaScript code, you should select all the next button elements and utilize forEach to assign a listener to each of them.

Inside that listener, you can manipulate the visibility of connected question divs by employing parentElement and nextElementSibling, ensuring to verify if the next element is indeed a question before altering the visibilities.

Additionally, applying/eliminating the visible class is more organized and simpler for troubleshooting compared to directly editing the style property.


The consolidated code appears as follows:

var nextButtons = document.querySelectorAll('.next');

nextButtons.forEach(nextButton =>
  nextButton.addEventListener("click", function() {
    var currentQuestion = nextButton.parentElement.parentElement;
    var nextElement = currentQuestion.nextElementSibling;
    if (nextElement.classList.contains("question")) {
      nextElement.classList.add("visible");
      currentQuestion.classList.remove("visible");
    }
  }));
.question {
  margin: 50px;
  width: 300px;
  height: 300px;
  border-radius: 10px;
  padding: 50px;
  text-align: center;
  color: white;
  background: #333;
  position: relative;
  display: none;
}

.visible {
  display: block;
}

.q-input,
.move {
  margin: 10px;
  border: none;
  padding: 10px;
}

.move {
  display: flex;
  justify-content: space-between;
}

.move button {
  padding: 5px;
  font-size: 16px;
  width: 60px;
  border-radius: 5px;
  border: none;
  cursor: pointer;
  transition: 0.4s;
}

.move button:hover {
  box-shadow: -2px -2px 20px #fff;
}

.move button:focus {
  outline: none;
}
<div class="question visible">
  <h1>Question <span class="one">1</span></h1>
  <p>What is your Name</p>
  <input type='text' class="q-input">
  <div class="move">
    <button class="prev">Prev</button>
    <button class="next">Next</button>
  </div>
</div>
<div class="question">
  <h1>Question 2</h1>
  <p>What is your Age</p>
  <input type="text" class="q-input">
  <div class="move">
    <button class="prev">Prev</button>
    <button class="next">Next</button>
  </div>
</div>
<div class="question">
  <h1>Question 3</h1>
  <p>What is your Sex</p>
  <input type="text" class="q-input">
  <div class="move">
    <button class="prev">Prev</button>
    <button class="next">Next</button>
  </div>
</div>

Answer №2

It is important to ensure that each element has a unique identifier (ID) in HTML, as having more than one element with the same ID can cause issues. In this case, the IDs for the buttons have been changed to use classes instead of duplicate IDs. To add functionality to your buttons, you can utilize forEach method along with an eventListener to iterate over them and perform specific actions.

var question = document.querySelectorAll('.question');
var next = document.querySelectorAll(".next");

next.forEach(n => {n.addEventListener("click", function() {
  var question = document.querySelectorAll(".question");

  for (var i = 0; i < question.length; i++) {
    if (question[i].style.display != "none") {
      question[i].style.display = "none";
      //resets to original questions
      if (i == question.length - 1) {
        question[0].style.display = "block";
      } else {
        question[i + 1].style.display = "block";
      }
      break;
    }
  }
})});
.question {
  margin: 50px;
  width: 300px;
  height: 300px;
  border-radius: 10px;
  padding: 50px;
  text-align: center;
  color: white;
  background: #333;
  position: relative;
  display: none;
}

.visible {
  display: block;
}

.q-input,
.move {
  margin: 10px;
  border: none;
  padding: 10px;
}

.move {
  display: flex;
  justify-content: space-between;
}

.move button {
  padding: 5px;
  font-size: 16px;
  width: 60px;
  border-radius: 5px;
  border: none;
  cursor: pointer;
  transition: 0.4s;
}

.move button:hover {
  box-shadow: -2px -2px 20px #fff;
}

.move button:focus {
  outline: none;
}
<div class="question visible">
  <h1>Question <span class="one">1</span></h1>
  <p>What is your Name</p>
  <input type='text' class="q-input">
  <div class="move">
    <button id="prev1">Prev</button>
    <button class="next" id="next1">Next</button>
  </div>
</div>
<div class="question">
  <h1>Question 2</h1>
  <p>What is your Age</p>
  <input type="text" class="q-input">
  <div class="move">
    <button id="prev2">Prev</button>
    <button class="next" id="next2">Next</button>
  </div>
</div>
<div class="question">
  <h1>Question 3</h1>
  <p>What is your Sex</p>
  <input type="text" class="q-input">
  <div class="move">
    <button id="prev3">Prev</button>
    <button class="next" id="next3">Next</button>
  </div>
</div>

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

What are the best practices for presenting Motion JPEG binary data streams using Angular, Ionic, and JavaScript?

I am developing an application for a device that will receive a POST request and send back a binary data stream in the format of multipart/x-mixed-replace. My goal is to display this stream on a specific section of my app's homepage. After conducting ...

Using a variable to contain a loop in Jquery

Seeking assistance with a jQuery function that retrieves values from a PHP form to create a variable for an ajax call. Is it possible to include a loop within a variable? Below is a snippet of my code to provide better context: ... var teacher_ids = $( & ...

Angular: Struggling with Parent Component not recognizing changes in Child Component

Currently, I am facing an issue with my shopping cart functionality. When the website first loads and a user does not have a saved shopping cart, they need to click "add to cart" before one is created. The problem lies in the fact that my app.component doe ...

Opening a browser tab discreetly and extracting valuable data from it

Greetings to the experts in Chrome Extension development, I am exploring ways to access information from a webpage without actually opening it in a separate tab. Is there a method to achieve this? Here's the scenario: While browsing Site A, I come a ...

Is there a way to continue a failed fetch request?

I am curious about the possibility of resuming an incomplete fetch request if it fails due to a non-code-related issue, like a lost network connection. In one of my current projects, we send a large download via AJAX to the client after they log in. This ...

CORS blocked in the live environment

error + whole page As a newcomer to JavaScript, I recently deployed my project. During development, everything was functioning well. However, I am now facing an issue with CORS when attempting to sign in (registration works without any problems, confirmin ...

What is the best way to eliminate an item from an array in JavaScript or AngularJS?

I'm attempting to eliminate objects from an array and retrieve the resulting array. I've been using a remove function, but it's not functioning as expected. Here is the input I'm working with: The goal is to remove all values in the ar ...

Discovering the tiniest value in every row within an HTML table with the help of PHP

I am working with a table that looks like this: 6xx 8xx 9xx 11xx 12xx 1 0.01 0.002 0.004 0.001 0.025 2 0.025 0.125 0.002 0.01 0.011 I need to highlight the smallest value in each row by making that cel ...

Error: The specified schema for the model "superheroes" is missing and has not been registered. Please ensure the schema is properly defined and registered

After updating my server with nodemon, I encountered the following error: C:\Users\mikae\Desktop\Project\node-express-swig-mongo\node_modules\mongoose\lib\index.js:523 throw new mongoose.Error.MissingSchem ...

What is the best way to extract a single image from JSON data using AngularJS?

Using ng-repeat in HTML, how can I display only a single image instead of all images? <img class="size" ng-src="{{image.image}}" /> In CSS, I aim to define the size of the image. .size { margin-left:0.3em; width:11em; height:11em; border:0.4em sol ...

Show drawer when modal is open in React Native

Currently, I am working on a project in react-native and facing an issue where the modal is appearing over the drawer navigator. Despite trying to adjust the zIndex property, it has not been effective. Details of my modal: <Modal visible={isVisible} ...

CSS for Responsive Web Development: Adjusting the Height of Mobile Sliders

I've been working on adjusting the height of the slider on my website for mobile screens, but I can't seem to get it right. The website in question is www.msstoreway.com. Despite adding the CSS code below, I was able to adjust the slider height ...

Refreshing a page following an AJAX request made with jQuery

I am working on a JSP page that shows student details. When a student is selected from the dropdown box, it triggers an onchange event to retrieve the minimum and maximum marks for that student. <form name="listBean"> <c:forEach var="Item" i ...

Display a text field upon clicking on a specific link

I am trying to create a text field that appears when a link is clicked, but I haven't been able to get it right yet. Here is what I have attempted: <span id="location_field_index"> <a href="javascript:void(0)" onclick="innerHTML=\"< ...

CSS: adjusting styles for different screen sizes on both desktop computers and smartphones

While diving into Emacs, I am in the process of creating a website called Prince. The layout of columns is controlled by the directives below: body { font-family: var(--s-font-family); font-size: var(--normal-font-size); column-count: 3; c ...

Creating a Click Counter with jQuery 2.0.1/2.0.2: A Step-by-Step Guide

Currently in the process of creating a fundraising webpage for charity, I have chosen to display an animated rabbit making its way Around The World. My progress so far includes a non-looping gif that plays on click, with a limitation on how often it can b ...

The changes made to $scope in AngularJS are not being displayed in the view

The View Section <div class="col-sm-8" data-ng-init="init_enable_disable()"> <select class="form-control" style="margin-top: 5px;" data-ng-model="schedule.scheduleType" data-ng-change="enable_disableDiv(schedule.scheduleType);"> ...

Unable to grab hold of specific child element within parent DOM element

Important Note: Due to the complexity of the issue, the code has been abstracted for better readability Consider a parent component structure like this: <child-component></child-component> <button (click)="doSomeClick()"> Do Some Click ...

The command `browser.find_elements_by_class_name('foo')` returned zero results

I'm encountering an issue with selenium while using Python 3.7. The website I'm working on has a structure similar to this: <html> <body> <div class="foo"> <div class="bar1">some ...

jQuery doesn't seem to function properly upon initial click

Working with Rails and attempting to implement an ajax bookmark icon functionality. When clicking for the first time, the request is sent but the image does not change; however, subsequent clicks work as expected (request sent and image changes). This is ...