Bianca
Bianca

Reputation: 33

Click nested elements in JavaScript

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]
    }
}

Upvotes: 1

Views: 741

Answers (2)

Turnip
Turnip

Reputation: 36632

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;
}

Upvotes: 3

Fennec
Fennec

Reputation: 1872

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;
}

Upvotes: 0

Related Questions