Home > Net >  How do i apply multiple classList.toggle to same class or id to avoid repetition?
How do i apply multiple classList.toggle to same class or id to avoid repetition?

Time:10-09

I'm a beginner in javascript so I'm still learning but I have the impression that my code is too repetitive but I don't know how to improve it, moreover I try to apply the same code to the same html element which have the same id or the same class but it doesn't work every time it applies only to the first element(as you can see with the arrow animation) so i have to repeate the same code and change the class name again and again.

Thanks in advance to those who will help me.

const projet1 = document.getElementById("projet1");
const projet2 = document.getElementById("projet2");
const projet3 = document.getElementById("projet3");

const prj = document.getElementById("prj");
var arrow = document.querySelectorAll(".arrow-down")[0]

projet1.style.display = "none";
projet2.style.display = "none";
projet3.style.display = "none";

prj1.onclick = function () {
    if (projet1.style.display !== "none") {
        projet1.style.display = "none";
        arrow.classList.toggle('rotate-arrow')

    } else {
        projet1.style.display = "flex";
        arrow.classList.toggle('rotate-arrow')

    }
    
};

prj2.onclick = function () {
    if (projet2.style.display !== "none") {
        projet2.style.display = "none";
        arrow.classList.toggle('rotate-arrow')

    } else {
        projet2.style.display = "flex";
        arrow.classList.toggle('rotate-arrow')

    }
    

};

prj3.onclick = function () {
    if (projet3.style.display !== "none") {
        projet3.style.display = "none";
        arrow.classList.toggle('rotate-arrow')

    } else {
        projet3.style.display = "flex";
        arrow.classList.toggle('rotate-arrow')

    }
    

};
.projet-contain{
        display: flex;
        flex-direction: column;
        margin-bottom: 50px;
        width: auto;
        height: auto;
        background: radial-gradient(circle, rgba(238,174,202,0.200) 0%, rgba(148, 188, 233, 0.200) 100%);;
        border-radius: 10px 10px 10px 10px;
        padding: 10px;
        user-select: none;
    }
    
    .preview{
        display: flex;
        justify-content: space-between;
        align-items: center;
    }
    
    section >div>div >a {
        text-decoration: none;
        color: white;
    }
    
    .convertigo{
        width: 10vw;
        
    }
    
    
    .arrow-down {
        transition: transform 0.5s;
        width: 1.5vw;
        
        -webkit-filter: invert(100%); /* safari 6.0 - 9.0 */
                filter: invert(100%);
                
    }
    
    .rotate-arrow {
        transform: rotate(180deg);
    }
    
    body{
      background:purple;
    }
<body>
        <section>
                <div id="prj1" >
                    <div >
                        <a >Projet Convertigo</a>
                        <svg   xmlns="http://www.w3.org/2000/svg" width="16" height="16"        fill="currentColor"  viewBox="0 0 16 16">
                        <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
                        </svg>
                        <img src="images/Convertigo.png"  alt="">
                    </div>
                    <div id="projet1">
                        <a>c'est la div 1</a>
                    </div>
                </div>
                <div id="prj2" >
                    <div >
                        <a >Projet Convertigo</a>
                        <svg   xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"  viewBox="0 0 16 16">
  <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
</svg>
                        <img src="images/Convertigo.png"  alt="">
                    </div>
                    <div id="projet2">
                        <a>c'est la div 2</a>
                    </div>
                </div>
                <div id="prj3" >
                    <div >
                        <a >Projet Convertigo</a>
                        <svg   xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"  viewBox="0 0 16 16">
  <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
</svg>
                        <img src="images/Convertigo.png"  alt="">
                    </div>
                    <div id="projet3">
                        <a>c'est la div 3</a>
                    </div>
                </div>
            </section>
     </body>

CodePudding user response:

You can improve javascript code by using function and querySelectorAll. Only arrow of first element was rotate because you set querySelectorAll(".arrow-down")[0] which take only first element.

const allProjet = document.querySelectorAll(".projet");

const prj = document.getElementById("prj");
var allArrows = document.querySelectorAll(".arrow-down")

allProjet.forEach(el => el.style.display = "none")

