2

On clicking, the url must change, and the image as well. I lost about 6h of my life to find a solution but now I'm here. Could anyone help...

/*
-----------------------------------------
Right-top sound box
-----------------------------------------
*/
function init() {
  let rtsb = document.querySelector('#backSound');

  function changeSound() {
    // changing sound image:
    let url1 = "url('https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOn1.jpg?v=1595501327338')";
    let url2 = "url('https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOff2.jpg?v=1595501337285')";
    let imSrc = rtsb.style.backgroundImage;
    imSrc = url1;

    if (imSrc === url1) {
      imSrc = url2;
    } else if (imSrc === url2) {
      imSrc = url1;
    }
  }

  rtsb.addEventListener('click', changeSound);
}

document.addEventListener('readystatechange', function() {
  if (document.readyState === "complete") {
    init();
  }
});
<div id="backSound" style="height:200px"></div>
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
hjemlandet
  • 25
  • 3
  • Is it what you expect? `console.log(imSrc, url1)` Look at this line `imSrc = url1;` what do you think is happening? What do you think is happening in the if right after that? – epascarello Jul 23 '20 at 16:02
  • You're not assigning `imSrc` back to `rtsb.style.backgroundImage`. At the end of `changeSound` put: `rtsb.style.backgroundImage = imSrc;` – ibrahim mahrir Jul 23 '20 at 16:02
  • Oh, I added rtsb.style.backgroundImage = imSrc at the end of changeSound, but it changes the image only once - when i click one more time it does not change back to default – hjemlandet Jul 23 '20 at 16:09
  • @hjemlandet remove the line `imSrc = url1;` right before the `if` and use `else` instead of `else if(...)` – ibrahim mahrir Jul 23 '20 at 16:11
  • @hjemlandet can you use css? – ibrahim mahrir Jul 23 '20 at 16:13
  • In CSS, I preinstalled the background that's contained in url1; but i created a custom button (
    ) with this background image. And when I click, this image must change to another, because it's a sound moderation button and i signals to chosen option (if sound on or off) That's why it's important
    – hjemlandet Jul 23 '20 at 16:20
  • and what interesting, when I remove the line imSrc = url1; and change (else if) to just (if) - it does not work at all) – hjemlandet Jul 23 '20 at 16:24

4 Answers4

3

You assume that the css will match exactly what you set. Issue is it will change the value. In your case it was changing the ' to a " so it would not match.

function init() {
  let rtsb = document.querySelector('#backSound');

  function changeSound() {
    // changing sound image:
    let url1 = 'url("https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOn1.jpg?v=1595501327338")';
    let url2 = 'url("https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOff2.jpg?v=1595501337285")';
    let imSrc = rtsb.style.backgroundImage;
    if (imSrc === url1) {
      rtsb.style.backgroundImage = url2;
    } else {
      rtsb.style.backgroundImage = url1;
    }
  }

  rtsb.addEventListener('click', changeSound);
}

document.addEventListener('readystatechange', function() {
  if (document.readyState === "complete") {
    init();
  }
});
<div id="backSound" style="height:200px">xxx</div>

Better solution is to just toggle a css class.

epascarello
  • 204,599
  • 20
  • 195
  • 236
2

This could be a lot simpler if you use css and toggle between the two images using a class.

I'll use the class sound-off to indicate that the second image is being used, if the class is not set then the fallback (sound-on image) will be used by default:

CSS: #backSound.sound-off is more specific than #backSound so when the class is set, the second image is used, otherwise the first one is used.

#backSound {
  background-image: url('https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOn1.jpg?v=1595501327338');
}

#backSound.sound-off {
  background-image: url('https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOff2.jpg?v=1595501337285');
}

JS: When a click happens, simply toggle the class sound-off on and off.

function changeSound() {
  rtsb.classList.toggle("sound-off");
}

Demo:

function init() {
  let rtsb = document.querySelector('#backSound');
  rtsb.addEventListener('click', e =>
    rtsb.classList.toggle("sound-off")
  );
}

document.addEventListener('readystatechange', function() {
  if (document.readyState === "complete") {
    init();
  }
});
#backSound {
  background-image: url('https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOn1.jpg?v=1595501327338');
  width: 100px;
  height: 100px;
  background-size: cover;
}

#backSound.sound-off {
  background-image: url('https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOff2.jpg?v=1595501337285');
}
<div id="backSound"></div>
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
  • @hjemlandet check out the **demo** – ibrahim mahrir Jul 23 '20 at 16:32
  • It works good, thanks! Although, I'm thinking on what can i do to make it work in just js... Maybe i should use promises and async code – hjemlandet Jul 23 '20 at 16:37
  • 1
    @hjemlandet I highly recommend that you stick to using css for this kind of stuff, otherwise you'll have to come up with another way of figuring which image is used because once the `backgroundImage` property is assigned to the value may get changed (for example the single quote `'` will become the double quote `"` and that will invalidate the `===` test you use in `if` as `url("...") !== url('...')`) – ibrahim mahrir Jul 23 '20 at 16:44
  • @hjemlandet If you have to do it in js you can use a class to keep track of which image to use. Don't forget to toggle it on and off on each click – ibrahim mahrir Jul 23 '20 at 16:46
1

Welcome to Stackoverflow. I will be the guy who comes up with the hippy solution.

You can have a checkbox in your HTML, remove JavaScript and use CSS only like so:

input[type="checkbox"] {
    display:none;
}

input[type="checkbox"] + span {
    display:inline-block;
    width:500px;
    height:500px;
    padding-top: 5px; /* align the label with the image*/
    vertical-align:middle;
    background:url(https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOn1.jpg?v=1595501327338) left top no-repeat;
    cursor:pointer;
}

input[type="checkbox"]:checked +  span {
    background:url(https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOff2.jpg?v=1595501337285) left top no-repeat;
}
<label>
    <input type="checkbox" id="c1" name="cc" class="mycheckbox" />
    <span></span>
</label>
Florin Simion
  • 448
  • 9
  • 20
  • CSS-only, impressive! Although I still think OP is gonna use js as the icons suggest they want to mute/unmute some sort of sound which can't be done via CSS alone, at least not without a framework like angular or vuejs where you can just bind the `checked` state of the checkbox in html – ibrahim mahrir Jul 24 '20 at 00:03
0
function changeSound() {
    // changing sound image:
    let url1 = "url('https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOn1.jpg?v=1595501327338')";
...
    let imSrc = rtsb.style.backgroundImage;
    imSrc = url1;

You are assigning url1 back to imSrc, therefore imSrc = "url('https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOn1.jpg?v=1595501327338')"
Do you expect rtsb.style.backgroundImage to also be changed? That is not the case as you are only changing the value assigned to the variable imSrc.

Simply:

function changeSound() {
    // changing sound image:
    let url1 = "url('https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOn1.jpg?v=1595501327338')";
    let url2 = "url('https://cdn.glitch.com/00f52d97-70e5-4e02-98af-d0b48468a631%2FsoundOff2.jpg?v=1595501337285')";
    let imSrc = rtsb.style.backgroundImage;

    if (imSrc === url1) {
      rtsb.style.backgroundImage = url2;
    } else if (imSrc === url2) {
      rtsb.style.backgroundImage = url1;
    }
  }
  • 1
    It still won't work because the single quotes `'` are transformed into double quotes `"` when assigned to `backgroundImage` and that will make the both `===` fail because `" !== '`, see [@epascarello's answer](https://stackoverflow.com/questions/63058407/why-does-this-code-not-work-urls-are-surely-fine-but-nothing-happens#63061261) for more details – ibrahim mahrir Jul 23 '20 at 23:57