4

So I'm creating multiple new child divs inside another parent div with this code:

var parentDiv = document.querySelector('.parent-div')
const newDiv = document.createElement('div');
parentDiv.appendChild(newDiv);

So now I want to add an onlick event for every div I created, that resets the color for every other div inside the parent div, so that no multiple child divs are selected, and then set the color only for the clicked div to another color!

Any ideas?

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
bl4ckshoxx
  • 51
  • 5
  • 1
    Add a single onclick handler on parent and handle event.target – DraganS Oct 16 '21 at 19:00
  • @Dragan good advice but, as a rule of thumbs, never use `event.target` without the `.closest()` method. Otherwise `target` might not represent what you expected to. – Roko C. Buljan Oct 16 '21 at 19:03
  • Just my curiosity: in the given example, where do I need to use closest? – DraganS Oct 16 '21 at 19:14
  • @DraganS in the same place where you use `event.target`... Or in other words `event.target.closest(".some_selector")` – Roko C. Buljan Oct 16 '21 at 22:28
  • what about currentTarget? https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget – Eduard Jacko Oct 16 '21 at 22:46
  • bl4ckshoxx - my advice to you - keep in mind that software development is not a religion - avoid to use dogmas. For example, if your requirement is to add an "Approve" button to your child divs and click on the button shouldn't change selection you shouldn't use closest. If you need to add an icon, then the selector closest is welcome :) In the given solution, you don't need closest. Also, let's say that you have margin around your items. Then you will be able to click the parent div, and click will add 'active' class to it. – DraganS Oct 17 '21 at 08:00

5 Answers5

1

var parentDiv = document.querySelector('.parent-div');
for (let i = 0; i < 10; ++i) {
  const newDiv = document.createElement('div');
  newDiv.className = "my-class";
  newDiv.innerText = `Foo${i}`;
  parentDiv.appendChild(newDiv);
}
parentDiv.onclick = (event) => {
  document.querySelectorAll('.my-class').forEach((el) => {
    el.className = "my-class";
  });
  event.target.className += " active";
}
.my-class {
  color: red;
}

.active {
  color: blue;
}
<div class="parent-div"></div>
DraganS
  • 2,621
  • 1
  • 27
  • 40
  • bl4ckshoxx - this is a lazy man solution. Small improvement might be to keep the active child div in a var (x) and replace loop in the click handler with x.className = 'my-class'; x = event.target; ... – DraganS Oct 16 '21 at 19:18
  • But this onclick event gets triggered when i press the parent div. I want every child div i create to hold an onclick method which when executed resets the color of all div and set the color of the pressed div, so that only one div is colored. Dont know if u get what im saying :D i tried ur way but the color on the other divs dont reset – bl4ckshoxx Oct 16 '21 at 20:07
  • Added css for you - just click "Run code snippet" and click some item – DraganS Oct 16 '21 at 20:29
  • This might be useful article to understand how the example does work: https://stackoverflow.com/questions/4616694/what-is-event-bubbling-and-capturing – DraganS Oct 16 '21 at 20:40
  • In JS, avoid using `parentDiv.onclick`. There's the superior `Element.addEventListener()`. Also, don't use `className = ` Use `Element.classList` and its appropriate methods like `add()`, `remove()`, `toggle()` etc. – Roko C. Buljan Oct 16 '21 at 22:32
0
        let parentDiv = document.querySelector('.parent-div');
        for (let x = 0; x < 10; x++) {

         let newDiv = document.createElement('div');
       newDiv.classList.add('see')

        parentDiv.appendChild(newDiv);
      }


      parentDiv.addEventListener('click', (e) => {
       if (e.target.tagName === 'DIV') {
         e.target.style.backgroundColor = 'red';
       }
     })
Remus
  • 26
  • 2
  • You should format the code with https://beautifier.io/ or something and add some comments to explain what the code does. – umitu Oct 17 '21 at 01:27
0

Just to suggest a more robust and flexible way:

// Utility functions
const EL = (sel, EL) => (EL||document).querySelector(sel);
const ELS = (sel, EL) => (EL||document).querySelectorAll(sel);
const ELNew = (tag, prop) => Object.assign(document.createElement(tag), prop);

// Now...

// Get element (Use an ID, not a class)
const EL_parent = EL('#parent');

// Function to toggle "is-active" class
const toggleActive = (EL_target, EL_parent) => {
  const EL_active = EL(".is-active", EL_parent);
  if (EL_active) EL_active.classList.remove("is-active");
  EL_target.classList.add("is-active");
};

// Function to create new child elements
const newChild = (content) => ELNew("div", {
  className: "child",
  innerHTML: content,
  onclick() {
    toggleActive(this, EL_parent);
  }  
});

// Create a couple of elements....
EL_parent.append(
  newChild("1 Lorem"),
  newChild("2 Ipsum"),
  newChild("3 Dolor"),
);
.is-active {
  background: gold;
}
<div id="parent"></div>

So just a better way, and to avoid sloppy code like className = or Event.target without the use of .closest(), as shown in the other answers.

Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
-1

I'm not sure if this is how you would want to do it for many reasons, but it might be beneficial for you to change the HTML value of the parent div. For example,

var parentDiv = document.querySelector('.parent-div')
parentDiv.innerHTML = parentDiv.innerHTML + "<div class='{class name}'></div>";
Dharman
  • 30,962
  • 25
  • 85
  • 135
Isaac
  • 1
-1

The approach proposed here is aware of which div was clicked the last time, changes its style accordingly and creates the onclick when the item is created.

var parentDiv = document.querySelector('.parent-div');
let lastDiv = undefined;
for (let i = 0; i < 10; i++) {
    let newDiv = document.createElement('div');
    newDiv.style.width = "100px";
    newDiv.style.height = "100px";
    newDiv.style.backgroundColor = "black";
    newDiv.style.border = "1px solid white";
    newDiv.onclick = function() {
        if (lastDiv) lastDiv.style.backgroundColor = "black";
        newDiv.style.backgroundColor = "green";
        lastDiv = newDiv;
    };
    parentDiv.appendChild(newDiv);
}
<div class="parent-div"></div>
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175