The Daily Leisure Of Big Men, My God, My King, I Want To Respect Your Printed Short-sleeved T-shirt, Shorts And Suit
${function() {
const variantData = data.variant || {"id":"7f8ee818-e5bd-4371-b827-c763bca68601","product_id":"c01a5337-4200-4805-89a0-99da49f31c2d","title":"Set-white-L","weight_unit":"kg","inventory_quantity":1000,"sku":"456454ysmytzX-Set-white-L","barcode":"","position":1,"option1":"Set-white","option2":"L","option3":"","note":"","image":{"src":"\/\/img.staticdj.com\/35fd52573c4c7ffa0f28ee50813a0f74.jpeg","path":"35fd52573c4c7ffa0f28ee50813a0f74.jpeg","width":2356,"height":2944,"alt":"The Daily Leisure Of Big Men, My God, My King, I Want To Respect Your Printed Short-sleeved T-shirt, Shorts And Suit","aspect_ratio":0.8002717391304348},"wholesale_price":[{"price":58,"min_quantity":1}],"weight":"0.55","compare_at_price":"58","price":"58","retail_price":"58","available":true,"url":"\/products\/the-daily-leisure-of-big-men-my-god-my-king-i-want-to-respect-your-printed-short-sleeved-t-shirt-shorts-and-suit?variant=7f8ee818-e5bd-4371-b827-c763bca68601","available_quantity":999999999,"options":[{"name":"Color","value":"Set-white"},{"name":"Size","value":"L"}],"off_ratio":"0","flashsale_info":{"variant_id":"7f8ee818-e5bd-4371-b827-c763bca68601","product_id":"","quantity":0,"discount_id":"","limit_time":0,"limit_buy":0,"user_limit_buy":0,"discount_sales":0,"discount_sales_rate":"","discount_stock":0,"ends_at":0,"starts_at":0,"allow_oversold":"","allocation_method":"","price":"58","compare_at_price":"","discount_price":"58","customary_saved_price":"","customary_off_ratio":"","discount_saved_price":"","discount_off_ratio":"0","use_before_price":false,"before_price":"","title":"","properties":"","color_setting_promotional_copy":"","discount_quantity":0,"is_need_split":false},"sales":0};
const saveType = "percentage";
const productLabelDiscountOn = false;
const map = {
B: ` `,
C: ` `,
A: `
${saveType == 'percentage'
? `-${variantData.off_ratio}%`
: `- `
}
`
}
const price_group_arr = ["B","C","A"];
const price_str_arr = price_group_arr.map(type => map[type]);
return `
-
${price_str_arr.join('')}
`;
}()}
${function(){
const isRTL = originData.isRTL;
const isMobile = originData.isMobile;
const inProductDetail = originData.inProductDetail;
if (!inProductDetail) {
return `
Flash sale cannot be displayed here. Please move it to the product detail area.
(This prompt will not be displayed on the client-side)
`;
}
const flashsaleData = originData.flashsaleData;
const image_domain = originData.image_domain;
const discount_info = flashsaleData.discount_info;
const setting = flashsaleData.product_setting;
if (!discount_info || !setting) return ``;
const displayType = setting.display_type;
const banner = setting.banner;
const productDisplay = setting.product_display;
const bannerConfig = JSON.parse(banner.config);
const productDisplayConfig = JSON.parse(productDisplay.config);
const colorConfig = productDisplayConfig.color;
const countdownConfig = productDisplayConfig.countdown;
let titleIcon = ``;
let bgImg = ``;
const deg = `${isRTL ? -90 : 90}deg`;
const { banner_bg_start, banner_bg_end, banner_text } = colorConfig;
let bgStyle = `background: linear-gradient(${deg}, ${banner_bg_start} 0%, ${banner_bg_end} 100%);`;
let bannerColor = `color: ${banner_text};`
if (banner.type === "TYPE_CUSTOM") {
const { desktop, mobile, image_render } = bannerConfig;
const bgSize = image_render === "fill" ? "background-size: cover;background-position: center;" : "background-position: center;background-size: auto 100%;";
if (isMobile && mobile) {
bgStyle = `background: URL(${image_domain + mobile});${bgSize}`;
} else if (!isMobile && desktop) {
bgStyle = `background: URL(${image_domain + desktop});${bgSize}`;
}
} else {
if (banner.type === "TYPE_ONE") {
titleIcon = productDisplay.text ? `
` : "";
bgImg = ``
}
if (banner.type === "TYPE_TWO") {
titleIcon = productDisplay.text ? `
` : ""
}
}
const { sale_bar_background_color, progress_sale_bar_background_color_start, progress_sale_bar_background_color_end } = colorConfig;
const rate = discount_info.discount_sales_rate;
const progressBarStyle = `background: linear-gradient(${deg}, ${progress_sale_bar_background_color_start} 0%, ${progress_sale_bar_background_color_end} 100%);`;
const saleCount = productDisplay.sales_progress.format === "FORMAT_NUMBER" ? discount_info.discount_sales : `${rate}%`;
const progressBarDom = productDisplay.sales_progress.enabled && rate > 0 ? `
` : ``;
const { countdown_bg, countdown_text } = colorConfig;
const { end_opened, end_format } = countdownConfig;
const tempMap = {
"DD_SSS": "DD:HH:mm:ss:SSS",
"HH_SSS": "HH:mm:ss:SSS",
"DD_ss": "DD:HH:mm:ss",
"HH_ss": "HH:mm:ss"
}
const isShowDD = [tempMap.DD_SSS, tempMap.DD_ss].includes(end_format);
const isShowSSS = [tempMap.DD_SSS, tempMap.HH_SSS].includes(end_format);
const countdown = discount_info.ends_remaining_seconds;
const countdownDom = end_opened ? `
${function() {
if (banner.type === "TYPE_TWO") return `
`
return ``;
}()}
` : ``;
const flashSaleDesc = discount_info.limit_user_product_discount > -1 ? `
Promo products limited to ${discount_info.limit_user_product_discount} item per person
` : "";
return `
${bgImg}
${titleIcon}
${productDisplay.text}
${progressBarDom}
${countdownDom}
${flashSaleDesc}
`}()}
${function(){
const dd = data.dd; const hh = data.hh; const mm = data.mm; const ss = data.ss; const sss = data.SSS;
const hours = data.d * 24 + data.h;
return `
${dd}D
·
${hours}
${hh}
:
${mm}
:
${ss}
.
${sss}
`
}()}
class SpzCustomDiscountFlashsale extends SPZ.BaseElement {
constructor(element) {
super(element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.getFlashSaleApi = "\/api\/storefront\/promotion\/flashsale\/display_setting\/product_setting";
this.timer = null;
this.variantId = "7f8ee818-e5bd-4371-b827-c763bca68601";
// 促销活动数据
this.flashsaleData = {}
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
buildCallback() {
this.templates_ = SPZServices.templatesForDoc();
this.viewport_ = this.getViewport();
// 挂载bind函数 解决this指向问题
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
this.switchVariant = this.switchVariant.bind(this);
}
mountCallback() {
// 获取数据
this.getData();
this.element.onclick = (e) => {
const cur = this.win.document.querySelector(".app_discount_flashsale_desc");
if (this.flashsaleData.product_setting.is_redirection && appDiscountUtils.inProductBody(this.element) && e.target !== cur) {
this.win.open(`/promotions/discount-default/${this.flashsaleData.discount_info.id}`);
}
}
// 绑定
this.viewport_.onResize(this.resize);
// 监听子款式切换,重新渲染
this.win.document.addEventListener('dj.variantChange', this.switchVariant);
}
unmountCallback() {
// 解绑
this.viewport_.removeResize(this.resize);
this.win.document.removeEventListener('dj.variantChange', this.switchVariant);
// 清除定时器
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
}
resize() {
if (this.timer) {
clearTimeout(this.timer)
this.timer = null;
}
this.timer = setTimeout(() => {
this.render();
}, 200)
}
switchVariant(event) {
const variant = event.detail.selected;
if (variant.product_id == 'c01a5337-4200-4805-89a0-99da49f31c2d' && variant.id != this.variantId) {
this.variantId = variant.id;
this.getData();
}
}
getData() {
const reqBody = {
product_id: "c01a5337-4200-4805-89a0-99da49f31c2d",
product_type: "default",
variant_id: this.variantId
}
this.flashsaleData = {};
this.win.fetch(this.getFlashSaleApi, {
method: "POST",
body: JSON.stringify(reqBody),
headers: {
"Content-Type": "application/json"
}
}).then(async (response) => {
if (response.ok) {
this.flashsaleData = await response.json();
this.render();
} else {
this.clearDom();
}
}).catch(err => {
this.clearDom();
});
}
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
render() {
this.templates_
.findAndRenderTemplate(this.element, {
isMobile: appDiscountUtils.judgeMobile(),
isRTL: appDiscountUtils.judgeRTL(),
inProductDetail: appDiscountUtils.inProductBody(this.element),
flashsaleData: this.flashsaleData,
image_domain: this.win.SHOPLAZZA.image_domain,
})
.then((el) => {
this.clearDom();
this.element.appendChild(el);
})
}
}
SPZ.defineElement('spz-custom-discount-flashsale', SpzCustomDiscountFlashsale);
${function(){
// 获取基础配置数据
const isRTL = originData.isRTL; // 是否从右到左显示
const isMobile = originData.isMobile; // 是否移动端
const inProductDetail = originData.inProductDetail; // 是否在商品详情页
const image_domain = originData.image_domain; // 图片域名
const copyBtnClass = originData.copyBtnClass; // 复制按钮类名
const copyClass = originData.copyClass; // 复制内容类名
// 优惠码列表
const list = originData.discountCodeData.list || [];
if (list.length === 0) {
return ``;
}
// 显示模式: 平铺或折叠
const isTiled = originData.discountCodeData.display_type === "DTE_TILE";
// 获取第一个配置作为默认配置
const productSetting = list[0].product_setting;
const { template_type, template_config } = productSetting;
const { text, tag, banner, coupon } = template_config.color;
// 优惠券样式配置
const {
coupon_border_color, // 边框颜色
coupon_background_color, // 背景色起始色
coupon_background_color_end, // 背景色结束色
coupon_color, // 文字颜色
coupon_button_background_color_start, // 按钮背景起始色
coupon_button_background_color_end, // 按钮背景结束色
coupon_button_color // 按钮文字颜色
} = coupon;
// 颜色透明度转换函数
const colorToRGBA = (color, alpha) => {
if (color.startsWith('#')) {
const hex = color.slice(1);
const r = parseInt(hex.slice(0, 2), 16);
const g = parseInt(hex.slice(2, 4), 16);
const b = parseInt(hex.slice(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
else if (color.includes('rgb')) {
const rgb = color.slice(color.indexOf('(') + 1, color.indexOf(')')).split(',');
const r = parseInt(rgb[0]);
const g = parseInt(rgb[1]);
const b = parseInt(rgb[2]);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
else {
return color
}
}
// 渲染平铺样式的优惠券列表
const renderTiledList = (list, isFold = false) => {
const rate = isRTL ? '34%' : '66%'; // RTL布局时调整分割线位置
let curDom = `
`;
// 循环渲染优惠券列表
for(const item of list) {
curDom += `
${item.discount_text}
${(isFold || item.product_setting.show_effective_date) && +item.ends_at !== -1 ? `${item.starts_at} - ${item.ends_at}` : ""}
`
}
return curDom;
}
let Dom = ``;
// 根据显示模式选择渲染方式
if (isTiled || list.length === 1) {
// 根据模板类型渲染不同样式
switch(template_type) {
// 文本样式
case 'text': {
Dom = `
${function(){
let textDom = '';
for(const item of list) {
textDom += `
${ item.discount_text }
Code:
${ item.code }
`
}
return textDom;
}()}
`;
break;
}
// 标签样式
case 'tag': {
const { text_color, background_color } = tag;
Dom = `
${function(){
let textDom = '';
for(const item of list) {
textDom += `
${ item.discount_text }
Code:
${ item.code }
`;
}
return textDom;
}()}
`
break;
}
// 横幅样式
case 'banner': {
Dom = `
${function(){
let textDom = '';
for(const item of list) {
textDom += `
${ item.discount_text }
Code:
${ item.code }
`;
}
return textDom;
}()}
`;
break;
}
// 优惠券样式
case 'coupon': {
Dom = `
${renderTiledList(list)}
`
break;
}
}
} else {
// 折叠模式样式
const foldStyle = `
`;
// 只显示前3个优惠券
const showList = list.slice(0, 3);
let couponDom = "";
for(const item of showList) {
couponDom += `
${item.discount_text}
`
}
// PC端弹窗
const webModal = `
${function(){
return renderTiledList(list, true);
}()}
`
// 移动端侧边栏
const mobileModal = `
`
couponDom += `
Click to claim
${isMobile ? mobileModal : webModal}
`;
Dom = `
${foldStyle}
${couponDom}
`
}
return `
${Dom}
`;
}()}
/**
* 优惠码组件模型类
* 处理优惠码的显示和交互逻辑
*/
class SpzCustomDiscountCodeModel extends SPZ.BaseElement {
constructor(element) {
super(element);
// 复制按钮和内容的类名
this.copyBtnClass = "discount_code_btn"
this.copyClass = "discount_code_value"
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
buildCallback() {
// 初始化服务
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.templates_ = SPZServices.templatesForDoc(this.element);
this.xhr_ = SPZServices.xhrFor(this.win);
}
/**
* 渲染优惠码组件
* @param {Object} data - 渲染数据
*/
doRender_(data) {
return this.templates_
.findAndRenderTemplate(this.element,
Object.assign(this.getDefaultData(), data)
)
.then((el) => {
this.clearDom();
this.element.appendChild(el);
// 绑定复制代码功能
this.copyCode(el, data);
});
}
/**
* 获取渲染模板
* @param {Object} data - 渲染数据
*/
getRenderTemplate(data) {
const renderData = Object.assign(this.getDefaultData(), data);
return this.templates_
.findAndRenderTemplate(this.element, renderData)
.then((el) => {
this.clearDom();
return el;
});
}
/**
* 清除DOM内容
*/
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
/**
* 获取默认数据
* @returns {Object} 默认数据对象
*/
getDefaultData() {
return {
isMobile: appDiscountUtils.judgeMobile(),
isRTL: appDiscountUtils.judgeRTL(),
image_domain: this.win.SHOPLAZZA.image_domain,
copyBtnClass: this.copyBtnClass,
copyClass: this.copyClass
}
}
/**
* 复制优惠码功能
* @param {Element} el - 当前元素
*/
copyCode(el) {
const copyBtnList = el.querySelectorAll(`.${this.copyBtnClass}`);
if (copyBtnList.length > 0) {
copyBtnList.forEach(item => {
item.onclick = async () => {
// 确保获取正确的元素和内容
const codeElement = item.querySelector(`.${this.copyClass}`);
if (!codeElement) return;
// 获取纯文本内容
const textToCopy = codeElement.innerText.trim();
// 尝试使用现代API,如果失败则使用备用方案
try {
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(textToCopy);
} else {
throw new Error('Clipboard API not available');
}
// 显示复制成功提示
this.showCopySuccessToast(textToCopy, el);
} catch (err) {
console.error('Modern clipboard API failed, trying fallback...', err);
// 使用备用复制方案
this.fallbackCopy(textToCopy, el);
}
const discountId = item.dataset["discountId"];
// 是否跳转落地页配置
const redirection = item.dataset["redirection"] === "true";
// 跳转到落地页
if (redirection && appDiscountUtils.inProductBody(this.element)) {
this.win.open(`/promotions/discount-default/${discountId}`);
}
}
})
}
}
/**
* 使用 execCommand 的复制方案
* @param {string} codeText - 要复制的文本
* @param {Element} el - 当前元素
*/
fallbackCopy(codeText, el) {
const textarea = this.win.document.createElement('textarea');
textarea.value = codeText;
// 设置样式使文本框不可见
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
textarea.style.top = '0';
// 添加 readonly 属性防止移动端虚拟键盘弹出
textarea.setAttribute('readonly', 'readonly');
this.win.document.body.appendChild(textarea);
textarea.focus();
textarea.select();
try {
this.win.document.execCommand('copy');
// 显示复制成功提示
this.showCopySuccessToast(codeText, el);
} catch (err) {
console.error('Copy failed:', err);
}
this.win.document.body.removeChild(textarea);
}
/**
* 创建 Toast 元素
* @returns {Element} 创建的 Toast 元素
*/
createToastEl_() {
const toast = document.createElement('ljs-toast');
toast.setAttribute('layout', 'nodisplay');
toast.setAttribute('hidden', '');
toast.setAttribute('id', 'discount-code-toast');
toast.style.zIndex = '1051';
return toast;
}
/**
* 挂载 Toast 元素到 body
* @returns {Element} 挂载的 Toast 元素
*/
mountToastToBody_() {
const existingToast = this.win.document.getElementById('discount-code-toast');
if (existingToast) {
return existingToast;
}
const toast = this.createToastEl_();
this.win.document.body.appendChild(toast);
return toast;
}
/**
* 复制成功的提醒
* @param {string} codeText - 要复制的文本
* @param {Element} el - 当前元素
*/
showCopySuccessToast(codeText, el) {
const $toast = this.mountToastToBody_();
SPZ.whenApiDefined($toast).then(toast => {
toast.showToast("Discount code copied !");
this.codeCopyInSessionStorage(codeText);
});
}
/**
* 复制优惠码成功后要存一份到本地存储中,购物车使用
* @param {string} codeText - 要复制的文本
*/
codeCopyInSessionStorage(codeText) {
try {
sessionStorage.setItem('other-copied-coupon', codeText);
} catch (error) {
console.error(error)
}
}
}
// 注册自定义元素
SPZ.defineElement('spz-custom-discount-code-model', SpzCustomDiscountCodeModel);
${function(){
return `
Discount code cannot be displayed here. Please move it to the product detail area.
(This prompt will not be displayed on the client-side)
`;
}()}
/**
* Custom discount code component that handles displaying and managing discount codes
* @extends {SPZ.BaseElement}
*/
class SpzCustomDiscountCode extends SPZ.BaseElement {
constructor(element) {
super(element);
// API endpoint for fetching discount codes
this.getDiscountCodeApi = "\/api\/storefront\/promotion\/code\/list";
// Debounce timer for resize events
this.timer = null;
// Current variant ID
this.variantId = "7f8ee818-e5bd-4371-b827-c763bca68601";
// Store discount code data
this.discountCodeData = {}
}
/**
* Check if layout is supported
* @param {string} layout - Layout type
* @return {boolean}
*/
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
/**
* Initialize component after build
*/
buildCallback() {
this.templates_ = SPZServices.templatesForDoc();
this.viewport_ = this.getViewport();
// Bind methods to maintain context
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
this.switchVariant = this.switchVariant.bind(this);
}
/**
* Setup component when mounted
*/
mountCallback() {
this.getData();
// Add event listeners
this.viewport_.onResize(this.resize);
this.win.document.addEventListener('dj.variantChange', this.switchVariant);
}
/**
* Cleanup when component is unmounted
*/
unmountCallback() {
this.viewport_.removeResize(this.resize);
this.win.document.removeEventListener('dj.variantChange', this.switchVariant);
// 清除定时器
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
}
/**
* Handle resize events with debouncing
*/
resize() {
if (this.timer) {
clearTimeout(this.timer)
this.timer = null;
}
this.timer = setTimeout(() => {
if (appDiscountUtils.inProductBody(this.element)) {
this.render();
} else {
this.renderSkeleton();
}
}, 200);
}
/**
* Handle variant changes
* @param {Event} event - Variant change event
*/
switchVariant(event) {
const variant = event.detail.selected;
if (variant.product_id == 'c01a5337-4200-4805-89a0-99da49f31c2d' && variant.id != this.variantId) {
this.variantId = variant.id;
this.getData();
}
}
/**
* Fetch discount code data from API
*/
getData() {
if (appDiscountUtils.inProductBody(this.element)) {
const reqBody = {
product_id: "c01a5337-4200-4805-89a0-99da49f31c2d",
variant_id: this.variantId,
product_type: "default",
}
if (!reqBody.product_id || !reqBody.variant_id) return;
this.discountCodeData = {};
this.win.fetch(this.getDiscountCodeApi, {
method: "POST",
body: JSON.stringify(reqBody),
headers: {
"Content-Type": "application/json"
}
}).then(async (response) => {
if (response.ok) {
let data = await response.json();
if (data.list && data.list.length > 0) {
data.list[0].product_setting.template_config = JSON.parse(data.list[0].product_setting.template_config);
// Format timestamps to local timezone
const zone = this.win.SHOPLAZZA.shop.time_zone;
data.list = data.list.map(item => {
if(+item.ends_at !== -1) {
item.ends_at = appDiscountUtils.convertTimestampToFormat(+item.ends_at, zone);
}
item.starts_at = appDiscountUtils.convertTimestampToFormat(+item.starts_at, zone);
return item;
});
}
this.discountCodeData = data;
this.render();
} else {
this.clearDom();
}
}).catch(err => {
console.error("discount_code", err)
this.clearDom();
});
} else {
this.renderSkeleton();
}
}
/**
* Clear component DOM except template
*/
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
/**
* Render discount codes with formatted dates
*/
render() {
// Render using discount code model
SPZ.whenApiDefined(document.querySelector('#spz_custom_discount_code_model')).then(renderApi => {
renderApi.doRender_({
discountCodeData: this.discountCodeData
})
}).catch(err => {
this.clearDom();
})
}
renderSkeleton() {
// Render template for non-product pages
this.templates_
.findAndRenderTemplate(this.element, {
isMobile: appDiscountUtils.judgeMobile()
})
.then((el) => {
this.clearDom();
this.element.appendChild(el);
})
.catch(err => {
this.clearDom();
});
}
}
// Register custom element
SPZ.defineElement('spz-custom-discount-code', SpzCustomDiscountCode);
const TAG = "spz-custom-product-automatic";
class SpzCustomProductAutomatic extends SPZ.BaseElement {
constructor(element) {
super(element);
this.variant_id = '7f8ee818-e5bd-4371-b827-c763bca68601';
this.isRTL = SPZ.win.document.dir === 'rtl';
}
static deferredMount() {
return false;
}
buildCallback() {
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.templates_ = SPZServices.templatesForDoc(this.element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.setupAction_();
this.viewport_ = this.getViewport();
}
mountCallback() {
console.log('自动折扣直出数据',{"downgrade":false,"automatic_discount_list":[],"hash":""});
this.init();
// 监听事件
this.bindEvent_();
}
async init() {
this.handleFitTheme();
const promotionComplex = {"downgrade":false,"automatic_discount_list":[],"hash":""};
let data = await this.getDiscountList();
if (data.hash && (data.hash !== promotionComplex.hash)) {
// 兜底方案, downgrade == true; 需要降级 则要请求接口,
// 但是直出数据可能存在缓存,一定会调用一次接口,直接判断hash版本,不一致就用接口的,一致就没必要重新渲染一模一样的数据了
console.log('%c 自动折扣hash不一致, 使用接口数据 ', 'background:#ffe3f4;border: 1px solid #ff4395; color: #ff4395;', data.hash);
this.renderApiData_(data);
}
}
async getDiscountList() {
const productId = 'c01a5337-4200-4805-89a0-99da49f31c2d';
const variantId = this.variant_id;
const productType = 'default';
const reqBody = {
product_id: productId,
variant_id: variantId,
discount_method: "DM_AUTOMATIC",
customer: {
customer_id: window.C_SETTINGS.customer.customer_id,
email: window.C_SETTINGS.customer.customer_email
},
product_type: productType
}
const url = `/api/storefront/promotion/display_setting/text/list`;
const data = await this.xhr_.fetchJson(url, {
method: "post",
body: reqBody
}).then(res => {
return res;
}).catch(err => {
this.setContainerDisabled(false);
})
return data;
}
async renderApiData_(data) {
const parentDiv = document.querySelector('.automatic_discount_container');
const newTplDom = await this.getRenderTemplate(data);
if(parentDiv){
parentDiv.innerHTML = '';
parentDiv.appendChild(newTplDom);
}
}
async renderDiscountList() {
this.setContainerDisabled(true);
const data = await this.getDiscountList();
this.setContainerDisabled(false);
// 重新渲染 抖动问题处理
this.renderApiData_(data);
}
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
doRender_(data) {
const renderData = data || {};
return this.templates_
.findAndRenderTemplate(this.element, renderData)
.then((el) => {
this.clearDom();
this.element.appendChild(el);
});
}
async getRenderTemplate(data) {
const renderData = data || {};
return this.templates_
.findAndRenderTemplate(this.element, { ...renderData, isRTL: this.isRTL })
.then((el) => {
this.clearDom();
return el;
});
}
setContainerDisabled(isDisable) {
const automaticDiscountEl = document.querySelector('.automatic_discount_container');
if(isDisable) {
automaticDiscountEl.setAttribute('disabled', '');
} else {
automaticDiscountEl.removeAttribute('disabled');
}
}
// 绑定事件
bindEvent_() {
window.addEventListener('click', (e) => {
let containerNodes = document.querySelectorAll(".automatic-container .panel");
let bool;
Array.from(containerNodes).forEach((node) => {
if(node.contains(e.target)){
bool = true;
}
})
// 是否popover面板点击范围
if (bool) {
return;
}
if(e.target.classList.contains('drowdown-icon') || e.target.parentNode.classList.contains('drowdown-icon')){
return;
}
const nodes = document.querySelectorAll('.automatic-container');
Array.from(nodes).forEach((node) => {
node.classList.remove('open-dropdown');
})
// 兼容主题
this.toggleProductSticky(true);
})
// 监听变体变化
document.addEventListener('dj.variantChange', async(event) => {
// 重新渲染
const variant = event.detail.selected;
if (variant.product_id == 'c01a5337-4200-4805-89a0-99da49f31c2d' && variant.id != this.variant_id) {
this.variant_id = variant.id;
this.renderDiscountList();
}
});
}
// 兼容主题
handleFitTheme() {
// top 属性影响抖动
let productInfoEl = null;
if (window.SHOPLAZZA.theme.merchant_theme_name === 'Wind' || window.SHOPLAZZA.theme.merchant_theme_name === 'Flash') {
productInfoEl = document.querySelector('.product-info-body .product-sticky-container');
} else if (window.SHOPLAZZA.theme.merchant_theme_name === 'Hero') {
productInfoEl = document.querySelector('.product__info-wrapper .properties-content');
}
if(productInfoEl){
productInfoEl.classList.add('force-top-auto');
}
}
// 兼容 wind/flash /hero 主题 (sticky属性影响 popover 层级展示, 会被其他元素覆盖)
toggleProductSticky(isSticky) {
let productInfoEl = null;
if (window.SHOPLAZZA.theme.merchant_theme_name === 'Wind' || window.SHOPLAZZA.theme.merchant_theme_name === 'Flash') {
productInfoEl = document.querySelector('.product-info-body .product-sticky-container');
} else if (window.SHOPLAZZA.theme.merchant_theme_name === 'Hero') {
productInfoEl = document.querySelector('.product__info-wrapper .properties-content');
}
if(productInfoEl){
if(isSticky) {
// 还原该主题原有的sticky属性值
productInfoEl.classList.remove('force-position-static');
return;
}
productInfoEl.classList.toggle('force-position-static');
}
}
setupAction_() {
this.registerAction('handleDropdown', (invocation) => {
const discount_id = invocation.args.discount_id;
const nodes = document.querySelectorAll('.automatic-container');
Array.from(nodes).forEach((node) => {
if(node.getAttribute('id') != `automatic-${discount_id}`) {
node.classList.remove('open-dropdown');
}
})
const $discount_item = document.querySelector(`#automatic-${discount_id}`);
$discount_item && $discount_item.classList.toggle('open-dropdown');
// 兼容主题
this.toggleProductSticky();
});
}
triggerEvent_(name, data) {
const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {});
this.action_.trigger(this.element, name, event);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
}
SPZ.defineElement(TAG, SpzCustomProductAutomatic);
${(function () {
const automatic_discount_list = originData.automatic_discount_list;
// 显示类型
const DISPLAY_TYPE = {
DTE_FOLD: 'DTE_FOLD', // 折叠
DTE_TILE: 'DTE_TILE' // 平铺
}
const DEFAULT_CONFIG = {
BG: 'rgba(235, 57, 27, 0.04)',
TEXT_COLOR: '#EB391B',
BORDER_COLOR: 'rgb(235, 57, 27)'
};
const isExist = automatic_discount_list?.length > 0 && automatic_discount_list.some(item => item.discount[0].product_enabled);
// 如果没有任何自动折扣,则隐藏,防止gap占位
if (!isExist) {
return `
`;
} else {
return `
${(function () {
return automatic_discount_list.map((item) => {
// 模版类型
const template_type = item.discount[0].template_type;
// 是否显示自动折扣
const is_show_automatic_discount = item.discount[0].product_enabled;
// 是否跳转落地页
const is_redirection = item.discount[0].is_redirection;
// 折扣图标
const discount_icon = item.discount_icon;
// 第一个自动折扣
const first_automatic_discount = item.discount[0];
// 显示折叠展示
const isFold = (item.discount[0].display_type || DISPLAY_TYPE.DTE_FOLD) === DISPLAY_TYPE.DTE_FOLD;
// 文本数组
const text_arr = item.discount[0].config.texts;
// 落地页链接
const first_landing_url = `/promotions/discount-default/${first_automatic_discount.discount_id}`;
// 自动折扣总数
const automatic_discount_total = item.discount.length;
// 是否显示折扣图标
const isHasDiscountIcon = discount_icon ? true : false;
// 是否显示折扣图标且模版类型不为tag
const isHasDiscountIconWithNoTag = (template_type != 'tag' && isHasDiscountIcon)? true : false;
// 文本颜色
let text_color = DEFAULT_CONFIG.TEXT_COLOR;
// 背景颜色
const bgFn = (curBg) => template_type === "text" ? "transparent" : curBg;
let bg_color = bgFn(DEFAULT_CONFIG.BG);
// 边框颜色
const borderFn = (curBorder) => template_type == "tag" ? curBorder : "initial";
let border_color = borderFn(DEFAULT_CONFIG.BORDER_COLOR);
// 模版配置
let template_config = first_automatic_discount.template_config;
// 兜底方案
try {
if(template_config.length !== 0){
template_config = JSON.parse(template_config);
text_color= isHasDiscountIconWithNoTag ? template_config.color[template_type].icon_text_color : template_config.color[template_type].text_color;
bg_color = bgFn(template_config.color[template_type].background_color);
const arrayRgba = bg_color.split(",");
arrayRgba.splice(3, 1, " 1)");
border_color = borderFn(`${arrayRgba.join(",")}`);
}
} catch (error) {
console.error('template_config_error', error);
template_config = {
color: {
[template_type]: {
icon_text_color: DEFAULT_CONFIG.TEXT_COLOR,
text_color: DEFAULT_CONFIG.TEXT_COLOR,
background_color: DEFAULT_CONFIG.BG
}
}
};
}
// 标签
const isTag = template_type == 'tag';
// 文字和横幅
const isTextAndBanner = template_type == 'text' || template_type == 'banner';
// 文字样式
const textStyle = `color: ${text_color}; background-color: transparent; border: none;`;
// 标签样式
const labelStyle = `color: ${text_color};border: 1px solid ${border_color};background-color:${bg_color};padding: 4px;`;
// 横幅样式
const bannerStyle = `color: ${text_color};border: none; background-color:${bg_color}`;
// 外层样式在标签样式下不展示颜色配置,除开标签类型,颜色都可以在外层覆盖
let outerStyle = '';
if (template_type == 'text') {
outerStyle = textStyle;
} else if (template_type == 'tag') {
outerStyle = "border: none;";
} else if (template_type == 'banner') {
outerStyle = bannerStyle;
}
/**
* 1. 标签一定是单独样式展示的
* 2. 折叠:横向布局,文字和横幅,合并成一行文本; 标签:单独样式处理
* 3. 平铺:纵向布局,文字、横幅和标签; 标签:单独样式处理
*/
let txtHtml = ``;
if (isFold) {
if(isTag) {
// 标签
const spanText = text_arr.map((text) => {
return `
${text} `;
}).join('');
txtHtml = `
${spanText}
`;
} else {
// 文字和横幅
txtHtml = `
${first_automatic_discount.config.text}
`;
}
} else {
// 文字和横幅, 但标签有自己的样式
const spanText = text_arr.map((text) => {
return `
${text} `;
}).join('');
// 都是纵向布局,标签有间距, 多活动多层级横向布局
txtHtml = `
${spanText}
`;
}
/**
* 显示图标的判断
*/
const discount_type = item.discount_type;
const isShowRebateIcon = ["DT_REBATE_CTQ_OTP", "DT_REBATE_CTQ_OTR", "DT_REBATE_CTA_OTP", "DT_REBATE_CTA_OTR", "DT_M_N_DISCOUNT"].includes(discount_type) && isTextAndBanner
const isShowBxgyIcon = ["DT_BUY_ONE_GET_ONE", "DT_BUY_X_GET_Y"].includes(discount_type)
const isShowBundleIcon = ["DT_CLASSIC_BUNDLE","DT_MIX_MATCH_BUNDLE"].includes(discount_type);
/**
* 渲染下拉框或抽屉的折扣列表
*/
const discount_list_html = (curItem) => {
return `
${function() {
return curItem.discount.map(childItem => {
return `
`}).join('');
}()}
`;
}
return `
${discount_list_html(item)}
${function() {
return text_arr.map((text) => {
return `
${text}
`;
}).join('');
}()}
`;
}).join('');
})()}
`
}
})()}
Color:
Set-white
${function(){
const optName = "Color";
const optionValue = data.originData.selectData ? data.originData.selectData[optName].value : data.originData.value;
const optionValueText = optionValue ? (optionValue) : '';
return `${optionValueText} `;
}()}
${function(){
const tipText = "Please select a {{ name }}".replace(/\{\{\s+name\s+\}\}/g, data);
return `${tipText}
`
}()}
Size:
L
${function(){
const optName = "Size";
const optionValue = data.originData.selectData ? data.originData.selectData[optName].value : data.originData.value;
const optionValueText = optionValue ? (optionValue) : '';
return `${optionValueText} `;
}()}
${function(){
const tipText = "Please select a {{ name }}".replace(/\{\{\s+name\s+\}\}/g, data);
return `${tipText}
`
}()}
Add to cart
$58.00
${function(){
const wholesale_enabled = false;
const qty = data.quantity || 1;
const currentSelectVariant = data.variant;
const defaultVariant = (data.product && data.product.variants && data.product.variants[0]);
const productVariant = {"id":"7f8ee818-e5bd-4371-b827-c763bca68601","product_id":"c01a5337-4200-4805-89a0-99da49f31c2d","title":"Set-white-L","weight_unit":"kg","inventory_quantity":1000,"sku":"456454ysmytzX-Set-white-L","barcode":"","position":1,"option1":"Set-white","option2":"L","option3":"","note":"","image":{"src":"\/\/img.staticdj.com\/35fd52573c4c7ffa0f28ee50813a0f74.jpeg","path":"35fd52573c4c7ffa0f28ee50813a0f74.jpeg","width":2356,"height":2944,"alt":"The Daily Leisure Of Big Men, My God, My King, I Want To Respect Your Printed Short-sleeved T-shirt, Shorts And Suit","aspect_ratio":0.8002717391304348},"wholesale_price":[{"price":58,"min_quantity":1}],"weight":"0.55","compare_at_price":"58","price":"58","retail_price":"58","available":true,"url":"\/products\/the-daily-leisure-of-big-men-my-god-my-king-i-want-to-respect-your-printed-short-sleeved-t-shirt-shorts-and-suit?variant=7f8ee818-e5bd-4371-b827-c763bca68601","available_quantity":999999999,"options":[{"name":"Color","value":"Set-white"},{"name":"Size","value":"L"}],"off_ratio":"0","flashsale_info":{"variant_id":"7f8ee818-e5bd-4371-b827-c763bca68601","product_id":"","quantity":0,"discount_id":"","limit_time":0,"limit_buy":0,"user_limit_buy":0,"discount_sales":0,"discount_sales_rate":"","discount_stock":0,"ends_at":0,"starts_at":0,"allow_oversold":"","allocation_method":"","price":"58","compare_at_price":"","discount_price":"58","customary_saved_price":"","customary_off_ratio":"","discount_saved_price":"","discount_off_ratio":"0","use_before_price":false,"before_price":"","title":"","properties":"","color_setting_promotional_copy":"","discount_quantity":0,"is_need_split":false},"sales":0};
const variantData = currentSelectVariant || defaultVariant || productVariant;
const wholesale_price = variantData.wholesale_price || [];
if(wholesale_enabled && wholesale_price.length > 0) {
let wholesaleIndex = wholesale_price.findIndex(item => {
return item.min_quantity > qty;
});
if(wholesaleIndex < 0){
wholesaleIndex = wholesale_price.length - 1;
}else if(wholesaleIndex > 0){
wholesaleIndex = wholesaleIndex - 1;
}
const wholesalePrice = wholesale_price[wholesaleIndex] || '';
return `
`
}else {
const price = variantData && variantData.price;
return price != undefined ? `
` : ' ';
}
}()}
Buy now
Product was out of stock.
Product does not exist
${function(){
return `
`
} ()}
${function(){
const { original_price, received_discounts, picked_qty } = data;
const button_text = originData.setting.button.text;
const button_config = JSON.parse(originData.setting.button.config);
const button_action = originData.setting.button.redirect_page;
const text = originData.setting.price_text_config.text;
const price_config = JSON.parse(originData.setting.price_text_config.config);
const price_text = text.replace(/\{picked_qty\}/g, `${picked_qty} `).replace(/\{original_price\}/g, ` `).replace(/\{received_discounts\}/g, ` `);
return `
${price_text}
${button_text}
`
}()}
${function(){
return `
`
} ()}
x ${data.discount_min_purchase_qty}
${function() {
const images = data.images || [];
const selectedVariant = data.variants.find(v => (v.available && v.is_hit_discount == true)) || data.variants[0];
const selectedIndex = !!selectedVariant ? images.findIndex(img => img.src === (selectedVariant.image && selectedVariant.image.src)) : 0;
const initialSlide = selectedIndex === -1 ? 0 : selectedIndex;
return `
${images.map((image, index) => `
`).join('')}
${images.map(image => { const imageWidth = image.width || 450; const imageHeight = image.height || 450; return ` ` }).join('')}
`;
}()}
${function() {
const productData = data;
const limit_purchase = data.limit_purchase || 0;
let product_change_event = '';
let mouse_over_event = '';
let mouse_out_event = '';
const product_options = productData.options.filter(Boolean) || [];
for (let opt of product_options) {
const nameEscape = opt.name.replace(/\/|\\|\s|\'|\"|`|\<|\>/g, '');
product_change_event = product_change_event + `apps-discount-quick-shop-selected-variant-${opt.id}.rerender(data=event.selectedValues.${opt.name});`;
mouse_out_event = mouse_out_event + `apps-discount-quick-shop-selected-variant-${opt.id}.rerender(data=event.selectData.${opt.name});`;
mouse_over_event = mouse_over_event + `@${nameEscape}Mouseover="apps-discount-quick-shop-selected-variant-${opt.id}.rerender(data=event);"`;
}
const selectedVariant = productData.variants.find(v => (v.available && v.is_hit_discount == true)) || productData.variants[0];
const statusLan = ((selectedVariant && !selectedVariant.available) || (!selectedVariant && !productData.available)) ?
"Sold out" :
"Add to cart";
const status = (
(selectedVariant && !selectedVariant.available) ||
(!selectedVariant && !data.available)) ? 'soldout' : 'available';
return `
${data.title || data.brief}
Add ${productData.discount_min_purchase_qty} items for discount
`;
}()}
${function() {
const selectedVariant = data.variant || data.variants[0];
const image = selectedVariant.image || data.product.image;
const imageWidth = image?.width || 120;
const imageHeight = image?.height || 120;
return `
`
}()}
${function() {
const defaultVariant = data.variants?.find(v => (v.available && v.is_hit_discount == true)) || data.variants?.[0];
const selectedVariant = data.variant || defaultVariant;
const isHasRrice = (selectedVariant.price || selectedVariant.price == 0) ? true : false;
if(selectedVariant.flash_sale_info && selectedVariant.flash_sale_info.discount_price) {
selectedVariant.price = selectedVariant.flash_sale_info.discount_price;
}
if(data.flash_sale_info && data.flash_sale_info.discount_price) {
data.price = data.flash_sale_info.discount_price;
}
return !!selectedVariant ? `
` : `
-
`;
}()}
${function(){
const defaultVariant = data.variants?.find(v => (v.available && v.is_hit_discount == true)) || data.variants?.[0];
const selectedVariant = data.variant || defaultVariant;
let show_flashsale_limit_tip = false;
let limit_user_product_discount;
if(selectedVariant.flash_sale_info && selectedVariant.flash_sale_info?.limit_user_product_type != "LUPT_NO_LIMIT" && selectedVariant.flash_sale_info?.limit_user_product_discount > 0) {
show_flashsale_limit_tip = true;
limit_user_product_discount = selectedVariant.flash_sale_info?.limit_user_product_discount;
}
if(data.flash_sale_info && data.flash_sale_info?.limit_user_product_type != "LUPT_NO_LIMIT" && data.flash_sale_info?.limit_user_product_discount > 0) {
show_flashsale_limit_tip = true;
limit_user_product_discount = data.flash_sale_info?.limit_user_product_discount;
}
return `
Promo products limited to ${limit_user_product_discount} item per person
`
}()}
${function() {
const currentProduct = data.product;
return (currentProduct.options || []).map((option, index) => {
const optionName = option.name || '';
const optionId = option.id || '';
const position = `option${index + 1}`;
return `
${optionName}:
${option.values.map((value,idx) => {
const selected = data.product.defaultSelectValues?.[optionName] == value ? 'checked' : '';
return `
${value}
`;
}).join('')}
`;
}).join('')
}()}
${function() {
const value = (data.originData && data.originData.value) || data.value;
const isHasValue = value ? true : false;
return `
${value}
`
}()}
${(function() {
const productsInfo = data.product_info && data.product_info.product ? data.product_info.product : data;
return productsInfo.map(product => {
let price = product.price || 0;
let priceMin = product.price_min || 0;
let priceMax = product.price_max || 0;
let compareAtPriceMax = product.compare_at_price_max || 0;
let compareAtPrice = product.compare_at_price || 0;
let title = product.title || '';
let id = product.id || '';
let url = product.url || '';
let type = product.type || '';
let is_sold_out = false;
if (product.available == false && product.inventory_policy != 'continue') {
is_sold_out = true;
}
const soldOutLang1 = "Sold out";
const soldOutLang2 = "Sold out";
const discountType = data.discount_info ? data.discount_info.discount_type : product.discount_type;
const defaultVariantTitle = product.variants[0]?.title.replace('-', '/');
const variantDiscountInfo = product.variants[0]?.discount_info || {};
let discount_min_purchase_qty = 0;
if (discountType === "DT_CLASSIC_BUNDLE" && data.discount_info.enable_min_purchase_qty) {
discount_min_purchase_qty = data.discount_info.min_purchase_qty_type === "spu" ? product.discount_min_purchase_qty : product.variants[0].discount_info.discount_min_purchase_qty;
}
let imageWidth;
if (product.image.width) {
imageWidth = product.image.width;
} else {
imageWidth = "300px";
}
let imageHeight;
if (product.image.height) {
imageHeight= product.image.height;
} else {
imageHeight = "300px";
}
if (product.published) {
return `
${function(){
if (soldOutLang1){
return `
${soldOutLang1}
`
}else{
return `
${soldOutLang2}
`
}
}()}
x ${discount_min_purchase_qty}
`
} else {
return ``;
}
}).join('');
})()}
class SpzCustomDiscountBundleProducts extends SPZ.BaseElement {
constructor(element) {
super(element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.getDiscountPriceApi = "\/api\/storefront\/promotion\/calculate\/discounted_price";
this.buyNowApi = "\/api\/checkout\/order";
this.batchAtcApi = "\/api\/cart\/batch";
// 款式信息集合
this.productStyleInfo = [];
// 弹窗内选择款式集合
this.modalVariantInfo = [];
this.show_classic_bundle_spu_style = false;
this.bundleProducts = []; //捆绑商品
this.bundleConfig = {}; //下方按钮配置
this.discountId = "";
this.discountType = "";
this.discountInfo = "";
this.lineItems = [];
this.tempCss = {};
this.renderQuickShop_ = this.win.SPZCore.Types.debounce(this.win, this.renderQuickShopModal.bind(this), 500);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
buildCallback() {
this.setupAction_();
};
init(data = []) {
this.productStyleInfo = data;
}
handleRequestError_(data) {
this.showToast(data?.message || data?.errors?.[0] || 'Unknown error');
};
showToast(message) {
SPZ.whenApiDefined(document.getElementById("discount_toast")).then((apis) => {
apis.showToast(message);
});
}
//外部组件调用传值
setBundleData(products, config = "", id = "", type = "", info = {}) {
this.bundleProducts = products;
if(config) {
this.bundleConfig = config;
this.discountId = id;
this.discountType = type;
this.discountInfo = info;
this.show_classic_bundle_spu_style = type === 'DT_CLASSIC_BUNDLE' && info.enable_min_purchase_qty && info.min_purchase_qty_type == 'spu';
// 经典捆绑初始化商品数据
if(type == 'DT_CLASSIC_BUNDLE') {
this.productStyleInfo = products.map((item) => {
return this.getFilteredVariants_(item, 'single');
});
}
}
}
handleChangeSort() {
const result = this.productStyleInfo.reduce((map, item) => {
if (!map[item.product_id]) {
map[item.product_id] = [];
}
map[item.product_id].push(item);
return map;
}, {});
Object.values(result).forEach((item) => {
this.handleSpzVariantRender_(item, item[0].product_id);
this.handleProductOption_(item[0].product_id, true);
});
}
// 调用spz-tag组件的doRender方法
handleSpzVariantRender_(data, id) {
const spzVariantTag = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionSpzVariantTags-${id}`);
spzVariantTag && SPZ.whenApiDefined(spzVariantTag).then((api) => {
api.render(data, true);
});
}
// 执行经典捆绑最低购买数量更新
handleMinPurchaseQtyUpdate_(data, id) {
const minPruchaseQty = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionMinPurchaseQty-${id}`);
minPruchaseQty && SPZ.whenApiDefined(minPruchaseQty).then((api) => {
api.render(data, true);
});
}
// 更新价格
updateProductPrice_(data) {
const bottomBtnContainer = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionBottomContainer`);
if (data.length == 0) {
bottomBtnContainer && SPZ.whenApiDefined(bottomBtnContainer).then((api) => {
const renderInfo = {
setting: this.bundleConfig,
...{
original_price: 0,
received_discounts: 0,
picked_qty: 0
}
}
api.render({original_price: 0, received_discounts: 0}, true);
});
return;
}
const reqBody = {
discount_id: this.discountId,
customer: {
customer_id: '',
email: '',
},
sales_channel: {
sale_channel_type: "online",
sale_channel_id: '1712724'
},
line_items: data
}
// 如果已经有一个请求在等待,那么取消这个请求
if (this.debounceTimer) {
clearTimeout(this.debounceTimer);
}
this.debounceTimer = setTimeout(() => {
this.xhr_.fetchJson(this.getDiscountPriceApi, {
method: "post",
body: reqBody
}).then((res)=>{
// 更新商品列表价格
Object.keys(res.line_items).forEach((key) => {
const currentProductPrice = SPZCore.Dom.scopedQuerySelector(document.body, `#appDiscountProductPrice-${key}`);
currentProductPrice && SPZ.whenApiDefined(currentProductPrice).then((api) => {
api.render(res.line_items[key], true);
});
});
// 更新底部按钮总价/总折扣价
const picked_qty = data.reduce((acc, item) => {
return acc + item.quantity;
}, 0);
bottomBtnContainer && SPZ.whenApiDefined(bottomBtnContainer).then((api) => {
const data = {
setting: this.bundleConfig,
...{
...res.total_price,
picked_qty
}
}
api.render(data, true);
});
}).catch((err)=>{
this.handleRequestError_(err);
}).finally(()=>{
})
}, 100);
}
// 还原商品价格
resetProductPrice_(data) {
const {price, compare_at_price, id} = data;
const currentProductPrice = SPZCore.Dom.scopedQuerySelector(document.body, `#appDiscountProductPrice-${id}`);
currentProductPrice && SPZ.whenApiDefined(currentProductPrice).then((api) => {
api.render({total_received_discounts: price, total_price: compare_at_price}, true);
});
}
//处理与selector组件的交互
handleProductOption_(productId, show) {
const currentProductOption = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionSelectOption-${productId}`);
if (!currentProductOption) {
return;
};
currentProductOption.toggleAttribute('show', show);
const isSelected = currentProductOption.hasAttribute('selected');
// !show 取消选中
// !isSelected 选中商品
if (!show || !isSelected) {
const productSelector = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionProductSelector`);
productSelector && SPZ.whenApiDefined(productSelector).then((api) => {
api.toggle_({ option: productId, value: show });
});
}
}
// 混搭弹窗内的前端库存校验
handleModalInventoryCheck_(data) {
if(this.discountType == 'DT_MIX_MATCH_BUNDLE' || this.discountType == 'DT_CLASSIC_BUNDLE') {
const currentVariantAddNum = this.modalVariantInfo.find((item) => item.variant_id == data.variant_id)?.quantity || 0;
const quickShopBody = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-shop-body');
if(!!data.variant && currentVariantAddNum == Number(data.variant.available_quantity)) {
quickShopBody && quickShopBody.setAttribute('status', 'soldout');
} else {
quickShopBody && quickShopBody.setAttribute('status', 'available');
}
} else {
return;
}
}
// 添加商品子款式
renderVariantTag() {
let variantInfo;
const quickShopBody = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-shop-body');
quickShopBody && SPZ.whenApiDefined(quickShopBody).then((api) => {
variantInfo = api.getVariantsData();
const productId = variantInfo.product_id;
const variantId = variantInfo.variant_id;
const minPruchaseQtyRender = variantInfo.product.discount_min_purchase_qty || variantInfo.variant.discount_info.discount_min_purchase_qty;
if(this.discountType === 'DT_MIX_MATCH_BUNDLE') {
const index = this.productStyleInfo.findIndex((item) => item.variant_id == variantInfo.variant_id);
if (index != -1) {
this.productStyleInfo[index].quantity = Number(this.productStyleInfo[index].quantity) + Number(variantInfo.quantity);
this.updateProductPrice_(this.productStyleInfo);
} else {
this.productStyleInfo.push(this.getFilteredVariants_(variantInfo));
// 若当前商品已选中,更新商品价格
const currentProductOption = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionSelectOption-${productId}`);
const isSelected = currentProductOption && currentProductOption.hasAttribute('selected');
isSelected && this.updateProductPrice_(this.productStyleInfo);
}
const selectedVariantsFilter = this.productStyleInfo.filter((item) => item.product_id == productId);
this.handleSpzVariantRender_(selectedVariantsFilter, productId);
this.handleProductOption_(productId, true);
} else {
if(this.discountInfo.enable_min_purchase_qty == true && this.discountInfo.min_purchase_qty_type == 'spu' && minPruchaseQtyRender > 1) {
const index = this.modalVariantInfo.findIndex((item) => item.variant_id == variantId);
if (index != -1) {
this.modalVariantInfo[index].quantity = Number(this.modalVariantInfo[index].quantity) + 1;
} else {
this.modalVariantInfo.push(this.getFilteredVariants_(variantInfo, 'classic_spu'));
}
const modalVariantTag = SPZCore.Dom.scopedQuerySelector(document.body, '#promotionModalVariantTagRender');
modalVariantTag && SPZ.whenApiDefined(modalVariantTag).then((api) => {
api.render(this.modalVariantInfo, true);
});
this.handleModalInventoryCheck_(variantInfo);
const selectedVariantsNum = this.modalVariantInfo.reduce((acc, item) => {
return acc + item.quantity;
}, 0);
if(selectedVariantsNum == minPruchaseQtyRender) {
this.handleSpzVariantRender_([this.getFilteredVariants_(variantInfo)], productId);
this.productStyleInfo = this.productStyleInfo.filter((item) => item.product_id != productId).concat(this.modalVariantInfo);
const renderData = this.productStyleInfo.filter((item) => item.product_id == productId).map((item) => {
return {
...item,
is_classic_bundle_product_list_variant_tag: true
}
});
const classicSpuTag = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionClassicSpuTags-${productId}`);
classicSpuTag && SPZ.whenApiDefined(classicSpuTag).then((api) => {
api.render(renderData, true);
});
this.updateProductPrice_(this.productStyleInfo);
const quickView = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-view');
quickView && SPZ.whenApiDefined(quickView).then((api)=>{
api.close();
});
this.modalVariantInfo = [];
} else {
return;
}
}
// this.productStyleInfo 中已存在与productId, variantId都相同的商品 则直接return 关闭弹窗
const isExist = this.productStyleInfo.some((item) => item.product_id == productId && item.variant_id == variantId);
if (isExist) {
const quickView = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-view');
quickView && SPZ.whenApiDefined(quickView).then((api)=>{
api.close();
});
return;
}
// 若 this.productStyleInfo 中已存在与productId相同的商品,则不再添加 否则替换
const index = this.productStyleInfo.findIndex((item) => item.product_id == productId);
if (index != -1) {
this.productStyleInfo[index] = this.getFilteredVariants_(variantInfo);
} else {
this.productStyleInfo.push(this.getFilteredVariants_(variantInfo));
}
const selectedVariantsFilter = this.productStyleInfo.filter((item) => item.product_id == productId);
this.handleSpzVariantRender_(selectedVariantsFilter, productId);
this.handleMinPurchaseQtyUpdate_({discount_min_purchase_qty: minPruchaseQtyRender}, productId);
this.updateProductPrice_(this.productStyleInfo);
}
const quickView = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-view');
quickView && SPZ.whenApiDefined(quickView).then((api)=>{
api.close();
});
});
}
// 单变体点击添加按钮
renderSingleVariant(data) {
const { product_id } = data;
const currentProduct = this.bundleProducts.find((product) => product.id == product_id);
// 若当前商品已存在,则不再添加 而是更新数量
const index = this.productStyleInfo.findIndex((item) => item.product_id == product_id);
if (index != -1) {
this.productStyleInfo[index].quantity = Number(this.productStyleInfo[index].quantity) + 1;
this.updateProductPrice_(this.productStyleInfo);
} else {
this.productStyleInfo.push(this.getFilteredVariants_(currentProduct, 'single'));
}
const renderProductArr = this.productStyleInfo.filter((item) => item.product_id == product_id);
this.handleSpzVariantRender_(renderProductArr, product_id);
this.handleProductOption_(product_id, true);
}
// 过滤选中商品的子款式 获取有用的信息 product_id,variant_id,price,compare_at_price,quantity,title,variant_title
getFilteredVariants_(data, type = '') {
const { id, title, variants, inventory_tracking, inventory_policy, inventory_quantity, product_type } = data;
const { product_id, variant_id, variant, quantity, product, discount_min_purchase_qty } = data;
const isSingle = type == 'single';
const variantData = isSingle ? (variants[0] || data) : variant;
const productData = isSingle ? data : product;
let item_quantity = 0;
if (this.discountType === 'DT_MIX_MATCH_BUNDLE') {
item_quantity = isSingle ? 1 : Number(quantity);
} else if (type === 'classic_spu') {
item_quantity = 1;
} else {
item_quantity = discount_min_purchase_qty || productData.discount_min_purchase_qty || variantData.discount_info.discount_min_purchase_qty || 1;
}
return {
product_id: isSingle ? id : product_id,
variant_id: variantData?.id || '',
price: variantData?.price || '0.00',
compare_at_price: variantData?.compare_at_price || '0.00',
quantity: item_quantity,
inventory_tracking: productData.inventory_tracking,
inventory_policy: productData.inventory_policy,
inventory_quantity: productData.inventory_quantity,
product_type: productData.product_type || this.bundleProducts.find((item) => item.id == product_id)?.product_type || this.bundleProducts.find((item) => item.id == id)?.product_type || '',
title: productData.title,
variant_title: variantData?.options.map((option) => option.value).join('/') || '',
is_multi_style: productData.variants.length > 1,
}
}
handleLoading_ (event) {
const { type, action } = event;
const loadingElementId = type === 'product' ? '#discount-match-drawer-products_loading' : '#apps-discount-whole-loading';
const loadingElement = document.querySelector(loadingElementId);
if (loadingElement) {
SPZ.whenApiDefined(loadingElement).then((api) => {
if (action === 'show') {
api.show_();
} else {
api.close_();
}
});
}
}
handleSelectProduct(productArr) {
// 从this.productStyleInfo 过滤出选中的商品
const selectedProducts = this.productStyleInfo.filter((item) => productArr.includes(item.product_id));
this.updateProductPrice_(selectedProducts);
}
// 渲染加购弹窗内容
async renderQuickShopModal(data){
this.handleLoading_({type: 'whole', action: 'show'});
this.xhr_.fetchJson(`/api/storefront/promotion/landing_page/product?product_id=${data.product_id}&discount_id=${this.discountId}&apply_scenario=1`, {
method: "get",
}).then(async(res)=>{
//flash主题放block有层级问题
if(/Flash/.test(window.C_SETTINGS.theme.merchant_theme_name) && document.querySelector(".productInfoSection")) {
this.tempCss.zIndex = document.querySelector(".product-info-body").style.zIndex;
document.querySelector('.product-info-body').style.zIndex="1048";
}
this.handleLoading_({type: 'whole', action: 'close'});
const $quickShop = await SPZ.whenApiDefined(document.querySelector('#apps-discount-quick-view-render'));
// 定义默认渲染的子款式
const selectedVariant = res.product.variants.find((v)=> (v.available && v.is_hit_discount)) || res.product.variants[0];
let selectedValues = {};
selectedVariant.options.length && selectedVariant.options.forEach(item => {
selectedValues[item.name] = item.value;
})
// 默认选中的 子款式、 options
res.product.defaultSelectValues = selectedValues;
let data = {...res.product, product:res.product, selectedVariant, show_classic_bundle_spu_style: this.show_classic_bundle_spu_style, discountType: this.discountType};
$quickShop.render(data);
// 打开加购弹窗
SPZ.whenApiDefined(document.querySelector(`#apps-discount-quick-view`)).then((api)=>{
api.open();
});
}).catch((err)=>{
this.handleLoading_({type: 'whole', action: 'close'});
})
}
// 获取选中的商品ids
getDefaultSelectorOptions_() {
try {
const selectedOptions = SPZCore.Dom.scopedQuerySelectorAll(document.body, '[id^="promotionSelectOption-"][selected]');
return SPZCore.Types.toArray(selectedOptions).map((item) => item.getAttribute('option'));
} catch (error) {
return [];
}
}
// 删除商品子款式
deleteVariantTag(data) {
const { product_id, variant_id } = data;
if(this.discountInfo.enable_min_purchase_qty == true && this.discountInfo.min_purchase_qty_type == 'spu') {
const modalProductVariants = this.modalVariantInfo.filter((item) => item.product_id == product_id && item.variant_id != variant_id);
const modalVariantTag = SPZCore.Dom.scopedQuerySelector(document.body, '#promotionModalVariantTagRender');
modalVariantTag && SPZ.whenApiDefined(modalVariantTag).then((api) => {
api.render(modalProductVariants, true);
});
this.handleModalInventoryCheck_(data);
this.modalVariantInfo = modalProductVariants;
return;
}
const currentProductVariants = this.productStyleInfo.filter((item) => item.product_id == product_id && item.variant_id != variant_id);
this.handleSpzVariantRender_(currentProductVariants, product_id);
// 更新selectedVariants
this.productStyleInfo = this.productStyleInfo.filter((item) => item.variant_id != variant_id);
if(currentProductVariants.length > 0) {
// currentProductVariants 中只要有一项是多款式商品,就更新价格
const isMultiStyle = currentProductVariants.some((item) => item.is_multi_style);
if (!isMultiStyle) return;
this.handleProductOption_(product_id, true);
const selected = this.getDefaultSelectorOptions_();
this.updateProductPrice_(this.productStyleInfo.filter((item) => selected.includes(item.product_id)));
} else {
this.handleProductOption_(product_id, false);
this.resetProductPrice_(this.bundleProducts.find((item) => item.id == product_id));
}
}
// 加购弹窗未参与活动 加购按钮不可点击 TODO 拆出来
handleNotHitDiscount_(data) {
const $quickShopBody = document.querySelector('#apps-discount-quick-shop-body');
//当前子框式未命中活动
if(data.variant.is_hit_discount == false) {
$quickShopBody.setAttribute('variantstatus', 'notHitDiscount')
} else {
$quickShopBody.setAttribute('variantstatus', '')
}
}
setupAction_() {
// 子款式 未参与活动
this.registerAction('handleNotHitDiscount', (invocation) => {
const data = invocation.args.data;
this.handleNotHitDiscount_(data);
});
// 渲染加购弹窗
this.registerAction('renderQuickShop', (invocation) => {
const data = invocation.args;
this.renderQuickShop_(data);
});
this.registerAction('renderSingleVariant', (invocation) => {
const data = invocation.args;
this.renderSingleVariant(data);
});
this.registerAction('getVariantInfo', (invocation) => {
this.renderVariantTag();
});
this.registerAction('deleteVariantTag', (invocation) => {
const data = invocation.args;
this.deleteVariantTag(data);
});
this.registerAction('getSelectedProduct', (invocation) => {
const data = invocation.args.data;
this.handleSelectProduct(data);
});
//TODO 加购下单逻辑单独拆组件
this.registerAction('handleClick', (data) => {
if(this.discountType == 'DT_CLASSIC_BUNDLE') {
this.lineItems = this.productStyleInfo;
} else {
const selectedOptions = SPZCore.Dom.scopedQuerySelectorAll(document.body, '[id^="promotionSelectOption-"]');
const idArr = [...selectedOptions].reduce((acc, item) => {
if (item.hasAttribute('selected')) {
const optionValue = item.getAttribute('option');
if (optionValue) {
acc.push(optionValue);
}
}
return acc;
}, []);
this.lineItems = this.productStyleInfo.filter((item) => idArr.includes(item.product_id));
}
const action = data.args.action === "cart";
if(action) {
//add to cart
this.xhr_
.fetchJson(this.batchAtcApi, {
method: 'POST',
body: {
line_items: this.lineItems.map((item) => {
return {
product_id: item.product_id,
variant_id: item.variant_id,
quantity: Number(item.quantity)
}
})
}
})
.then((data) => {
setTimeout(() => {
window.location.href = '/cart';
});
})
.catch(async (error) => {
await error.then((data) => {
this.handleRequestError_(data);
});
});
} else {
//checkout
this.xhr_
.fetchJson(this.buyNowApi, {
method: 'POST',
body: {
line_items: (this.lineItems || []).map((product) => {
return {
quantity: Number(product.quantity),
variant_id: product.variant_id,
note: product.note || '',
properties: product.properties || {}
}
}),
refer_info: { source: 'buy_now' }
}
})
.then(async (data) => {
if (data.state === 'success') {
window.location.href = data.data?.checkout_url;
}
this.handleRequestError_(data);
})
.catch(async (error) => {
await error.then((data) => {
this.handleRequestError_(data);
});
});
}
});
this.registerAction('resetModalVariantInfo', () => {
//flash主题放block有层级问题
if(/Flash/.test(window.C_SETTINGS.theme.merchant_theme_name) && document.querySelector(".productInfoSection")) {
document.querySelector('.product-info-body').style.zIndex = this.tempCss.zIndex;
}
this.modalVariantInfo = [];
});
this.registerAction('handleModalInventoryCheck', (invocation) => {
const data = invocation.args.data;
this.handleModalInventoryCheck_(data);
});
};
};
SPZ.defineElement('spz-custom-discount-bundle-products', SpzCustomDiscountBundleProducts);
${function(){
if(originData.discount_info.discount_id === "0") return;
const title = originData.product_setting.document.discount_text || '';
const title_color = JSON.parse(originData.product_setting.discount_text_config) || '';
const promotioUrl = '/promotions/discount-default/' + originData.discount_info.discount_id;
const is_redirection = originData.product_setting.is_redirection;
let dom = originData ? `
` : `
`;
return dom;
}()}
class SpzCustomDiscountBundle extends SPZ.BaseElement {
constructor(element) {
super(element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.variant_id = '7f8ee818-e5bd-4371-b827-c763bca68601';
this.discountCardApi = "\/api\/storefront\/promotion\/product_details_page\/card";
this.productsApi = "\/api\/storefront\/promotion\/product_page\/product\/list";
this.bundleRenderElement = "appDiscountProductBundle";
this.model = {
loading: false,
page: 2,
limit: 20,
params: {
count: 0,
has_more: false,
sort: {
by: "price",
direction: "asc"
}
}
}
this.discountId = "";
this.discountType = "";
this.bundleProducts = []; //捆绑活动商品
this.buttomConfig = {};//总价及下方按钮配置
this.renderDiscount = this.win.SPZCore.Types.debounce(this.win, this.discountHandel.bind(this) , 500);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
async getDiscountCardList() {
const productId = 'c01a5337-4200-4805-89a0-99da49f31c2d';
const productType = 'default';
const variantId = this.variant_id;
const reqBody = {
product_id: productId,
variant_id: variantId,
discount_types: ["DT_CLASSIC_BUNDLE","DT_MIX_MATCH_BUNDLE"],
discount_methods: ["DM_AUTOMATIC"],
customer: {
customer_id: '',
email: '',
},
product_type: productType
}
const data = await this.xhr_.fetchJson(this.discountCardApi, {
method: "post",
body: reqBody
}).then(res => {
return res;
}).catch(err => {
console.error(err);
})
return data;
};
async discountHandel() {
const $bundle = document.querySelector(".app-discount-bundle-inner");
$bundle && SPZCore.Dom.removeElement($bundle);
const data = await this.getDiscountCardList();
if(!data.discount_info || data.discount_info.discount_id === "0") {
return;
}
//变量赋值
this.bundleProducts = data.product_info.product;
this.buttomConfig = data.product_setting;
this.discountId = data.discount_info.discount_id;
this.discountType = data.discount_info.discount_type;
this.model.params ={
count: data.product_info.count,
has_more: data.product_info.has_more,
sort: data.product_info.sort
}
//给捆绑组件传值
SPZ.whenApiDefined(document.getElementById("appDiscountBundleProductsFunc")).then((api) => {
api.setBundleData(this.bundleProducts, this.buttomConfig, this.discountId, this.discountType, data.discount_info);
})
document.querySelector(".app_discount_bundle").dataset.discountType = data.discount_info.discount_type;
SPZ.whenApiDefined(document.getElementById(this.bundleRenderElement))
.then(apis => {
apis.render(data,true).then(() => {
SPZ.whenApiDefined(document.getElementById("bundleProductsRender")).then((api) => {
api.render(data,true).then(() => {
this.bindEvent_();
if(this.bundleProducts.length < 5) {
document.querySelector(".app-discount-bundle-arrow-left").style.display="none";
document.querySelector(".app-discount-bundle-arrow-right").style.display="none";
}
//经典捆绑渲染按钮
if(this.discountType === "DT_CLASSIC_BUNDLE") {
SPZ.whenApiDefined(document.getElementById("promotionBottomContainer")).then((api) => {
const buttonData = {
setting: this.buttomConfig,
...data.product_info.total_price
}
api.render(buttonData, true);
})
}
})
})
})
.then(() => {
document.querySelector(".app-discount-bundle-inner").classList.add("discount_bundle_" + data.product_setting.template_type || "vertical");
});
});
//本地调试 放商详block里
const isSection = document.querySelector(
'div[data-section-type^="shoplazza://apps/publicapp/blocks/discount_bundle/"] .app_discount_bundle'
);
if(!isSection) {
document.querySelector(".app_discount_bundle").classList.add("productInfoSection");
}
};
// 获取加载的商品数据,拼接html模板
async loadData(cb) {
// 请求数据
this.model.loading = true;
//查询活动商品接口
const reqBody = {
discount_id: this.discountId,
page: this.model.page,
limit: this.model.limit,
"apply_scenario": "AS_ENTITLED_PRODUCT",
sort: this.model.params.sort,
sales_channel: {
sale_channel_type: "online",
sale_channel_id: '1712724'
},
product_id: 'c01a5337-4200-4805-89a0-99da49f31c2d'
}
this.xhr_.fetchJson(this.productsApi, {
method: "post",
body: reqBody
}).then(async(res)=>{
const count = res.count;
this.model.params.has_more = res.has_more;
if (count > 0) {
this.model.page++;
if (res.products && res.products.length > 0) {
let products = res.products.map((product) => {
return {
...product,
url: appDiscountUtils.globalizePath(product.url),
image_padding_bottom: appDiscountUtils.image_padding_bottom(product.image.width, product.image.height,'no-limit'),
discount_type: this.discountType
}
});
// 获取商品列表渲染模板, dom挂载
const $content = document.querySelector(".app-discount-bundle-products");
this.templates_ = SPZServices.templatesForDoc();
this.templates_.renderTemplate(document.querySelector('#appDiscountBundleProductsTemplate'), products).then((el) => {
const childNodes = el.querySelectorAll('.as-render-product-item');
if (childNodes && childNodes.length > 0) {
$content.append(...childNodes);
}
}).then(() => {
//重新渲染ljs-selector
const productSelector = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionProductSelector`);
productSelector && SPZ.whenApiDefined(productSelector).then((api) => {
api.init();
});
});
this.bundleProducts = [...this.bundleProducts, ...res.products];
SPZ.whenApiDefined(document.getElementById("appDiscountBundleProductsFunc")).then((api) => {
api.setBundleData(this.bundleProducts);
})
// 监听load去掉灰色背景
document.dispatchEvent(new CustomEvent('fire.load.img'));
// 触发懒加载
cb && cb(products);
window.lazyLoadInstance && window.lazyLoadInstance.update();
}
}
this.model.loading = false;
}).catch((err)=>{
console.error(err);
this.model.loading = false;
})
};
setupAction_() {
this.registerAction('shiftMove', (data) => {
const $el = document.querySelector(".app-discount-bundle-products");
const action = data.args.direct === "right";
const scrollwidth = action ? $el.offsetWidth : -$el.offsetWidth;
$el.scrollBy({
left: scrollwidth,
behavior: 'smooth'
});
});
};
bindEvent_() {
// 监听子款式切换,重新渲染
document.addEventListener('dj.variantChange', async(event) => {
const variant = event.detail.selected;
if (variant.product_id == 'c01a5337-4200-4805-89a0-99da49f31c2d') {
this.variant_id = variant.id;
}
this.renderDiscount();
});
// 监听滚动,请求数据
const $el = document.querySelector(".app-discount-bundle-products");
if($el) {
$el.addEventListener("scroll", this.win.SPZCore.Types.debounce(
this.win,
() => {
const isLeft = $el.scrollLeft === 0;
const isRightEnd = $el.scrollLeft + $el.offsetWidth + 10 >= $el.scrollWidth;
const isBottomEnd = $el.scrollTop + $el.clientHeight + 10 >= $el.scrollHeight;
const isEnd = isBottomEnd && isRightEnd;
if(isEnd && this.model.params.has_more && !this.model.loading) {
this.loadData();
}
},
50
))
};
};
buildCallback() {
this.setupAction_();
};
mountCallback() {
this.renderDiscount();
this.bindEvent_();
};
}
SPZ.defineElement('spz-custom-discount-bundle', SpzCustomDiscountBundle);
people are viewing this right now
${function() {
const minInventory = parseInt('10');
const maxInventory = parseInt('50');
const randomInventory = Math.round(Math.random() * (maxInventory - minInventory)) + minInventory;
const customText = "Only {stock} item(s) left in stock!".replace(/\{stock\}/g, '' + randomInventory + ' ');
const barWidth = (randomInventory / maxInventory) * 100 + '%';
return `
`;
}()}
/** @private {string} */
class SpzCustomAnchorScroll extends SPZ.BaseElement {
static deferredMount() {
return false;
}
constructor(element) {
super(element);
/** @private {Element} */
this.scrollableContainer_ = null;
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
buildCallback() {
this.viewport_ = this.getViewport();
this.initActions_();
}
setTarget(containerId, targetId) {
this.containerId = '#' + containerId;
this.targetId = '#' + targetId;
}
scrollToTarget() {
const container = document.querySelector(this.containerId);
const target = container.querySelector(this.targetId);
const {scrollTop} = container;
const eleOffsetTop = this.getOffsetTop_(target, container);
this.viewport_
.interpolateScrollIntoView_(
container,
scrollTop,
scrollTop + eleOffsetTop
);
}
initActions_() {
this.registerAction(
'scrollToTarget',
(invocation) => this.scrollToTarget(invocation?.caller)
);
this.registerAction(
'setTarget',
(invocation) => this.setTarget(invocation?.args?.containerId, invocation?.args?.targetId)
);
}
/**
* @param {Element} element
* @param {Element} container
* @return {number}
* @private
*/
getOffsetTop_(element, container) {
if (!element./*OK*/ getClientRects().length) {
return 0;
}
const rect = element./*OK*/ getBoundingClientRect();
if (rect.width || rect.height) {
return rect.top - container./*OK*/ getBoundingClientRect().top;
}
return rect.top;
}
}
SPZ.defineElement('spz-custom-anchor-scroll', SpzCustomAnchorScroll);
const STRENGTHEN_TRUST_URL = "/api/strengthen_trust/settings";
class SpzCustomStrengthenTrust extends SPZ.BaseElement {
constructor(element) {
super(element);
this.renderElement_ = null;
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
buildCallback() {
this.xhr_ = SPZServices.xhrFor(this.win);
const renderId = this.element.getAttribute('render-id');
SPZCore.Dom.waitForChild(
document.body,
() => !!document.getElementById(renderId),
() => {
this.renderElement_ = SPZCore.Dom.scopedQuerySelector(
document.body,
`#${renderId}`
);
if (this.renderElement_) {
this.render_();
}
this.registerAction('track', (invocation) => {
this.track_(invocation.args);
});
}
);
}
render_() {
this.fetchData_().then((data) => {
if (!data) {
return;
}
SPZ.whenApiDefined(this.renderElement_).then((apis) => {
apis?.render(data);
document.querySelector('#strengthen-trust-render-1539149753700').addEventListener('click',(event)=>{
if(event.target.nodeName == 'A'){
this.track_({type: 'trust_content_click'});
}
})
});
});
}
track_(data = {}) {
const track = window.sa && window.sa.track;
if (!track) {
return;
}
track('trust_enhancement_event', data);
}
parseJSON_(string) {
let result = {};
try {
result = JSON.parse(string);
} catch (e) {}
return result;
}
fetchData_() {
return this.xhr_
.fetchJson(STRENGTHEN_TRUST_URL)
.then((responseData) => {
if (!responseData || !responseData.data) {
return null;
}
const data = responseData.data;
const moduleSettings = (data.module_settings || []).reduce((result, moduleSetting) => {
return result.concat(Object.assign(moduleSetting, {
logos: (moduleSetting.logos || []).map((item) => {
return moduleSetting.logos_type == 'custom' ? this.parseJSON_(item) : item;
})
}));
}, []);
return Object.assign(data, {
module_settings: moduleSettings,
isEditor: window.self !== window.top,
});
});
}
}
SPZ.defineElement('spz-custom-strengthen-trust', SpzCustomStrengthenTrust);
${data.module_title}
To display this card to customers, you need to go to "Booster & Store Conversion" to turn on the trust enhancement feature.
${item.content.replaceAll("{store_name}","Biggmans")}
To display this card to customers, you need to go to "Booster & Store Conversion" to turn on the trust enhancement feature.