function toggleClass(el, arrow) {
    if (el.style.display !== "none") {
        el.style.display = "none";
        arrow.classList.toggle('rotate-arrow')

    } else {
        el.style.display = "flex";
        arrow.classList.toggle('rotate-arrow')

    }
    
};
prj1.onclick = () => toggleClass(allProjet[0], allArrows[0])

prj2.onclick = () => toggleClass(allProjet[1], allArrows[1])

prj3.onclick = () => toggleClass(allProjet[2], allArrows[2])
.projet-contain{
        display: flex;
        flex-direction: column;
        margin-bottom: 50px;
        width: auto;
        height: auto;
        background: radial-gradient(circle, rgba(238,174,202,0.200) 0%, rgba(148, 188, 233, 0.200) 100%);;
        border-radius: 10px 10px 10px 10px;
        padding: 10px;
        user-select: none;
    }
    
    .preview{
        display: flex;
        justify-content: space-between;
        align-items: center;
    }
    
    section >div>div >a {
        text-decoration: none;
        color: white;
    }
    
    .convertigo{
        width: 10vw;
        
    }
    
    
    .arrow-down {
        transition: transform 0.5s;
        width: 1.5vw;
        
        -webkit-filter: invert(100%); /* safari 6.0 - 9.0 */
                filter: invert(100%);
                
    }
    
    .rotate-arrow {
        transform: rotate(180deg);
    }
    
    body{
      background:purple;
    }
<body>
        <section>
                <div id="prj1" >
                    <div >
                        <a >Projet Convertigo</a>
                        <svg   xmlns="http://www.w3.org/2000/svg" width="16" height="16"        fill="currentColor"  viewBox="0 0 16 16">
                        <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
                        </svg>
                        <img src="images/Convertigo.png"  alt="">
                    </div>
                    <div id="projet1" >
                        <a>c'est la div 1</a>
                    </div>
                </div>
                <div id="prj2" >
                    <div >
                        <a >Projet Convertigo</a>
                        <svg   xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"  viewBox="0 0 16 16">
  <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
</svg>
                        <img src="images/Convertigo.png"  alt="">
                    </div>
                    <div id="projet2" >
                        <a>c'est la div 2</a>
                    </div>
                </div>
                <div id="prj3" >
                    <div >
                        <a >Projet Convertigo</a>
                        <svg   xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"  viewBox="0 0 16 16">
  <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
</svg>
                        <img src="images/Convertigo.png"  alt="">
                    </div>
                    <div id="projet3" >
                        <a>c'est la div 3</a>
                    </div>
                </div>
            </section>
     </body>

CodePudding user response:

Below is the updated code:
Added Class and inline-style: style="display:none;"
Removed IDs

const projectContain = document.querySelectorAll(".projet-contain");
projectContain.forEach((elm) => {
  elm.addEventListener("click",function(){
    let projectContent = elm.querySelector(".project-content");
    let arrow = elm.querySelector(".arrow-down");
    if (projectContent.style.display !== "none") {
        projectContent.style.display = "none";
        arrow.classList.toggle('rotate-arrow')
    } else {
        projectContent.style.display = "flex";
        arrow.classList.toggle('rotate-arrow')
    }
  });
});
.projet-contain{
        display: flex;
        flex-direction: column;
        margin-bottom: 50px;
        width: auto;
        height: auto;
        background: radial-gradient(circle, rgba(238,174,202,0.200) 0%, rgba(148, 188, 233, 0.200) 100%);;
        border-radius: 10px 10px 10px 10px;
        padding: 10px;
        user-select: none;
    }
    
    .preview{
        display: flex;
        justify-content: space-between;
        align-items: center;
    }
    
    section >div>div >a {
        text-decoration: none;
        color: white;
    }
    
    .convertigo{
        width: 10vw;
        
    }
    
    
    .arrow-down {
        transition: transform 0.5s;
        width: 1.5vw;
        
        -webkit-filter: invert(100%); /* safari 6.0 - 9.0 */
                filter: invert(100%);
                
    }
    
    .rotate-arrow {
        transform: rotate(180deg);
    }
    
    body{
      background:purple;
    }
