Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <style>
- /*Custom override styles*/
- #lipscore-service-review-list {
- padding: 0 5rem 20px;
- overflow: hidden;
- position: relative;
- -webkit-overflow-scrolling: touch;
- }
- #lipscore-service-review-list .lipscore-review-list-box-container {
- display: flex;
- position: relative;
- will-change: transform;
- width: max-content;
- cursor: grab;
- user-select: none;
- transition: transform 0.1s ease-out;
- }
- #lipscore-service-review-list .lipscore-review-list-box-container:active {
- cursor: grabbing;
- }
- #lipscore-service-review-list .lipscore-review-box {
- flex: 0 0 400px;
- height: auto;
- margin: 0 10px;
- padding: 20px;
- background-color: #f2f2f2;
- border-radius: 8px;
- display: flex;
- flex-direction: column;
- transition: transform 0.3s ease, box-shadow 0.3s ease;
- box-shadow: -4px 4px 10px rgba(0, 0, 0, 0.1);
- backface-visibility: hidden;
- will-change: transform;
- }
- /* Pause animation on hover */
- #lipscore-service-review-list:hover .lipscore-review-list-box-container {
- animation-play-state: paused;
- }
- #lipscore-service-review-list:active {
- cursor: grabbing;
- }
- #lipscore-service-review-list::-webkit-scrollbar {
- display: none;
- }
- #lipscore-service-review-list .lipscore-review-info-wrapper {
- display: flex;
- flex-direction: column;
- }
- #lipscore-service-review-list .lipscore-review-creation-info {
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- }
- #lipscore-service-review-list .lipscore-review-author {
- font-size: 14px;
- color: #555;
- font-weight: normal;
- margin-right: 5px;
- }
- #lipscore-service-review-list .lipscore-review-date {
- font-size: 16px;
- font-weight: bold;
- color: #555;
- margin-top: 15px;
- }
- #lipscore-service-review-list .lipscore-review-rating-stars-wrapper {
- margin-top: 10px;
- }
- #lipscore-service-review-list .lipscore-rating-star {
- width: 16px;
- height: 16px;
- margin-right: 2px;
- }
- #lipscore-service-review-list .lipscore-review-content {
- margin-top: 15px;
- }
- #lipscore-service-review-list .lipscore-review-text {
- font-size: 16px;
- line-height: 1.4;
- color: #000;
- font-weight: normal;
- }
- #lipscore-service-review-list .lipscore-show-review-original-text-btn {
- font-size: 12px;
- color: #555;
- font-weight: 300;
- margin-top: 15px;
- background: none;
- border: none;
- padding: 0;
- cursor: pointer;
- text-align: left;
- }
- .lipscore-service-review-badge-small-short.lipscore-no-border,
- .lipscore-service-review-badge-small-long.lipscore-no-border {
- padding: 0 3rem;
- }
- .lipscore-real-reviews-badge-container {
- text-align: end;
- margin: 5px 0 15px 0;
- }
- .lipscore-real-reviews-badge-right {
- display: inline-block;
- }
- #lipscore-service-review-list .lipscore-text-muted.lipscore-review-info-delim,
- #lipscore-service-review-list .lipscore-visually-hidden,
- #lipscore-service-review-list
- .lipscore-review-content-wrapper
- > *:not(.lipscore-review-text),
- #lipscore-service-review-list .lipscore-review-footer,
- #lipscore-service-review-list .lipscore-review-media,
- #lipscore-service-review-list .lipscore-review-reply,
- #lipscore-service-review-list .lipscore-review-footer-wrapper,
- #lipscore-service-review-list .lipscore-review-vote-wrapper,
- #lipscore-service-review-list .lipscore-review-flag-wrapper,
- #lipscore-service-review-list .lipscore-review-imported-wrapper,
- #lipscore-service-review-list .lipscore-widget-lang,
- #lipscore-service-review-list .lipscore-paginator {
- display: none !important;
- }
- @media (max-width: 768px) {
- #lipscore-service-review-list {
- padding: 0 15px 20px;
- height: auto;
- overflow-x: hidden;
- }
- #lipscore-service-review-list .lipscore-review-list-box-container {
- display: flex;
- flex-wrap: nowrap;
- transition: transform 0.3s ease;
- width: 100%;
- }
- #lipscore-service-review-list .lipscore-review-box {
- flex: 0 0 calc(100% - 40px);
- width: calc(100% - 40px);
- margin: 0 20px;
- padding: 15px;
- }
- .lipscore-service-review-badge-small-short.lipscore-no-border, .lipscore-service-review-badge-small-long.lipscore-no-border {
- padding: 0;
- width: 100%;
- text-align:center;
- }
- .lipscore-real-reviews-badge-container {
- text-align: center;
- }
- }
- </style>
- <div id="lipscore-service-review-list"></div>
- <script>
- class InfiniteSlider {
- constructor(containerSelector, options = {}) {
- this.container = document.querySelector(containerSelector);
- if (!this.container) {
- console.error('Container element not found.');
- return;
- }
- this.reviews = this.container.innerHTML;
- this.isMobile = this.checkIfMobile();
- this.options = Object.assign(
- {
- speed: 50, // Pixels per second for auto-scroll
- slideSelector: '.lipscore-review-box',
- autoScroll: !this.isMobile, // Set initial autoScroll based on mobile status
- },
- options
- );
- this.totalWidth = 0;
- this.slideWidth = 0;
- this.currentPosition = 0;
- this.isDragging = false;
- this.isHovering = false;
- this.isContainerVisible = true;
- this.isPageVisible = true;
- this.animationFrameId = null;
- this.lastTimestamp = 0;
- this.init();
- }
- // Update this method to only update isMobile and return the value
- updateMobileStatus() {
- this.isMobile = this.checkIfMobile();
- return this.isMobile;
- }
- // Add this method to check if the device is mobile
- checkIfMobile() {
- return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
- navigator.userAgent
- );
- }
- // Initialize slider
- init() {
- this.updateContent();
- this.initObservers();
- this.bindEvents();
- this.startAnimation();
- }
- // Update content for infinite scroll
- updateContent() {
- this.container.innerHTML = this.reviews + this.reviews;
- // Cache total width and slide width
- this.totalWidth = this.container.scrollWidth;
- const slide = this.container.querySelector(this.options.slideSelector);
- if (slide) {
- const slideStyles = window.getComputedStyle(slide);
- this.slideWidth =
- slide.offsetWidth +
- parseFloat(slideStyles.marginLeft) +
- parseFloat(slideStyles.marginRight);
- }
- }
- // Update position for infinite scrolling
- updatePosition() {
- if (this.currentPosition >= this.totalWidth / 2) {
- this.currentPosition -= this.totalWidth / 2;
- } else if (this.currentPosition < 0) {
- this.currentPosition += this.totalWidth / 2;
- }
- this.container.style.transform = `translateX(${-this.currentPosition}px)`;
- }
- // Animation step function
- step(timestamp) {
- const progress = timestamp - this.lastTimestamp;
- this.lastTimestamp = timestamp;
- // Only auto-scroll if it's not a mobile device and other conditions are met
- if (
- !this.isMobile &&
- !this.isDragging &&
- !this.isHovering &&
- this.isContainerVisible &&
- this.isPageVisible &&
- this.options.autoScroll
- ) {
- this.currentPosition += (progress * this.options.speed) / 1000;
- this.updatePosition();
- }
- this.animationFrameId = requestAnimationFrame(this.step.bind(this));
- }
- // Start the animation loop
- startAnimation() {
- this.lastTimestamp = performance.now();
- this.animationFrameId = requestAnimationFrame(this.step.bind(this));
- }
- // Handle dragging
- startDragging(e) {
- e.preventDefault();
- this.isDragging = true;
- this.startX = e.type.includes('mouse') ? e.pageX : e.touches[0].pageX;
- this.scrollLeft = this.currentPosition;
- this.container.style.cursor = 'grabbing';
- this.container.style.transition = 'none';
- }
- stopDragging() {
- if (!this.isDragging) return;
- this.isDragging = false;
- this.container.style.cursor = 'grab';
- this.container.style.transition = 'transform 0.3s ease-out';
- const slideIndex = Math.round(this.currentPosition / this.slideWidth);
- this.currentPosition = slideIndex * this.slideWidth;
- this.updatePosition();
- }
- drag(e) {
- if (!this.isDragging) return;
- e.preventDefault();
- const x = e.type.includes('mouse') ? e.pageX : e.touches[0].pageX;
- const sensitivity = this.isMobile ? 2 : 1;
- const walk = (x - this.startX) * sensitivity;
- this.currentPosition = this.scrollLeft - walk;
- this.updatePosition();
- }
- // Handle resize event with debounce
- resizeHandler() {
- clearTimeout(this.resizeTimeout);
- this.resizeTimeout = setTimeout(() => {
- const wasMobile = this.isMobile;
- const isMobileNow = this.updateMobileStatus();
- if (wasMobile !== isMobileNow) {
- this.options.autoScroll = !isMobileNow;
- }
- this.updateContent();
- this.updatePosition();
- }, 250);
- }
- // Initialize observers for visibility and DOM mutations
- initObservers() {
- // Intersection Observer for container visibility
- const observerOptions = {
- root: null,
- threshold: 0,
- };
- this.intersectionObserver = new IntersectionObserver((entries) => {
- entries.forEach((entry) => {
- if (entry.target === this.container) {
- this.isContainerVisible = entry.isIntersecting;
- }
- });
- }, observerOptions);
- this.intersectionObserver.observe(this.container);
- // Page visibility API
- document.addEventListener('visibilitychange', () => {
- this.isPageVisible = !document.hidden;
- });
- }
- // Bind all necessary events
- bindEvents() {
- // Drag events
- this.container.addEventListener('mousedown', this.startDragging.bind(this));
- this.container.addEventListener(
- 'touchstart',
- this.startDragging.bind(this),
- {
- passive: false,
- }
- );
- document.addEventListener('mousemove', this.drag.bind(this));
- document.addEventListener('touchmove', this.drag.bind(this), {
- passive: false,
- });
- document.addEventListener('mouseup', this.stopDragging.bind(this));
- document.addEventListener('touchend', this.stopDragging.bind(this));
- // Hover events
- this.container.addEventListener(
- 'mouseenter',
- () => (this.isHovering = true)
- );
- this.container.addEventListener(
- 'mouseleave',
- () => (this.isHovering = false)
- );
- // Window resize
- window.addEventListener('resize', this.resizeHandler.bind(this));
- }
- // Cleanup event listeners and observers
- cleanup() {
- cancelAnimationFrame(this.animationFrameId);
- this.container.removeEventListener(
- 'mousedown',
- this.startDragging.bind(this)
- );
- this.container.removeEventListener(
- 'touchstart',
- this.startDragging.bind(this),
- {
- passive: false,
- }
- );
- document.removeEventListener('mousemove', this.drag.bind(this));
- document.removeEventListener('touchmove', this.drag.bind(this), {
- passive: false,
- });
- document.removeEventListener('mouseup', this.stopDragging.bind(this));
- document.removeEventListener('touchend', this.stopDragging.bind(this));
- window.removeEventListener('resize', this.resizeHandler.bind(this));
- document.removeEventListener(
- 'visibilitychange',
- this.visibilityChangeHandler
- );
- this.intersectionObserver.unobserve(this.container);
- }
- }
- document.addEventListener('DOMContentLoaded', function () {
- let currentContainer = null;
- let slider = null; // Declare the slider variable at the correct scope
- // Initialize slider function
- function initializeSlider(container) {
- if (slider) {
- // Clean up the previous slider if it exists
- slider.cleanup();
- }
- slider = new InfiniteSlider(container, {
- speed: 50, // Custom speed
- });
- }
- // MutationObserver to detect changes in the DOM
- const observer = new MutationObserver((mutations) => {
- const newContainer = document.querySelector(
- '#lipscore-service-review-list .lipscore-review-list-box-container'
- );
- if (newContainer && newContainer !== currentContainer) {
- if (currentContainer) {
- if (slider) slider.cleanup(); // Clean up the previous slider before re-initializing
- }
- currentContainer = newContainer;
- initializeSlider('#lipscore-service-review-list .lipscore-review-list-box-container'); // Initialize the slider
- }
- });
- // Start observing the document body for changes
- observer.observe(document.body, {
- childList: true,
- subtree: true,
- });
- });
- </script>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement