Zooone Pure Himalayan Shilajit Gummie
🔥Best Sellers
🛡️30-Day Return
${function() {
const variantData = data.variant || {"id":"2df105e5-5459-49db-a871-e638f49258d7","product_id":"acef0118-8273-4e6f-920d-fe9ba058dd4c","title":"\ud835\udfd1\ud835\udfce-\ud835\udc03\ud835\udc1a\ud835\udc32 \ud835\udc12\ud835\udc2e\ud835\udc29\ud835\udc29\ud835\udc25\ud835\udc32-60 Gummies","weight_unit":"kg","inventory_quantity":534,"sku":"SHILAJIT-CUMMIES* 1","barcode":"","position":1,"option1":"\ud835\udfd1\ud835\udfce-\ud835\udc03\ud835\udc1a\ud835\udc32 \ud835\udc12\ud835\udc2e\ud835\udc29\ud835\udc29\ud835\udc25\ud835\udc32-60 Gummies","option2":"","option3":"","note":"","image":{"src":"\/\/img.staticdj.com\/5551b390fd780cfcb9d1a17b3d043d71.png","path":"5551b390fd780cfcb9d1a17b3d043d71.png","width":1500,"height":1500,"alt":"Zooone Pure Himalayan Shilajit Gummie zoooneofficial","aspect_ratio":1},"wholesale_price":[{"price":25.99,"min_quantity":1}],"weight":"0","compare_at_price":"39.99","price":"25.99","retail_price":"39.99","available":true,"url":"\/products\/zooone-pure-himalayan-shilajit-gummie-hleh?variant=2df105e5-5459-49db-a871-e638f49258d7","available_quantity":999999999,"options":[{"name":"Specification","value":"\ud835\udfd1\ud835\udfce-\ud835\udc03\ud835\udc1a\ud835\udc32 \ud835\udc12\ud835\udc2e\ud835\udc29\ud835\udc29\ud835\udc25\ud835\udc32-60 Gummies"}],"off_ratio":"35","flashsale_info":{"variant_id":"2df105e5-5459-49db-a871-e638f49258d7","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":"25.99","compare_at_price":"","discount_price":"25.99","customary_saved_price":"","customary_off_ratio":"","discount_saved_price":"","discount_off_ratio":"35","use_before_price":false,"before_price":"","title":"","properties":"","color_setting_promotional_copy":"","discount_quantity":0,"is_need_split":false},"sales":1087};
const saveType = "percent";
const productSaveLabel = true;
return `
-
${saveType == 'percent' ? `-${variantData.off_ratio}% ` : `- ` }
`; }()}
Specification-
𝟑𝟎-𝐃𝐚𝐲 𝐒𝐮𝐩𝐩𝐥𝐲-60 Gummies
${function(){
const enable_selected_variants = "true" === 'false';
const optionValue = data.value;
return `
${optionValue ? `${enable_selected_variants ? '-' : ''}${optionValue}` : ''}
`;
}()}
${function(){
return `
Please select a Specification
`;
}()}
const addToCartText = "Add to cart";
SPZCore.Dom.waitForChild(
document.body,
() => !!document.querySelector('[data-click="addToCart"], [role="addToCart"]'),
() => {
const addToCartEle = window.SPZCore.Dom.scopedQuerySelector(
document.body,
'[data-click="addToCart"], [role="addToCart"]'
);
const getContentChild_ = function(el) {
if(el) {
const childs = el.childNodes;
for (let i = childs.length - 1; i >= 0; i--) {
const child = childs[i];
if (child.getAttribute && child.getAttribute('role') === 'content') {
return child;
}
}
}
return;
}
const changeAddToCartText = function(text) {
const contentEle = getContentChild_(addToCartEle);
if(contentEle){
const addToCartChilds = addToCartEle.childNodes;
for (let i = addToCartChilds.length - 1; i >= 0; i--) {
const child = addToCartChilds[i];
if (typeof child.getAttribute !== 'function' || (child.getAttribute('role') !== 'content' && child.getAttribute('role') !== 'loading')) {
addToCartEle.removeChild(child);
}
}
}else{
addToCartEle.innerHTML = addToCartText;
}
}
changeAddToCartText(addToCartText);
}
);
const SITE = (window.C_SETTINGS && window.C_SETTINGS.routes && window.C_SETTINGS.routes.root) || '';
const PRODUCT_PLAN_INFO_URL =
`${SITE}/api/storefront/selling_plans/product_plan_info/:product_id`;
const { i18nProductDetail, i18nProduct } = JSON.parse(
document.querySelector('#i18n-json').textContent
);
const currentI18nProduct = i18nProductDetail || i18nProduct;
class SpzCustomSubscription extends SPZ.BaseElement {
constructor(element) {
super(element);
this.productPlanInfo = null;
this.cycle = null;
this.optionid_ = null;
this.form_ = null;
this.variantId_ = null;
this.variantChangeData = null;
this.cycleList = [1,2];
this.productId = this.element.getAttribute('productId');
this.initialCycle = this.element.getAttribute('cycles');
this.noPlanShowTitle = JSON.parse(this.element.getAttribute('noPlanShowTitle'));
}
get initIsCycleSubscribe() {
if(this.initialCycle == 2) {
return true;
}
if(this.initialCycle == 1) {
return false;
}
return null;
}
get productInfo() {
let pJson = document.querySelector('#product-json');
if (pJson) {
return JSON.parse(pJson.innerHTML);
}else if(typeof $ === 'function' && typeof $(document).data === 'function') {
return $(document).data('djproduct');
}
return null;
}
get hasSKU() {
if(this.productPlanInfo?.sku) {
return true;
}
return false
}
get hasSPU() {
if(this.productPlanInfo?.spu) {
return true;
}
return false
}
get originalPrice() {
if(!this.variantChangeData?.selected?.price){
return '';
};
return this.variantChangeData.selected.price;
}
get defaultPlanData() {
if (!this.productPlanInfo) {
return {};
}
let planInfo = {};
if(this.hasSPU && this.productPlanInfo?.spu[this.productId]) {
planInfo = this.productPlanInfo.spu[this.productId];
}else if(this.hasSKU && this.productPlanInfo?.sku[this.variantId_]) {
planInfo = this.productPlanInfo.sku[this.variantId_];
}
return planInfo;
}
get defaultCycle_() {
if(!this.defaultPlanData) {
return null;
}
return this.defaultPlanData.cycles;
}
get defaultOption_() {
if(!this.defaultPlanData) {
return null;
}
return this.defaultPlanData.selected_selling_plan_option_id;
}
get isCycleSubscribe() {
if(this.cycle === 2) {
return true;
}
if(this.cycle === 1) {
return false;
}
return null;
}
get currentOption_() {
if(!this.isCycleSubscribe){
return null;
}
if(!this.optionId_) {
return this.defaultOption_;
}
return this.optionId_;
}
get currentPlanData() {
if(!this.defaultPlanData) {
return {};
}
let result = Object.assign({},this.defaultPlanData);
if(result.selected_selling_plan_option_id !== this.optionId_) {
result.selected_selling_plan_option_id = this.optionId_;
result.selling_plan_options = result.selling_plan_options.map(item => {
return {
...item,
selected_enabled: item.selling_plan_option_id === result.selected_selling_plan_option_id
}
})
}
if (result.cycles !== this.cycle) {
result.cycles = this.cycle;
}
return result;
}
fetchData_(product_id) {
return SPZServices.xhrFor(this.win).fetchJson(PRODUCT_PLAN_INFO_URL.replace(/:product_id/gi, product_id))
.then((data) => {
this.productPlanInfo = data;
}
);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
mountCallback() {
this.getElement_();
Promise.all([this.productInfoReady_(), this.fetchData_(this.productId)]).then(() => {
this.initVariantId();
this.init_();
this.initActions_();
if(!!this.variantId_) {
this.track_('product_view', this.initIsCycleSubscribe);
}
this.showPlan_(true);
if(!!this.variantId_){
this.changeBuyNowText();
this.dispatchSubScribeIdChange_();
}
});
}
productInfoReady_() {
if(this.productInfo) {
return Promise.resolve();
}
SPZUtils.Event.listen(document,'load',()=> {
if(this.productInfo) {
return Promise.resolve();
}else{
return Promise.reject();
}
})
}
getElement_() {
this.titleEle = SPZCore.Dom.scopedQuerySelector(document.body, '[role="plugin-subscription-title"]');
this.noPlanTipsEle = SPZCore.Dom.scopedQuerySelector(this.element, '[role="plugin-subscription-plan-tips"]');
this.noPaymentTipsEle = SPZCore.Dom.scopedQuerySelector(this.element, '[role="plugin-subscription-payment-tips"]');
this.renderEle = SPZCore.Dom.scopedQuerySelector(this.element, '[role="plugin-subscription-content-render"]');
this.productEle = SPZCore.Dom.scopedQuerySelector(document.body, '[data-section-type="product"], [data-section-type="product_detail"], [data-section-type="product_club"]')
this.buyNowEle = SPZCore.Dom.scopedQuerySelector(this.productEle, '[data-click="submit"], [role="buyNow"]');
this.addToCartEle = SPZCore.Dom.scopedQuerySelector(this.productEle, '[data-click="addToCart"], [role="addToCart"]');
}
init_() {
this.cycle = this.defaultCycle_;
this.optionId_ = this.defaultOption_;
this.variantChangeData = this.productInfo;
}
initVariantId() {
const formData = this.getFormData();
if (formData) {
if(formData['variant_id'] && formData['variant_id'] !== 'undefined') {
this.variantId_ = formData['variant_id'];
}else{
this.variantId_ = ''
}
}else if(this.productInfo?.selected?.id){
this.variantId_ = this.productInfo.selected.id
}else{
this.variantId_ = ''
}
}
getFormData() {
this.form_ = this.element.closest('form');
if(!this.form_) {
return null;
}
const result = {
quantity: 1,
};
const formData = new FormData(this.form_);
const formDataKey = formData.keys();
for (const key of formDataKey) {
result[key] = formData.get(key);
}
return result;
}
showPlan_(rerender = false) {
if (!this.variantId_) {
return this.hide_();
}
if (rerender) {
this.renderPlan_();
}
}
renderPlan_() {
if (Object.keys(this.currentPlanData).length === 0) {
this.showNoPlanTips_(true);
this.showNoPaymentTips_(false);
this.showRender_(false);
if(this.noPlanShowTitle) {
this.showTitle_(true);
}else{
this.showTitle_(false);
}
return;
}
this.showRender_(true);
this.showNoPaymentTips_(true);
this.showTitle_(true);
this.showNoPlanTips_(false);
const selectedPlanItem = this.currentPlanData.selling_plan_options.filter((item) => item.selected_enabled === true)[0];
SPZ.whenApiDefined(this.renderEle).then((apis) => {
apis.render({ ...this.currentPlanData, originalPrice: this.originalPrice, selectedPlanItem }, false);
});
}
showTitle_(visible = true) {
if(this.titleEle) {
this.titleEle.toggleAttribute('hide', !visible);
}
}
showNoPlanTips_(visible = true) {
if(this.noPlanTipsEle) {
this.noPlanTipsEle.toggleAttribute('hide', !visible);
}
}
showNoPaymentTips_(visible = true) {
if(this.noPaymentTipsEle){
this.noPaymentTipsEle.toggleAttribute('hide', !visible);
}
}
showRender_(visible = true) {
if(this.renderEle){
this.renderEle.toggleAttribute('hide', !visible);
}
}
hide_() {
this.showTitle_(false);
this.element.toggleAttribute('hide', true);
}
show_() {
this.showTitle_(true);
this.element.toggleAttribute('hide', false);
}
dispatchSubScribeIdChange_() {
this.dispatchEvent_('payment_ec_refresh', {
sources: 'subscription'
});
}
dispatchEvent_(name, data) {
const event = SPZUtils.Event.create(this.win, name, data, { bubbles: true });
this.element.dispatchEvent(event);
}
initActions_() {
this.onVariantChange_();
this.element.addEventListener('change', (e) => {
if(e.target?.role === 'plugin-subscription-option-selector') {
this.onOptionChange_(e.target.value);
}
if(e.target?.role === 'plugin-subscription-option-card') {
this.changeCardOption_(e.target.value);
}
});
this.registerAction(
'changeCycle',
(invocation) => this.onCycleChange_(invocation.args?.selectedOptions[0])
);
this.registerAction('subscribeChange', (invocation) => {
this.dispatchSubScribeIdChange_(invocation.args);
});
this.addToCartEle.addEventListener('click', () => {
this.track_('add_to_cart');
});
this.buyNowEle.addEventListener('click', () => {
this.track_('add_to_cart');
});
this.submitInterrapt();
}
onVariantChange_() {
SPZUtils.Event.listen(document, 'dj.variantChange', (e) => {
if(this.variantId_ === e.detail?.selected?.id) {
return;
}
if(!this.variantId_ && e.detail?.selected?.id) {
this.show_();
}
this.variantId_ = e.detail.selected?.id;
this.optionId_ = this.defaultOption_;
this.cycle = this.defaultCycle_;
this.variantChangeData = Object.assign(this.variantChangeData, e.detail);
this.changeBuyNowText();
this.changeAddToCartText(e.detail);
this.showPlan_(true);
this.track_('product_view');
});
}
onOptionChange_(op, render = true) {
this.optionId_ = op;
this.changeBuyNowText();
if(render) {
this.showPlan_(true);
}
}
onCycleChange_(val, render = true) {
const cy = Number(val);
if (this.cycleList.includes(cy)) {
this.cycle = cy;
this.changeBuyNowText();
if(render) {
this.showPlan_(true);
}
}
}
submitInterrapt() {
if(!this.form_) {
window.djInterceptors.request.use((config) => {
if(config?.url === '/api/cart') {
return this.addToCartRequestData_(config);
}
if(config?.url === '/api/checkout/order') {
return this.checkoutOrderRequestData_(config);
}
})
}
}
addToCartRequestData_(config) {
const cartConfig = { ...config };
const hasProductId = cartConfig?.body?.product_id;
const hasVariantId = cartConfig?.body?.variant_id;
if(cartConfig?.method == 'POST' && hasProductId && hasVariantId) {
if (!cartConfig.body.properties) {
cartConfig.body.properties = {};
}
if(this.currentOption_) {
cartConfig.body.properties = {
...cartConfig.body.properties,
_selling_plan_option_id: this.currentOption_
}
}
}
return cartConfig;
}
checkoutOrderRequestData_(config) {
const orderConfig = { ...config };
const hasVariantId = orderConfig?.body?.line_items[0]?.variant_id;
if(orderConfig?.method == 'POST' && hasVariantId) {
if (!orderConfig.body.line_items[0].properties) {
orderConfig.body.line_items[0].properties = {};
}
if(this.currentOption_) {
orderConfig.body.line_items[0].properties = {
...orderConfig.body.line_items[0].properties,
_selling_plan_option_id: this.currentOption_
}
}
}
return orderConfig;
}
changeCardOption_(val) {
const oneTimeInputEle = document.querySelector('.one-time [role=plugin-subscription-option-card]');
if(val == 0) {
this.onCycleChange_(1, true);
oneTimeInputEle.toggleAttribute('disabled',true);
return;
}
oneTimeInputEle.toggleAttribute('disabled',false);
this.onCycleChange_(2, false);
this.onOptionChange_(val, true);
}
getContentChild_(el) {
if(el) {
const childs = el.childNodes;
for (let i = childs.length - 1; i >= 0; i--) {
const child = childs[i];
if (child.getAttribute && child.getAttribute('role') === 'content') {
return child;
}
}
}
return;
}
changeBuyNowText() {
let buyNowText = currentI18nProduct.buy_now;
let subscribeText = "Subscribe";
const contentEle = this.getContentChild_(this.buyNowEle);
// 1. 有role="content"的元素,替换role="content"的元素
if(contentEle) {
contentEle.innerHTML = this.isCycleSubscribe ? subscribeText : buyNowText;
}else{
// 2. 不存在role="content"的元素,直接替换文本
if(!this.buyNowEle) {
return;
}
this.buyNowEle.innerHTML = this.isCycleSubscribe
? this.buyNowEle.innerHTML.replace(buyNowText, subscribeText) :
this.buyNowEle.innerHTML.replace(subscribeText, buyNowText);
}
}
changeAddToCartText(data) {
const contentEle = this.getContentChild_(this.addToCartEle);
// 1. 有role="content"的元素,移除role不等于content和loading的元素
if(contentEle) {
const addToCartChilds = this.addToCartEle.childNodes;
for (let i = addToCartChilds.length - 1; i >= 0; i--) {
const child = addToCartChilds[i];
// 移除元素(role不等于content和loading)
if (typeof child.getAttribute !== 'function' || (child.getAttribute('role') !== 'content' && child.getAttribute('role') !== 'loading')) {
this.addToCartEle.removeChild(child);
}
}
}else{
// 2. 不存在role="content"的元素,直接替换文本
const addToCartText = this.getAddToCartText_(data);
this.addToCartEle.innerHTML = addToCartText;
}
}
getAddToCartText_(data) {
const selected = data?.selected;
const productAvailable = data?.product?.available;
const variantAvailable = data?.selected?.available;
const variantId = data?.selected?.id;
let text = currentI18nProduct.add_to_cart;
if (!productAvailable) {
text = currentI18nProduct.sold_out;
}
if (selected && !variantId) {
text = currentI18nProduct.unavailable;
}
if (productAvailable && selected && variantId && !variantAvailable) {
text = currentI18nProduct.sold_out;
}
return text;
}
track_(eventName, optionSelected = this.isCycleSubscribe) {
if(window && window.sa && typeof window.sa.registerExtraInfo === 'function') {
window.sa.registerExtraInfo(eventName, {
function_name: "product_subscription",
module: "apps",
option_selected: optionSelected
}, optionSelected === null);
}
}
}
SPZ.defineElement('spz-custom-subscription', SpzCustomSubscription);
Purchase options:
Subscribe
& Save
20%
$25.99
$20.79
Delivery frequency
Skip, modify or cancel any time
${function() {
const blockStyle = 1;
const subscriptionLang = {"my_subscription":"My subscriptions","agree_to_subscription_terms":"By checking this box, you confirm that one or more items in your cart is a deferred or recurring purchase. Your subscription will automatically renew and your payment method will automatically be charged at the frequency listed on this page until you cancel it. You can change and cancel your subscription by clicking My Subscription. You accept and agree to the Subscription Policy.","agree_to_subscription_terms_error_message":"Please agree to the subscription terms to proceed with checkout","subscription_billing":"Subscription renewal charge","subscription_billing_tips":"After subscribing, you'll be billed automatically at regular intervals. You can check billing details or cancel anytime in your account's subscription management page after placing the order.","every_x_years":"Every {{ x }} year(s)","every_x_months":"Every {{ x }} month(s)","every_x_weeks":"Every {{ x }} week(s)","every_x_days":"Every {{ x }} day(s)","purchase_options":"Purchase options","subscribe":"Subscribe","save":"Save","delivery_frequency":"Delivery frequency","modify_tips":"Skip, modify or cancel any time","one_time":"One-Time Purchase"};
const planTextLang = {
day: subscriptionLang.every_x_days,
week: subscriptionLang.every_x_weeks,
month: subscriptionLang.every_x_months,
year: subscriptionLang.every_x_years,
};
const regex = /\{\{\s*x\s*\}\}/;
return `
${function() {
const selected = data.cycles === 1 ? 'selected' : '';
return `
`
}()}
${function() {
const selected = data.cycles === 2 ? 'selected' : '';
return `
Subscribe
& Save
${ data.selectedPlanItem.discount_value }%
Delivery frequency
${function() {
const disabled = data.cycles === 1 ? 'disabled' : '';
return `
${data.selling_plan_options.map(item => {
const interval = item.interval;
const count = item.interval_count;
const planText = planTextLang[interval].replace(regex,count);
const selected = item.selected_enabled ? 'selected' : '';
return item.selected_enabled ? `
${planText}
`: `
${planText}
`
}).join('')}
`
}()}
${function() {
const checked = item.selected_enabled && data.cycles === 2 ? 'checked' : '';
const disabled = data.cycles === 1 ? 'disabled' : '';
return `
${function() {
const interval = item.interval;
const count = item.interval_count;
const planText = planTextLang[interval].replace(regex,count);
return `
${planText}
`
}()}
`
}()}
Skip, modify or cancel any time
`
}()}
${function() {
const checked = data.cycles == 1 ? 'checked' : '';
const disabled = data.cycles == 1 ? 'disabled' : '';
return `
`
}()}
${function(){
const disabled = data.cycles === 1 ? 'disabled' : '';
return `
Subscribe
& Save
${
data.selling_plan_options.map(item => {
const checked = item.selected_enabled && data.cycles === 2 ? 'checked' : '';
const interval = item.interval;
const count = item.interval_count;
const planText = planTextLang[interval].replace(regex,count);
return `
${planText}
Save
Save ${ item.discount_value }%
`
}).join('')}
Skip, modify or cancel any time
`
}()}
`;
}()}
Add to cart
- $25.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]) || Object.keys(data).length > 1 ? data : null;
const productVariant = {"id":"2df105e5-5459-49db-a871-e638f49258d7","product_id":"acef0118-8273-4e6f-920d-fe9ba058dd4c","title":"\ud835\udfd1\ud835\udfce-\ud835\udc03\ud835\udc1a\ud835\udc32 \ud835\udc12\ud835\udc2e\ud835\udc29\ud835\udc29\ud835\udc25\ud835\udc32-60 Gummies","weight_unit":"kg","inventory_quantity":534,"sku":"SHILAJIT-CUMMIES* 1","barcode":"","position":1,"option1":"\ud835\udfd1\ud835\udfce-\ud835\udc03\ud835\udc1a\ud835\udc32 \ud835\udc12\ud835\udc2e\ud835\udc29\ud835\udc29\ud835\udc25\ud835\udc32-60 Gummies","option2":"","option3":"","note":"","image":{"src":"\/\/img.staticdj.com\/5551b390fd780cfcb9d1a17b3d043d71.png","path":"5551b390fd780cfcb9d1a17b3d043d71.png","width":1500,"height":1500,"alt":"Zooone Pure Himalayan Shilajit Gummie zoooneofficial","aspect_ratio":1},"wholesale_price":[{"price":25.99,"min_quantity":1}],"weight":"0","compare_at_price":"39.99","price":"25.99","retail_price":"39.99","available":true,"url":"\/products\/zooone-pure-himalayan-shilajit-gummie-hleh?variant=2df105e5-5459-49db-a871-e638f49258d7","available_quantity":999999999,"options":[{"name":"Specification","value":"\ud835\udfd1\ud835\udfce-\ud835\udc03\ud835\udc1a\ud835\udc32 \ud835\udc12\ud835\udc2e\ud835\udc29\ud835\udc29\ud835\udc25\ud835\udc32-60 Gummies"}],"off_ratio":"35","flashsale_info":{"variant_id":"2df105e5-5459-49db-a871-e638f49258d7","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":"25.99","compare_at_price":"","discount_price":"25.99","customary_saved_price":"","customary_off_ratio":"","discount_saved_price":"","discount_off_ratio":"35","use_before_price":false,"before_price":"","title":"","properties":"","color_setting_promotional_copy":"","discount_quantity":0,"is_need_split":false},"sales":1087};
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 ? `
` : ' ';
}
}()}
Product was out of stock.
Product is unavailable.
${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"];
// 跳转决策: is_redirection + link(可选覆盖)
const setting = {
is_redirection: item.dataset["redirection"] === "true",
link: item.dataset["link"],
};
const landingUrl = `/promotions/discount-default/${discountId}`;
const finalUrl = appDiscountUtils.resolveDiscountHref(setting, landingUrl);
if (finalUrl && appDiscountUtils.inProductBody(this.element)) {
this.win.open(finalUrl, '_blank', 'noopener');
}
}
})
}
}
/**
* 使用 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 = "2df105e5-5459-49db-a871-e638f49258d7";
// 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 == 'acef0118-8273-4e6f-920d-fe9ba058dd4c' && 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: "acef0118-8273-4e6f-920d-fe9ba058dd4c",
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);
Ships from US, Estimated Delivery:Aug-20 - Aug-24
${function() {
const type = 'hero';
const postageFreeAmount = 55;
const custom_text_hero = "Buy {amount} more to enjoy FREE Shipping";
const totalPrice = +data.total_price;
const diffPrice = postageFreeAmount - totalPrice;
const percentDiff = (diffPrice > 0 ? (totalPrice / postageFreeAmount * 100) : 100) + '%';
let tipText = "Your order is free delivery";
const custom_text_wind = "Buy {amount} more to enjoy FREE Shipping";
const custom_text = type === 'hero' ? custom_text_hero : custom_text_wind;
if (diffPrice > 0) {
tipText = custom_text.replace('{amount}', `
`);
}
return `
${type === 'hero' ?
`
` :
`
${tipText}
Your order is free delivery
`
}
`;
}()}