Home > database >  Why last function is applying to other elements also on 2nd change
Why last function is applying to other elements also on 2nd change

Time:09-29

I have created a color changer for different properties like border & background for elements.

Color changing 1 at a time but issue occurs when I click on next element , now the color of both elements changes (on next click) . Is there a way to change only 1 at a time .

The method to solve this can be creating a color-picker with each click and remove when work is done but if possible can the solution be regarding the input color-picker in html

To see the issue :
1)Click on any circle & change its color (works fine)
2)Now click on any other circle and try to change its color
Issue seen : Now on 2nd step both circles color changes at same time

var restyleBG = document.getElementsByClassName("restyleBackground")
for (let i = 0; i < restyleBG.length; i  ) {
  restyleBG[i].addEventListener('click', changeBGcolor)

  function changeBGcolor() {
    event.stopPropagation()
    var colorPicker = document.getElementById("colorClock");
    colorPicker.click();
    colorPicker.addEventListener('input', function() {
      var colorPickerVal = colorPicker.value;
      restyleBG[i].style.backgroundColor = colorPickerVal;
    })
  }
}
#clockStyleCircle {
  position: absolute;
  width: 16vw;
  height: 16vw;
  text-align: center;
  padding: 0%;
  top: 28.5%;
  left: 28.5%;
  border-radius: 50%;
  border: 3px solid black;
  background-color: rgb(255, 233, 35);
  z-index: 1;
}

#clockOuterCircle {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 42vw;
  height: 42vw;
  margin: auto;
  border-radius: 50%;
  border: 4px solid rgb(255, 62, 62);
  background-color: rgb(253, 133, 133);
  user-select: none;
}

#another-circle {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 4px green solid;
  background-color: blue;
  position: absolute;
  top: 20px;
  left: 20px;
}

.colour-picker {
  display: none;
}
<body>
  <input type="color" name="colorClock" id="colorClock">
  <div id="clockOuterCircle" class="restyleBackground">
    <div id="clockStyleCircle" class="restyleBackground"></div>
  </div>
  <!-- another circle -->
  <div id="another-circle" class="restyleBackground"></div>
  <!-- ... -->
</body>

Thanks for help in advance

CodePudding user response:

What is going on ?

Your problem here is that for every time you click on a circle you add an EventListener to your colorPicker which then changes the color of the circle. So every time you change the value of the colorPicker, the circles that got clicked on change their color.

How to achieve what you want

You could try to remove the EventListener after the change happened, but this isn't good practice. What you should do is create a global variable that holds the index to the current circle of the circles array that got clicked on and add an EventListener to the input element, that changes the color of the circle with the index of that reference variable. Below you can see the code.

var restyleBG = document.getElementsByClassName("restyleBackground")

let current = 0;

var colorPicker = document.getElementById("colorClock");
colorPicker.addEventListener('input', function() {
      restyleBG[current].style.backgroundColor = colorPicker.value;
 })

for (let i = 0; i < restyleBG.length; i  ) {
  restyleBG[i].addEventListener('click', changeBGcolor)

  function changeBGcolor() {
    event.stopPropagation()
    colorPicker.click();
    current = i;
  }
}
#clockStyleCircle {
  position: absolute;
  width: 16vw;
  height: 16vw;
  text-align: center;
  padding: 0%;
  top: 28.5%;
  left: 28.5%;
  border-radius: 50%;
  border: 3px solid black;
  background-color: rgb(255, 233, 35);
  z-index: 1;
}

#clockOuterCircle {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 42vw;
  height: 42vw;
  margin: auto;
  border-radius: 50%;
  border: 4px solid rgb(255, 62, 62);
  background-color: rgb(253, 133, 133);
  user-select: none;
}

#another-circle {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 4px green solid;
  background-color: blue;
  position: absolute;
  top: 20px;
  left: 20px;
}

.colour-picker {
  display: none;
}
<body>
  <input type="color" name="colorClock" id="colorClock">
  <div id="clockOuterCircle" class="restyleBackground">
    <div id="clockStyleCircle" class="restyleBackground"></div>
  </div>
  <!-- another circle -->
  <div id="another-circle" class="restyleBackground"></div>
  <!-- ... -->
</body>

CodePudding user response:

As I said in comments on every click you were adding new event listeners so after the second click there you have more than one event registered. so from the second click, your input Listener will call all previous color changes, that's why it is changing the color of all 3 circles. I have removed the listener after every color change so this code works fine

Check the console once to get the listener calls, also check by removing the "removeEventListener" and check how many "input event called" will appear after changing color if all three circles (this will help to understand the problem in your code )

Also, you may not be needed to add an input evenlistener inside the loop, I have approached same to understand the problem in your code You can add eventListner outside the loop So that you may not need to remove it

var restyleBG = document.getElementsByClassName("restyleBackground")
   var colorPicker = document.getElementById("colorClock");
   var element;
for (let i = 0; i < restyleBG.length; i  ) {
  restyleBG[i].addEventListener('click', ()=> changeBGcolor(restyleBG[i]))
 
}
function changeBGcolor(restyle) {
    event.stopPropagation()
    colorPicker.click();
    element = restyle
    colorPicker.addEventListener('input', respond)
}
function respond() {
      var colorPickerVal = colorPicker.value;
      console.log('input event called')
      element.style.backgroundColor = colorPickerVal;
}

colorPicker.addEventListener('change',function (){
    console.log('input event removed')
   colorPicker.removeEventListener('input', respond)
})
#clockStyleCircle {
  position: absolute;
  width: 16vw;
  height: 16vw;
  text-align: center;
  padding: 0%;
  top: 28.5%;
  left: 28.5%;
  border-radius: 50%;
  border: 3px solid black;
  background-color: rgb(255, 233, 35);
  z-index: 1;
}

#clockOuterCircle {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 42vw;
  height: 42vw;
  margin: auto;
  border-radius: 50%;
  border: 4px solid rgb(255, 62, 62);
  background-color: rgb(253, 133, 133);
  user-select: none;
}

#another-circle {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 4px green solid;
  background-color: blue;
  position: absolute;
  top: 20px;
  left: 20px;
}

.colour-picker {
  display: none;
}
<body>
  <input type="color" name="colorClock" id="colorClock">
  <div id="clockOuterCircle" class="restyleBackground" >
    <div id="clockStyleCircle" class="restyleBackground" ></div>
  </div>
  <!-- another circle -->
  <div id="another-circle" class="restyleBackground" ></div>
  <!-- ... -->
</body>

  • Related