Search code examples
javascripthtmlcsssassaccordion

Copying text from accordion triggers click button


Hello I have this siple accordion, and I have an issue, that whenever i copy text from accordion, click event listener triggers and closes the accordion. I would like to make it work without using jQuery

How could I fix it? and how would I make it , so when i click somewhere else than on .question / .answer it would close automaticaly? i tried adding event listener to window, but after a long time of not figuring out how to makeit work I gave up.

here is my codepen : https://codepen.io/drabfi/pen/LYrBxzWhttps://codepen.io/drabfi/pen/LYrBxzW

<div class="accordion">
  <h2 class="accordion-title">Frequently asked questions</h2>
  <div class="content-container active">
    <div class="question">What is the return Policy</div>
    <div class="answer">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Incidunt dolores non eaque beatae dolor veniam amet, molestiae neque quibusdam ipsa!</div>
  </div>
  <div class="content-container">
    <div class="question">Where can you find us</div>
    <div class="answer">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Incidunt dolores non eaque beatae dolor veniam amet, molestiae neque quibusdam ipsa!</div>
  </div>
  <div class="content-container">
    <div class="question">Some other text</div>
    <div class="answer">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Incidunt dolores non eaque beatae dolor veniam amet, molestiae neque quibusdam ipsa!</div>
  </div>
</div>
const accordion = document.querySelectorAll(".content-container");

for(let i=0;i<accordion.length;i++){
  accordion[i].addEventListener("click", function (){
   if(this.classList.contains("active")){
      accordion.forEach((panel)=>panel.classList.remove("active"));
   }else{
      accordion.forEach((panel)=>panel.classList.remove("active"));
      this.classList.add("active");
   }
  })
}
.accordion{
    margin: 0 auto;
    width: 60%;
    border-color: #fff;
    padding: 2rem;
    border-radius: 30px;
    &-title{
        margin-bottom: 2rem;
        text-align: center;
    }
    .content-container
        .question{
            padding: 1rem 0;
            font-size: 22px;
        cursor: pointer;
        border-bottom: 1px solid #000;
        position: relative;
        &::after{
            content: "+";
            position: absolute;
            right: -5px;

        }
        }
        .answer{
           padding-top: 1rem;
           font-size: 22px;
           line-height: 1.5;
           width: 100%; 
           height: 0px;
           overflow: hidden;
           transition: all .5s;
        }
}

// js styling link

.accordion .content-container.active{
    .question{

        &::after{
            content: "-";
            font-size: 2rem;
            transition: .5s;
        }
    }
    .answer{
        height: 150px;
    }
}
    

I would be very happy to see the solutions so I could move on from this spot. Thank you for any advices.


Solution

  • you need to learn a bit about event delegation...

    const
      accordion   = document.querySelector('.accordion')
    , accordionEl = accordion.querySelectorAll('.content-container')
      ;
    accordion.onclick = ({target: elmAcc}) =>
      {
      if (!elmAcc.matches('.content-container > div.question')) return // select only this div
    
      let elContainer = elmAcc.closest('.content-container')
    
      if (elContainer.classList.toggle('active'))
        accordionEl.forEach( panel => panel.classList.toggle('active', panel===elContainer))
      }
      
    // clicking outside will close accordion :
    document.addEventListener('click', event =>
      {
      if (!accordion.contains(event.target)) 
        accordionEl.forEach( panel => panel.classList.remove('active'))
      });
    .accordion {
      margin        : 0 auto;
      width         : 60%;
      border-color  : #fff;
      padding       : 2rem;
      border-radius : 30px;
      }
    .accordion-title {
      margin-bottom : 2rem;
      text-align    : center;
      }
    .accordion .content-container .question {
      padding       : 1rem 0;
      font-size     : 22px;
      cursor        : pointer;
      border-bottom : 1px solid #000;
      position      : relative;
      }
    .accordion .content-container .question::after {
      content  : "+";
      position : absolute;
      right    : -5px;
      }
    .accordion .answer {
      padding-top : 1rem;
      font-size   : 22px;
      line-height : 1.5;
      width       : 100%;
      height      : 0px;
      overflow    : hidden;
      transition  : all 0.5s;
      }
    .accordion .content-container.active .question::after {
      content    : "-";
      font-size  : 2rem;
      transition : 0.5s;
      }
    .accordion .content-container.active .answer {
      height : 150px;
      }
    <div class="accordion">
      <h2 class="accordion-title">Frequently asked questions</h2>
      <div class="content-container">
        <div class="question">What is the return Policy</div>
        <div class="answer">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Incidunt dolores non eaque beatae dolor veniam amet, molestiae neque quibusdam ipsa!</div>
      </div>
      <div class="content-container">
        <div class="question">Where can you find us</div>
        <div class="answer">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Incidunt dolores non eaque beatae dolor veniam amet, molestiae neque quibusdam ipsa!</div>
      </div>
      <div class="content-container">
        <div class="question">Some other text</div>
        <div class="answer">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Incidunt dolores non eaque beatae dolor veniam amet, molestiae neque quibusdam ipsa!</div>
      </div>
    </div>