Home > Software engineering >  How to simplify this simple JS script?
How to simplify this simple JS script?

Time:01-10

I'd like to know how I could make the code shorter by not repeating everything basically 4 times (each for every individual .section1-item). I'd like to know if there is a syntax or something that could make the code look cleaner and most of all not so redundant. I'm very new to JS and I'd like to learn more about it, and how I could make it more optimised.

  • When clicked, a card must get the class .active-card and the 3 others must not this same class.
  • When active, a card img must have the "images/tcheen-logo-jaune.png" , and the 3 others must have the "images/tcheen-logo-white.png".

const section1Card1 = document.querySelector(
    ".section1-col:nth-of-type(1) .section1-item:nth-child(1)"
);
const section1Card2 = document.querySelector(
    ".section1-col:nth-of-type(1) .section1-item:nth-child(2)"
);
const section1Card3 = document.querySelector(
    ".section1-col:nth-of-type(3) .section1-item:nth-child(1)"
);
const section1Card4 = document.querySelector(
    ".section1-col:nth-of-type(3) .section1-item:nth-child(2)"
);
//
const section1Card1Img = document.querySelector(
    ".section1-col:nth-of-type(1) .section1-item:nth-child(1) img"
);
const section1Card2Img = document.querySelector(
    ".section1-col:nth-of-type(1) .section1-item:nth-child(2) img"
);
const section1Card3Img = document.querySelector(
    ".section1-col:nth-of-type(3) .section1-item:nth-child(1) img"
);
const section1Card4Img = document.querySelector(
    ".section1-col:nth-of-type(3) .section1-item:nth-child(2) img"
);
//
const cardIndexDot1 = document.querySelector(".image-index-dot:nth-of-type(1)");
const cardIndexDot2 = document.querySelector(".image-index-dot:nth-of-type(2)");
const cardIndexDot3 = document.querySelector(".image-index-dot:nth-of-type(3)");
const cardIndexDot4 = document.querySelector(".image-index-dot:nth-of-type(4)");
//
const section1Cards = document.querySelectorAll(".section1-item");
const section1CardsImg = document.querySelectorAll(".section1-item img");

section1Card1.addEventListener("click", () => {
    console.log("bon");
    if (!section1Card1.classList.contains("active-card")) {
        section1Card2.classList.remove("active-card");
        section1Card3.classList.remove("active-card");
        section1Card4.classList.remove("active-card");
        section1CardsImg.src = "images/tcheen-logo-white.png";
        section1Card1.classList.add("active-card");
        section1Card1Img.src = "images/tcheen-logo-jaune.png";
        cardIndexDot1.classList.add("image-index-dot-active");
        cardIndexDot2.classList.remove("image-index-dot-active");
        cardIndexDot3.classList.remove("image-index-dot-active");
        cardIndexDot4.classList.remove("image-index-dot-active");
        console.log("oui");
    }
});
section1Card2.addEventListener("click", () => {
    console.log("bon");
    if (!section1Card2.classList.contains("active-card")) {
        section1Card1.classList.remove("active-card");
        section1Card3.classList.remove("active-card");
        section1Card4.classList.remove("active-card");
        section1CardsImg.src = "images/tcheen-logo-blanc.png";
        section1Card2.classList.add("active-card");
        section1Card2Img.src = "images/tcheen-logo-jaune.png";
        cardIndexDot2.classList.add("image-index-dot-active");
        cardIndexDot1.classList.remove("image-index-dot-active");
        cardIndexDot3.classList.remove("image-index-dot-active");
        cardIndexDot4.classList.remove("image-index-dot-active");
        console.log("oui");
    }
});
section1Card3.addEventListener("click", () => {
    console.log("bon");
    if (!section1Card3.classList.contains("active-card")) {
        section1Card1.classList.remove("active-card");
        section1Card2.classList.remove("active-card");
        section1Card4.classList.remove("active-card");
        section1CardsImg.src = "images/tcheen-logo-blanc.png";
        section1Card3.classList.add("active-card");
        section1Card3Img.src = "images/tcheen-logo-jaune.png";
        cardIndexDot3.classList.add("image-index-dot-active");
        cardIndexDot2.classList.remove("image-index-dot-active");
        cardIndexDot1.classList.remove("image-index-dot-active");
        cardIndexDot4.classList.remove("image-index-dot-active");
        console.log("oui");
    }
});
section1Card4.addEventListener("click", () => {
    console.log("bon");
    if (!section1Card4.classList.contains("active-card")) {
        section1Card1.classList.remove("active-card");
        section1Card2.classList.remove("active-card");
        section1Card3.classList.remove("active-card");
        section1CardsImg.src = "images/tcheen-logo-blanc.png";
        section1Card4.classList.add("active-card");
        section1Card4Img.src = "images/tcheen-logo-jaune.png";
        cardIndexDot4.classList.add("image-index-dot-active");
        cardIndexDot2.classList.remove("image-index-dot-active");
        cardIndexDot3.classList.remove("image-index-dot-active");
        cardIndexDot1.classList.remove("image-index-dot-active");
        console.log("oui");
    }
});
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: "Poppins";
}

