J'ai plusieurs divs qui, lorsqu'ils sont cliqués, ajoutent une bordure et les redimensionnent un peu. Je fais une boucle sur tous les éléments en utilisant foreach et sur clic, je supprime la bordure et la propriété d'échelle de chaque élément, sauf l'élément cliqué, auquel j'ajoute une bordure et une échelle. Mon code est complètement logique et est censé fonctionner, mais pour une raison quelconque, je ne semble pas comprendre, il applique uniquement les styles aux éléments cliqués mais ne les supprime pas du reste des éléments (comme mon code le dit).

JS

    document.querySelectorAll('.projcolorpick div').forEach(el => {
            el.onclick = (e) => {
                el.style.border = "none"
                el.style.transform  = "scale(1)"
                e.target.style.border = "2px solid #fff"
                e.target.style.transform = "scale(1.2)" 
                projcolor = e.target.style.background   
            }
        }) 
     } 
1
Uriel 28 août 2020 à 07:34

3 réponses

Meilleure réponse

Essayez quelque chose comme ça ... chaque élément a besoin d'un attribut id pour que cela fonctionne (la partie filtre - s'il y a un attribut unique ...)

    const list = Array.from(document.querySelectorAll('.projcolorpick div'));
    list.forEach(el => {
            el.addEventListener('click', (e) => {
                //code that affects the element you click on
                el.style.border = "2px solid #fff"
                el.style.transform = "scale(1.2)" 
                projcolor = e.target.style.background;
                list.filter(x=>x.id!=el.id).forEach(otherEl=>{
                    //code that affects the other elements you didn't click on
                    otherEl.style.border = "none"
                    otherEl.style.transform  = "scale(1)"
                });
            });
        }); 
     
    ```
edit:
fixed some typos.
1
altruios 28 août 2020 à 04:51

Vous n'avez pas vraiment besoin d'un attribut id sur chaque div et je recommanderais d'utiliser des attributions de classe au lieu de changer leurs attributs individuels. Vous pouvez comparer les éléments DOM réels les uns avec les autres comme c==ev.target, comme vous pouvez le voir dans mon code ci-dessous:

// === populate the page first ... ============================= START =
const cont=document.getElementById('container');
cont.innerHTML=
[...Array(3)].map(cp=>'<div class="projcolorpick">'+
  [...Array(8)].map(d=>{
    let hsl= "hsl("+Math.floor(Math.random()*360)+",100%,80%)";
    return '  <div style="background-color:'+hsl+'">'+hsl+'</div>'}).join('\n')
  +'</div>').join('\n');
// === populate the page first ... =============================== END =
  
// now, do the action:
cont.onclick=ev=>{
  if (   ev.target.parentNode.classList.contains('projcolorpick')
      && ev.target.tagName=='DIV'){
    [...ev.target.parentNode.children].forEach(c=>c.classList.toggle('selected',c==ev.target));
    ev.target.parentNode.style.backgroundColor=ev.target.textContent;
  }
}
.projcolorpick {border: 2px solid #888}
.selected {border: 2px solid #fff; transform:scale(1.2);}
div {margin:6px; padding:4px}
.projcolorpick div {width:200px; height:20px}
<div id="container"></div>

L'action se déroule ici:

cont.onclick=ev=>{
      if (   ev.target.parentNode.classList.contains('projcolorpick')
          && ev.target.tagName=='DIV'){
        [...ev.target.parentNode.children].forEach(c=>c.classList.toggle('selected',c==ev.target));
        ev.target.parentNode.style.backgroundColor=ev.target.textContent;
      }
    }

J'utilise une pièce jointe d'événement déléguée à la div .container parent. La première instruction if garantit que seuls les clics sur les éléments .projcolorpick>div sont traités.

Si vous souhaitez inclure plus d'une génération entre elles, vous devez utiliser quelque chose comme ev.target.closest('.projcolorpick') à la place ...

Maintenant, à l'intérieur du bloc if, deux choses se produisent:

  1. En utilisant toggle() sur tous les éléments DOM de ev.target.parentNode.children, la classe "selected" est soit
    • attribué ou
    • supprimé.
  2. Le texte trouvé dans le div cliqué est appliqué en tant que background-color au conteneur parent .projcolorpick.
1
cars10m 28 août 2020 à 08:57

forEach s'applique uniquement aux Array, sauf si vous le configurez autrement.

querySelectorAll ne renvoie pas de tableaux, mais des objets de type tableau (NodeLists)

Pour autoriser le bouclage sur NodeList s, ajoutez le code suivant:

if (window.NodeList && !NodeList.prototype.forEach) { 
    NodeList.prototype.forEach = Array.prototype.forEach;
}


var nL = document.querySelectorAll('*');

console.log(nL instanceof NodeList); // true
1
Kithraya 28 août 2020 à 04:54