rufus
rufus

Reputation: 857

Javascript click and toggle class issue

I am just playing around trying to get a simple 3 slide slider working but run into some issues with the javascript. All i want to happen is on click of the slider colour i would like the current slider to slide out and the selected one to slide in. I am trying to do it by adding an active class to the slider number that I have clicked to show. I just cant quite work out where I have gone wrong. I don't want to use jQuery as I am trying to learn vanilla javascript.

Thanks as always

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

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

Upvotes: 1

Views: 82

Answers (4)

Naga Sai A
Naga Sai A

Reputation: 10975

To achieve expected result, use below option

  1. Use one section to avoid looping of section elements

  2. Use querySelectorAll or elementsByClassName instead of querySelector to fetch all elements in array

  3. Use forEach to loop through all elements of class- box and add addEventListener and run another loop with forEach for span elements

  4. Use classList to add or remove

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>

code sample - https://codepen.io/nagasai/pen/vRoPwp

Upvotes: 1

raul.vila
raul.vila

Reputation: 1984

Another less verbose 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>

Upvotes: 1

Leeish
Leeish

Reputation: 5213

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 primitive example solution. It's overly verbose but shows you what is needed. This can be condensed.

To get an idea of how it can be condensed, all three listeners CAN be condensed into a single listener how you had it, listen just to the .box selector. But if you do that, you need a way to identify which box was clicked. This can be done via a data attribute or by looking at the html text. A data attribute would be my preferred method, as it separates the content from the logic a bit, but either would work.

Upvotes: 2

Brandon Mowat
Brandon Mowat

Reputation: 374

You're only adding an event listener to the first box and you're toggling every box's active class in order, and the last one is yellow, so you result with a yellow background.

querySelector returns the first DOM element it finds, which is the red box.

For the functionality that you want, you have to add event listeners to each box (querySelectorAll)

Upvotes: 4

Related Questions