:root {
    --color-yellow: #efd858;
    --color-pink: #eebcd8;
    --color-green: #6cbe99;
    --color-black: #1a1a1a;
    --color-white: #ffffff;
}

html {
    scroll-behavior: smooth;
}

/*  */
.yellow-bg {
    background-color: var(--color-yellow);
}

img {
    width: 100%;
}

/*  */
.section1 {
    position: relative;
    display: flex;
    justify-content: center;
    gap: 40px;
    padding-top: 98px;
}

.section1-col {
    width: 20%;
}

.section1-img {
    width: 27%;
}

.section1-img img {
    border-radius: 10px;
}

.section1-item {
    padding: 30px 18px 80px;
    position: relative;
    border-radius: 10px;
    background: var(--color-green);
}

.section1-item:nth-of-type(odd) {
    margin-bottom: 15px;
}

.section1-item img {
    position: absolute;
    display: inline-block;
    top: 18px;
    right: 18px;
    width: 12.5%;
}

.section1-item h3 {
    font-weight: 500;
    font-size: 20px;
    line-height: 26px;
    width: 75%;
}

.section1-item p {
    font-weight: 400;
    font-size: 16px;
    line-height: 26px;
}

.image-index {
    position: absolute;
    bottom: -36px;
    width: 120px;
    display: flex;
    justify-content: space-between;
}

.image-index-dot {
    width: 15px;
    aspect-ratio: 1;
    border-radius: 100%;
    background: var(--color-black);
}

/*  */
.active-card {
    background: var(--color-yellow);
}

.image-index-dot-active {
    background: var(--color-yellow);
}
<section >
    <div >
        <article >
            <img src="images/tcheen-logo-jaune.png" alt="Tcheen Logo">
            <h3>Eco-responsable et original</h3>
            <p>La crème des prestataires sensibilisés à l’engagement durable.</p>
        </article>
        <article >
            <img src="images/tcheen-logo-blanc.png" alt="Tcheen Logo">
            <h3>Devis instantané</h3>
            <p>Obtenez le match parfait et votre devis en 2 minutes chrono !</p>
        </article>
    </div>
    <div >
        <img src="https://source.unsplash.com/random/390x500/?space,planet" alt="Image 1">
    </div>
    <div >
        <article >
            <img src="images/tcheen-logo-blanc.png" alt="Tcheen Logo">
            <h3>100% Transparent</h3>
            <p>Nos frais de service sont transparents et sans surcoût sur vos prestations.</p>
        </article>
        <article >
            <img src="images/tcheen-logo-blanc.png" alt="Tcheen Logo">
            <h3>Accompagnement personnalisé</h3>
            <p>Nous vous accompagnons de A à Z avant et pendant votre événement.</p>
        </article>
    </div>
    <div >
        <div ></div>
        <div ></div>
        <div ></div>
        <div ></div>
    </div>
