Issue with clicking and toggling classes in Javascript

I am experimenting with creating a simple 3 slide slider, but I am facing some issues with the JavaScript. My goal is to have the current slider slide out and the selected one slide in when clicking on the slider color. I'm attempting to achieve this by adding an active class to the clicked slider number for display. However, I can't seem to pinpoint where I went wrong. I prefer not to use jQuery as I want to practice vanilla JavaScript.

Thank you in advance!

window.onload = onPageLoad();

function onPageLoad() {
  document.querySelector('.red').classList.add('active');
};

document.querySelector('.box').addEventListener('click', function() {
  document.querySelector('.red').classList.toggle('active');
  document.querySelector('.green').classList.toggle('active');
  document.querySelector('.yellow').classList.toggle('active');
});

* {
  padding: 0;
  margin: 0;
}

.main__wrapper {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
/* CSS styles continue... */
<div class="main__wrapper">
  <section class="red"></section>
  <section class="green"></section>
  <section class="yellow"></section>

  <div class="slide__select">
    <div class="box"><span>red</span></div>
    <div class="box"><span>green</span></div>
    <div class="box"><span>yellow</span></div>
  </div>
</div>

Answer №1

The event listener is only being applied to the initial box, causing a toggling of the active class for each subsequent box leading to a yellow background on the final box.

Using querySelector will return the first DOM element found, which in this case is the red box.

To achieve the desired functionality, event listeners need to be added to each individual box using querySelectorAll.

Answer №2

window.onload = onPageLoad();

function onPageLoad() {
  document.querySelector('.red').classList.add('active');
};

document.querySelector('.redbox').addEventListener('click', function() {
  document.querySelector('.red').classList.add('active');
  document.querySelector('.green').classList.remove('active');
  document.querySelector('.yellow').classList.remove('active');
});
document.querySelector('.greenbox').addEventListener('click', function() {
  document.querySelector('.red').classList.remove('active');
  document.querySelector('.green').classList.add('active');
  document.querySelector('.yellow').classList.remove('active');
});
document.querySelector('.yellowbox').addEventListener('click', function() {
  document.querySelector('.red').classList.remove('active');
  document.querySelector('.green').classList.remove('active');
  document.querySelector('.yellow').classList.add('active');
});
* {
  padding: 0;
  margin: 0;
}

.main__wrapper {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

.red,
.green,
.yellow {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  transform: translateX(-100%);
  transition: transform 1.2s;
}

.red {
  background-color: red;
}

.green {
  background-color: green;
}

.yellow {
  background-color: yellow;
}

.active {
  transform: translateX(0) !important;
  transition: transform 1s !important;
}

.slide__select {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 60%;
  height: 20%;
  z-index: 10;
  display: flex;
}

.box {
  position: relative;
  flex: 1 0 0;
  color: $color-white;
  display: flex;
  align-items: center;
  cursor: pointer;
  background-color: #A68D71;
}

.box span {
  display: block;
  position: relative;
  z-index: 11;
}

.box::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  background-color: yellow;
  width: 100%;
  height: 0;
  transition: height .3s;
}

.box:hover::after {
  height: 100%;
  transition: height .3s;
}
<div class="main__wrapper">

  <section class="red">

  </section>

  <section class="green">

  </section>

  <section class="yellow">

  </section>

  <div class="slide__select">
    <div class="redbox box">
      <span>red</span>
    </div>
    <div class="greenbox box">
      <span>green</span>
    </div>
    <div class="yellowbox box">
      <span>yellow</span>
    </div>
  </div>

</div>

Here is a comprehensive example solution. It may seem lengthy, but it effectively demonstrates the necessary functionality. This code can be simplified.

To streamline the code, all three listeners could be combined into just one listener targeting the .box selector. To determine which box was clicked, consider using a data attribute or parsing the html text. Using a data attribute would enhance code clarity and separation of concerns. However, either approach will accomplish the desired outcome.

Answer №3

Here's a more concise solution:

window.onload = onPageLoad();

function onPageLoad() {
  document.querySelector('.red').classList.add('active');
};

var boxes = document.querySelectorAll('.box');
for (var i = 0; i < boxes.length; i++) {
  boxes[i].addEventListener('click', toggleSections);
}

var colors = ['red', 'green', 'yellow'];

function toggleSections(ev) {
  var color = ev.currentTarget.innerText;
  for (var c = 0; c < colors.length; c++) {
    var colorElem = document.querySelector('.' + colors[c]);
    if (colors[c] != color) {
      colorElem.classList.remove('active');
    } else {
      colorElem.classList.add('active');
    }
  }
}
* {
  padding: 0;
  margin: 0;
}

.main__wrapper {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

.red,
.green,
.yellow {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  transform: translateX(-100%);
  transition: transform 1.2s;
}

.red {
  background-color: red;
}

.green {
  background-color: green;
}

.yellow {
  background-color: yellow;
}

.active {
  transform: translateX(0) !important;
  transition: transform 1s !important;
}

.slide__select {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 60%;
  height: 20%;
  z-index: 10;
  display: flex;
}

.box {
  position: relative;
  flex: 1 0 0;
  color: $color-white;
  display: flex;
  align-items: center;
  cursor: pointer;
  background-color: #A68D71;
}

.box span {
  display: block;
  position: relative;
  z-index: 11;
}

.box::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  background-color: yellow;
  width: 100%;
  height: 0;
  transition: height .3s;
}

.box:hover::after {
  height: 100%;
  transition: height .3s;
}
<div class="main__wrapper">

  <section class="red">

  </section>

  <section class="green">

  </section>

  <section class="yellow">

  </section>

  <div class="slide__select">
    <div class="box">
      <span>red</span>
    </div>
    <div class="box">
      <span>green</span>
    </div>
    <div class="box">
      <span>yellow</span>
    </div>
  </div>

</div>

Answer №4

To get the desired outcome, consider the following options:

  1. Use a single section to prevent multiple loops of section elements

  2. Instead of using querySelector, opt for querySelectorAll or elementsByClassName to retrieve all elements in an array

  3. Utilize forEach to iterate through all elements with the class "box", add an event listener and then run another loop using forEach for span elements

  4. Employ classList to add or remove classes

window.onload = onPageLoad();

function onPageLoad() {
  document.querySelector('.red').classList.add('active');
};

// use querySelectorAll to get all elements of class-box and forEach to loop through
document.querySelectorAll('.box').forEach(function(ele){
  //Add clici event through addEventListener
  ele.addEventListener('click', function() {
// use another querySelectorAll to get all elements of tag span and forEach to loop through
document.querySelectorAll('span').forEach(function(e){
  e.classList.remove('active');
  //use querySelector for section element and empty classList to remove active and red/green/yellow class names
  document.querySelector('section').className ='';
});
//toggle active class for clicked element
ele.children[0].classList.toggle("active");
//add active class for section
document.querySelector('section').classList.add('active');
//add class red/yellow/green using span innerHTML
document.querySelector('section').classList.add(ele.children[0].innerHTML);
 });
});
* {
  padding: 0;
  margin: 0;
}

.main__wrapper {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

.red,
.green,
.yellow {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  transform: translateX(-100%);
  transition: transform 1.2s;
}

.red {
  background-color: red;
}

.green {
  background-color: green;
}

.yellow {
  background-color: yellow;
}

.active {
  transform: translateX(0) !important;
  transition: transform 1s !important;
}

.slide__select {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 60%;
  height: 20%;
  z-index: 10;
  display: flex;
}

.box {
  position: relative;
  flex: 1 0 0;
  color: $color-white;
  display: flex;
  align-items: center;
  cursor: pointer;
  background-color: #A68D71;
}

.box span {
  display: block;
  position: relative;
  z-index: 11;
}

.box::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  background-color: yellow;
  width: 100%;
  height: 0;
  transition: height .3s;
}

.box:hover::after {
  height: 100%;
  transition: height .3s;
}
<div class="main__wrapper">

  <section class="red">

  </section>
  <div class="slide__select">
    <div class="box">
      <span>red</span>
    </div>
    <div class="box">
      <span>green</span>
    </div>
    <div class="box">
      <span>yellow</span>
    </div>
  </div>

</div>

For more details on the code sample provided, visit: https://codepen.io/nagasai/pen/vRoPwp

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 is the method to retrieve JSON data with data['file.file']?

When trying to query my data using var x = data.file.file;, I encountered an issue where data['file.file'] fails. Is there a way to access this data without having to split the string and walk recursively through it? ...

The div element is unable to activate the modal due to tabindex issues

Seeking Assistance with a Specific Scenario I have a specific layout where a div is enclosing an image. The desired functionality is that when the div is clicked with a mouse, a small tooltip modal should appear displaying address information. This can be ...

.click function failing to trigger on dynamically loaded form

I'm facing an issue with a form that displays images from my database. After retrieving the filepaths, they are loaded dynamically into the form along with a "Delete" <button> for users to delete the image via AJAX. Although I can successfully ...

What could be causing the malfunction in my Bootstrap navbar?

<!-- Including Bootstrap CSS files locally-->> <link rel="stylesheet" href="bootstrap.min.css"> <link rel="stylesheet" href="bui.css" <!-- Creating a Navbar--> <nav class="navbar navbar-expand-lg navbar-light bg- ...

Enabling auto-expansion for textareas with every keystroke

Currently, I have implemented the following script: jQuery.each(jQuery('textarea[data-autoresize]'), function() { var offset = this.offsetHeight - this.clientHeight; var resizeTextarea = function(el) { jQuery(el).css('h ...

What is the best way to set a value for a variable within a UI component in React?

I'm still learning the ropes with React and JavaScript. My current challenge involves declaring a temporary variable and assigning the value of companyData.name to it, as I need to gather data from two variables like companyData.name. Below is my cod ...

My objective is to upload a video file and store it on the server using multer

My goal is to effectively receive and save a video file in the uploads folder with the proper extensions using node, express, and multer. Despite successfully passing the video to the server, it doesn't save as intended. Below is my backend code snipp ...

What is the best way to combine relative paths or create distinct identifiers for SVG files located within multiple layers of folders

I have a collection of icons exported from "Figma" organized in folders, and I'm using grunt-svgstore to create a sprite sheet. However, the result contains duplicated IDs even after trying 'allowDuplicateItems: false' and 'setUniqueIds ...

Is it allowed to use any AngularJS directives within other directives?

I am trying to create a directive that will display a list of objects from my controller. Inside this directive, I want to be able to use one of several possible sub-directives, but the specific one to be used may vary. If I set the sub-directive name in t ...

There is an error in ReactJS: TypeError - _this.props.match is not defined

I am experiencing a TypeError in my console tab and I can't seem to figure out where the error is occurring in my source code. I am relatively new to ReactJS so any help in identifying what I'm doing wrong would be greatly appreciated. Thank you ...

Alter Text Using Typewriter

Recently, I have been experimenting with code on my glitch website, trying to create typewriter text. Thanks to help from a user on StackOverflow, I was able to achieve this effect successfully. However, I am now facing a new challenge. My goal is to make ...

Angular: seamlessly transferring all directives from parent component to child without interference

Imagine we have a component called main that includes another one named sub. I would like for the directive passed to main in the client side, such as: <main dir1='dirval1'></main> for the main component to act as a thin wrapper and ...

Is the format of this HTML tag correct?

I was provided with a code from our design department to add to a page, and since I am relatively new to the design aspect of things, I'm seeking clarification. Is this a valid tag? Also, what does <--if subcontent add rel="test1"--> mean? The c ...

What is preventing me from generating a string for transform:translate within Angular.js?

Attempting a new approach here $scope.graph.transform = "transform: translate(" + $scope.graph.width + "," + $scope.graph.height + ");"; Despite my efforts <h3>transform: <span ng-bind="grap ...

Automatically select a radio button upon loading the page

Below is the code I am currently using: jQuery('#choice_1_10_3_1').attr('checked','checked'); I need this radio button to be checked automatically when the page loads. Despite no errors being shown in the console, the code i ...

I'm attempting to render HTML emails in ReactJS

I have been attempting to display an HTML page in React JS, but I am not achieving the same appearance. Here is the code snippet I used in React JS: <div dangerouslySetInnerHTML={{ __html: data }}/> When executed in regular HTML, the page looks lik ...

The code encountered an error with message TS2345 stating that the argument type '(a: Test, b: Test) => boolean | 1' cannot be assigned to a parameter type of '(a: Test, b: Test) => number'

Apologies for the lengthy subject, but I am having trouble understanding the response. Here is my code snippet: this.rezerwacjeFilteredByseaarchInput.sort(function (a, b) { if (a[5]===null) { // console.log(a[5]); return 1; } ...

How can I retrieve the name of the upcoming middleware function in Express.JS?

Hey there, I'm currently facing a challenge with retrieving the names of middleware functions in a specific request route. Let's consider the code snippet below as an example: const authorizeRoute = (req,res,next) => { let nextFunctionName = ...

Struggling to generate package using manifoldjs

Excited to dive into the new tool called ManifoldJS introduced by Microsoft at Build 2015, I'm facing some challenges. My website is up and running as a basic HTML- and JS-based app using Angular and TypeScript. I've even created a manifest.json ...

Styling a Pie or Doughnut Chart with CSS

I am working on creating a doughnut chart with rounded segments using Recharts, and I want it to end up looking similar to this: Although I have come close to achieving the desired result, I am encountering some issues: Firstly, the first segment is over ...