Tristan Tran
Tristan Tran

Reputation: 1513

Toggle button background color when clicked

I have this function, intended to toggle the background between two predefined colors of a button each time it is clicked:

const showAvailButtonClicked = (targetButton, clickedColor, unClickedColor) => {
  let clickedElement = document.getElementById(targetButton)
  let currColor = clickedElement.style.backgroundColor
  if (currColor == clickedColor) {
    clickedElement.style.backgroundColor = unClickedColor
  } else {
    alert("Current color:" + currColor)
    clickedElement.style.backgroundColor = clickedColor
  }
}

let targetButton = document.getElementById("testbutton")
targetButton.addEventListener("click", () => {
  showAvailButtonClicked("testbutton","#ba0202", "#0f2e0c")
})
#testbutton {
  background-color: #0f2e0c;
}
<button id="testbutton">Toggle</button>

I encounter two issues with this simple code above:

1 - The button starts out with this color unClickedColor = #0f2e0c. However, on the very first click, the alert does not register any color. ie. the alert message shows Current color: only.

2 - On the 2nd and subsequent clicks, the registered color from this line let currColor = clickedElement.style.backgroundColor gives RGB format rgb(r, g, b). How do I force it into hexadecimal format so that I can make the color comparison? Thanks.

Upvotes: 2

Views: 6470

Answers (3)

Jon P
Jon P

Reputation: 19772

Use getComputedStyle and keep RGB, no reason why you can't use it. Alos use data attribute to store the alternate color for various buttons and then to store the original color.

document.querySelectorAll(".toggle").forEach(function(el) {
  //Don't use arrow function we want acces to "this"
  el.addEventListener("click", function() {
    //grab the computed style
    let style = getComputedStyle(this);
    //Note color will be RGB
    console.log("Current color: " + style.backgroundColor);
    //Store current color
    let tempStyle = style.backgroundColor;
    //swap the color
    this.style.backgroundColor = this.dataset.altcolor;
    //store the previous color
    this.dataset.altcolor = tempStyle;
  });
});
.toggle {
  background-color: #0f2e0c;
}

.toggle.alt {
  background-color: #0000FF;
}
<button class="toggle" data-altcolor="#ba0202">Toggle</button>
<button class="toggle" data-altcolor="#ff0000">Toggle</button>
<button class="toggle alt" data-altcolor="#00ff00">Toggle</button>

Upvotes: 1

gavgrif
gavgrif

Reputation: 15499

Far better off to attach a class to the button on the click and have the styling on that class.

The following snippet has the base background color set for the button and then when its clicked - toggles a"clicked" class - that when applied - provides an alternate background color.

This is simpler to implement because you are not having to determine the existing background color followed by some funky hex comparison and also its much better to separate the html, js and css into their own realms.

let testButton = document.getElementById("testbutton");

testButton.addEventListener("click", () => {
  testButton.classList.toggle('clicked');
})
#testbutton {
  background-color: #0f2e0c;
  color: white
}

#testbutton.clicked {
  background-color: #ba0202;
}
<button id="testbutton">Toggle</button>

Upvotes: 5

Sifat Haque
Sifat Haque

Reputation: 6057

  1. You need to use window.getComputedStyle(clickedElement).backgroundColor. The style property only contains styles assigned in a style attribute or set by scripting. You can also use the following instead:
const currColor = window.getComputedStyle ? window.getComputedStyle(clickedElement, null).getPropertyValue("background-color") : clickedElement.style.backgroundColor;
  1. By default browser will give you rgb value. You need to convert that to hex manually. I've used this function for that purpose.
function rgb2hex(rgb) {
    if (/^#[0-9A-F]{6}$/i.test(rgb)) return rgb;

    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2);
    }
    return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

function rgb2hex(rgb) {
    if (/^#[0-9A-F]{6}$/i.test(rgb)) return rgb;

    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2);
    }
    return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

const showAvailButtonClicked = (targetButton, clickedColor, unClickedColor) => {
  let clickedElement = document.getElementById(targetButton);

  let currColor = rgb2hex(window.getComputedStyle(clickedElement).backgroundColor);

  alert("Current color:" + currColor);
  
  if (currColor == clickedColor) {
    clickedElement.style.backgroundColor = unClickedColor
  } else {
    clickedElement.style.backgroundColor = clickedColor
  }
}

let targetButton = document.getElementById("testbutton")

targetButton.addEventListener("click", () => {
  showAvailButtonClicked("testbutton","#ba0202", "#0f2e0c")
})
#testbutton {
  background-color: #0f2e0c;
  color: #fff;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <button id="testbutton">Toggle</button>

</body>
</html>

Upvotes: 3

Related Questions