Zerion
Zerion

Reputation: 51

Is there a more optimal way to change multiple classes and ids with javascript than this?

I'm creating a meal customisation feature on a website where the customer can choose a variety of different ingredients to configure their meal. I have the back end working perfectly, but I'm having a bit of trouble with the front end.

I've used a variety of id's, classes and functions to create a hover overlay and then apply a border around the food images once they are clicked (selected) but it's quite a long method. It works, but as there are a lot more ingredients than this (another 30) I'm a bit worried about the functions getting too long.

HTML

<img id="food" onclick="select()" src="https://website.com/uploads/2020/03/Curried-Chicken-Breast-1-scaled.jpg" style="width:250px;">

<img id="food1" onclick="select1()" src="https://website.com/uploads/2020/03/Curried-Chicken-Breast-1-scaled.jpg" style="width:250px;">

CSS:

#food:hover, #food1:hover, #food2:hover, #food3:hover, #food4:hover, #food5:hover, #food6:hover, #food7:hover{
    filter: brightness(75%); !important;
}

.selected {
  border: 3px solid #186472 !important;
}

JavaScript

<script>
function select(){
    document.getElementById("food").classList.add('selected');
    document.getElementById("food1").classList.remove('selected');
    document.getElementById("food2").classList.remove('selected');
    document.getElementById("food3").classList.remove('selected');
    document.getElementById("food4").classList.remove('selected');
    document.getElementById("food5").classList.remove('selected');
    document.getElementById("food6").classList.remove('selected');
    document.getElementById("food7").classList.remove('selected');
}

function select1(){
    document.getElementById("food").classList.remove('selected');
    document.getElementById("food1").classList.add('selected');
    document.getElementById("food2").classList.remove('selected');
    document.getElementById("food3").classList.remove('selected');
    document.getElementById("food4").classList.remove('selected');
    document.getElementById("food5").classList.remove('selected');
    document.getElementById("food6").classList.remove('selected');
    document.getElementById("food7").classList.remove('selected');
}

function select2(){
    document.getElementById("food").classList.remove('selected');
    document.getElementById("food1").classList.remove('selected');
    document.getElementById("food2").classList.add('selected');
    document.getElementById("food3").classList.remove('selected');
    document.getElementById("food4").classList.remove('selected');
    document.getElementById("food5").classList.remove('selected');
    document.getElementById("food6").classList.remove('selected');
    document.getElementById("food7").classList.remove('selected');
}

function select3(){
    document.getElementById("food").classList.remove('selected');
    document.getElementById("food1").classList.remove('selected');
    document.getElementById("food2").classList.remove('selected');
    document.getElementById("food3").classList.add('selected');
    document.getElementById("food4").classList.remove('selected');
    document.getElementById("food5").classList.remove('selected');
    document.getElementById("food6").classList.remove('selected');
    document.getElementById("food7").classList.remove('selected');
}

function select4(){
    document.getElementById("food").classList.remove('selected');
    document.getElementById("food1").classList.remove('selected');
    document.getElementById("food2").classList.remove('selected');
    document.getElementById("food3").classList.remove('selected');
    document.getElementById("food4").classList.add('selected');
    document.getElementById("food5").classList.remove('selected');
    document.getElementById("food6").classList.remove('selected');
    document.getElementById("food7").classList.remove('selected');
}

function select5(){
    document.getElementById("food").classList.remove('selected');
    document.getElementById("food1").classList.remove('selected');
    document.getElementById("food2").classList.remove('selected');
    document.getElementById("food3").classList.remove('selected');
    document.getElementById("food4").classList.remove('selected');
    document.getElementById("food5").classList.add('selected');
    document.getElementById("food6").classList.remove('selected');
    document.getElementById("food7").classList.remove('selected');
}

function select6(){
    document.getElementById("food").classList.remove('selected');
    document.getElementById("food1").classList.remove('selected');
    document.getElementById("food2").classList.remove('selected');
    document.getElementById("food3").classList.remove('selected');
    document.getElementById("food4").classList.remove('selected');
    document.getElementById("food5").classList.remove('selected');
    document.getElementById("food6").classList.add('selected');
    document.getElementById("food7").classList.remove('selected');
}

function select7(){
    document.getElementById("food").classList.remove('selected');
    document.getElementById("food1").classList.remove('selected');
    document.getElementById("food2").classList.remove('selected');
    document.getElementById("food3").classList.remove('selected');
    document.getElementById("food4").classList.remove('selected');
    document.getElementById("food5").classList.remove('selected');
    document.getElementById("food6").classList.remove('selected');
    document.getElementById("food7").classList.add('selected');
}
</script>

Image example

Upvotes: 0

Views: 116

Answers (5)

