${function() {
const variantData = data.variant || {"id":"cc1f9de2-4ec2-4831-b129-2dfba7e3516b","product_id":"c597c59c-97a7-4c9d-88f0-23a5abd34467","title":"","weight_unit":"lb","inventory_quantity":68,"sku":"29623","barcode":"191069296234","position":1,"option1":"","option2":"","option3":"","note":"","image":null,"wholesale_price":[{"price":13.99,"min_quantity":1}],"weight":"0","compare_at_price":"13.99","price":"13.99","retail_price":"13.99","available":true,"url":"\/products\/melatonin-5mg-60-rapid-release-softgels?variant=cc1f9de2-4ec2-4831-b129-2dfba7e3516b","available_quantity":68,"options":[],"off_ratio":0,"flashsale_info":[],"sales":244};
const saveType = "amount";
const saveText = "Save {{saved_amount}}";
const productLabelDiscountOn = false;
const sale_price = ` `;
const compare_at_price = ` `;
return `
-
${("Sale price {price}").replace(/\{\s*price\s*\}/, sale_price)}
${("Original price {price}").replace(/\{\s*price\s*\}/, compare_at_price)}
${saveText.replace('\{\{saved_amount\}\}',
saveType == 'percentage'
? variantData.off_ratio + '%'
: ` `
)}
`;
}()}
const TAG = 'spz-custom-flash-sale-tag';
class SpzCustomFlashSaleTag extends SPZ.BaseElement {
constructor(element) {
super(element);
this.variants_ = [];
this.dataId_ = [];
};
buildCallback = () => {
if (this.element.hasAttribute('data-id')) {
this.dataId_ = this.element.getAttribute('data-id');
}
if (this.dataId_) {
const scriptElement = document.querySelector("#" + this.dataId_);
try {
this.variants_ = JSON.parse(scriptElement.textContent);
if (this.variants_.length === 1) {
const currentSelectVariant = this.variants_[0];
currentSelectVariant.variant_id = currentSelectVariant.id;
this.doRenderTag_(currentSelectVariant);
}
} catch (error) {
console.log('error', error);
}
}
this.setupAction_();
};
doRenderTag_ = (currentSelectVariant) => {
if (!currentSelectVariant) {
this.childElement.setAttribute('hidden', '');
return;
}
this.childElement = this.element.querySelector('div');
const currentVariant = this.variants_.find(item => item?.id == currentSelectVariant?.variant_id);
if (Array.isArray(currentVariant?.flashsale_info)) {
this.childElement.setAttribute('hidden', '');
return;
}
const flashSaleInfo = currentVariant?.flashsale_info;
if (!flashSaleInfo?.discount_id) {
this.childElement.setAttribute('hidden', '');
return;
}
const currentTime = (new Date().getTime() / 1000);
const isValid = (flashSaleInfo.ends_at === -1 || (flashSaleInfo.ends_at && Math.min(currentTime, flashSaleInfo.ends_at)));
if (!isValid) {
this.childElement.setAttribute('hidden', '');
return
}
const flashSaleTagName = flashSaleInfo?.color_setting_promotional_copy || '';
if (!flashSaleTagName) {
this.childElement.setAttribute('hidden', '');
return
}
const flashSaleTagDoms = this.element.querySelectorAll('[role="flash-sale-tag-tile"]');
if (!flashSaleTagDoms?.length) {
this.childElement.setAttribute('hidden', '');
return
}
this.childElement.removeAttribute('hidden', '');
;[...flashSaleTagDoms].forEach(item => {
item.innerHTML = flashSaleTagName;
})
};
setupAction_ = () => {
this.registerAction('renderTag', async (invocation) => {
this.doRenderTag_(invocation.args.data);
});
};
setData_ = (variants) => {
this.variants_ = variants;
};
isLayoutSupported = (layout) => {
return layout == SPZCore.Layout.CONTAINER;
};
}
SPZ.defineElement(TAG, SpzCustomFlashSaleTag)
const TAG = "spz-custom-product-automatic";
class SpzCustomProductAutomatic extends SPZ.BaseElement {
constructor(element) {
super(element);
this.variant_id = 'cc1f9de2-4ec2-4831-b129-2dfba7e3516b';
}
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":[{"discount_type":"DT_BUY_ONE_GET_ONE","discount_icon":"\/\/img.staticdj.com\/oss\/operation\/e42568373e54f6f551dcbce82a1c6b12.svg","discount":[{"discount_id":"492593093472693225","discount_type":"DT_BUY_ONE_GET_ONE","discount_method":"DM_AUTOMATIC","config":{"text":"Buy one get one at 50%<\/span> off","texts":["Buy one get one at 50%<\/span> off"],"off_text":""},"product_enabled":true,"template_type":"text","is_redirection":true,"template_config":"{\"color\":{\"text\":{\"icon_text_color\":\"#EB391B\"},\"tag\":{\"text_color\":\"#EB391B\",\"background_color\":\"rgba(235, 57, 27, 0.04)\"},\"banner\":{\"icon_text_color\":\"#EB391B\",\"background_color\":\"rgba(235, 57, 27, 0.04)\"}}}","display_type":"DTE_UNKNOWN"}]}],"hash":"eb7b64bc5edec3c85484d3d1691983f6"});
this.init();
// 监听事件
this.bindEvent_();
}
async init() {
this.handleFitTheme();
const promotionComplex = {"downgrade":false,"automatic_discount_list":[{"discount_type":"DT_BUY_ONE_GET_ONE","discount_icon":"\/\/img.staticdj.com\/oss\/operation\/e42568373e54f6f551dcbce82a1c6b12.svg","discount":[{"discount_id":"492593093472693225","discount_type":"DT_BUY_ONE_GET_ONE","discount_method":"DM_AUTOMATIC","config":{"text":"Buy one get one at 50%<\/span> off","texts":["Buy one get one at 50%<\/span> off"],"off_text":""},"product_enabled":true,"template_type":"text","is_redirection":true,"template_config":"{\"color\":{\"text\":{\"icon_text_color\":\"#EB391B\"},\"tag\":{\"text_color\":\"#EB391B\",\"background_color\":\"rgba(235, 57, 27, 0.04)\"},\"banner\":{\"icon_text_color\":\"#EB391B\",\"background_color\":\"rgba(235, 57, 27, 0.04)\"}}}","display_type":"DTE_UNKNOWN"}]}],"hash":"eb7b64bc5edec3c85484d3d1691983f6"};
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 = 'c597c59c-97a7-4c9d-88f0-23a5abd34467';
const variantId = this.variant_id;
const productType = '';
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)
.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 == 'c597c59c-97a7-4c9d-88f0-23a5abd34467' && 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);
Buy one get one at 50% off
${(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('');
})()}
`
}
})()}
${function(){
const variantData = data.variant || {"id":"cc1f9de2-4ec2-4831-b129-2dfba7e3516b","product_id":"c597c59c-97a7-4c9d-88f0-23a5abd34467","title":"","weight_unit":"lb","inventory_quantity":68,"sku":"29623","barcode":"191069296234","position":1,"option1":"","option2":"","option3":"","note":"","image":null,"wholesale_price":[{"price":13.99,"min_quantity":1}],"weight":"0","compare_at_price":"13.99","price":"13.99","retail_price":"13.99","available":true,"url":"\/products\/melatonin-5mg-60-rapid-release-softgels?variant=cc1f9de2-4ec2-4831-b129-2dfba7e3516b","available_quantity":68,"options":[],"off_ratio":0,"flashsale_info":[],"sales":244};
return `
Sku:
${variantData && variantData.sku}
`
}()}
Add to cart
$13.99
${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":"cc1f9de2-4ec2-4831-b129-2dfba7e3516b","product_id":"c597c59c-97a7-4c9d-88f0-23a5abd34467","title":"","weight_unit":"lb","inventory_quantity":68,"sku":"29623","barcode":"191069296234","position":1,"option1":"","option2":"","option3":"","note":"","image":null,"wholesale_price":[{"price":13.99,"min_quantity":1}],"weight":"0","compare_at_price":"13.99","price":"13.99","retail_price":"13.99","available":true,"url":"\/products\/melatonin-5mg-60-rapid-release-softgels?variant=cc1f9de2-4ec2-4831-b129-2dfba7e3516b","available_quantity":68,"options":[],"off_ratio":0,"flashsale_info":[],"sales":244};
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 is unavailable.