UNPKG

zz-shopify-components

Version:

Reusable Shopify components for theme projects

366 lines (348 loc) 12.1 kB
class WorldVideoList extends HTMLElement { page = 1; productType = 4; videoList = []; pageList = []; observerVideo = null; hasMore = true; pageSize = 8; constructor() { super(); } connectedCallback() { this.shopSelect = this.dataset.shopSelect; this.baseUrl = this.dataset.requestType === 'prod' ? 'https://h130-app-server-us.hoverx1.cn' : 'https://h130-app-server-test-us.hoverx1.cn'; if (this.shopSelect === 'JP') { this.baseUrl = this.dataset.requestType === 'prod' ? 'https://h130-app-server-jp.hoverx1.cn' : 'https://h130-app-server-test-jp.hoverx1.cn'; } this.init(); } init() { document.addEventListener('DOMContentLoaded', (event) => { if (this.shopSelect === 'JP') { this.productType = 3; } this.initData(); // 初始化切换 this.initSwitch(); // 初始化滚动 this.initScrollAction(); this.addVideoAction(); this.initDataLayer(); }); } initLazyLoad() { const observer = lozad('.world-lozad', { rootMargin: '30px 0px', }); // lazy loads elements with default selector as '.lozad' observer.observe(); } initData() { try { this.x1Img = this.dataset.x1Img; this.x1ProImg = this.dataset.x1proImg; this.x121Img = this.dataset.x121Img; this.x121Links = this.dataset.x121Links; this.x1Links = this.dataset.x1Links; this.x1ProLinks = this.dataset.x1proLinks; } catch (error) { console.error('初始化错误', error); } this.loadMoreData(); } initScrollAction() { const videoPageList = this.querySelector('.video-page-list'); const videoPageLeftArrow = this.querySelector('.video-page-left-arrow'); const videoPageRightArrow = this.querySelector('.video-page-right-arrow'); let swiperIndex = 0; // 点击 right 按钮 向左滑动 videoPageRightArrow.addEventListener('click', () => { videoPageList.scrollBy({ left: 400, behavior: 'smooth' }); swiperIndex++; window.zzAnalytics && window.zzAnalytics.trackEvent('world_video_scroll', { timestamp: new Date().toISOString(), }); if (swiperIndex > 0) { videoPageLeftArrow.classList.remove('tw-hidden'); } }); // 点击 left 按钮 向右滑动 videoPageLeftArrow.addEventListener('click', () => { videoPageList.scrollBy({ left: -400, behavior: 'smooth' }); swiperIndex--; if (swiperIndex === 0) { videoPageLeftArrow.classList.add('tw-hidden'); } }); } initSwitch() { const btnPro = this.querySelector('#switch-pro'); const btnX1 = this.querySelector('#switch-x1'); const btnX1Smart = this.querySelector('#switch-x1-smart'); btnPro.addEventListener('click', (event) => { event.stopPropagation(); btnPro.classList.add('tw-bg-black', 'tw-text-white'); btnPro.classList.remove('tw-bg-transparent', 'tw-text-black'); if(btnX1) { btnX1.classList.add('tw-bg-transparent', 'tw-text-black'); btnX1.classList.remove('tw-bg-black', 'tw-text-white'); } if(btnX1Smart) { btnX1Smart.classList.add('tw-bg-transparent', 'tw-text-black'); btnX1Smart.classList.remove('tw-bg-black', 'tw-text-white'); } // 这里可以加你切换到 PRO&PROMAX 的逻辑 if (this.productType !== 4) { this.productType = 4; this.page = 1; this.loadMoreData(); } }); if(btnX1) { btnX1.addEventListener('click', (event) => { event.stopPropagation(); btnX1.classList.add('tw-bg-black', 'tw-text-white'); btnX1.classList.remove('tw-bg-transparent', 'tw-text-black'); btnPro.classList.add('tw-bg-transparent', 'tw-text-black'); btnPro.classList.remove('tw-bg-black', 'tw-text-white'); // 这里可以加你切换到 X1 的逻辑 if (this.productType !== 1) { this.productType = 1; this.page = 1; this.loadMoreData(); } }); } if(btnX1Smart) { btnX1Smart.addEventListener('click', (event) => { event.stopPropagation(); btnX1Smart.classList.add('tw-bg-black', 'tw-text-white'); btnX1Smart.classList.remove('tw-bg-transparent', 'tw-text-black'); btnPro.classList.add('tw-bg-transparent', 'tw-text-black'); btnPro.classList.remove('tw-bg-black', 'tw-text-white'); // 这里可以加你切换到 X1 的逻辑 if (this.productType !== 3) { this.productType = 3; this.page = 1; this.loadMoreData(); } }); } } initDataLayer() { let startTime = 0; const worldVideoList = document.querySelector('.world-video-list'); const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { // 进入视窗:开始计时 startTime = Date.now(); window.zzAnalytics && window.zzAnalytics.trackEvent('world_video_show', { timestamp: new Date().toISOString(), }); } else { // 离开视窗:结束计时并累加 if (startTime) { const duration = Date.now() - startTime; startTime = 0; // 大于2秒 上报 if (duration > 2000) { window.zzAnalytics && window.zzAnalytics.trackEvent('world_video_show_time', { timestamp: new Date().toISOString(), duration: duration, }); } } } }); }); observer.observe(worldVideoList); } addFooterAction() { // 监听 video-page-content-footer 出现在视口上就发送请求第二页数据 const videoPageContentFooter = this.querySelector( '#video-page-content-footer' ); const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { this.loadNextPage(); window.zzAnalytics && window.zzAnalytics.trackEvent('world_video_scroll', { timestamp: new Date().toISOString(), }); } }); }); observer.observe(videoPageContentFooter); } addVideoAction() { // 改成在父级 video-page-content 添加监听事件 const videoPageContent = this.querySelector('#video-page-content'); if (videoPageContent) { videoPageContent.addEventListener('click', (event) => { // 检查点击的元素是否是 .video-item 或其子元素 const videoItem = event.target.closest('.video-item'); if (videoItem) { event.stopPropagation(); const itemDataStr = videoItem.getAttribute('data-item'); const itemData = JSON.parse(decodeURIComponent(itemDataStr)); // 找到视频在list位置 const videoIndex = this.videoList.findIndex( (item) => item.id === itemData.id ); const dialog = this.querySelector('world-video-dialog'); if (dialog) { dialog.showModal(videoIndex); } } }); } } loadNextPage() { this.page++; this.loadMoreData(); } loadMoreData() { if (!this.hasMore && this.page !== 1) { return; } httpRequest .get( '/shopify/media-list', { page: this.page, pageSize: this.pageSize, productType: this.productType, shop: this.shopSelect, }, { baseUrl: this.baseUrl } ) .then((res) => { if (res.code === 200) { if (this.page === 1) { // 切换类型 清空数据 this.videoList = res.data.list; this.updatePageList(res.data.list, true); } else { this.videoList = [...this.videoList, ...res.data.list]; this.updatePageList(res.data.list); } if (res.data.list.length < this.pageSize) { this.hasMore = false; this.hideFooter(); } else { this.hasMore = true; } } }); } hideFooter() { const footer = this.querySelector('#video-page-content-footer'); if (footer) { footer.style.display = 'none'; } } // 插入一页的数据 8条 updatePageList(pageData, isFirst = false) { const videoIndexList = [0, 3, 6, 7]; if (isFirst) { const videoPageContent = this.querySelector('#video-page-content'); const headerFooter = $('#world-video-header-footer').html(); if (videoPageContent) { videoPageContent.innerHTML = headerFooter; this.addFooterAction(); } } const template = $('#video-page-item').html(); let replacedTemplate = template; pageData.forEach((item, index) => { const replaceSrc = `video-${index + 1}`; const replacePoster = `poster-${index + 1}`; if (videoIndexList.includes(index)) { replacedTemplate = replacedTemplate .replace(new RegExp(`{${replaceSrc}}`, 'g'), item.videoUrl) .replace(new RegExp(`{${replacePoster}}`, 'g'), item.pictureUrl); } else { replacedTemplate = replacedTemplate.replace( new RegExp(`{${replaceSrc}}`, 'g'), item.pictureUrl ); } // 将item转成 json字符串 const itemJson = JSON.stringify(item); const replaceItem = `video-item-${index + 1}`; replacedTemplate = replacedTemplate.replace( new RegExp(`{${replaceItem}}`, 'g'), encodeURIComponent(itemJson) ); }); for (let i = 1; i < 9; i++) { const replaceItem = `item-display-${i}`; if (i > pageData.length) { replacedTemplate = replacedTemplate.replace( new RegExp(`{${replaceItem}}`, 'g'), 'tw-hidden' ); } else { replacedTemplate = replacedTemplate.replace( new RegExp(`{${replaceItem}}`, 'g'), '' ); } } $('#video-page-content-footer').before(replacedTemplate); this.initLazyLoad(); const dialog = this.querySelector('world-video-dialog'); if (dialog) { dialog.updateSlide(pageData, this.productType, isFirst); } } updateDialogInfo(index) { const dialog = this.querySelector('world-video-dialog'); if (!dialog) return; // 找到dialog下面swiper-wrapper const swiperWrapper = dialog.querySelector('.swiper-wrapper'); if (!swiperWrapper) return; // 找到swiper-wrapper 清空 swiperWrapper.innerHTML = ''; // 遍历videoList 添加元素 const template = $('#video-swiper-slide').html(); this.videoList.forEach((item, index) => { let replacedTemplate = template .replace(new RegExp('{video-url}', 'g'), item.videoUrl) .replace( new RegExp('{avatar}', 'g'), item.userInfo && item.userInfo.avatar ) .replace( new RegExp('{nickname}', 'g'), item.userInfo && item.userInfo.nickname ) .replace(new RegExp('{content}', 'g'), item.content) .replace(new RegExp('{likeCount}', 'g'), item.likeCount) .replace(new RegExp('{commentCount}', 'g'), item.commentCount) .replace(new RegExp('{mediaId}', 'g'), item.id); if (this.productType === 1) { replacedTemplate = replacedTemplate .replace(new RegExp('{product-links}', 'g'), this.x1Links) .replace(new RegExp('{product-icon}', 'g'), this.x1Img); } else if (this.productType === 4) { replacedTemplate = replacedTemplate .replace(new RegExp('{product-links}', 'g'), this.x1ProLinks) .replace(new RegExp('{product-icon}', 'g'), this.x1ProImg); } else if (this.productType === 3) { replacedTemplate = replacedTemplate .replace(new RegExp('{product-links}', 'g'), this.x121Links) .replace(new RegExp('{product-icon}', 'g'), this.x121Img); } $('#video-swiper-wrapper').append(replacedTemplate); }); } } customElements.define('world-video-list', WorldVideoList);