${(function(){
const get_random_six_digits = () => {
return Math.random().toString().slice(-6)
};
const wholesale_enabled = false;
const setting_product_image_display = "133.33%";
const product_image = data.image;
const secondary_image = data.secondImage;
const image_width = product_image.width;
let image_height = product_image.height;
if(setting_product_image_display == '100%'){
image_height = image_width
}else if(setting_product_image_display == '133.33%'){
image_height = image_width * 1.3333;
}else if(setting_product_image_display == '75%'){
image_height = image_width * 0.75;
};
const product_image_hover_on = true && !!secondary_image.src;
const has_save_label = true && ((+data.compare_at_price) > (+data.price));
const is_single_variant = data.variants.length == 1;
const min_price_variant_href = (data.min_price_variant && data.min_price_variant.available) ? data.min_price_variant.withinUrl : data.withinUrl;
const retail_price_max = data.retail_price_max || data.compare_at_price_max;
const THUMBNAILS_MAX_SIZE = 3;
const thumbnails = data.thumbVariants.slice(0, THUMBNAILS_MAX_SIZE);
const image_wrap_id = 'image_wrap_' + get_random_six_digits();
const image_carousel_id = 'image_carousel_' + get_random_six_digits();
const thumbnails_selector_id = 'thumbnails_selector_' + get_random_six_digits();
const form_id = 'form_' + get_random_six_digits();
const mixed_wholesale = data.mixed_wholesale;
return `
${
data.price_min != data.price_max
? `from
`
: `
`
}
+${data.remainInvisibleThumbCount}
`
})()}
✈FREE STANDARD SHIPPING OVER $69
We will donate 1% of your spending to help stray cats and dogs. Thank you for your contribution to charity.♥
✈FREE STANDARD SHIPPING OVER $69
We will donate 1% of your spending to help stray cats and dogs. Thank you for your contribution to charity.♥
1/4
${data.index + 1}/${data.total}
${Array(data.total).fill(0).map((num, index) => `
`).join('')}
Looking for a tote bag that's both fun and functional? Our quilted tote bag is thoughtfully designed to make everyday carrying easier-while adding a fun, festive touch to your look. Perfect for everyday use or seasonal outings, this bag combines sturdy construction with charming prints to brighten up any outing. It's the perfect combination of practicality and personality!
PRODUCT DETAILS
Dimensions:
Crafted from quilted fabric featuring a stylish wave stitched pattern
Made of premium Jetiy cotton-poly blend, combining the softness and breathability of cotton with the durability and easy care of polyester.
Vibrant colors achieved through premium polyester printing
Easy-care: Safe for machine washing; use gentle cycle with cold water, air dry recommended. Avoid bleach.
Each item is meticulously crafted to order, reflecting the highest standards of quality. Created with care and dedication.
All products are made to order and printed to the best standards available. Made with so much love!
Please Note: As each of our products is made to order, there may be approximately a 20% variation in color, pattern, binding and stitches compared to the sample photos. However, we ensure the main design is kept as shown. Additionally, the dimensions of this quilt may have a slight variance of 1-3 inches due to the handmade nature of the product.
${function(){
const rules = data.data.rules;
return `
`
}()}
${function(){
const isCart = data.data.isCart;
const isCollection = data.data.isCollection;
const isProduct = data.data.isProduct;
const isIndex = data.data.isIndex;
return `
${isCart ? 'The items in the shopping cart do not participate in any recommendation rule. Add the participating items to your shopping cart to check the design.' : ''}
${isProduct ? 'This product did not participated in any recommendation rule. Switch to another product to check the design.' : ''}
${isCollection ? 'The items in this collection do not participate in any recommendation rule. Switch the participating items to check the design.' : ''}
${isIndex ? 'The home page do not participate in any recommendation rule.' : ''}
(This prompt would not display on client-side)
Recommended Products
`
}()}
${function(){
const rule = data.data;
const quickShopButtonVisible = !rule.config.quick_shop_button_type || rule.config.quick_shop_button_type === 'button';
const getImageHeight = function(image){
const image_size = rule.config.image_size || 0;
const imageWidth = image.width || 600;
const imageHeight = image.height || 800;
let ratio = 0;
if(image_size == 0){
ratio = (imageHeight / imageWidth).toFixed(2);
}else if(image_size == 1){
ratio = 1.5;
}else if(image_size == 2){
ratio = 1;
}else if(image_size == 3){
ratio = 0.75;
}
return imageWidth * ratio;
};
const toQuery = obj =>
Object.keys(obj)
.map(k =>
Array.isArray(obj[k])
? obj[k].map(v => `${k}[]=${encodeURIComponent(v)}`).join('&')
: `${k}=${encodeURIComponent(obj[k])}`
)
.join('&');
return `
`
}()}
const isSpecialHeroTheme = window.SHOPLAZZA?.theme?.merchant_theme_name == 'Hero' && window.SHOPLAZZA?.theme?.merchant_theme_c_version == '2.2.19';
const specialHeroThemeClassName = 'hero_2_2_19_smart_recommend_block';
class SpzSmartBlockComponent extends SPZ.BaseElement {
constructor(element) {
super(element);
this.templates_ = null;
this.container_ = null;
this.i18n_ = {};
this.config_ = {};
this.show_type_ = 3;
this.product_resource_id_ = '';
this.collection_resource_id_ = '';
this.cart_items_ = [];
this.customer_id_ = '';
this.order_id_ = '';
}
static deferredMount() {
return false;
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
buildCallback() {
const template_type = window.C_SETTINGS.meta.page.template_type;
if (template_type === 1) {
this.show_type_ = 3;
this.product_resource_id_ = window.C_SETTINGS.meta.page.resource_id;
} else if (template_type === 2) {
this.show_type_ = 4;
this.collection_resource_id_ = window.C_SETTINGS.meta.page.resource_id;
} else if (template_type === 15){
this.show_type_ = 5;
} else if (template_type === 13){
this.show_type_ = 6;
} else if (template_type === 20){
this.show_type_ = 7;
this.customer_id_ = window.C_SETTINGS.customer.customer_id;
} else if (template_type === 35){
this.show_type_ = 8;
this.order_id_ = window.location.pathname.split('/').pop();
}
this.templates_ = SPZServices.templatesForDoc(this.element);
this.setAction_();
}
mountCallback() {
const that = this;
const themeName = window.C_SETTINGS.theme.merchant_theme_name;
const isGeek = /Geek/.test(themeName);
this.fetchRules().then((res) => {
if (res && res.rules && res.rules.length) {
const blockEl = document.getElementById('smart_recommend_block');
this.initBlockClass(blockEl);
this.initItemClass(blockEl);
SPZ.whenApiDefined(blockEl).then((api) => {
api.render({data: res}, true).then(() => {
if (isGeek && that.show_type_ === 6) {
blockEl.querySelector('.plugin_container_wrpper').style.padding = '30px 0';
}
const recommendStyle = document.createElement('style');
recommendStyle.innerHTML = `
.plugin__recommend_container,.app-recommend-card {
display: none !important;
}
`;
document.head.appendChild(recommendStyle);
const fetchList = [];
res.rules.forEach((rule) => {
fetchList.push(this.fetchRuleProductList(rule.id));
});
const fetchAll = Promise.all(fetchList);
fetchAll.then((p_res) => {
res.rules.forEach((rule, index) => {
rule.products = p_res[index] && p_res[index].products;
if (rule.products && rule.products.length) {
const modalRender = document.getElementById('smart_recommend_js_root');
const $dest = document.getElementById('cart');
const isLifeStyle = /Life.*Style/.test(window.C_SETTINGS.theme.merchant_theme_name);
if (modalRender && isLifeStyle && $dest.clientWidth > 767) {
modalRender.classList.add('zb-mt-[-180px]')
}
}
const ruleEl = document.getElementById('smart_recommend_rule_' + rule.id);
SPZ.whenApiDefined(ruleEl).then((api) => {
api.render({data: rule}, true).then(() => {
that.impressListen(`#smart_recommend_rule_ul_${rule.id}`, function(){
that.trackRuleImpress(rule);
});
const btnElList = document.querySelectorAll(`#smart_recommend_rule_ul_${rule.id} button`);
btnElList.forEach((btnEl) => {
if (btnEl && rule.config && rule.config.quick_shop_button_bg_color && rule.config.quick_shop_button_text_color) {
btnEl.style.backgroundColor = rule.config.quick_shop_button_bg_color;
btnEl.style.color = rule.config.quick_shop_button_text_color;
}
});
if (isSpecialHeroTheme) {
ruleEl.querySelectorAll(`.smart_recommend_title`).forEach(dom=>{
dom.classList.add('type-title-font-family');
});
document.querySelectorAll(`.${specialHeroThemeClassName} #smart_recommend_rule_ul_${rule.id} .zb-recommend-price-line-through .money`).forEach(dom=>{
dom.classList.add('type-body-font-family');
});
};
});
});
});
});
})
})
} else {
if (window.top !== window.self) {
const template_type = window.C_SETTINGS.meta.page.template_type;
const holderEl = document.getElementById('smart_recommend_preview_no_data_placeholder');
SPZ.whenApiDefined(holderEl).then((api) => {
api.render({data: { isCart: template_type === 13, isCollection: template_type === 2, isProduct: template_type === 1, isIndex: template_type === 15 }}, true);
});
}
}
});
}
initBlockClass(blockEl) {
if (!blockEl) return;
if (blockEl.parentElement && blockEl.parentElement.offsetWidth === document.body.clientWidth) {
blockEl.classList.add('smart_recommend_block_fullscreen');
};
if (isSpecialHeroTheme) {
blockEl.classList.add(specialHeroThemeClassName);
};
}
initItemClass(blockEl) {
if (blockEl) {
const containerWidth = blockEl.offsetWidth;
let itemWidth = '';
if (containerWidth > 780) {
itemWidth = '16%';
} else if (containerWidth > 600) {
itemWidth = '20%';
} else {
itemWidth = '24%';
}
const itemStyleEl = document.createElement('style');
itemStyleEl.innerHTML = `.zb-recommend-li-item{ width: ${itemWidth}; }`;
document.body.appendChild(itemStyleEl);
}
}
setAction_() {
this.registerAction('quickShop', (data) => {
const that = this;
const product_id = data.args.product_id;
const productIndex = data.args.productIndex;
const rule_id = data.args.rule_id;
const ssp = data.args.ssp;
const scm = data.args.scm;
const cfb = data.args.cfb;
const ifb = data.args.ifb;
const modalRender = document.getElementById('smart_recommend_product_modal_render');
if (modalRender) {
document.body.appendChild(modalRender);
}
if (product_id) {
this.fetchProductData(product_id).then((res) => {
const product = res.products && res.products.length && res.products[0] || {};
product.cfb = cfb;
product.ifb = ifb;
SPZ.whenApiDefined(modalRender).then((api) => {
api.render({product: product, productIndex: productIndex, rule_id: rule_id, ssp: ssp, scm: scm, show_type: that.show_type_}, true).then(() => {
const modalEl = document.getElementById('smart_recommend_product_modal');
SPZ.whenApiDefined(modalEl).then((modal) => {
that.impressListen('#smart_recommend_product_modal', function(){
that.trackQuickShop({ rule_id: rule_id, product_id: product_id });
});
modal.open();
});
const formEl = document.getElementById('smart_recommend_product_form');
SPZ.whenApiDefined(formEl).then((form) => {
form.setProduct(product);
});
const variantEl = document.getElementById('smart_recommend_product_variants');
SPZ.whenApiDefined(variantEl).then((variant) => {
variant.handleRender(product);
});
});
})
});
}
});
this.registerAction('handleScroll', (data) => {
this.directTo(data.args.rule_id, data.args.direction);
});
this.registerAction('handleProductChange', (data) => {
const variant = data.args.data.variant;
const product = data.args.data.product;
const imageRenderEl = document.getElementById('smart_recommend_product_image');
SPZ.whenApiDefined(imageRenderEl).then((api) => {
api.render({ variant: variant, product: product });
});
});
this.registerAction('handleAtcSuccess', (detail) => {
const data = detail.args;
data.data.product = data.data.product || {};
data.data.variant = data.data.variant || {};
const product_id = data.data.product.id;
const product_title = data.data.product.title;
const variant_id = data.data.variant.id;
const price = data.data.variant.price;
const rule_id = data.rule_id;
const aid = `smart_recommend.${this.show_type_}.${rule_id}`;
const ifb = data.data.product.ifb;
const cfb = data.data.product.cfb;
const ssp = data.ssp;
const scm = data.scm;
const spm = `smart_recommend_${this.show_type_}.${data.spmIndex}`;
const params = {
id: product_id,
product_id: product_id,
number: 1,
name: product_title,
variant_id: variant_id,
childrenId: variant_id,
item_price: price,
source: 'add_to_cart',
_extra: {
aid: aid,
ifb: ifb,
cfb: cfb,
scm: scm,
spm: `..${window.C_SETTINGS.meta.page.template_name}.${spm}`,
ssp: ssp,
}
};
this.tranckAddToCart(params);
});
this.registerAction('addATCHook', (data) => {
const params = data.args;
const spm = `smart_recommend_${this.show_type_}.${params.spmIndex}`;
this.myInterceptor_ = window.djInterceptors && window.djInterceptors.track.use({
event: 'dj.addToCart',
params: {
aid: `smart_recommend.${this.show_type_}.` + params.rule_id,
ssp: params.ssp,
scm: params.scm,
cfb: params.cfb,
spm: `..${window.C_SETTINGS.meta.page.template_name}.${spm}`,
},
once: true
});
});
}
tranckAddToCart(detail) {
if (window.$) {
window.$(document.body).trigger('dj.addToCart', detail);
}
}
fetchRules() {
const payload = {
show_type: this.show_type_,
};
let that = this;
if (this.show_type_ === 6) {
let line_items = [];
return this.fetchCart().then((res) => {
if (res && res.cart && res.cart.line_items) {
line_items = res.cart.line_items.map((item) => {
return { product_id: item.product_id, variant_id: item.variant_id, quantity: item.quantity, price: item.price }
});
}
payload.line_items = line_items;
that.cart_items_ = line_items;
return that.fetchRulesRequest(payload);
});
} else {
if (this.show_type_ === 3) {
payload.line_items = [{ product_id: this.product_resource_id_ }];
} else if (this.show_type_ === 4) {
payload.collection_id = this.collection_resource_id_;
} else if (this.show_type_ === 7) {
payload.customer_id = this.customer_id_;
} else if (this.show_type_ === 8) {
payload.order_id = this.order_id_;
}
return this.fetchRulesRequest(payload);
}
}
fetchRulesRequest(payload) {
return fetch(window.C_SETTINGS.routes.root + "/api/possum/recommend_query", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
}).then(function(res){
if(res.ok){
return res.json();
}
});
}
fetchCart() {
return fetch(`/api/cart/cart-select?r=${Math.random().toString(36).slice(-4)}`)
.then((res) => {
if (res.ok) {
return res.json();
}
});
}
fetchRuleProductList(rule_id) {
const payload = {
page: 1,
limit: 100,
fields: ["title", "url", "image", "min_price_variant.price", "min_price_variant.compare_at_price"],
rule_id: rule_id,
};
if (this.show_type_ === 3) {
payload.line_items = [{ product_id: this.product_resource_id_ }];
} else if (this.show_type_ === 4) {
payload.collection_id = this.collection_resource_id_;
} else if (this.show_type_ === 6) {
payload.line_items = this.cart_items_;
} else if (this.show_type_ === 7) {
payload.customer_id = this.customer_id_;
} else if (this.show_type_ === 8) {
payload.order_id = this.order_id_;
}
return fetch(window.C_SETTINGS.routes.root + "/api/possum/recommend_products", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
}).then(function(res){
if(res.ok){
return res.json();
}
}).catch(function(err){
console.log(err);
});
}
fetchProductData(product_id) {
return fetch(window.C_SETTINGS.routes.root + "/api/possum/products", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
product_ids: [product_id],
fields: [ "images", "options", "min_price_variant", "variants"]
})
}).then(function(res){
if(res.ok){
return res.json();
}
}).catch(function(err){
console.log(err);
const loadingEl = document.getElementById('smart_recommend_loading');
if (loadingEl) {
loadingEl.style.display = 'none';
}
});
}
getStyle(ele, style) {
if (!ele) return;
if (window.getComputedStyle) {
return window.getComputedStyle(ele)[style];
}
return ele.currentStyle[style];
}
directTo(id, direction) {
const scrollElement = document.getElementById(`smart_recommend_rule_ul_${id}`);
const blockWidth = parseInt(this.getStyle(scrollElement, 'width'));
const scrollLength = (blockWidth * 0.19 - 12) * 5;
const scrollPoint = scrollElement.scrollWidth - scrollElement.clientWidth;
if (!scrollElement) return;
if (direction === 'left') {
if (document.dir === 'rtl') {
scrollElement.scrollTo({
left: Math.abs(scrollElement.scrollLeft) >= scrollPoint - 100 ? 0 : scrollElement.scrollLeft - scrollLength,
behavior: 'smooth'
});
return;
}
scrollElement.scrollTo({
left: Math.max(scrollElement.scrollLeft - scrollLength, 0),
behavior: 'smooth'
});
} else {
if (document.dir === 'rtl') {
scrollElement.scrollTo({
left: Math.abs(scrollElement.scrollLeft) >= scrollPoint + 100 ? 0 : scrollElement.scrollLeft + scrollLength,
behavior: 'smooth'
});
return;
}
scrollElement.scrollTo({
left: scrollElement.scrollLeft >= scrollPoint - 100 ? 0 : scrollElement.scrollLeft + scrollLength,
behavior: 'smooth'
});
}
}
trackRuleImpress(rule) {
if (window.sa && window.sa.track) {
window.sa.track("plugin_common", {
plugin_name: "upsell",
event_type: "impressions",
rule_id: rule.id,
ssp: rule.ssp,
scm: rule.scm,
show_type: this.show_type_,
support_app_block: window.C_SETTINGS.theme.support_app_block
});
window.sa.track("module_impressions", {
aid: `smart_recommend.${this.show_type_}.${rule.id}`,
support_app_block: window.C_SETTINGS.theme.support_app_block
});
}
}
trackQuickShop(data) {
window.sa && sa.track && sa.track("plugin_common", {
plugin_name: "upsell",
event_type: "quick_shop",
rule_id: data.rule_id,
product_id: data.product_id,
show_type: this.show_type_,
});
}
impressListen(selector, cb) {
const el = document.querySelector(selector);
const onImpress = (e) => {
if (e) {
e.stopPropagation();
}
cb();
};
if (el && !el.getAttribute('imprsd')) {
el.addEventListener('impress', onImpress)
} else if (el) {
onImpress();
}
}
}
SPZ.defineElement('spz-custom-smart-block', SpzSmartBlockComponent);
${(function(){
const product = data.product;
const toQuery = obj =>
Object.keys(obj)
.map(k =>
Array.isArray(obj[k])
? obj[k].map(v => `${k}[]=${encodeURIComponent(v)}`).join('&')
: `${k}=${encodeURIComponent(obj[k])}`
)
.join('&');
return `
${product.images.map((image) => {
return ` `
}).join('')}
`;
})()}
${(function(){
const product = data.product;
const avail_variants = product.variants.filter(function(variant){
return variant.available;
});
const selected_variant = product.min_price_variant.available ? product.min_price_variant : avail_variants.length && avail_variants[0];
return `
${option.name}
${
option.values.map(function(value, index){
const checked = selected_variant["option"+option.position] == value ? "checked": "";
return `
${value}
`
}).join("")
}
`
})()}
${data.mm} m
${data.ss} s
Your shopping bag is empty
Continue shopping
Your cart is reserved for
!
*${item.quantity}
${item.item_text}
${discount_item.title}
(- )
${(function(){
var total_price = data.total_price;
var postageFreeAmount = 69;
var freeAmount = postageFreeAmount - total_price;
var isFreeShipping = freeAmount <= 0;
var rate = Math.min(total_price / postageFreeAmount * 100, 100).toFixed(2);
const textArray = ("Spend {{ amount }} more and get free shipping!").split(/\{\{\s*amount\s*\}\}/);
const textArrayHtml = textArray.map((text, index) => {
if (index == 0) {
return `${text} `;
}
return `${text} `;
}).join('');
return `
${textArrayHtml}
You've got free shipping
`
})()}
${function() {
const textArray = ("Save {{save_amount}}").split(/\{\{\s*save_amount\}\}/);
if (textArray.length > 0 && textArray.length < 2) {
textArray.push('');
}
return textArray.map((text, index) => {
if (index == 0) {
return `${text} `;
}
return `
${text}
`;
}).join('');
}()}
${function() {
const textArray = ("Save {{save_amount}}").split(/\{\{\s*save_amount\}\}/);
if (textArray.length > 0 && textArray.length < 2) {
textArray.push('');
}
return textArray.map((text, index) => {
if (index == 0) {
return `${text} `;
}
return `
${text}
`;
}).join('');
}()}
${discount_application.title}:
-
${data.invalid_msg}
Check out
Taxes and shipping calculated at checkout
${(function(){
var total_price = data.total_price;
var postageFreeAmount = 69;
var freeAmount = postageFreeAmount - total_price;
var isFreeShipping = freeAmount <= 0;
var rate = Math.min(total_price / postageFreeAmount * 100, 100).toFixed(2);
const textArray = ("Spend {{ amount }} more and get free shipping!").split(/\{\{\s*amount\s*\}\}/);
const textArrayHtml = textArray.map((text, index) => {
if (index == 0) {
return `
${text} `;
}
return `
${text} `;
}).join('');
return `
${textArrayHtml}
You've got free shipping
`
})()}
${data.invalid_msg}
${function() {
const textArray = ("Save {{save_amount}}").split(/\{\{\s*save_amount\}\}/);
if (textArray.length > 0 && textArray.length < 2) {
textArray.push('');
}
return textArray.map((text, index) => {
if (index == 0) {
return `${text} `;
}
return `
${text}
`;
}).join('');
}()}
${function() {
const textArray = ("Save {{save_amount}}").split(/\{\{\s*save_amount\}\}/);
if (textArray.length > 0 && textArray.length < 2) {
textArray.push('');
}
return textArray.map((text, index) => {
if (index == 0) {
return `${text} `;
}
return `
${text}
`;
}).join('');
}()}
${function() {
const textArray = ("Save {{save_amount}}").split(/\{\{\s*save_amount\}\}/);
if (textArray.length > 0 && textArray.length < 2) {
textArray.push('');
}
return textArray.map((text, index) => {
if (index == 0) {
return `${text} `;
}
return `
${text}
`;
}).join('');
}()}
${discount_application.title}:
-
Check out
${data.invalid_msg}
Check out
Taxes and shipping calculated at checkout
Subtotal:
${discount_application.title}:
-
Check out
Taxes and shipping calculated at checkout
const summaryStickyRender = document.querySelector('#cart-drawer-summary-sticky-render');
if (summaryStickyRender) {
document.body.style.setProperty('--cart-drawer-summary-sticky-height', summaryStickyRender.clientHeight + 'px');
}
${function(){
console.log('quick-shop-render',data);
const productData = data.product;
let product_change_event = '',
mouse_over_event = ' ';
mouse_out_event = '';
const product_options = productData.options.filter(Boolean) || [];
const selectedVariant = productData.variants.find(v => v.available) || productData.variants[0];
const statusLan = ((selectedVariant && !selectedVariant.available) || (!selectedVariant && !productData.available)) ?
"Sold out" :
"Add to cart";
return `
`
}()}
${function(){
const currentSelectVariant = data.variant;
const defaultVariant = (data.product && data.product.variants && data.product.variants[0]);
const variantData = currentSelectVariant || defaultVariant || data;
const retail_price = variantData.retail_price || 0;
return `
`
}()}
${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":"8a97d147-ab71-4430-bb01-9a3004ee8d1f","product_id":"c27a478f-a3c0-4983-bb0c-e662cd8e775a","title":"Short Bag (15\"x14\")","weight_unit":"kg","inventory_quantity":1000,"sku":"-Short Bag (15\"x14\")-A00157470","barcode":"","position":1,"option1":"Short Bag (15\"x14\")","option2":"","option3":"","note":"","image":null,"wholesale_price":[{"price":24.99,"min_quantity":1}],"weight":"0","compare_at_price":"32.49","price":"24.99","retail_price":"32.49","available":true,"url":"\/products\/pom-winter-trio-quilted-tote-bag-ncu0nt9885?variant=8a97d147-ab71-4430-bb01-9a3004ee8d1f","available_quantity":999999999,"options":[{"name":"Size","value":"Short Bag (15\"x14\")"}],"off_ratio":"23","flashsale_info":{"variant_id":"8a97d147-ab71-4430-bb01-9a3004ee8d1f","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":"24.99","compare_at_price":"","discount_price":"24.99","customary_saved_price":"","customary_off_ratio":"","discount_saved_price":"","discount_off_ratio":"23","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 ? `
` : ' ';
}
}()}
${function(){
const optionName = option.name || '';
const optionId = option.id || '';
let isThumbImage = !!option.showThumbImage;
const thumbStyle = "image_with_text";
const variantType = "button";
const isSelected = (value) => {
const selected = (data.selectedOptions || []).find(v => v.name === optionName);
return selected && selected.value.length && selected.value[0] == value;
};
const getThumbImage = (value) => {
const options = data.product.options || [];
const option = options.find(o => o.name === optionName);
if (option.thumbImages) {
const thumbImage = option.thumbImages.find(t => t.value === value);
if (thumbImage && thumbImage.image) {
return {
src: thumbImage.image.src,
alt: thumbImage.image.alt
};
}
}
return {src: '', alt: ''};
};
return `
${optionName}:
${data.selectedOptions && data.selectedOptions.length && data.selectedOptions.find(v => v.name === optionName).value[0]}
`
}()}
${data.value}
const TAG = 'spz-custom-painter-button-animation';
const MAX_ITERATION_COUNT = 99999999;
const SITE = (window.C_SETTINGS && window.C_SETTINGS.routes && window.C_SETTINGS.routes.root) || '';
const ADD_TO_CART_ANIMATION_SETTING =
`${SITE}/api/marketing_atmosphere_app/add_to_cart_btn_animation/setting`;
class SpzCustomPainterButtonAnimation extends SPZ.BaseElement {
/**@override */
static deferredMount() {
return false;
}
/** @param {!SpzElement} element */
constructor(element) {
super(element);
/** @private {!../../src/service/xhr-impl.Xhr} */
this.xhr_ = SPZServices.xhrFor(this.win);
/** @private {Object} */
this.data_ = null;
/** @private {Element} */
this.addToCartButton_ = null;
/** @private {boolean} */
this.productAvailable_ = true;
/** @private {number} */
this.timerId_ = null;
/** @private {number} */
this.animationExecutionCount_ = 0;
/** @private {boolean} */
this.selectedVariantAvailable_ = true;
/** @private {number} */
this.delay_ = 5000;
/** @private {number} */
this.iterationCount_ = 5;
/** @private {string} */
this.animationClass_ = '';
}
/** @override */
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
/** @override */
buildCallback() {
this.productAvailable_ = this.element.hasAttribute('product-available');
this.selectedVariantAvailable_ = this.element.hasAttribute('selected-variant-available');
}
/** @override */
mountCallback() {
this.render_();
}
/** @private */
render_() {
if (!this.productAvailable_) {
return;
}
this.fetch_().then((data) => {
if (!data) {
return;
}
this.data_ = data;
this.animationClass_ = `painter-${data.animation_name}-animation`;
this.iterationCount_ =
data.animation_iteration_count === 'infinite'
? MAX_ITERATION_COUNT
: data.animation_iteration_count;
const animationDuration = 1;
const animationDelay = data.animation_delay || 5;
this.delay_ = (animationDuration + animationDelay) * 1000;
this.handleButtonEffect_();
});
}
/**
* @param {JsonObject} data
* @return {(null|Object)}
* @private
*/
parseJson_(data) {
try {
return JSON.parse(data);
} catch (e) {
return null;
}
}
/**
* @return {Promise}
* @private
*/
fetch_() {
return this.xhr_.fetchJson(ADD_TO_CART_ANIMATION_SETTING).then((data) => {
if (!data || !data.enabled) {
return null;
}
return this.parseJson_(data.detail);
});
}
/** @private */
getAddToCartButton_() {
this.addToCartButton_ = SPZCore.Dom.scopedQuerySelector(
document.body,
'[data-section-type="product"] [role="addToCart"], [data-section-type="product_detail"] [role="addToCart"], [data-section-type="product_detail"] [data-click="addToCart"], [data-section-type="product"] [data-click="addToCart"]'
);
}
/** @private */
restartAnimation_() {
this.addToCartButton_.classList.remove(this.animationClass_);
this.addToCartButton_./* OK */ offsetWidth;
this.addToCartButton_.classList.add(this.animationClass_);
this.animationExecutionCount_++;
}
/** @private */
clearTimer_() {
this.win.clearInterval(this.timerId_);
this.timerId_ = null;
}
/** @private */
setupTimer_() {
this.timerId_ = this.win.setInterval(() => {
this.restartAnimation_();
if (this.animationExecutionCount_ >= this.iterationCount_) {
this.removeAnimationClass_();
this.clearTimer_();
}
}, this.delay_);
}
/** @private */
restartTimer_() {
if (this.animationExecutionCount_ >= this.iterationCount_) {
this.removeAnimationClass_();
return;
}
this.setupTimer_();
}
/** @private */
listenVariantChange_() {
SPZUtils.Event.listen(self.document, 'dj.variantChange', (e) => {
const selectedVariant = e.detail && e.detail.selected;
if (!selectedVariant) {
return;
}
const {available} = selectedVariant;
if (this.selectedVariantAvailable_ !== available) {
this.selectedVariantAvailable_ = available;
this.clearTimer_();
if (available) {
this.restartTimer_();
}
}
});
}
/** @private */
removeAnimationClass_() {
this.win.setTimeout(() => {
this.addToCartButton_.classList.remove(this.animationClass_);
}, 1000);
}
/** @private */
handleButtonEffect_() {
this.getAddToCartButton_();
if (!this.addToCartButton_) {
return;
}
if (this.selectedVariantAvailable_) {
++this.animationExecutionCount_;
this.addToCartButton_.classList.add(this.animationClass_);
if (this.iterationCount_ === 1) {
this.removeAnimationClass_();
return;
}
this.setupTimer_();
}
this.listenVariantChange_();
}
}
SPZ.defineElement(TAG, SpzCustomPainterButtonAnimation);
const TAG = "spz-custom-popup";
const DISPLAY_TYPE = {
POPUP: "PTT_POPUP" // 弹窗
};
const API = {
LIST: `/api/storefront/promotion/placement/list`, // 获取弹窗列表
REPORT: `/api/storefront/promotion/placement/data/report` // 上报数据
};
const DISPLAY_DEVICE = {
PC_AND_MOBILE: "PD_PC_MOBILE", // PC和移动端
PC: "PD_PC", // PC
MOBILE: "PD_MOBILE" // 移动端
};
const REPORT_EVENT = {
CLICK: "PE_CLICK", // 点击事件
IMPRESSION: "PE_IMPRESSION" // 曝光事件
};
class SpzCustomPopup extends SPZ.BaseElement {
constructor(element) {
super(element);
this.popupList_ = []; // 弹窗数据
this.popupZIndex = 1050; // 弹窗层级
// 节流处理 每5s内多次点击 算一次点击上报
this.throttleReport = this.win.SPZCore.Types.throttle(
this.win,
(data) => {
this.reportData(data)
},
5000
)
}
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() {
this.fetchData_();
}
// 接口请求,获取数据
fetchData_() {
const id = window.SHOPLAZZA.meta.page.template_type === 51 ? window.SHOPLAZZA.meta.page.resource_id : 0;
return this.xhr_.fetchJson(API.LIST, {
method: 'POST',
body: {
page_id: window.SHOPLAZZA.meta.page.template_type,
placement_type: DISPLAY_TYPE.POPUP,
discount_id: id
}
}).then((res) => {
// 请求成功 执行render
this.doRender_(res.list);
}).catch((err) => {
console.error(err);
});
}
// 渲染dom
doRender_(data) {
this.popupList_ = data || [];
if (this.popupList_.length > 0) {
this.popupList_.forEach((item) => {
item.config = JSON.parse(item.config);
})
}
return this.templates_
.findAndRenderTemplate(this.element, { list: this.popupList_ })
.then((el) => {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
this.element.appendChild(el);
})
.then(() => {
// 遍历显示弹窗
this.popupList_.forEach((item) => {
this.showPopup_(item);
});
})
}
showPopup_(popup) {
// 展示弹窗 符合展示条件的弹窗
const $popup = document.querySelector(`#popup-${popup.id}`);
$popup && SPZ.whenApiDefined($popup).then((api)=> {
const isPC = this.viewport_.getWidth() >= 960;
const isMobile = this.viewport_.getWidth() < 960;
const isMatchPCDevice = popup.device === DISPLAY_DEVICE.PC_AND_MOBILE || popup.device === DISPLAY_DEVICE.PC;
const isMatchMobileDevice = popup.device == DISPLAY_DEVICE.PC_AND_MOBILE || popup.device === DISPLAY_DEVICE.MOBILE;
if((isPC && isMatchPCDevice) || (isMobile && isMatchMobileDevice)) {
// 根据推送时间 延迟展示弹窗
setTimeout(() => {
api.open();
}, popup.delay_seconds * 1000);
}
})
}
// 上报数据
async reportData(data) {
this.xhr_.fetchJson(API.REPORT, {
method: "POST",
body: {
placement_id: data.placement_id,
event: data.event
}
});
}
setupAction_() {
this.registerAction('handleTrack', async(invocation) => {
// 如果是主题编辑器则不用处理
if(window.top !== window.self) {
return;
}
const data = invocation.args;
const event = data.event;
// 点击上报 节流处理
if(event === REPORT_EVENT.CLICK) {
await this.throttleReport(data);
} else {
this.reportData(data);
}
});
}
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, SpzCustomPopup);