Sean
Sean

Reputation: 8040

If you're asking users to select items from a series of things, you should consider using radio buttons. Using radio buttons will make things easier from a code standpoint by removing the need to set the selected state with javascript, and it will be more accessible for users.

Here's one way to approach it with no javascript needed, making use of the :checked CSS pseudo-class and CSS adjacent sibling combinator (+) to add a red border to checked food items.

.food {
  display: inline-block;
}
.food input {
  visibility: hidden;
}
.food img {
  border: 5px solid white;
}
.food input:checked + label img {
  border: 5px solid red;
}
.food input:not(:checked) + label {
  cursor: pointer;
}
.food input:not(:checked) + label:hover img {
  opacity: 0.75;
}
<div class="food">
  <input type="radio" id="food1" name="food" value="food1" />
  <label for="food1"><img alt="food1" src="https://placehold.it/100/100/?text=food1"/></label>
</div>
<div class="food">
  <input type="radio" id="food2" name="food" value="food2" />
  <label for="food2"><img alt="food2" src="https://placehold.it/100/100/?text=food2"/></label>
</div>
<div class="food">
  <input type="radio" id="food3" name="food" value="food3" />
  <label for="food3"><img alt="food3" src="https://placehold.it/100/100/?text=food3"/></label>
</div>

Upvotes: 1

Ahmed Tag Amer
Ahmed Tag Amer

Reputation: 1422

Read JS comments:

window.onload = function() {
  var foods = document.getElementsByClassName('food'); // To get length of all food pictures.
        for(var i = 0; i < foods.length; i++) { // for loop to create click function on each image.
            var food = foods[i]; // get current class index.
            food.onclick = function() { // DOM onclick function.
                Array.from(foods).forEach(function(e){e.classList.remove('selected')}) // remove 'selected' class from all 'food' classes. 
                this.classList.add('selected'); // add selected class to current '.food'.
            }
        }
    }
.food:hover {
    filter: brightness(75%); !important;
}

.selected {
  border: 3px solid #186472 !important;
}
<img class="food" src="https://picsum.photos/200">

<img class="food" src="https://picsum.photos/200">

<img class="food" src="https://picsum.photos/200">

<img class="food" src="https://picsum.photos/200">

<img class="food" src="https://picsum.photos/200">

<img class="food" src="https://picsum.photos/200">

<img class="food" src="https://picsum.photos/200">

<img class="food" src="https://picsum.photos/200">

<img class="food" src="https://picsum.photos/200">

Upvotes: 0

Mister Jojo
Mister Jojo

Reputation: 22320

You have to use
- a better CSS
- the div for group images
- event delegation

HTML

<div id="Group-Images">
  <img id="food1" src="Curried-Chicken-Breast-1-scaled.jpg" >
  <img id="food2" src="Curried-Chicken-Breast-2-scaled.jpg" >
  <img id="food3" src="Curried-Chicken-Breast-3-scaled.jpg" >
</div>

CSS

#Group-Images > img {
  width: 250px;
}
#Group-Images > img:hover {
  filter: brightness(75%) !important;
}
#Group-Images > img.selected {
  border: 3px solid #186472 !important;
}

JS

const GroupImages = document.getElementById('Group-Images')
  ,   AllImages   = GroupImages.querySelectorAll('img')
  ;
GroupImages.onclick=e=>
  {
  if (!e.target.matches('img')) return

  // console.log( e.target.id) // --> food1, food2,... foodN

  AllImages.forEach(imh=>
    {
    if (img===e.target) { img.classList.add('selected')   }
    else                { img.classList.remove('selected') }
    })
  }

Upvotes: 0

Marty1452
Marty1452

Reputation: 405

Use classes like selector:

<img class="food" onclick="select(this)" src="https://website.com/uploads/2020/03/Curried-Chicken-Breast-1-scaled.jpg" style="width:250px;">

<img class="food" onclick="select1(this)" src="https://website.com/uploads/2020/03/Curried-Chicken-Breast-1-scaled.jpg" style="width:250px;">

JavaScript will looks like this:

<script>
$food_els = document.getElementByClassName("food");
function select(e) {
    for (var i = 0; i < $food_els.length; i++) {
        if ($food_els[i] == e) {
            $food_els[i].classList.add("selected");
        }
        else {
            $food_els[i].classList.remove("selected");
        }
    }
}
</script>

Upvotes: 0

user3814024
user3814024

Reputation:

you could aways make it as a function.

function select( val ){

    for (let i = 0; i < 7; ++i){
        document.getElementById(`food${i}`).classList.remove('selected');
    } 

    document.getElementById(`food${val}`).classList.add('selected');
}

// select(1)

Upvotes: 0

Related Questions