</section>

CodePudding user response:

This should get you close. I did not actually test this code because I did not have the html.

const cards = document.querySelectorAll(".section1-item");
const cardImages = document.querySelectorAll(".section1-item img");
const cardDots = document.querySelectorAll(".image-index-dot");


for (let [card, index] of cards.entries()) {
  card.addEventListener("click", () => {
    console.log("bon");
    if (!card.classList.contains("active-card")) {
      // remove the class from all the cards
      for (let innerCard of cards) {
        innerCard.classList.remove("active-card");
      }
      // not sure why the img src is being set twice
      cardImages[index].src = "images/tcheen-logo-white.png";
      card.classList.add("active-card");
      cardImages[index].src = "images/tcheen-logo-jaune.png";
      
      for (let dot of cardDots) {
        dot.classList.add("image-index-dot-active");
      }
      cardDots[index].add("image-index-dot-active");
    }
  });
}

CodePudding user response:

  1. Loop through each .section1-item element, and add a click listener to it.
  2. Remove .active-class from all .section1-item elements.
  3. Add .active-class to the clicked element.
  4. Use a pseudo-class to set the image. I removed the images from the section and instead added a ::before in the CSS.

const section1Cards = document.querySelectorAll(".section1-item");

for (section1Card of section1Cards) {
  section1Card.addEventListener("click", (event) => {
     let clickedCard = event.currentTarget;
     for (_secCard of section1Cards) {
       _secCard.classList.remove('active-card');
     }
     
     clickedCard.classList.add('active-card');
  })
}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Poppins";
}

:root {
  --color-yellow: #efd858;
  --color-pink: #eebcd8;
  --color-green: #6cbe99;
  --color-black: #1a1a1a;
  --color-white: #ffffff;
}

html {
  scroll-behavior: smooth;
}


/*  */

.yellow-bg {
  background-color: var(--color-yellow);
}

img {
  width: 100%;
}


/*  */

.section1 {
  position: relative;
  display: flex;
  justify-content: center;
  gap: 40px;
  padding-top: 98px;
}

.section1-col {
  width: 20%;
}

.section1-img {
  width: 27%;
}

.section1-img img {
  border-radius: 10px;
}

.section1-item {
  padding: 30px 18px 80px;
  position: relative;
  border-radius: 10px;
  background: var(--color-green);
}

.section1-item:nth-of-type(odd) {
  margin-bottom: 15px;
}

.section1-item h3 {
  font-weight: 500;
  font-size: 20px;
  line-height: 26px;
  width: 75%;
}

.section1-item p {
  font-weight: 400;
  font-size: 16px;
  line-height: 26px;
}

.image-index {
  position: absolute;
  bottom: -36px;
  width: 120px;
  display: flex;
  justify-content: space-between;
}

.image-index-dot {
  width: 15px;
  aspect-ratio: 1;
  border-radius: 100%;
  background: var(--color-black);
}



.active-card {
  background: var(--color-yellow);
}

/* ADDED */

.section1-item::before {
  content: url('https://via.placeholder.com/90x90.png?text=Blanc');
  position: absolute;
  display: inline-block;
  top: 18px;
  right: 18px;
  width: 12.5%;
}

/* ADDED */

.section1-item.active-card::before {
  content: url('https://via.placeholder.com/90/8f8.png/000/?text=Jaune');
}

.image-index-dot-active {
  background: var(--color-yellow);
}
<section >
  <div >
    <article >
      <h3>Eco-responsable et original</h3>
      <p>La crème des prestataires sensibilisés à l’engagement durable.</p>
    </article>
    <article >
      <h3>Devis instantané</h3>
      <p>Obtenez le match parfait et votre devis en 2 minutes chrono !</p>
    </article>
  </div>
  <div >
    <img src="https://source.unsplash.com/random/390x500/?space,planet" alt="Image 1">
  </div>
  <div >
    <article >
      <h3>100% Transparent</h3>
      <p>Nos frais de service sont transparents et sans surcoût sur vos prestations.</p>
    </article>
    <article >
      <h3>Accompagnement personnalisé</h3>
      <p>Nous vous accompagnons de A à Z avant et pendant votre événement.</p>
    </article>
  </div>
  <div >
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
  </div>
