Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Darkening an image when clicked is requiring an initial click on that image, and I don't know why

I’m trying to make an item tracker for a game as a webapp. I wanted to have the icon of each item displayed in a grid, and when you click on the image it darkens to indicate that you’ve gotten it. So far I’ve only figured out how to affect the opacity of the images, but works well enough for now. Though when the opacity starts at 1.0, it requires a second click to activate, but only for the first time. After that it works as intended, toggling on click. If I set the initial opacity to 0.5, it works on the first click.

I made a table to place the images in a grid (added 8 for the time being) and gave each one a unique id, and the class "Loot" like so:

function lootDarken(x) {
  image = document.getElementById(x);
  if (image.style.opacity === "1") {
    image.style.opacity = "0.5";
  } else {
    image.style.opacity = "1";
  }
}
<table>
  <tr>
    <td><img onClick="lootDarken('Loot1')" id="Loot1" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot2')" id="Loot2" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot3')" id="Loot3" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot4')" id="Loot4" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot5')" id="Loot5" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot6')" id="Loot6" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot7')" id="Loot7" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot8')" id="Loot8" class="Loot" src="https://picsum.photos/200/300"></td>
  </tr>
</table>

Also, if there’s a cleaner/easier way to place these images in a grid, please share. I have to go through hundreds of these.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I thought maybe it was because the opacity wasn’t officially set, and that clicking it the first only set the opacity to 1 since technically, the opacity wasn’t 1. So I added the class "Loot" in order to set the opacity on startup. That didn’t work, so I tried setting the initial opacity to 0.5 just to see what would happen and that worked wonderfully.

I also tried reversing the function, making it check if the opacity is not 1:

function lootDarken(x) {
    
    image = document.getElementById(x);
    if (image.style.opacity != "1") {
        image.style.opacity = "1";
    } else {
        image.style.opacity = "0.5";
    }
    
}

But that led to the same result. I don’t even know what is happening that’s causing this weird interaction, so I came here hoping for an explanation… and maybe tips on how to make it less repetitive.

>Solution :

The problem with the original snippet is that image.style.opacity is not set initially:

const img = document.querySelector('img');
img.onclick = function() {
  console.log('Opacity:'+this.style.opacity);
  console.log(this.style.opacity == '' ? 1 : 0);
}
<img src="https://picsum.photos/200/300">

You can solve your problem by adjusting the if-statement:

function lootDarken(x) {
  image = document.getElementById(x);
  if (image.style.opacity === "1" || image.style.opacity === "") {
    image.style.opacity = "0.5";
  } else {
    image.style.opacity = "1";
  }
}
function lootDarken(x) {
  image = document.getElementById(x);
  if (image.style.opacity === "1" || image.style.opacity === "") {
    image.style.opacity = "0.5";
  } else {
    image.style.opacity = "1";
  }
}
<table>
  <tr>
    <td><img onClick="lootDarken('Loot1')" id="Loot1" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot2')" id="Loot2" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot3')" id="Loot3" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot4')" id="Loot4" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot5')" id="Loot5" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot6')" id="Loot6" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot7')" id="Loot7" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img onClick="lootDarken('Loot8')" id="Loot8" class="Loot" src="https://picsum.photos/200/300"></td>
  </tr>
</table>

Instead of trying to modify the opacity with the style attribute, you could also toggle a class which lowers the opacity. By doing so you can also add a CSS transition to the effect

const loots = document.querySelectorAll('img.Loot');

loots.forEach(function(loot, index) {
  loot.onclick = function() {
    this.classList.toggle('dark');
  };
});
img.Loot {
  opacity: 1;
  transition: opacity 0.5s ease-in-out;
}

img.Loot.dark {
  opacity: 0.5;
}
<table>
  <tr>
    <td><img id="Loot1" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img id="Loot2" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img id="Loot3" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img id="Loot4" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img id="Loot5" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img id="Loot6" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img id="Loot7" class="Loot" src="https://picsum.photos/200/300"></td>
    <td><img id="Loot8" class="Loot" src="https://picsum.photos/200/300"></td>
  </tr>
</table>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading