Reputation: 51
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>
Upvotes: 0
Views: 116
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
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
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
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
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