Возникли трудности с таргетингом на конкретную кнопку «Показать больше», при нажатии на которую отображается скрытый текст всех отзывов, а не только тот, на который я нажимаю

#javascript #foreach

#javascript #для каждого

Вопрос:

Итак, что я пытаюсь сделать, так это отобразить несколько карточек отзывов. С помощью кнопки «Показать больше» / «показать меньше». При нажатии я хочу, чтобы текст этого конкретного отзыва показывал больше / показывал меньше. Но на данный момент моя функция заставляет все отзывы показывать больше / показывать меньше текста. Пожалуйста, помогите, я не знаю, чего мне не хватает.

 const testimonialCards = document.querySelectorAll('#feedback-text'); //returns nodelist
const testimonialArray = Array.from(testimonialCards); //converts nodelist to array
const showMoreButton = document.querySelectorAll('.js-show-more');
const showMoreButtonArray = Array.from(showMoreButton);

//looping through the testimonial cards
testimonialArray.forEach(e => {
  //looping through buttons array
  showMoreButtonArray.forEach(t => {

    //adding onclick method to the buttons
    t.addEventListener('click', function() {

      //conditional to check if the hidden exists, if so so, remove it and add the show all class etc.
      if (e.classList.contains('excerpt-hidden')) {
        e.classList.remove('excerpt-hidden');
        e.classList.add('showAllContent');
        showMoreButton.innerText = "Show Less";
      } else {
        e.classList.add('excerpt-hidden');
        e.classList.remove('showAllContent');
        showMoreButton.innerText = "Show More";
      }
    });
  });
});  
 /*Css for show more text and show less using the height of the text container*/

.js-show-more {
  border: 0;
  border-radius: 0;
  background-color: unset;
  color: #b83426;
  text-transform: uppercase;
  cursor: pointer;
}


/*truncating text*/

.excerpt-hidden {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  height: 65px;
  width: 80%;
  margin: 0 auto 1em;
}

.showAllContent {
  height: auto;
  overflow: initial;
  -webkit-line-clamp: none;
}  
 <!--This is my testimonial card, I would have about 8 cards on pageload-->

<testimonial class="testimonial-card" flag="sa.svg">

  <h4>Title</h4>
  <p class="excerpt-hidden expanded-text" id="feedback-text">
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has
    survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing
    software like Aldus PageMaker including versions of Lorem Ipsum.
  </p>
  <button class="js-show-more">Show More</button>

</testimonial>  

Ответ №1:

Это должно сработать:

 const testimonialCards = document.querySelectorAll('#feedback-text'); //returns nodelist
const showMoreButtons = document.querySelectorAll('.js-show-more');

//looping through buttons array
showMoreButtons.forEach((t, i) => {

  //adding onclick method to the buttons
  t.addEventListener('click', function() {
    const e = testimonialCards[i]

    // conditional to check if the hidden exists, if so so, 
    // remove it and add the show all class etc.
    if (e.classList.contains('excerpt-hidden')) {
      e.classList.remove('excerpt-hidden');
      e.classList.add('showAllContent');
      t.innerText = "Show Less";
    } else {
      e.classList.add('excerpt-hidden');
      e.classList.remove('showAllContent');
      t.innerText = "Show More";
    }
  });
});  
 /*Css for show more text and show less using the height of the text container*/

.js-show-more {
  border: 0;
  border-radius: 0;
  background-color: unset;
  color: #b83426;
  text-transform: uppercase;
  cursor: pointer;
}


/*truncating text*/

.excerpt-hidden {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  height: 65px;
  width: 80%;
  margin: 0 auto 1em;
}

.showAllContent {
  height: auto;
  overflow: initial;
  -webkit-line-clamp: none;
}  
 <testimonial class="testimonial-card" flag="sa.svg">

  <h4>Title</h4>
  <p class="excerpt-hidden expanded-text" id="feedback-text">
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has
    survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing
    software like Aldus PageMaker including versions of Lorem Ipsum.
  </p>
  <button class="js-show-more">Show More</button>
</testimonial>

<testimonial class="testimonial-card" flag="sa.svg">
  <h4>Title 2</h4>
  <p class="excerpt-hidden expanded-text" id="feedback-text">
    It has
    survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing
    software like Aldus PageMaker including versions of Lorem Ipsum.
    
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
  </p>
  <button class="js-show-more">Show More</button>

</testimonial>  

Ответ №2:

Проблемы:

  • Вы повторяете showMoreButton для каждого отзыва. Это совершенно не нужно и является причиной проблемы, с которой вы столкнулись. С каждым отзывом связана одна кнопка. Вам просто нужно перебрать отзывы, получить кнопку в текущем отзыве и добавить к ней прослушиватель событий.

  • Вам не нужно конвертировать, NodeList возвращаемый document.querySelectorAll , в массив. Вы можете использовать .forEach() метод с NodeList .

Решение:

Вы могли бы добавить отдельного click слушателя для каждой кнопки, но есть способ получше. Вы могли бы воспользоваться всплывающими событиями.

Оберните все отзывы в оболочку div и добавьте click событие в элемент оболочки, а не в каждую кнопку, связанную с каждым отзывом.

Когда click событие запускается на элементе-оболочке div , выполните следующие действия:

  1. Проверьте, Event.target есть ли кнопка.
  2. Если это так, найдите родительский элемент нажатой кнопки, а затем выберите #feedback-text элемент.
  3. Затем переключите классы excerpt-hidden и showAllContent для выбранного #feedback-text элемента.
  4. Наконец, измените текст нажатой кнопки.

Следующий фрагмент кода показывает пример с двумя отзывами.

 const testimonialWrapper = document.querySelector('.wrapper');

testimonialWrapper.addEventListener('click', function(event) {
  const target = event.target;

  if (target.matches('.js-show-more')) {
    const p = target.parentElement.querySelector('#feedback-text');

    p.classList.toggle('excerpt-hidden');
    p.classList.toggle('showAllContent');

    target.textContent = 
        target.textContent == 'Show More' ? 'Show Less' : 'Show More';
  }
});  
 .js-show-more {
  border: 0;
  border-radius: 0;
  background-color: unset;
  color: #b83426;
  text-transform: uppercase;
  cursor: pointer;
}

.excerpt-hidden {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  height: 65px;
  width: 80%;
  margin: 0 auto 1em;
}

.showAllContent {
  height: auto;
  overflow: initial;
  -webkit-line-clamp: none;
}  
 <div class="wrapper">
  <testimonial class="testimonial-card" flag="sa.svg">

    <h4>Title</h4>
    <p class="excerpt-hidden expanded-text" id="feedback-text">
      Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has
      survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop
      publishing software like Aldus PageMaker including versions of Lorem Ipsum.
    </p>
    <button class="js-show-more">Show More</button>

  </testimonial>

  <testimonial class="testimonial-card" flag="sa.svg">

    <h4>Title</h4>
    <p class="excerpt-hidden expanded-text" id="feedback-text">
      Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has
      survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop
      publishing software like Aldus PageMaker including versions of Lorem Ipsum.
    </p>
    <button class="js-show-more">Show More</button>

  </testimonial>
</div>