zz-shopify-components
Version:
Reusable Shopify components for theme projects
366 lines (348 loc) • 12.1 kB
JavaScript
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);