</section>

The code above is only taking care of the sections. I would like to take the opportunity to show how to add/remove classes by using querySelect, instead of looping through all the .image-index-dot elements as I did with .section1-item.

const section1Cards = document.querySelectorAll(".section1-item");

for (let section1Card of section1Cards) {
  section1Card.addEventListener("click", (event) => {
     let clickedCard = event.currentTarget;
     let index = 0, startsCountAtOne = 1;
     let activeCardClass = 'active-card';
     let activeDotClass = 'image-index-dot-active';

     for (let [_index, _secCard] of section1Cards.entries()) {
        if (_secCard !== clickedCard) {
          _secCard.classList.remove(activeCardClass);
        } else {
          _secCard.classList.add(activeCardClass);
          index = _index   startsCountAtOne;
        }
     }

     let activeDot = document.querySelector('.image-index > .'   activeDotClass);
     let clickedDot = document.querySelector(`.image-index > :nth-child(${index})`)
     
     activeDot.classList.remove(activeDotClass);
     clickedDot.classList.add(activeDotClass);
  })
}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Poppins";
}

:root {
  --color-yellow: #efd858;
  --color-pink: #eebcd8;
  --color-green: #6cbe99;
  --color-black: #1a1a1a;
  --color-white: #ffffff;
}

html {
  scroll-behavior: smooth;
}


/*  */

.yellow-bg {
  background-color: var(--color-yellow);
}

img {
  width: 100%;
}


/*  */

.section1 {
  position: relative;
  display: flex;
  justify-content: center;
  gap: 40px;
  padding-top: 98px;
}

.section1-col {
  width: 20%;
}

.section1-img {
  width: 27%;
}

.section1-img img {
  border-radius: 10px;
}

.section1-item {
  padding: 30px 18px 80px;
  position: relative;
  border-radius: 10px;
  background: var(--color-green);
}

.section1-item:nth-of-type(odd) {
  margin-bottom: 15px;
}

.section1-item h3 {
  font-weight: 500;
  font-size: 20px;
  line-height: 26px;
  width: 75%;
}

.section1-item p {
  font-weight: 400;
  font-size: 16px;
  line-height: 26px;
}

.image-index {
  position: absolute;
  bottom: -36px;
  width: 120px;
  display: flex;
  justify-content: space-between;
}

.image-index-dot {
  width: 15px;
  aspect-ratio: 1;
  border-radius: 100%;
  background: var(--color-black);
}



.active-card {
  background: var(--color-yellow);
}

/* ADDED */

.section1-item::before {
  content: url('https://via.placeholder.com/90x90.png?text=Blanc');
  position: absolute;
  display: inline-block;
  top: 18px;
  right: 18px;
  width: 12.5%;
}

/* ADDED */

.section1-item.active-card::before {
  content: url('https://via.placeholder.com/90/8f8.png/000/?text=Jaune');
}

.image-index-dot-active {
  background: var(--color-yellow);
}
<section >
  <div >
    <article >
      <h3>Eco-responsable et original</h3>
      <p>La crème des prestataires sensibilisés à l’engagement durable.</p>
    </article>
    <article >
      <h3>Devis instantané</h3>
      <p>Obtenez le match parfait et votre devis en 2 minutes chrono !</p>
    </article>
  </div>
  <div >
    <img src="https://source.unsplash.com/random/390x500/?space,planet" alt="Image 1">
  </div>
  <div >
    <article >
      <h3>100% Transparent</h3>
      <p>Nos frais de service sont transparents et sans surcoût sur vos prestations.</p>
    </article>
    <article >
      <h3>Accompagnement personnalisé</h3>
      <p>Nous vous accompagnons de A à Z avant et pendant votre événement.</p>
    </article>
  </div>
  <div >
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
  </div>
</section>

  • Related