Said
Said

Reputation: 186

How to add and remove a class to a div element plain javascript

I am trying to add different classes to a div based on what is clicked, which I've managed to do, but need to remove the previously clicked/selected class and replace with the clicked one, Can't seem to get the remove part right. Most of the solutions I've come across are either toggles or adding and removing between two classes, but not 3 or more.

Thanks

This is what I have tried so far and the add part works as expected but when I click a different button it does not remove the previous clicked one

The HTML

<button id="btn-1" data-width="w-1/3">Mobile</button>
<button id="btn-2" data-width="w-2/3">Tablet</button>
<button id="btn-3" data-width="w-full">Desktop</button>

<div class="frame">
  Some Content
</div>

The Javascript

let setMobile = document.querySelector('#btn-1');
let setTablet = document.querySelector('#btn-2');
let setDesktop = document.querySelector('#btn-3');
let btns = [setMobile, setTablet, setDesktop];

function getBtnId(btn) {
    btn.addEventListener('click', function() {
        let frame = document.querySelector('.frame')
        frame.classList.add(this.dataset.width)
        if(frame.classList.contains(btns)){
            frame.classList.remove(this.dataset.width)
        }
        console.log(this.dataset.width);
    });
}

btns.forEach(getBtnId);

Basically, what I am trying to do is a responsive frame which will adjust its width depending on what is clicked.

Upvotes: 0

Views: 928

Answers (3)

Jon P
Jon P

Reputation: 19772

Here's a generalized version to work with multiple elements. I've wrapped each frame and buttons in a section element. Then I've bound the event listeners to the sections and used event bubbling / event delegation to perform the switch. I've also used a data attribute on the target frame to hold the current state.

function setWidthClass(event) {
  var newWidth = event.target.dataset.width;
  //This identifies a button click with our dataset
  if (newWidth) {
    //get the target div
    var target = this.querySelector(".frame");

    //if the target has a class set remove it
    if (target.dataset.width) {
      target.classList.remove(target.dataset.width);
    }

    //Add the new class 
    target.classList.add(newWidth);

    //Update the data on the target element
    target.dataset.width = newWidth;
  }
}

//Add the event listener
var sections = document.querySelectorAll(".varyWidth");
for (var i = 0; i < sections.length; i++) {
  sections[i].addEventListener("click", setWidthClass);
}
.w-third {
  color: red;
}

.w-half {
  color: blue;
}

.w-full {
  color: green;
}
<section class="varyWidth">
  <button data-width="w-third">Mobile</button>
  <button data-width="w-half">Tablet</button>
  <button data-width="w-full">Desktop</button>

  <div class="frame">
    Some Content
  </div>
</section>
<section class="varyWidth">
  <button data-width="w-third">Mobile</button>
  <button data-width="w-half">Tablet</button>
  <button data-width="w-full">Desktop</button>

  <div class="frame">
    Some Content
  </div>
</section>
<section class="varyWidth">
  <button data-width="w-third">Mobile</button>
  <button data-width="w-half">Tablet</button>
  <button data-width="w-full">Desktop</button>

  <div class="frame">
    Some Content
  </div>
</section>

Upvotes: 1

j3py
j3py

Reputation: 1257

Rather than track the current class, you can also just reset it:

let setMobile = document.querySelector('#btn-1');
let setTablet = document.querySelector('#btn-2');
let setDesktop = document.querySelector('#btn-3');
let btns = [setMobile, setTablet, setDesktop];

function getBtnId(btn) {
  btn.addEventListener('click', function() {
    let frame = document.querySelector('.frame')
    
    // reset the classList
    frame.classList = ["frame"];
    
    frame.classList.add(this.dataset.width)
    console.log(this.dataset.width);
 });
}

btns.forEach(getBtnId);
<button id="btn-1" data-width="w-1/3">Mobile</button>
<button id="btn-2" data-width="w-2/3">Tablet</button>
<button id="btn-3" data-width="w-full">Desktop</button>

<div class="frame">
  Some Content
</div>

Upvotes: 0

Nidhin Joseph
Nidhin Joseph

Reputation: 10237

You can store the current class in a variable and use the remove() to remove the previous class on each click.

let setMobile = document.querySelector('#btn-1');
let setTablet = document.querySelector('#btn-2');
let setDesktop = document.querySelector('#btn-3');
let btns = [setMobile, setTablet, setDesktop];
var currentClass;

function getBtnId(btn) {
  btn.addEventListener('click', function() {
    let frame = document.querySelector('.frame')
    if (currentClass) {
      frame.classList.remove(currentClass);
    }
    currentClass = this.dataset.width;
    frame.classList.add(currentClass);
    console.log(this.dataset.width);
  });
}

btns.forEach(getBtnId);
<button id="btn-1" data-width="w-1/3">Mobile</button>
<button id="btn-2" data-width="w-2/3">Tablet</button>
<button id="btn-3" data-width="w-full">Desktop</button>

<div class="frame">
  Some Content
</div>

Upvotes: 1

Related Questions