<body>
        <section>
                <div >
                    <div >
                        <a >Projet Convertigo</a>
                        <svg   xmlns="http://www.w3.org/2000/svg" width="16" height="16"        fill="currentColor"  viewBox="0 0 16 16">
                        <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
                        </svg>
                        <img src="images/Convertigo.png"  alt="">
                    </div>
                    <div  style="display:none;">
                        <a>c'est la div 1</a>
                    </div>
                </div>
                <div >
                    <div >
                        <a >Projet Convertigo</a>
                        <svg   xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"  viewBox="0 0 16 16">
  <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
</svg>
                        <img src="images/Convertigo.png"  alt="">
                    </div>
                    <div  style="display:none;">
                        <a>c'est la div 2</a>
                    </div>
                </div>
                <div >
                    <div >
                        <a >Projet Convertigo</a>
                        <svg   xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"  viewBox="0 0 16 16">
  <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
</svg>
                        <img src="images/Convertigo.png"  alt="">
                    </div>
                    <div  style="display:none;">
                        <a>c'est la div 3</a>
                    </div>
                </div>
            </section>
     </body>

CodePudding user response:

Bind "click" event to an ancestor element that contains all elements you wish to be clickable. In the example the ancestor element is the <section>. Then make the event handler (the function called when "click" event is triggered) act only on elements you wish to react when clicked. In the example it is each .preview. For more details, see event delegation.

Details are commented in example

// Reference the <section>
const box = document.querySelector(".box");

// Bind the <section> to the "click" event
box.onclick = function(event) {
  // Reference the element the user clicked
  const clicked = event.target;
  /*
  If the element the user clicked isn't <section> AND it has className
  .preview...
  ...reference the element that follows clicked element...
  ...reference the element within the clicked element with the className
  .arrow-down...
  ...toggle the element that follows clicked element className .hidden...
  ...toggle the element .arrow-down className .rotate-arrow
  */
  if (clicked !== this && clicked.matches(".preview")) {
    const content = clicked.nextElementSibling;
    const arrow = clicked.querySelector('.arrow-down');
    content.classList.toggle('hidden');
    arrow.classList.toggle('rotate-arrow');
  }
}
body {
  background: purple;
}
/* Added so .style attribute isn't needed */
.projet {
  display: flex;
}
/* Same as previous */
.hidden {
  display: none;
}

.projet-contain {
  display: flex;
  flex-direction: column;
  margin-bottom: 50px;
  width: auto;
  height: auto;
  background: radial-gradient(circle, rgba(238, 174, 202, 0.200) 0%, rgba(148, 188, 233, 0.200) 100%);
  ;
  border-radius: 10px 10px 10px 10px;
  padding: 10px;
  user-select: none;
}

.preview {
  display: flex;
  justify-content: space-between;
  align-items: center;
  /* Added for UX */
  cursor: pointer;
}

section>div>div>b, a {
  text-decoration: none;
  color: white;
}

b {
  /* Added so user click bypasses it */
  pointer-events: none;
}

.convertigo {
  width: 10vw;
}

.arrow-down {
  transition: transform 0.5s;
  width: 1.5vw;
  -webkit-filter: invert(100%);
  /* safari 6.0 - 9.0 */
  filter: invert(100%);
  /* Added so user click bypasses it */
  pointer-events: none;
}

.rotate-arrow {
  transform: rotate(180deg);
}
<!--All #ids removed and added .box to <section>-->
<body>
  <section >
    <div >
      <div >
        <!--Changed <a> to <b>-->
        <b>Projet Convertigo</b>
        <!--Having two class attributes one one element is invalid HTML-->
        <!--Fixed by combining values in one class attribute-->
        <svg  xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
          <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
        </svg>
        <img src="images/Convertigo.png"  alt="">
      </div>
      <div >
        <a>c'est la div 1</a>
      </div>
    </div>
    <div >
      <div >
        <b>Projet Convertigo</b>
        <svg  xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
          <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
        </svg>
        <img src="images/Convertigo.png"  alt="">
      </div>
      <div >
        <a>c'est la div 2</a>
      </div>
    </div>
    <div >
      <div >
        <b>Projet Convertigo</b>
        <svg  xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
          <path d="M3.204 5h9.592L8 10.481 3.204 5zm-.753.659 4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
        </svg>
        <img src="images/Convertigo.png"  alt="">
      </div>
      <div >
        <a>c'est la div 3</a>
      </div>
    </div>
  </section>
</body>

  • Related