1

Using only JavaScript, I want to create five nested divs. When clicking one of them, I want that only that div's background to change its color (according to an array of colors).

My problem here is that, because the divs are nested, clicking on any one of them will just color the largest one (the parent). The rest of the code is okay because if I struggle to click on a border, I can actually achieve what I want. But the idea is to work when clicking inside of the smaller div.

var currentParent = document.body;
var colors = ['red', 'black', 'green', 'pink', 'purple']
var divArray = []

for (let i = 0; i < 5; i++) {
    let currentDiv = document.createElement("div")
    currentDiv.style.width = `${(i * 10 + 20)}px`
    currentDiv.style.height = `${(i * 10 + 20)}px`
    currentDiv.position = i
    currentParent.append(currentDiv)
    divArray.push(currentDiv)
    currentParent = currentDiv
}

for (let i = 0; i < 5; i++) {
    divArray[i].onclick = function() {
        this.style.backgroundColor = colors [this.position]
    }
}
2
  • look into event.stopPropagation, and learn about event "bubbling". See e.g. javascript.info/bubbling-and-capturing Commented Sep 7, 2020 at 18:44
  • You can use stopPropagation to prevent event bubbling to parents but will need more advanced css if you want the children of the one you click unchanged Commented Sep 7, 2020 at 18:47

2 Answers 2

4

Each loop, a DIV larger than its parent is appended. This means that only the last div can be clicked because it covers the others.

If the sizing logic is reversed so that the DIVs become smaller each loop, the code will work as you expect.

Use event.stopPropagation(); to prevent the event from bubbling to the other elements.

var currentParent = document.body;
var colors = ['red', 'black', 'green', 'pink', 'purple']
var divArray = []

for (let i = 0; i < 5; i++) {
    let currentDiv = document.createElement("div")
    currentDiv.style.width = `${(60 - i * 10)}px`
    currentDiv.style.height = `${(60 - i * 10)}px`
    currentDiv.position = i
    currentParent.append(currentDiv)
    divArray.push(currentDiv)
    currentParent = currentDiv
}

for (let i = 0; i < 5; i++) {
    divArray[i].onclick = function(e) {
        e.stopPropagation();
        this.style.backgroundColor = colors [this.position]
    } 
}
div {
  outline: 1px solid orange;
  background: #FFF;
}

Sign up to request clarification or add additional context in comments.

Comments

0

You need to stop event Propagation on the onclick event, like so

divArray[i].onclick = function(event) {
  event.stopPropagation();
  this.style.backgroundColor = colors [this.position]
}

There is also preventDefault, to prevent the default behaviors, like a link or form button for example.

var currentParent = document.body;
var colors = ['red', 'black', 'green', 'pink', 'purple']
var divArray = []

for (let i = 0; i < 5; i++) {
    let currentDiv = document.createElement("div")
    currentDiv.style.width = `${(i * 10 + 20)}px`
    currentDiv.style.height = `${(i * 10 + 20)}px`
    currentDiv.position = i
    currentParent.append(currentDiv)
    divArray.push(currentDiv)
    currentParent = currentDiv
}

for (let i = 0; i < 5; i++) {
    divArray[i].onclick = function() {
        this.style.backgroundColor = colors [this.position]
    }
}
div{
  border: 1px solid #000;
}

1 Comment

Pretty sure it's a css problem, check the positions of your divs, if you are using position:absolute or position:relative check the z-index ... I can't tell without your css, but from the js the divs are getting bigger and bigger, in a way that the last div cover the precedent one (you can't click the precedent div) ... edited my answer to illustrate the issue

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.