${(function(){
const get_random_six_digits = () => {
return Math.random().toString().slice(-6)
};
const wholesale_enabled = false;
const setting_product_image_display = "100%";
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;
};
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}
`
})()}
All items: Buy 2 get 10% off Buy 3 get 15% off Buy 4 get 25% off
All items: Buy 2 get 10% off Buy 3 get 15% off Buy 4 get 25% off
1/5
${data.index + 1}/${data.total}
${Array(data.total).fill(0).map((num, index) => `
`).join('')}
The Viking symbol on this energy pyramid is derived from the ancient Rune script system. In Nordic mythological legends, Odin, the father of the gods, hung upside - down on the World Tree Yggdrasil for nine days and nights in search of deeper wisdom. Eventually, he comprehended and brought forth the Runes. These Runes were not only the writing system of the ancient Nordic people but also a mysterious medium through which they communicated with the gods and understood nature and destiny. Each Rune contains unique power and meaning, carrying the thousand - year - old cultural heritage of Northern Europe. ๐งโ๏ธ
The Viking symbol on the pyramid has a unique and profound meaning. It represents protection and blessing. In ancient Nordic culture, people believed that this symbol could ward off evil forces and bring peace and good luck to the owner. It was the spiritual sustenance of the ancient Nordic people's yearning for a better life. Through the passage of time, the mysterious power it holds still attracts people to explore and pursue. ๐
Coil : The coil at the top of the pyramid is believed to have the function of gathering and guiding energy in the field of energy studies. It is like an energy hub that can collect the surrounding energy and channel it into the pyramid in an orderly manner, enabling the energy to be released stably and continuously. ๐
White Crystal : White crystal is known as the "King of Energy". It has powerful purification and energy - amplifying functions. It can clear negative energy in the surrounding environment, making the energy field pure and harmonious. At the same time, it can also enhance people's mental clarity, improve concentration and spiritual perception. ๐
Gold Foil : Gold foil not only gives the energy pyramid a magnificent appearance. In energy studies, gold foil is regarded as an element that can strengthen energy. It can increase the vibration frequency of the overall energy, enhance the stability and durability of energy, and attract positive energy and good luck. โจ
Energy Balance : Through the coordinated action of the Rune and various energy materials, this energy pyramid can effectively balance the energy fields of the human body and the surrounding environment. It relieves discomfort such as fatigue and anxiety caused by energy imbalance, allowing people to regain physical and mental harmony and balance and be full of vitality. ๐
Fortune Enhancement : Its mysterious - emitting energy is believed to be able to improve personal fortune and attract positive opportunities and noble people. Whether you are seeking a breakthrough in career development or longing for more luck and beauty in life, it can give you a boost and make your life journey smoother. ๐
Spiritual Soothing : In the fast - paced modern life, people often face various pressures and troubles. The gentle energy released by this energy pyramid can soothe the soul tenderly, reduce anxiety and stress, and create a peaceful spiritual haven for you, allowing you to maintain a calm and positive mindset. ๐งโ๏ธ
At Home : Place it in the southeast direction of the living room to enhance the overall energy aura of the family, promote harmonious family relationships, and help attract wealth and blessings; put it on the bedside table in the bedroom. It can safeguard your energy field while you sleep, bringing a sound sleep and beautiful dreams. ๐
At Work : Place it on the left side of the desk to enhance work luck, stimulate work inspiration and creativity, and attract the help and support of noble people, making you more efficient and successful in your career. ๐ผ
Bring this mysterious Viking Symbol Energy Pyramid home, just like opening a door to the mysterious energy world of Northern Europe. Let the ancient wisdom and power safeguard your life, bring you all - round energy care, and start a new journey full of miracles and beauty. ๐
${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 = 99;
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 = 99;
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(){
const productData = data.product;
let product_change_event = '',
mouse_over_event = ' ';
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 + `quick-shop-selected-variant-${opt.id}.rerender(data=event.selectedValues.${opt.name});`;
mouse_out_event = mouse_out_event + `@${nameEscape}Mouseout="quick-shop-selected-variant-${opt.id}.rerender(data=event.selectData.${opt.name}, redo=true);"`;
mouse_over_event = mouse_over_event + `@${nameEscape}Mouseover="quick-shop-selected-variant-${opt.id}.rerender(data=event, redo=true);"`;
}
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":"4d25938a-3f5b-48df-abc4-3e692a967e86","product_id":"2d15e580-8ac0-493f-984c-882d07fbbbea","title":"","weight_unit":"kg","inventory_quantity":1000,"sku":"BGPJ000249","barcode":"","position":1,"option1":"","option2":"","option3":"","note":"","image":null,"wholesale_price":[{"price":29.99,"min_quantity":1}],"weight":"0","compare_at_price":"0","price":"29.99","retail_price":"0","available":true,"url":"\/products\/lune-symbols-gift-rune-pyramid?variant=4d25938a-3f5b-48df-abc4-3e692a967e86","available_quantity":999999999,"options":[],"off_ratio":"0","flashsale_info":{"variant_id":"4d25938a-3f5b-48df-abc4-3e692a967e86","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":"29.99","compare_at_price":"","discount_price":"29.99","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 ? `
` : ' ';
}
}()}
${function() {
let variantImageShowed = false;
const currentProduct = data.product;
return (currentProduct.options || []).map((option, index) => {
const optionName = option.name || '';
const optionId = option.id || '';
const position = `option${index + 1}`;
let isThumbImage = false;
if (currentProduct.need_variant_image && !variantImageShowed) {
const variantNames = ["color"] || [];
for (let i = 0, len = variantNames.length; i < len; i++) {
const name = variantNames[i].toLowerCase();
if (name === optionName.toLowerCase()) {
isThumbImage = true;
variantImageShowed = true;
}
}
}
const variantType = "button";
const thumbStyle = "image_with_text";
return `
${optionName}:
${option.values.map((value, idx) => {
const selected = data.selectedValues[optionName] == value ? 'checked' : '';
let thumbImage = null;
if (isThumbImage) {
const variants = currentProduct.variants;
for (let i = 0, len = variants.length; i < len; i++) {
const variant = variants[i];
if (variant[position] == value && thumbImage == null) {
thumbImage = variant.image;
break;
}
}
}
return `
${value}
`
}).join('')}
${optionName}
${option.values.map(value => {
const selected = data.selectedValues[optionName] == value ? 'selected' : '';
return `${value} `
}).join('')}
`
}).join('');
}()}
${data.originData && data.originData.value || data.value}
${function() {
const price = data.variant?.price || data.product.selectedVariant?.price;
const compare_at_price = data.variant?.compare_at_price || data.product.selectedVariant?.compare_at_price;
return `
`
}()}
${function() {
return data.product.options.length > 0 ? data.product.options.map((option, index) => {
return `
${function() {
if(data.product.config.isMobile === false) {
return `
`
} else {
return `
`
}
}()}
`
}).join('') : ``;
}()}
${function() {
const value = (data.originData && data.originData.value) || data.value;
const isHasValue = value ? true : false;
return `
${value ? value : "" }
`
}()}
${data.product.selectedSkuText ? data.product.selectedSkuText : ''}
${function() {
return (data.product.options || []).map((option, index) => {
return `
${option.name}:
${option.values.map((value,idx) => {
let selectedOptions = data.product.selectedVariant.options;
let selected = '';
if(selectedOptions.length) {
for(const key in selectedOptions) {
if(selectedOptions[key].value == value) {
selected = 'checked'
}
}
}
return `
${value}
`;
}).join('')}
`;
}).join('')
}()}
${data.value ? data.value : ''}
${function() {
let dropdownCloseEvent = '';
if(!data.config.isMobile && (data.config.style == 'circle' || data.config.style == 'square')) {
data.product.options?.forEach((item, index) => {
dropdownCloseEvent += `app-atc-popover-${index}.close;`;
})
}
return `
`;
}()}
${function(){
let product_change_event = '';
const product_options = data.product.options?.filter(Boolean) || [];
for (let opt of product_options) {
const nameEscape = opt.name.replace(/\/|\\|\s|\'|\"|`|\<|\>/g, '');
product_change_event = product_change_event + `add-cart-selected-variant-${opt.id}.rerender(data=event.selectedValues.${opt.name});`;
}
return `
${function() {
const isDarkBg = data.isDarkBg;
const textColor = isDarkBg ? '#ffffff' : '#212B36';
const delPriceColor = isDarkBg ? '#E0E0E2' : '#9CA0B0';
const variantColor = isDarkBg ? '#ffffff' : '#939393';
const config = data.config;
return `
`
}()}
${function(){
if(data.is_button_click_info) {
return `
${data.config.button_text || 'Add to cart'}
${data.config.button_text || 'Add to cart'}
`
} else {
return `
`
}
}()}
${function() {
if(data.is_button_click_info) {
return `
${function(){
let product_change_event = '';
const product_options = data.product.options?.filter(Boolean) || [];
for (let opt of product_options) {
const nameEscape = opt.name.replace(/\/|\\|\s|\'|\"|`|\<|\>/g, '');
product_change_event = product_change_event + `add-cart-selected-variant-${opt.id}.rerender(data=event.selectedValues.${opt.name});`;
}
return `
`
}()}
`
} else {
return ``
}
}()}
`
}()}
const TAG = 'spz-custom-add-to-cart';
class SpzCustomAddToCart extends SPZ.BaseElement {
constructor(element) {
super(element);
this.plugin_timestamp = Date.now();
this.defaultColorConfig = {
module_bg: "#FFFFFF",
button_bg: "#E84926",
button_color: "#FFFFFF",
text_color: "#202020",
price_color: "#E84926",
border_color: "#E6E6E6",
border_bg: "#FFFFFF",
round_size: '4'
};
this.config = this.defaultColorConfig;
this.originStickyTop = 0;
this.qty = 1;
this.variantId = this.element.getAttribute('variant-id');
this.trackMap = {
qty: this.trackQty.bind(this),
variant: this.trackVariant.bind(this),
addToCart: this.trackAddtoCart.bind(this),
atcView: this.trackAtcView.bind(this),
}
this.isHasView = false;
this.isFirstUpdateVariant=false;
}
static deferredMount() {
return false;
}
buildCallback() {
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.templates_ = SPZServices.templatesForDoc(this.element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.locale_ = SPZServices.localeFor(this.win);
this.hasGlobalAtcListener = !!document.querySelector('#add-cart-event-proxy');
this.setupAction_();
}
mountCallback() {
// ๅๅงๅ
this.init();
}
async init() {
// ๅฆๆไธๆฏ่ฏฆๆ
้กต๏ผไธ้่ฆๆง่กๅ้ขjs
if (window.SHOP_PARAMS.template_type !== '1') return;
await this.setLocale();
this.handleIsRender();
this.bingEvents();
}
bingEvents() {
// ่ฎพๅคๅๆข ้ๆฐๆธฒๆ
window.addEventListener('resize',
SPZCore.Types.debounce(
this.win,
(invocation) => {
// ๅ
ณ้ญๅผน็ช, ่งฃๅณๅๆขๅฑๅนๅฐบๅฏธไธ่ฝๆปๅจ็้ฎ้ข
this.triggerEvent_('closeShopModal');
this.config = {
...this.config,
isMobile: window.innerWidth < 768 ? true : false,
position: window.innerWidth < 768 ? 'down' : this.config.display_position
};
this.renderAddToCart();
},
200
))
}
// ่ทๅๅค่ฏญ่จ
async setLocale() {
let data;
try {
//ๅค่ฏญ่จ
data = await this.locale_.i18n(['product', 'products']);
} catch (error) {
console.error(error);
}
this.i18n = {
'sold_out': 'Sold out',
'add_to_cart': 'Add to cart',
'unavailable': 'Unavailable',
'product_unavailable': 'Product is unavailable.',
...data?.product?.product_detail,
...data?.products?.product,
}
}
getProductData() {
let pJson = document.querySelector('#product-json');
if (pJson) {
return JSON.parse(pJson.innerHTML)?.product;
} else if (typeof $ === 'function') {
return $(document).data('djproduct')?.product;
}
return undefined;
}
getAddCartBtn() {
return document.querySelector('[data-section-type="product_detail"] [data-click="addToCart"], [data-section-type="product_detail"] [role="addToCart"], [data-section-type="product_detail"] [data-click="buyNow"], [data-section-type="product_detail"] [role="buyNow"], [data-section-type="product"] [data-click="addToCart"], [data-section-type="product"] [role="addToCart"], [data-section-type="product"] [data-click="buyNow"], [data-section-type="product"] [role="buyNow"]');
}
handleObserver() {
if(this.config.trigger_condition == 'theme_hidden') {
const $addCartBtn = this.getAddCartBtn();
if($addCartBtn) {
// ้
็ฝฎไบๅ ่ดญ/่ดญไนฐๆ้ฎ; ่ฎพ็ฝฎๆ้ฎไธบobserver่งๅฏ็ฎๆ
$addCartBtn.setAttribute('id', 'app-atc-need-sticky-buttons')
}
}
}
findAncestor(node, selector) {
while (node) {
if (node.querySelector(selector)) {
return node;
}
node = node.parentElement;
}
return null;
}
getThemeProductInfoForm() {
let $themeForm = '';
const $themeProductInfo = document.querySelector('[data-section-type="product_detail"], [data-section-type="product"]');
$themeForm = $themeProductInfo?.querySelector('form');
return $themeForm;
}
// ่ทๅไธป้ขๅๅๅ ่ดญๆฐ้
getThemeQuantity() {
let $themeForm = this.getThemeProductInfoForm();
if($themeForm) {
const formData = new FormData($themeForm);
const quantity = formData.get('quantity');
return quantity;
} else {
return null;
}
}
getThemeInitVariantsData() {
const $themeForm = this.getThemeProductInfoForm();
const formData = new FormData($themeForm);
}
// ่ทๅไธป้ขๅๅง่กจๅๆฐๆฎ
getThemeProductFormData = () => {
const $themeForm = this.getThemeProductInfoForm();
if($themeForm) {
const form_data = new FormData($themeForm);
const form_data_format = {}
for (const [key, value] of form_data) {
form_data_format[key] = value;
}
return form_data_format;
} else {
return null;
}
}
brightnessByColor(c) {
let color = '' + c,
isHEX = c.indexOf('#') == 0,
isRGB = c.indexOf('rgb') == 0;
let r, g, b;
if (isHEX) {
var m = color.substr(1).match(color.length == 7 ? /(\S{2})/g : /(\S{1})/g);
if (m) {
(r = parseInt(m[0], 16)), (g = parseInt(m[1], 16)), (b = parseInt(m[2], 16));
}
}
if (isRGB) {
const m = color.match(/^rgba\((\d+),\s*(\d+),\s*(\d+),(\d+)\)$/);
if (m) {
(r = m[1]), (g = m[2]), (b = m[3]);
}
}
if (typeof r != 'undefined') return (r * 299 + g * 587 + b * 114) / 1000;
};
getSelectedVariant() {
const product = this.getProductData();
return product.variants.find(item => item.id == this.variantId);
}
setSelectedOption(product) {
const selectedVariant = this.getSelectedVariant();
const productData = Object.assign({}, product);
// ๅค็ไธๆ้้กน
productData?.options?.forEach(option => {
option.selectList = [];
option.values?.forEach(value => {
let selectStatus = '';
selectedVariant?.options?.forEach(item => {
if(item.name == option.name && item.value == value) {
selectStatus = 'checked';
}
})
option.selectList.push({name: option.name, value: value, checked: selectStatus});
})
})
return productData;
}
getSelectedSkuText() {
const selectVariant = this.getSelectedVariant();
if(!selectVariant) {
return '';
}
const selectList = selectVariant.options;
for (var i = 0; i < selectList.length; i++) {
selectList[i].value = selectVariant[`option${i + 1}`];
}
const selectedSkuText = selectList
.map( item => {
return item.value;
})
.join('/');
return selectedSkuText;
}
// ๆฏๅฆๅฑ็คบ ๅ ่ดญๅผน็ช
getIsButtonClickInfo() {
const product = this.getProductData();
const isMultipleProduct = product.available && !product.has_only_default_variant; // ๅคๆฌพๅผๅๅ
const isButtonClickInfo = this.config.isMobile && (this.config.style_mobile === "mb_simple" || this.config.style_mobile === "mb_circle") && this.config.button_click_mobile === 'info' && isMultipleProduct;
return isButtonClickInfo;
}
// ๆฏๅฆ่ท้ไธป้ข็ๅ ่ดญๆฐ้ isFollowThemeQty (็งปๅจ็ซฏ simpleใcircleๆจก็ใ PC็ซฏ simpleๆจก็ๅ ่ดญๆฐ้ไปไธป้ข่ทๅ)
getIsFollowThemeQty() {
const followThemeQtyMobile = (this.config.style_mobile === "mb_simple" || this.config.style_mobile === "mb_circle") && this.config.isMobile;
const followThemeQtyPc = this.config.style === "simple" && !this.config.isMobile;
const isFollowThemeQty = (followThemeQtyPc || followThemeQtyMobile) ? true : false;
return isFollowThemeQty;
}
getBannerRenderData() {
const product = this.getProductData();
// ๅฝๅ้ไธญๅไฝ
const selectedVariant = this.getSelectedVariant();
// ๅไฝoptionsไธๆๅ่กจๆฐๆฎๅค็
const productData = this.setSelectedOption(product);
// ้ไธญ็skuๆๆก
const selectedSkuText = this.getSelectedSkuText();
// ๆฏๅฆๅฑ็คบ ๅ ่ดญๅผน็ช
const is_button_click_info = this.getIsButtonClickInfo();
// ไธป้ขๆฏๅฆๆ้
็ฝฎๅ ่ดญ/่ดญไนฐๆ้ฎ
const isHasAddCartBtn = this.getAddCartBtn() ? true : false;
// ๅ ่ดญๆฐ้ๆฏๅฆ่ท้ไธป้ข
const isFollowThemeQty = this.getIsFollowThemeQty();
// ๆต
่ฒ่ๆฏ้ข่ฒ้
็ฝฎ
const brightness = this.brightnessByColor(this.config.module_bg);
const isDarkBg = brightness < 115;
const renderData = {
product: {
...productData,
config: {...this.config},
selectedVariant,
selectedSkuText,
},
config: this.config,
qty: this.qty,
variant: selectedVariant,
selectedVariant,
selectedSkuText,
is_button_click_info,
isDarkBg,
isHasAddCartBtn,
isFollowThemeQty,
i18n: this.i18n,
hasGlobalAtcListener: this.hasGlobalAtcListener
};
return renderData;
}
// render add_to_cart
async renderAll() {
const renderData = this.getBannerRenderData();
this.triggerEvent_('renderBanner', renderData);
}
getConfigData() {
return fetch(`/api/add-to-cart-config`).then(res => {
return res.json();
});
}
async getConfig() {
if(!this.config.hasOwnProperty('open_status')) {
const res = await this.getConfigData();
if (res.state === 0 && res.data.open_status) {
// configๆฐๆฎ่ฝฌๅ
this.transConfigData(res.data);
}
}
return this.config;
}
transConfigData(data) {
const resConfig = data;
this.config = {
...this.config,
...resConfig,
isMobile: window.innerWidth < 768 ? true : false,
position: window.innerWidth < 768 ? 'down' : resConfig.display_position
};
// ้ข่ฒ่ท้็ณป็ปๆถ
if(resConfig.color_setting === 'default' || resConfig.color_setting === 'theme') {
this.config = {
...this.config,
...this.defaultColorConfig
}
}
}
// ๆฏๅฆๅบ็จๅฐๅๅบ
async handleIsRender() {
const res = await this.getConfigData();
if (res.state === 0 && res.data.open_status) {
// configๆฐๆฎ่ฝฌๅ
this.transConfigData(res.data);
this.handleObserver();
// ๆธฒๆๅ ่ดญๅ
ๅฎน
this.renderAddToCart();
}
}
renderAddToCart() {
const product = this.getProductData();
if (product.product_type === 'gift_card') return ;
if (!product.available) return;
this.renderAll();
}
// ้ๆฉๅไฝ ไธๆฅ
trackVariant() {
const product = this.getProductData();
window.sa &&
sa.track('plugin_atc_variant_click', {
product_id: product.id,
style: this.config.style,
style_mobile: this.config.style_mobile
});
}
// ๆดๆนๆฐ้ไธๆฅ
trackQty() {
const product = this.getProductData();
window.sa &&
sa.track('plugin_atc_qty_click', {
product_id: product.id,
style: this.config.style,
style_mobile: this.config.style_mobile
});
}
// ๅ ่ดญไธๆฅ
trackAddtoCart() {
const product = this.getProductData();
let properties = '';
let source = 'atc';
if (this.config.button_action === 'checkout') {
source = 'buy_now';
}
const obj = {
product_id: product.id,
style: this.config.style,
style_mobile: this.config.style_mobile,
button_action: this.config.button_action,
plugin_timestamp: this.plugin_timestamp
};
const options = {
product_id: product.id,
variant_id: this.variantId,
quantity: this.qty,
source,
variant: this.getSelectedVariant(),
product: product,
process: (window.SHOP_PARAMS.product_settings || {}).add_to_cart_process,
properties: properties
}
// ๆณจๅๆๅ
ๅๆฐๅฐadd_to_cartไบไปถ
window.spzutm && window.spzutm.registerParams('add_to_cart', { add_to_cart: JSON.stringify(obj) });
window.sa && sa.track('plugin_atc_button_click', obj);
this.trackHookAddTocart();
}
trackAtcView() {
const product = this.getProductData()
if(!this.isHasView) {
sa.track('plugin_atc_view', {
product_id: product.id,
button_action: this.config.button_action,
style: this.config.style,
style_mobile: this.config.style_mobile,
plugin_timestamp: this.plugin_timestamp
});
this.isHasView = true;
}
}
trackHookAddTocart(options) {
//FLASHๅไนๅไธป้ขtriggerไบไปถไธๆฅ้็จHOOK
window.djInterceptors &&
window.djInterceptors.track &&
window.djInterceptors.track.use({
event: 'dj.addToCart',
params: {
id: options.product_id,
number: options.quantity,
childrenId: options.variant.id,
item_price: options.variant.price,
name: options.product.title,
type: options.variant.type ? options.variant.type : options.product.type,
properties: properties,
quantity: options.quantity,
variant_id: options.variant.id,
product_id: options.product_id,
source: 'atc',
process: options.process
},
once: true
});
}
// ๅ ่ดญๅผน็ช
renderShopModal_() {
const renderData = this.getBannerRenderData();
this.triggerEvent_('showAddToCartModal', renderData);
}
showSuccessToast() {
this.triggerEvent_('showAddToCartToast');
}
updateSelectVariant = async(selectedVariant, product) => {
const configData = await this.getConfig();
const productData = this.setSelectedOption(product);
const selectedSkuText = this.getSelectedSkuText();
const renderData = {
...productData,
selectedVariant,
config: configData,
selectedSkuText
};
this.triggerEvent_('variantChange', renderData);
const renderBannerData = this.getBannerRenderData();
if(renderBannerData.is_button_click_info && this.config.style_mobile === "mb_circle") {
this.triggerEvent_('renderBannerClickInfo', renderBannerData);
}
}
getUrlVariantId() {
const urlParams = new URLSearchParams(window.location.search);
const variantId = urlParams.get('variant');
return variantId;
}
// ๅ่ฏฆ้กตๅไฝๅๆข
djVariantChange(detail) {
const product = this.getProductData();
// ๆฏๅฆไธบๅ่ฏฆ้กตๅฝๅๅๅ
const isDetailProduct = product?.id === detail?.product?.id;
if(!detail || !isDetailProduct) {
return;
}
const selectVariant = detail.selected;
// ๆดๆฐๅไฝid
const variantId = selectVariant.id;
const oldVariantId = this.variantId;
if(variantId) {
this.triggerEvent_('renderSelectedVariant');
if(oldVariantId !== variantId || !this.isFirstUpdateVariant) {
this.isFirstUpdateVariant = true;
this.variantId = variantId;
this.updateSelectVariant(selectVariant, detail.product);
}
} else if(!variantId){
// ไธป้ขๆช้ไธญๅไฝ
const isDisabledAtc = this.disabledAtc();
if(isDisabledAtc) {
this.triggerEvent_('renderBannerNoSelectedVariant', { product: detail.product });
}
}
}
// ไธๅฑ็คบๅไฝ็ๆจก็
isHiddenVariantsTemplate() {
return ((this.config.style_mobile === 'mb_circle' || this.config.style_mobile === 'mb_simple') && this.config.isMobile) || (this.config.style === 'simple' && !this.config.isMobile);
}
// ไธป้ขๆช้ไธญๅไฝ
isUnSelectedThemeVariants() {
// ไธๅฑ็คบๅไฝ็ๆจก็
const formData = this.getThemeProductFormData();
return (formData && formData.hasOwnProperty('variant_id') && (!formData.variant_id || formData.variant_id === 'undefined'));
}
// ็ฆ็จๅ ่ดญ
disabledAtc() {
// ไธๅฑ็คบๅไฝ็ๆจก็
const isHiddenVariantsTemplate = this.isHiddenVariantsTemplate();
const isUnSelectedThemeVariant = this.isUnSelectedThemeVariants();
return isHiddenVariantsTemplate && isUnSelectedThemeVariant;
}
// ๆปๅจ่ณไธป้ขๅไฝๅค
scrollToThemeVariant() {
const themeFormEl = this.getThemeProductInfoForm();
if(themeFormEl) {
this.triggerEvent_('showUnSelectedVariantTips');
setTimeout(() => {
themeFormEl.scrollIntoView({ behavior: 'smooth' });
}, 1000);
}
}
async setupAction_() {
// ไธๆฅๅค็
this.registerAction('saTrack', async(invocation) => {
const data = invocation.args;
// this.trackMap[data.type]?.();
})
// ๆดๆฐvariantId
this.registerAction('updateVriantId', async(invocation) => {
const data = invocation.args.data;
if(data.variant_id && data.variant_id != 'undefined') {
this.variantId = data.variant_id;
}
})
// ๆธฒๆๅผน็ชๅ ่ดญ&่ดญไนฐๆ้ฎ
this.registerAction('renderShopModal', async(invocation) => {
this.renderShopModal_();
})
this.registerAction('bannerExtraRender', async(invocation) => {
const renderData = this.getBannerRenderData();
if(renderData.is_button_click_info && this.config.style_mobile === "mb_circle") {
this.triggerEvent_('renderBannerClickInfo', renderData);
}
})
// ๅ ่ดญๆฐ้ๅๆญฅ
this.registerAction('handleAddToCart', async(invocation) => {
// ไธป้ขๆช้ไธญๅไฝ
const isDisabledAtc = this.disabledAtc();
if(isDisabledAtc) {
this.scrollToThemeVariant();
return;
}
const quantity = this.getThemeQuantity();
if(this.config.button_action === "checkout" ) {
this.triggerEvent_('updateQty', { quantity: Number(quantity) || this.qty });
this.triggerEvent_('handleBuyNow');
} else {
this.triggerEvent_('updateQty', { quantity: Number(quantity) || this.qty });
this.triggerEvent_('handleAtc');
}
})
// ๆธฒๆๅผน็ชๅ ่ดญ&่ดญไนฐๆ้ฎ
this.registerAction('handleFixedBanner', async(invocation) => {
// ๅบๅฎๅฎไฝๆถ, ่งฆๅljs-sticky ็ปไปถshowStickyๆนๆณ,ๅฑ็คบbanner
if(this.config.trigger_condition == 'fixed') {
this.triggerEvent_('showBanner');
// this.trackAtcView();
}
})
this.registerAction('handleVariantsRender', async(invocation) => {
const data = invocation.args.data;
// ไธป้ขๆช้ไธญๅไฝ
const isDisabledAtc = this.disabledAtc();
if(isDisabledAtc) {
this.triggerEvent_('renderBannerNoSelectedVariant', { product: data });
return;
}
this.triggerEvent_('renderSelectedVariant', { product: data });
this.triggerEvent_('variantChange', data);
})
this.registerAction('handleShowErrorToast', async(invocation) => {
const data = invocation.args.data;
if(data?.message) {
this.triggerEvent_('showAtcErrorToast', 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.LOGIC;
}
}
SPZ.defineElement(TAG, SpzCustomAddToCart)
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);
const TAG = "spz-custom-announcement";
const DISPLAY_TYPE = {
ANNOUNCEMENT: "PTT_BANNER" // ๅ
ฌๅๆ
};
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" // ๆๅ
ไบไปถ
};
const POSITION = {
TOP: "PP_TOP", // ้กถ้จ
BOTTOM: "PP_BOTTOM" // ๅบ้จ
}
const MODE = {
FIXED: "PM_FIXED", // ๅบๅฎ
NORMAL: "PM_SCROLLING" // ๆปๅจ
}
const THEME_NAME = window.SHOPLAZZA.theme.merchant_theme_name;
class SpzCustomAnnouncement extends SPZ.BaseElement {
constructor(element) {
super(element);
this.announcementList_ = []; // ๅ
ฌๅๆ ๆฐๆฎ
}
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_();
this.createAnnouncementDom_();
this.listenCartChange_();
}
fetchData_(type = '') {
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.ANNOUNCEMENT,
discount_id: id
}
}).then((res) => {
this.announcementList_ = res.list || [];
if (this.announcementList_.length > 0) {
this.announcementList_.forEach((item) => {
item.config = JSON.parse(item.config);
});
}
if(type === 'cartChange') {
this.announcementList_.forEach((item) => {
this.updateText_(item);
});
} else {
this.doRender_(this.announcementList_);
}
}).catch((error) => {
console.error(error);
})
}
doRender_(data) {
return this.templates_
.findAndRenderTemplate(this.element, { list: this.announcementList_ })
.then((el) => {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
this.element.appendChild(el);
})
.then(() => {
this.announcementList_.forEach((item) => {
this.showAnnouncement_(item);
});
}).then(() => {
this.handleThemeCompatibility_();
});
}
// ๆดๆฐๆๆก
updateText_(item) {
const announcement = document.querySelector(`#announcement-${item.id}`);
const announcementText = announcement.querySelectorAll('.announcement_text');
const textArr = item.config.text_discount.replace_texts;
const textDom = textArr.map((text) => {
return `${text} `;
}).join(',');
announcementText.forEach((text) => {
text.innerHTML = textDom;
});
}
// ๅๅปบๅ
ฌๅๆ dom
createAnnouncementDom_() {
const isHero = /Hero/.test(THEME_NAME);
const isEva = /Eva/.test(THEME_NAME);
const headerEl = document.querySelector('[data-section-type="header"]');
const headerSticky = headerEl && SPZCore.Dom.computedStyle(this.win, headerEl).position === 'sticky';
// ๅๅปบๆปๅจ็ๅบ้จๅ
ฌๅๆ
const announcementBottomContainer = document.createElement('div');
announcementBottomContainer.className = 'announcement__container_bottom bootstrap';
document.body.appendChild(announcementBottomContainer);
// ๅๅปบๅบๅฎ็ๅบ้จๅ
ฌๅๆ
const announcementBottomSticky = document.createElement('ljs-sticky');
announcementBottomSticky.className = 'announcement__container_bottom-sticky';
announcementBottomSticky.setAttribute('layout', 'container');
announcementBottomSticky.setAttribute('position', 'bottom');
announcementBottomSticky.style.position = 'fixed';
announcementBottomSticky.style.bottom = '0';
announcementBottomSticky.style.left = '0';
announcementBottomSticky.style.right = '0';
announcementBottomSticky.style.zIndex = '1030';
document.body.appendChild(announcementBottomSticky);
const announcementTopContainer = document.createElement('div');
announcementTopContainer.classList.add('announcement__container_top');
if (isHero) {
announcementTopContainer.classList.add('announcement__container_top_zIndex_1030');
}
announcementTopContainer.classList.add('bootstrap');
document.body.insertBefore(announcementTopContainer, document.body.children[0]);
const announcementTopFixedContainer = document.createElement('div');
announcementTopFixedContainer.classList.add('announcement__container_top-fixed');
if (isHero) {
announcementTopFixedContainer.classList.add('announcement__container_top_zIndex_1030');
}
announcementTopFixedContainer.classList.add('bootstrap');
const insertBeforeElement = headerSticky ? headerEl : document.body;
insertBeforeElement.insertBefore(announcementTopFixedContainer, insertBeforeElement.children[0]);
if (isEva) {
const evaHeader = document.querySelector('header.header');
const isEvaMaskHeader = evaHeader && SPZCore.Dom.computedStyle(this.win, evaHeader).position === 'absolute';
let fixedBannerTopContainer = document.querySelector('.announcement__container_top-fixed');
if (isEvaMaskHeader) {
if (fixedBannerTopContainer) {
fixedBannerTopContainer.remove();
}
const newBanner = document.createElement('div');
newBanner.className = 'announcement__container_top-fixed bootstrap';
document.body.insertBefore(newBanner, document.body.firstChild);
fixedBannerTopContainer = newBanner;
} else {
if (!headerEl) return;
const observer = new MutationObserver(() => {
const isSticky = SPZCore.Dom.computedStyle(this.win, headerEl).position === 'sticky';
if (!isSticky) return;
const isTopFixedAnnouncementInHeader = headerEl.querySelector('.announcement__container_top-fixed');
if (isTopFixedAnnouncementInHeader) return;
const announcementTopFixedContainer = document.querySelector('.announcement__container_top-fixed');
if (announcementTopFixedContainer) {
announcementTopFixedContainer.remove();
headerEl.insertBefore(announcementTopFixedContainer, headerEl.children[0]);
observer.disconnect();
}
});
observer.observe(headerEl, { attributes: true, attributeFilter: ['style', 'class'] });
}
if (headerSticky && !isEvaMaskHeader && fixedBannerTopContainer) {
fixedBannerTopContainer.style.position = 'relative';
fixedBannerTopContainer.style.zIndex = '29';
}
}
}
// ๅฑ็คบๅ
ฌๅๆ
showAnnouncement_(item) {
const announcement = document.querySelector(`#announcement-${item.id}`);
const announcementBottomContainer = document.querySelector('.announcement__container_bottom');
const announcementBottomSticky = document.querySelector('.announcement__container_bottom-sticky');
const announcementTopContainer = document.querySelector('.announcement__container_top');
const announcementTopFixedContainer = document.querySelector('.announcement__container_top-fixed');
const isPC = this.viewport_.getWidth() >= 960;
const isMobile = this.viewport_.getWidth() < 960;
const isMatchPCDevice = item.device === DISPLAY_DEVICE.PC_AND_MOBILE || item.device === DISPLAY_DEVICE.PC;
const isMatchMobileDevice = item.device == DISPLAY_DEVICE.PC_AND_MOBILE || item.device === DISPLAY_DEVICE.MOBILE;
if((isPC && isMatchPCDevice) || (isMobile && isMatchMobileDevice)) {
if (item.position === POSITION.BOTTOM) {
if(item.mode === MODE.FIXED) {
announcementBottomSticky && announcementBottomSticky.appendChild(announcement);
} else {
announcementBottomContainer && announcementBottomContainer.appendChild(announcement);
}
} else {
if (item.mode === MODE.FIXED) {
announcementTopFixedContainer && announcementTopFixedContainer.appendChild(announcement);
} else {
announcementTopContainer && announcementTopContainer.appendChild(announcement);
}
}
this.reportData({
placement_id: item.id,
event: REPORT_EVENT.IMPRESSION
});
}
}
// ๅค็ไธป้ขๅ
ผๅฎน
handleThemeCompatibility_() {
try {
const isBoost = /Boost/.test(THEME_NAME);
const isHyde = /Hyde/.test(THEME_NAME);
const isEva = /Eva/.test(THEME_NAME);
const boostHeader = document.querySelector('.boost-header');
const fixedBannerTopContainer = document.querySelector('.announcement__container_top-fixed');
const notFixedBannerTopContainer = document.querySelector('.announcement__container_top');
const headerEl = document.querySelector('[data-section-type="header"]');
const headerSticky = headerEl && SPZCore.Dom.computedStyle(this.win, headerEl).position === 'sticky';
const header = document.querySelector('.header__fixed') || document.querySelector('.header__wrapper');
const headerFixed = header && SPZCore.Dom.computedStyle(this.win, header).position === 'fixed';
const handleScroll = SPZCore.Types.throttle(this.win, () => {
if (isHyde) {
if (header && headerSticky) {
header.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`;
} else {
notFixedBannerTopContainer.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`;
}
}
if (isEva) {
const evaHeader = document.querySelector('header.header');
const isEvaMaskHeader = evaHeader && SPZCore.Dom.computedStyle(this.win, evaHeader).position === 'absolute';
if (!isEvaMaskHeader) return;
if (evaHeader.classList.contains('header__fixed')) {
evaHeader.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`;
} else {
notFixedBannerTopContainer.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`;
}
if(document.documentElement.scrollTop === 0) {
evaHeader.style.marginTop = '0';
}
}
if (headerSticky) return;
if (headerFixed) {
header.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`;
} else {
const observer = new MutationObserver((mutationsList, observer) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList' && fixedBannerTopContainer.childElementCount > 0) {
notFixedBannerTopContainer.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`;
observer.disconnect(); // ๅๆญข่งๅฏ
break;
}
}
});
// ๅผๅง่งๅฏ fixedBannerTopContainer ็ๅญ่็นๅๅ
observer.observe(fixedBannerTopContainer, { childList: true, subtree: true });
// ๅๅงๆฃๆฅ
if (fixedBannerTopContainer.childElementCount > 0) {
notFixedBannerTopContainer.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`;
}
if(header) {
header.style.marginTop = '0';
}
}
if (isBoost) {
fixedBannerTopContainer.style.zIndex = '1031';
if (boostHeader && boostHeader.classList.contains('header__fixed')) {
boostHeader.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`;
} else {
notFixedBannerTopContainer.style.marginTop = `${fixedBannerTopContainer.offsetHeight}px`;
}
}
}, 16);
window.addEventListener('scroll', handleScroll);
window.dispatchEvent(new Event('scroll'));
} catch (error) {
console.error('error', error);
}
}
// ไธๆฅๆฐๆฎ
async reportData(data) {
// ๅฆๆๆฏไธป้ข็ผ่พๅจๅไธ็จๅค็
if(window.top !== window.self) {
return;
}
this.xhr_.fetchJson(API.REPORT, {
method: "POST",
body: {
placement_id: data.placement_id,
event: data.event
}
});
}
// ็ๅฌ่ดญ็ฉ่ฝฆๅๅไบไปถdj.cartChange
listenCartChange_() {
SPZUtils.Event.listen(document, 'dj.cartChange', (event) => {
this.fetchData_('cartChange');
});
}
setupAction_() {
this.registerAction('handleClose', (invocation) => {
const data = invocation.args;
const id = data.id;
const announcement = document.querySelector(`#announcement-${id}`);
announcement && SPZCore.Dom.removeElement(announcement);
window.dispatchEvent(new Event('scroll'));
});
this.registerAction('handleJumpLink', (invocation) => {
const data = invocation.args;
if(!data.show_url) return;
data.url && window.open(data.url, data.open_new_window ? '_blank' : '_self');
this.reportData({
placement_id: data.id,
event: REPORT_EVENT.CLICK
});
});
}
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, SpzCustomAnnouncement);
${function() {
return data.originData.list.map((item) => {
const background = item.config.background;
const interactive = item.config.interactive;
const textArr = item.config.text_discount.replace_texts;
const textColor = item.config.text_discount.color;
const backgroundSize = background.presentation_rule === 'fill' ? 'cover' : 'contain';
const pcImage = (background.url && background.upload) ? background.url : '';
const mobileImage = (background.mobile_url && background.upload) ? background.mobile_url : '';
const color1 = background.color;
const color2 = background.color2 || background.color;
const backgroundStyle = `background: url(//img.fantaskycdn.com/${pcImage}) center / ${backgroundSize} no-repeat, linear-gradient(to right, ${color1}, ${color2});`;
const backgroundMobileStyle = `background: url(//img.fantaskycdn.com/${mobileImage}) center / ${backgroundSize} no-repeat, linear-gradient(to right, ${color1}, ${color2});`;
return `
${textArr.map((text) => {
return `
${text}
`
}).join(',')}
${textArr.map((text) => {
return `
${text}
`
}).join(',')}
`
})
}()}