testimonials.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. document.addEventListener("DOMContentLoaded", () => {
  2. const testimonialsGrids = document.querySelectorAll('[data-testimonials]');
  3. testimonialsGrids.forEach((grid) => {
  4. let commentCards = grid.querySelectorAll('[data-comment]');
  5. const leftArrow = grid.querySelector('[data-nav-arrow="prev"]');
  6. const rightArrow = grid.querySelector('[data-nav-arrow="next"]');
  7. let autoInterval;
  8. let autoTimeoutReset;
  9. let allComments = [];
  10. const totalComments = commentCards.length;
  11. const AUTOPLAY_INTERVAL = 5000;
  12. const RESET_DELAY = 5000;
  13. function getCommentsData() {
  14. const comments = grid.querySelectorAll('[data-comment]');
  15. allComments = [];
  16. comments.forEach((comment) => {
  17. const clonedComment = comment.cloneNode(true);
  18. allComments.push(clonedComment);
  19. });
  20. return allComments;
  21. }
  22. function updateComments() {
  23. removeAllComments();
  24. allComments.forEach((commentData, index) => {
  25. if (index < 3) {
  26. addCommentToDOM(commentData);
  27. }
  28. if (index === (totalComments - 1)) {
  29. addCommentToDOM(commentData, 'start');
  30. }
  31. if (index === 3) {
  32. addCommentToDOM(commentData, 'end');
  33. }
  34. });
  35. commentCards = grid.querySelectorAll('[data-comment]');
  36. positionCommentsWithTranslate();
  37. }
  38. function addCommentToDOM(comment, position = 'end') {
  39. const card = comment.cloneNode(true);
  40. if (position === 'start') {
  41. grid.insertBefore(card, grid.firstChild);
  42. } else {
  43. grid.appendChild(card);
  44. }
  45. return card;
  46. }
  47. function positionCommentsWithTranslate(gap = 24) {
  48. const cardWidth = commentCards[0].offsetWidth;
  49. const offset = -(cardWidth + gap) * 2;
  50. commentCards.forEach((card, index) => {
  51. const translateX = offset + (cardWidth + gap) * index;
  52. card.style.position = 'absolute';
  53. card.style.visibility = 'visible';
  54. card.style.transform = `translateX(${translateX}px)`;
  55. });
  56. }
  57. window.addEventListener('resize', () => {
  58. positionCommentsWithTranslate();
  59. });
  60. function removeAllComments() {
  61. grid.innerHTML = '';
  62. }
  63. function removeCommentFromDOM(index) {
  64. if (index < 0 || index >= commentCards.length) {
  65. return false;
  66. }
  67. commentCards[index].remove();
  68. return true;
  69. }
  70. // Autoplay functions
  71. function startAutoPlay() {
  72. if (autoInterval) return;
  73. autoInterval = setInterval(() => {
  74. moveLeft();
  75. }, AUTOPLAY_INTERVAL);
  76. }
  77. function stopAutoPlay() {
  78. if (autoInterval) {
  79. clearInterval(autoInterval);
  80. autoInterval = null;
  81. }
  82. }
  83. function resetAutoPlayTimeout() {
  84. clearTimeout(autoTimeoutReset);
  85. stopAutoPlay();
  86. autoTimeoutReset = setTimeout(() => {
  87. startAutoPlay();
  88. }, RESET_DELAY);
  89. }
  90. function moveLeft() {
  91. removeCommentFromDOM(0);
  92. const reorganizeComments = [];
  93. for (let index = 0; index < totalComments - 1; index++) {
  94. reorganizeComments[index] = allComments[index + 1];
  95. }
  96. reorganizeComments[totalComments - 1] = allComments[0];
  97. allComments = reorganizeComments;
  98. const card = addCommentToDOM(allComments[3], 'end');
  99. commentCards = grid.querySelectorAll('[data-comment]');
  100. positionCommentsWithTranslate();
  101. card.style.visibility = 'hidden';
  102. setTimeout(() => {
  103. card.style.visibility = 'visible';
  104. }, 1000);
  105. }
  106. function moveRight() {
  107. removeCommentFromDOM(commentCards.length - 1);
  108. const reorganizeComments = [];
  109. reorganizeComments[0] = allComments[totalComments - 1];
  110. for (let index = 0; index < totalComments - 1; index++) {
  111. reorganizeComments[index + 1] = allComments[index];
  112. }
  113. allComments = reorganizeComments;
  114. const card = addCommentToDOM(allComments[0], 'start');
  115. commentCards = grid.querySelectorAll('[data-comment]');
  116. positionCommentsWithTranslate();
  117. card.style.visibility = 'hidden';
  118. setTimeout(() => {
  119. card.style.visibility = 'visible';
  120. }, 1000);
  121. }
  122. if (leftArrow) {
  123. leftArrow.addEventListener('click', () => {
  124. moveLeft();
  125. resetAutoPlayTimeout();
  126. });
  127. }
  128. if (rightArrow) {
  129. rightArrow.addEventListener('click', () => {
  130. moveRight();
  131. resetAutoPlayTimeout();
  132. });
  133. }
  134. // Pause autoplay on hover
  135. grid.addEventListener('mouseenter', () => {
  136. stopAutoPlay();
  137. });
  138. grid.addEventListener('mouseleave', () => {
  139. startAutoPlay();
  140. });
  141. function initial() {
  142. getCommentsData();
  143. updateComments();
  144. }
  145. window.addEventListener('load', () => {
  146. initial();
  147. positionCommentsWithTranslate();
  148. // Start autoplay after 1 second
  149. setTimeout(() => startAutoPlay(), 1000);
  150. });
  151. });
  152. });