${function() {
const variantData = data.variant || {"id":"768a39eb-b8a2-4fa4-8acb-1843487607f9","product_id":"6ead13be-c6e3-4de6-afb3-06edcf5f5ea5","title":"\ud83d\udd25Blue-2 Piece rag-Unnecessary","weight_unit":"kg","inventory_quantity":875,"sku":"P-\u5927\u5e73\u677f\u62d6\u628a-\u84dd\u8272-2\u5757\u62b9\u5e03-1","barcode":"","position":1,"option1":"\ud83d\udd25Blue","option2":"2 Piece rag","option3":"Unnecessary","note":"","image":{"src":"\/\/img.staticdj.com\/6898d6213f3a83211716aa51c23daff4.jpeg","path":"6898d6213f3a83211716aa51c23daff4.jpeg","width":800,"height":800,"alt":"","aspect_ratio":1},"wholesale_price":[{"price":36.89,"min_quantity":1}],"weight":"0","compare_at_price":"70.81","price":"36.89","retail_price":"70.81","available":true,"url":"\/products\/grosser-flachmopp-im-neuen-stil-2-3?variant=768a39eb-b8a2-4fa4-8acb-1843487607f9","available_quantity":999999999,"options":[{"name":"\ud83d\udd25To give you a clean and tidy home","value":"\ud83d\udd25Blue"},{"name":"Style","value":"2 Piece rag"},{"name":"Supplement (mop bucket):","value":"Unnecessary"}],"off_ratio":48,"flashsale_info":[],"sales":1};
const saveType = "percentage";
const saveText = "Save {{saved_amount}}";
const productLabelDiscountOn = true;
return `
-
${saveText.replace('\{\{saved_amount\}\}',
saveType == 'percentage'
? variantData.off_ratio + '%'
: ` `
)}
`;
}()}
🔥To Give You A Clean And Tidy Home
: 🔥Blue
${function(){
const optName = "🔥To give you a clean and tidy home";
const optionValue = data.originData.selectData ? data.originData.selectData[optName].value : data.originData.value;
const optionValueText = optionValue ? (': ' + optionValue) : '';
return `
${optionValueText}
`
}()}
${function(){
const tipText = "Please select a {{ name }}".replace(/\{\{\s+name\s+\}\}/g, data);
return `${tipText}
`
}()}
Style
: 2 Piece rag
${function(){
const optName = "Style";
const optionValue = data.originData.selectData ? data.originData.selectData[optName].value : data.originData.value;
const optionValueText = optionValue ? (': ' + optionValue) : '';
return `
${optionValueText}
`
}()}
${function(){
const tipText = "Please select a {{ name }}".replace(/\{\{\s+name\s+\}\}/g, data);
return `${tipText}
`
}()}
Supplement (Mop Bucket):
: Unnecessary
${function(){
const optName = "Supplement (mop bucket):";
const optionValue = data.originData.selectData ? data.originData.selectData[optName].value : data.originData.value;
const optionValueText = optionValue ? (': ' + optionValue) : '';
return `
${optionValueText}
`
}()}
${function(){
const tipText = "Please select a {{ name }}".replace(/\{\{\s+name\s+\}\}/g, data);
return `${tipText}
`
}()}
The current produc does not participate any Rebate. Switch the participating product to check the design.
(This prompt will not be displayed on the client-side.)
${function() {
const show = rebate.format_rules.length > data.maxShowCount;
return `
${rule}
${function() {
if(!show) return "";
return `
`;
}()}
`;
}()}
${originData.rebate.format_rules.join(", ")}
if(window.self === window.top) {
(window.disabled_exts ||=[]).push('product_detail_rebate');
}
class SpzRebateComponent extends SPZ.BaseElement {
constructor(element) {
super(element);
}
xhr_ = SPZServices.xhrFor(this.win);
viewport_ = this.getViewport();
action_ = null;
lang = document.documentElement.lang || 'en-US';
landPage = "\/promotions\/rebate\/";
pageType = 1;
cart = [];
initData = null;
rebateInfo = null;
renderData = null;
footerImage = `${this.win.SHOPLAZZA["image_domain"]}oss/operation/e8ebb03dbb710457ca3b4b6a70898ab2.svg`;
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
buildCallback() {
this.initData = this.getProduct();
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.registerAction("triggerGetRenderData", () => {
const event = SPZUtils.Event.create(this.win, "triggerGetRenderData", this.renderData);
this.action_.trigger(this.element, "getRenderData", event);
});
this.registerAction("bindPropagation", () => {
document.querySelector(".product_detail_rebate_list").addEventListener("click", e => {
e.stopPropagation();
this.win.sa &&
this.win.sa.track("plugin_rebate_promotion_click", {
plugin_timestamp: Date.now(),
plugin_location: "info",
product_id: this.initData.product.id,
discount_id: this.rebateInfo.discount_list.map((item) => item.discount_id)[0],
});
});
});
}
async mountCallback() {
document.addEventListener("dj.variantChange", e => {
const data = e.detail;
if (document.querySelector("#product-select-modal.show")) return;
if (this.initData && this.initData.product && data.product && this.initData.product.id === data.product.id) {
this.initData = data;
this.initRebate(this.initData, true);
} else {
this.initData = data;
this.getRebateInfo();
}
});
document.addEventListener("dj.addToCart", e => {
const v = e.detail;
this.rebateInfo &&
this.win.sa &&
this.win.sa.track("plugin_rebate_atc", {
variant_discount_id: this.getVariantDiscountId(v.variant_id).map(item => item.discount_id),
discount_ids: this.rebateInfo.discount_list.map(item => item.discount_id),
variant_id: v.variant_id,
product_id: v.product_id,
price: v.item_price,
number: v.number,
});
});
await this.getRebateInfo();
if (document.querySelector(".plugin-container__bottom-fixed")) {
this.showDiscountPopupsInfoBar();
} else {
this.win.addEventListener("extloaded", () => {
this.showDiscountPopupsInfoBar();
});
}
}
getProduct = (() => {
document.addEventListener("dj.variantChange", e => {
if (!e.detail || !e.detail.product) return;
const productJson = document.querySelector("#product-json");
if (productJson && productJson.textContent && JSON.parse(productJson.textContent)) {
productJson.textContent = JSON.stringify(e.detail);
}
if (this.win.jQuery && this.win.jQuery.fn && this.win.jQuery(document).data("djproduct")) {
this.win.jQuery(document).data("djproduct", e.detail);
}
});
return () => {
let productData = null;
if (this.win.jQuery && this.win.jQuery.fn) {
try {
let product = this.win.jQuery(document).data("djproduct");
if (product) {
productData = JSON.parse(JSON.stringify(product));
} else {
productData = null;
}
} catch (error) {
productData = null;
}
}
if (!productData) {
const productJson = document.querySelector("#product-json");
productData = (productJson && productJson.textContent && JSON.parse(productJson.textContent)) || null;
}
return productData;
};
})();
initRebate = this.win.SPZCore.Types.debounce(
this.win,
(async (data, variantChange) => {
let discount_list = Object.assign([], this.rebateInfo.discount_list);
/* 按子商品的多少对优惠信息进行排序 */
discount_list &&
discount_list.sort((a, b) => {
return b.variant_ids.length - a.variant_ids.length;
});
/* 选中子商品时 筛选子商品的优惠信息 */
if (data.selected && data.selected.id) {
discount_list = this.getVariantDiscountId(data.selected.id);
}
/* 无满减信息 */
if (!(discount_list && discount_list.length)) {
return;
}
const isSection = !!document.querySelector(
`div[data-section-type^="shoplazza://apps/publicapp/blocks/rebate"] #rebate_custom_component`
);
if (
(this.rebateInfo.rebate_type == "sku" && data && data.selected && data.selected.id) ||
this.rebateInfo.rebate_type == "spu"
) {
let nowLandpage = this.landPage;
if (discount_list[0]) {
nowLandpage = this.landPage + discount_list[0].discount_id || "";
}
const info = {
rebate: discount_list[0],
maxShowCount: this.win.innerWidth > 768 ? 3 : 1,
landPage: nowLandpage,
modalFooterImg: `url(${`${this.win.SHOPLAZZA["image_domain"]}oss/operation/e8ebb03dbb710457ca3b4b6a70898ab2.svg`})`,
};
this.renderData = info;
if(isSection) {
SPZ.whenApiDefined(
document.getElementById("app_rebate_section")
).then(apis => {
apis.render(info, true);
});
} else {
// 重新渲染 抖动问题处理
this.templates_ = SPZServices.templatesForDoc();
const newTplDom = await this.templates_.renderTemplate(document.querySelector('#appRebateBlockTpl'), info)
const parentDiv = document.querySelector('#app_rebate_block');
const oldDom = parentDiv.querySelector('.app_rebate_list');
if(oldDom){
parentDiv.replaceChild(newTplDom, oldDom);
} else {
parentDiv.appendChild(newTplDom);
}
}
}
this.insertSlideTag(this.rebateInfo.tag, variantChange);
var pluginCurrencyEvent = new CustomEvent("plugin_currency_update");
document.dispatchEvent(pluginCurrencyEvent);
}).bind(this),
10
);
getRebateInfo = async () => {
if (this.initData && this.initData.product && this.initData.product.id) {
var variant_ids = this.initData.product.variants.map(variant => variant.id);
const res = await this.xhr_.fetchJson(
"\/api\/discount-rebate\/product-discount",
{
method: "POST",
body: {
product_id: this.initData.product.id,
product_type: this.initData.product.product_type,
variant_ids: variant_ids,
},
}
);
if (!SPZCore.Types.isEmptyObject(res.rebate_info)) {
res.rebate_info.tag = res.tag;
res.rebate_info.rebate_type = res.rebate_type;
this.rebateInfo = res.rebate_info;
this.initRebate(this.initData);
} else {
if (this.win.top !== this.win.self) {
const noActivity = document.getElementById("no-rebate-activity");
noActivity && (noActivity["style"].display = "block");
}
}
}
};
getVariantDiscountId = (variant_id) => {
if (!variant_id || !this.rebateInfo) return [];
var rebateId = this.rebateInfo.variant_discount_map[variant_id];
return this.rebateInfo.discount_list.filter(item => item.discount_id == rebateId) || [];
};
insertSlideTag = (tag, variantChange) => {
setTimeout(() => {
if (tag) {
var tag_container;
var modal = document.getElementById("product-select-modal");
if (modal && modal.classList.contains("show")) {
if (!variantChange && modal.querySelector(".slider-discount-tag")) return;
if (
variantChange &&
modal.querySelector(".slider-discount-tag:not(.rebate-tag)")
)
return;
tag_container = modal;
} else {
var product_detail_card = document.querySelector(
'.page_container > [data-section-type="product_detail"], .page_container > [data-section-type="product-template"]'
);
if(!product_detail_card) return;
if (!variantChange && product_detail_card.querySelector(".slider-discount-tag")) return;
if (variantChange && product_detail_card.querySelector(".slider-discount-tag:not(.rebate-tag)"))
return;
tag_container = product_detail_card;
}
if (tag_container.matches("#product-select-modal") && this.pageType === 13 && document.documentElement.clientWidth < 768)
return;
const tagDom = `<div class="slider-discount-tag dj_skin_product_title rebate-tag">${tag}</div>`
if (document.querySelector(".sep-loaded-slider")) {
var loadedSlider = tag_container.querySelector(".sep-loaded-slider");
loadedSlider.querySelectorAll(".slider-discount-tag").forEach(function(element) {
element.remove();
});
loadedSlider.insertAdjacentHTML("beforeend", tagDom);
} else {
if (tag_container.querySelector(".support-slick")) {
var supportSlick = tag_container.querySelectorAll(".support-slick, .sep-slider");
supportSlick.forEach((element) => {
element.querySelectorAll(".slider-discount-tag").forEach((element) => {
element.remove();
});
element.insertAdjacentHTML("beforeend",tagDom);
});
} else {
var sepSlider = tag_container.querySelector(".sep-slider");
sepSlider.querySelectorAll(".slider-discount-tag").forEach(function(element) {
element.remove();
});
sepSlider.insertAdjacentHTML("beforeend",tagDom);
}
}
if (document.documentElement.clientWidth < 768) {
const sliderDiscountTagHeight = tag_container.querySelector(".slider-discount-tag").offsetHeight || 0;
document.querySelector(".product-image__swiper_bullets").style.bottom = `${sliderDiscountTagHeight + 15}px`;
}
}
}, 1000);
};
fetchInfoBar = () => {
let discount_ids = [];
if (this.pageType === 1) {
discount_ids = this.rebateInfo && this.rebateInfo.discount_list.map(item => item.discount_id);
} else if (this.pageType === 38) {
discount_ids = [this.win.rebateObj.rebateCollection_id] || [];
}
const productObj = this.getProduct();
return this.xhr_.fetchJson("\/api\/discount-rebate\/global-text", {
method: "POST",
body: {
product_type: productObj && productObj.product && productObj.product.product_type,
line_items: (this.cart.line_items || []).map(item => ({
variant_id: item.variant_id,
product_id: item.product_id,
quantity: item.quantity,
price: item.price,
selected: !item.unchecked,
})),
discount_ids: discount_ids,
},
});
};
renderBottomBanner = res => {
if (!res.tips) return;
if (document.querySelector(".discount__info-bar")) return;
var bar_style = `background:linear-gradient(90deg,${res.config.background_color_start},${res.config.background_color_end}); color:${res.config.color};`;
let data = { tips: res.tips, landPage: this.landPage + res.id, bar_style };
const html = SPZCore.Dom.htmlFor(this.element);
const banner = html([
`<a impr="1" imprevt="1" id="rebate_bottom_bar" href=${data.landPage} class="discount__info-bar text-truncate" data-activity-type="rebate" style="${data.bar_style}">${data.tips}</a>`,
]);
document.querySelector(".plugin-container__bottom-fixed").appendChild(banner);
const pluginCurrencyEvent = new CustomEvent("plugin_currency_update");
document.dispatchEvent(pluginCurrencyEvent);
if (res.id) {
var trackParams = {
page: this.pageType,
discount_id: res.id,
product_id: this.getProduct()?.product.id,
};
banner.addEventListener("click", () => {
this.win.sa &&
this.win.sa.track("plugin_rebate_promotion_click", {
plugin_timestamp: Date.now(),
plugin_location: "bottom_bar",
product_id: trackParams.product_id,
discount_id: trackParams.discount_id,
});
});
this.win.sa && this.win.sa.track("plugin_rebate_banner_pv", trackParams);
}
};
showDiscountPopupsInfoBar = () => {
if ([13, 14, 19, 30, 31].includes(this.pageType)) return;
if (document.querySelector(".plugin-container__bottom-fixed .discount__info-bar")) return;
this.fetchInfoBar().then(this.renderBottomBanner);
document.addEventListener("dj.cartChange", () => {
this.fetchInfoBar().then(this.renderBottomBanner);
});
};
}
SPZ.defineElement("spz-custom-rebate", SpzRebateComponent);
people are viewing this right now
Add to cart
$36.89
${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":"768a39eb-b8a2-4fa4-8acb-1843487607f9","product_id":"6ead13be-c6e3-4de6-afb3-06edcf5f5ea5","title":"\ud83d\udd25Blue-2 Piece rag-Unnecessary","weight_unit":"kg","inventory_quantity":875,"sku":"P-\u5927\u5e73\u677f\u62d6\u628a-\u84dd\u8272-2\u5757\u62b9\u5e03-1","barcode":"","position":1,"option1":"\ud83d\udd25Blue","option2":"2 Piece rag","option3":"Unnecessary","note":"","image":{"src":"\/\/img.staticdj.com\/6898d6213f3a83211716aa51c23daff4.jpeg","path":"6898d6213f3a83211716aa51c23daff4.jpeg","width":800,"height":800,"alt":"","aspect_ratio":1},"wholesale_price":[{"price":36.89,"min_quantity":1}],"weight":"0","compare_at_price":"70.81","price":"36.89","retail_price":"70.81","available":true,"url":"\/products\/grosser-flachmopp-im-neuen-stil-2-3?variant=768a39eb-b8a2-4fa4-8acb-1843487607f9","available_quantity":999999999,"options":[{"name":"\ud83d\udd25To give you a clean and tidy home","value":"\ud83d\udd25Blue"},{"name":"Style","value":"2 Piece rag"},{"name":"Supplement (mop bucket):","value":"Unnecessary"}],"off_ratio":48,"flashsale_info":[],"sales":1};
const variantData = currentSelectVariant || defaultVariant || productVariant;
const wholesale_price = variantData.wholesale_price || [];
if(wholesale_enabled && wholesale_price.length > 0) {
let wholesaleIndex = wholesale_price.findIndex(item => {
return item.min_quantity > qty;
});
if(wholesaleIndex < 0){
wholesaleIndex = wholesale_price.length - 1;
}else if(wholesaleIndex > 0){
wholesaleIndex = wholesaleIndex - 1;
}
const wholesalePrice = wholesale_price[wholesaleIndex] || '';
return `
`
}else {
const price = variantData && variantData.price;
return price != undefined ? `
` : ' ';
}
}()}
Buy now
Product was out of stock.
Product is unavailable.
${function() {
const postageFreeAmount = 69.99;
const custom_text = "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";
if (diffPrice > 0) {
tipText = custom_text.replace('{amount}', `
`);
}
return `
`;
}()}
/** @private {string} */
class SpzCustomAnchorScroll extends SPZ.BaseElement {
static deferredMount() {
return false;
}
constructor(element) {
super(element);
/** @private {Element} */
this.scrollableContainer_ = null;
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
buildCallback() {
this.viewport_ = this.getViewport();
this.initActions_();
}
setTarget(containerId, targetId) {
this.containerId = '#' + containerId;
this.targetId = '#' + targetId;
}
scrollToTarget() {
const container = document.querySelector(this.containerId);
const target = container.querySelector(this.targetId);
const {scrollTop} = container;
const eleOffsetTop = this.getOffsetTop_(target, container);
this.viewport_
.interpolateScrollIntoView_(
container,
scrollTop,
scrollTop + eleOffsetTop
);
}
initActions_() {
this.registerAction(
'scrollToTarget',
(invocation) => this.scrollToTarget(invocation?.caller)
);
this.registerAction(
'setTarget',
(invocation) => this.setTarget(invocation?.args?.containerId, invocation?.args?.targetId)
);
}
/**
* @param {Element} element
* @param {Element} container
* @return {number}
* @private
*/
getOffsetTop_(element, container) {
if (!element./*OK*/ getClientRects().length) {
return 0;
}
const rect = element./*OK*/ getBoundingClientRect();
if (rect.width || rect.height) {
return rect.top - container./*OK*/ getBoundingClientRect().top;
}
return rect.top;
}
}
SPZ.defineElement('spz-custom-anchor-scroll', SpzCustomAnchorScroll);
const STRENGTHEN_TRUST_URL = "/api/strengthen_trust/settings";
class SpzCustomStrengthenTrust extends SPZ.BaseElement {
constructor(element) {
super(element);
this.renderElement_ = null;
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
buildCallback() {
this.xhr_ = SPZServices.xhrFor(this.win);
const renderId = this.element.getAttribute('render-id');
SPZCore.Dom.waitForChild(
document.body,
() => !!document.getElementById(renderId),
() => {
this.renderElement_ = SPZCore.Dom.scopedQuerySelector(
document.body,
`#${renderId}`
);
if (this.renderElement_) {
this.render_();
}
this.registerAction('track', (invocation) => {
this.track_(invocation.args);
});
}
);
}
render_() {
this.fetchData_().then((data) => {
if (!data) {
return;
}
SPZ.whenApiDefined(this.renderElement_).then((apis) => {
apis?.render(data);
document.querySelector('#strengthen-trust-render-1539149753700').addEventListener('click',(event)=>{
if(event.target.nodeName == 'A'){
this.track_({type: 'trust_content_click'});
}
})
});
});
}
track_(data = {}) {
const track = window.sa && window.sa.track;
if (!track) {
return;
}
track('trust_enhancement_event', data);
}
parseJSON_(string) {
let result = {};
try {
result = JSON.parse(string);
} catch (e) {}
return result;
}
fetchData_() {
return this.xhr_
.fetchJson(STRENGTHEN_TRUST_URL)
.then((responseData) => {
if (!responseData || !responseData.data) {
return null;
}
const data = responseData.data;
const moduleSettings = (data.module_settings || []).reduce((result, moduleSetting) => {
return result.concat(Object.assign(moduleSetting, {
logos: (moduleSetting.logos || []).map((item) => {
return moduleSetting.logos_type == 'custom' ? this.parseJSON_(item) : item;
})
}));
}, []);
return Object.assign(data, {
module_settings: moduleSettings,
isEditor: window.self !== window.top,
});
});
}
}
SPZ.defineElement('spz-custom-strengthen-trust', SpzCustomStrengthenTrust);
${data.module_title}
To display this card to customers, you need to go to "Booster & Store Conversion" to turn on the trust enhancement feature.
${item.content.replaceAll("{store_name}","Gzpai")}
To display this card to customers, you need to go to "Booster & Store Conversion" to turn on the trust enhancement feature.
const getPluginI18nMessages = (message, replaceObj = {}) => {
const lang = document.documentElement.lang || "en-US";
const [form, key] = message.split('.')
let text = window.payment_plugin_message['en-US'][form][key];
if (window.payment_plugin_message[lang][form].hasOwnProperty(key)) {
text = window.payment_plugin_message[lang][form][key];
}
Object.keys(replaceObj).forEach(key => {
text = text.replace(new RegExp(`\{${key}\}`, 'gi'), replaceObj[key]);
})
return text;
}
const zhCN = {
ec: {
not_active_channel: "请到收款设置中{channelName}或在「快捷支付按钮」设置中选择其他的服务提供方,否则按钮将无法展示",
not_support_theme: "当前主题不支持添加「快捷支付按钮」",
more_button: "更多支付方式",
skeleton_layer_tips_title: "快捷支付按钮",
skeleton_layer_tips_content: "请点击左侧列表中的「快捷支付按钮」,在设置页面开启想要的展示的支付按钮",
mock_tips: "快捷支付按钮是否展示还取决于买家使用的浏览器以及商品的货币、金额",
not_find_form_tips: "快捷支付按钮组件仅支持配置到商品详情卡片内",
}
};
const zhTW = {
ec: {
not_active_channel: "请到收款设置中{channelName}或在「快捷支付按钮」设置中选择其他的服务提供方,否则按钮将无法展示",
not_support_theme: "当前主题不支持添加「快捷支付按钮」",
more_button: "更多付款方式",
}
};
const arSA = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "المزيد من خيارات الدفع",
}
};
const deDE = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "Weitere Bezahlmöglichkeiten",
}
};
const esES = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "Más opciones de pago",
}
};
const frFR = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "Plus d'options de paiement",
}
};
const idID = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "Opsi pembayaran lainnya",
}
};
const itIT = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "Altre opzioni di pagamento",
}
};
const jaJP = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "その他の支払いオプション",
}
};
const koKR = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "더 많은 결제 옵션",
}
};
const enUS = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "More payment options",
skeleton_layer_tips_title: "Express Checkout Button",
skeleton_layer_tips_content: "Please click the「Express checkout button」on the block list,then you could enable the payment option you want to display in settings.",
mock_tips: "Whether the Express checkout button is displayed also depends on the browser used by the buyer and the currency and amount of the product.",
not_find_form_tips: "Express Checkout Button could only be added to Product details block.",
}
};
const nlNL = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "Meer betalingsmogelijkheden",
}
};
const plPL = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "Więcej Opcji Płatności",
}
};
const ptPT = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "Mais opções de pagamento",
}
};
const ruRU = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "Другие варианты оплаты",
}
};
const thTH = {
ec: {
not_active_channel: "Please activate {channelName} on B Admin or select another provider in the「Express checkout button」 settings, otherwise it will not display.",
not_support_theme: "This Theme doesn't support adding「Express checkout button」",
more_button: "ตัวเลือกการชำระเงินเพิ่มเติม",
}
};
window.payment_plugin_message = {
getPluginI18nMessages,
"zh-CN": zhCN,
"zh-TW": zhTW,
"ar-SA": arSA,
"de-DE": deDE,
"es-ES": esES,
"fr-FR": frFR,
"id-ID": idID,
"it-IT": itIT,
"ja-JP": jaJP,
"ko-KR": koKR,
"en-US": enUS,
"nl-NL": nlNL,
"pl-PL": plPL,
"pt-PT": ptPT,
"ru-RU": ruRU,
"th-TH": thTH,
}
document.dispatchEvent(new CustomEvent('payment_plugin_message_reader'));
try {
const dom = document.getElementById('pm-payment-express-button-1539149753700-12');
dom.i18n = window?.payment_plugin_message?.getPluginI18nMessages;
if (dom.i18n) {
document.dispatchEvent(new CustomEvent('payment_ec_core_ready', {
detail: {
i18n: true
}
}))
} else {
document.addEventListener('payment_plugin_message_reader', () => {
dom.i18n = window?.payment_plugin_message?.getPluginI18nMessages;
document.dispatchEvent(new CustomEvent('payment_ec_core_ready', {
detail: {
i18n: true
}
}))
}, {once: true});
}
} catch (e) {
}
// 通用工具方法
try {
const dom = document.getElementById('pm-payment-express-button-1539149753700-12')
const ROOT_URL = (C_SETTINGS && C_SETTINGS.routes && C_SETTINGS.routes.root) || '';
const eventListeners = {};
const commonUtils = function () {
return {
getProduct() {
const productJson = document.querySelector('#product-json');
if (productJson?.textContent) {
return JSON.parse(productJson.textContent);
}
if (window.jQuery) {
const $product = window.jQuery?.(document)?.data('djproduct');
const productData = JSON.parse(JSON.stringify($product || {}));
return productData || {};
}
return {};
},
isChrome() {
return navigator?.userAgent?.indexOf('Chrome') > -1 || navigator?.userAgent?.indexOf('CriOS') > -1;
},
isSafari() {
let userAgentString = navigator.userAgent;
let chromeAgent = userAgentString.indexOf('Chrome') > -1 || navigator?.userAgent?.indexOf('CriOS') > -1;
let safariAgent = userAgentString.indexOf('Safari') > -1;
if (chromeAgent && safariAgent) {
safariAgent = false;
}
return safariAgent;
},
isPreview() {
return !!window?.C_EDITING_SETTINGS?.oseid;
},
multiply(a, b) {
const precision = 2; // 保留两位小数
return Number((a * b).toFixed(precision));
},
loadScript(fnReady, id, src, datasets, onError, attributeConfig = {}) {
const sdkDomId = id + '-sdk';
if (fnReady() || document.getElementById(sdkDomId)) {
return Promise.resolve({id: true});
}
return new Promise((resolve) => {
const s = document.createElement('script');
s.id = sdkDomId;
s.src = src;
s.defer = true;
if (datasets) {
Object.keys(datasets).map((item) => {
s.dataset[item] = datasets[item];
});
}
s.onload = function () {
window.dispatchEvent(new CustomEvent(`${id}-loaded`));
resolve({id: true});
};
s.onerror = function () {
resolve({id: false});
onError && onError();
};
Object.keys(attributeConfig).forEach((key) => {
s.setAttribute(key, attributeConfig[key]);
});
document.head.appendChild(s);
});
},
track(eventName, data) {
window.sa && window?.sa?.track('pm_' + eventName, JSON.parse(JSON.stringify(data)));
},
getExtUrl(name) {
const url = document.cookie.match(new RegExp('\\b' + name.replace(/_/g, '-') + '-(v[s0-9]+)'));
if (url && url[1]) {
return `${name}.${url[1]}.js`;
} else {
return window?.exts?.[name];
}
},
req: {
post: async (url, data = {}) => {
try {
const response = await fetch(req.ROOT_URL + url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
...data,
body: JSON.stringify(data.body),
});
return await response.json()
} catch (error) {
throw new Error('post request error' + error);
}
},
get: async (url, data = {}) => {
try {
const response = await fetch(ROOT_URL + url);
return await response.json()
} catch (error) {
throw new Error('get request error' + error);
}
}
},
debounce(fn, wait) {
let timeout = null;
return function () {
if (timeout !== null) {
clearTimeout(timeout);
}
timeout = setTimeout(function () {
fn.apply(this, arguments);
}, wait);
}
},
delayCallback(cb) {
window.requestIdleCallback ? requestIdleCallback(cb, {timeout: 50}) : setTimeout(cb, 50);
},
loadFilly(tag, cb) {
if (!tag) {
return
}
const script = document.createElement('script');
script.type = 'text/javaScript';
script.src = `//static.staticdj.com/${tag}`;
script.onload = cb;
document.getElementsByTagName('head')[0].appendChild(script);
},
ecEvent: {
on: (eventName, listener, useCapture) => {
eventListeners[eventName] = listener;
window.addEventListener(eventName, listener, useCapture);
},
emit: (eventName, data) => window.dispatchEvent(new CustomEvent(eventName, {detail: data})),
}
}
}
dom.commonUtilsFn = commonUtils;
document.dispatchEvent(new CustomEvent('payment_ec_core_ready', {
detail: {
commonUtils: true
}
}))
} catch (e) {
}
// 核心数据
try {
const dom = document.getElementById('pm-payment-express-button-1539149753700-12');
const coreData = function () {
const {getProduct} = dom.commonUtils;
let productDetail = getProduct();
let productPrice = productDetail?.selected?.price
|| 36.89;
const shopCurrencyCode = "USD";
const expressCheckoutList = {
sdkErrorList: [],
paymentChannelList: [],
disabledChannelList: [],
showChannelList: [],
blockChannelList: [],
extraChannelList: [],
};
const channelType = {
googlepay: ['shoplazzagoogle'],
applepay: ['shoplazzaapple'],
credit: ['paypal']
};
const ecGlobalVarEnums = {
paypal: 'pluginPaypalEC'
};
const providerEnums = {
SHOPLAZZA: 'shoplazza',
STRIPE: 'stripe',
PAYPAL: 'paypal'
};
const channelEnums = {
SHOPLAZZA_GOOGLE: 'shoplazzagoogle',
SHOPLAZZA_APPLE: 'shoplazzaapple',
STRIPE_GOOGLE: 'stripegoogle',
STRIPE_APPLE: 'stripeapple',
PAYPAL: 'paypal'
};
const channelThemeConfig = {
[channelEnums.PAYPAL]: {
default: {
url: 'oss/operation/f557c83808e1cd456411170286a1ea95.svg',
classList: ['paypal-card'],
},
},
[channelEnums.SHOPLAZZA_GOOGLE]: {
light: {
url: 'oss/operation/778afb93da43adf75bdc80b078e5d4fd.svg',
classList: ['googlepay-light'],
},
dark: {
url: 'oss/operation/e53180c224f0b0af44b44663775aa930.svg',
classList: ['googlepay-dark'],
},
},
[channelEnums.SHOPLAZZA_APPLE]: {
light: {
url: 'oss/operation/dadceb884044e0a9bbfe26c15192f542.svg',
classList: ['applepay-light'],
},
dark: {
url: 'oss/operation/6597f66eac8b0681ebfb75941e8f6f52.svg',
classList: ['applepay-dark'],
},
},
};
function getContainerDomId() {
const domIdObj = {};
Object.keys(providerEnums).forEach(key => {
domIdObj[providerEnums[key]] = FormatterContainerDomId(providerEnums[key])
})
return domIdObj;
}
function FormatterContainerDomId(provider) {
const domIDSuffix = '-express-button-container';
const prefix = 'pm-';
return `${prefix}${provider}${domIDSuffix}-1539149753700-12`
}
return {
ecGlobalVarEnums,
providerEnums,
channelEnums,
productPrice,
shopCurrencyCode,
getChannelThemeConfig(ecName) {
const themeType = window.PaymentEC?.settings?.express_theme_configs?.[ecName]?.theme_type?.toLowerCase() ||
'default';
return channelThemeConfig[ecName][themeType] || channelThemeConfig[ecName]['dark'];
},
getProductPrice() {
return productDetail?.selected?.price;
},
getProductDetail() {
return productDetail;
},
setProductDetail(data) {
productDetail = data;
},
isRequiresShipping() {
return productDetail?.product?.requires_shipping
},
getOpenChannelType() {
const {paymentChannelList, blockChannelList} = expressCheckoutList
const openList = paymentChannelList.filter(item => blockChannelList.includes(item)) || [];
return {
hasApplepay: openList.filter(item => channelType.applepay.includes(item))?.length > 0,
hasGooglepay: openList.filter(item => channelType.googlepay.includes(item))?.length > 0,
hasCredit: openList.filter(item => channelType.credit.includes(item))?.length > 0
}
},
containerDomId: getContainerDomId(),
channel2ProviderEnums: {
[channelEnums.PAYPAL]: providerEnums.PAYPAL,
[channelEnums.SHOPLAZZA_GOOGLE]: providerEnums.SHOPLAZZA,
[channelEnums.SHOPLAZZA_APPLE]: providerEnums.SHOPLAZZA,
[channelEnums.STRIPE_GOOGLE]: providerEnums.STRIPE,
[channelEnums.STRIPE_APPLE]: providerEnums.STRIPE,
},
getExpressCheckoutList() {
return expressCheckoutList;
},
setShowChannel(showChannelList = []) {
expressCheckoutList.showChannelList = showChannelList;
return expressCheckoutList;
},
setBlockChannel(blockChannelList = []) {
expressCheckoutList.blockChannelList = blockChannelList;
return expressCheckoutList;
},
setPaymentChannelList(paymentChannelList = []) {
expressCheckoutList.paymentChannelList = paymentChannelList;
return expressCheckoutList;
},
setSdkErrorList(paymentChannelList = []) {
expressCheckoutList.sdkErrorList = paymentChannelList;
return expressCheckoutList;
},
setExtraChannelList(extraChannelList = []) {
expressCheckoutList.extraChannelList = extraChannelList;
return expressCheckoutList;
},
setDisabledChannelList(disabledChannelList = []) {
expressCheckoutList.disabledChannelList = disabledChannelList;
return expressCheckoutList;
}
}
}
dom.coreDataFn = coreData;
document.dispatchEvent(new CustomEvent('payment_ec_core_ready', {
detail: {
coreData: true
}
}))
} catch (e) {
console.log(e);
}
// 通用业务数据处理方法
try {
const dom = document.getElementById('pm-payment-express-button-1539149753700-12')
const businessUtils = function () {
const {track, isChrome, isSafari, req, isPreview, multiply} = dom.commonUtils;
const {getProductPrice, containerDomId, ecGlobalVarEnums} = dom.coreData;
const {
channelEnums,
shopCurrencyCode,
isRequiresShipping,
getProductDetail,
setShowChannel,
setBlockChannel,
setSdkErrorList,
setExtraChannelList,
setDisabledChannelList,
setPaymentChannelList,
getExpressCheckoutList
} = dom.coreData;
const _businessUtils = {
getECConfig: async () => {
if (window.PaymentEC?.settings) {
return window.PaymentEC?.settings;
}
const result = await req.get('/api/payment/settings');
const ecConfig = result?.settings?.express_checkout_config || {};
const {blockChannelList} = getExpressCheckoutList();
setPaymentChannelList(blockChannelList.filter(ecName =>
ecConfig?.express_channels?.includes(ecName)) || []);
window.PaymentEC.settings = {...ecConfig, currencyCode: shopCurrencyCode};
return window.PaymentEC.settings;
},
getAttributeConfig(channelInfo) {
const {ecGlobalVar, ecName} = channelInfo;
const config = {
paypal: {
'data-namespace': ecGlobalVar
}
};
return config[ecName] || {};
},
getThemeFormData() {
let themeFormData = {};
const formDOM = dom.closest("form");
if (formDOM) {
themeFormData = {
note: '',
product_id: '',
variant_id: '',
quantity: 1,
properties: {},
};
const formData = new FormData(formDOM);
const formDataKey = formData.keys();
for (const key of formDataKey) {
const value = formData.get(key);
const propertiesKey = key.match(/^properties(?:\.(\w+)$|\[(\w+)\]$)/);
if (!propertiesKey) {
themeFormData[key] = value;
continue;
}
const objKey = propertiesKey[1] || propertiesKey[2];
themeFormData['properties'] = {...themeFormData['properties'], [objKey]: value};
}
}
return themeFormData;
},
getProductFormData() {
const themeFormData = _businessUtils.getThemeFormData()
return [{
...themeFormData,
note: themeFormData?.note || "",
product_id: themeFormData?.product_id || "",
variant_id: themeFormData?.variant_id || "",
quantity: themeFormData?.quantity || 1,
// 与主题确认,只以一个为准,防止form不存在的数据仍被传递
properties: themeFormData?.properties || {},
}]
},
getOrderFetchParams(data) {
if (!data) {
return {};
}
return {
line_items: data.map((item) => ({
...item,
note: item?.note || "",
quantity: item?.quantity || 1,
product_id: item?.product_id,
variant_id: item?.variant_id,
properties: item?.properties,
})),
refer_info: {
source: 'buy_now',
},
customer_note: '',
};
},
isAllowTheme() {
const allowThemeList = ['Nova 2023', 'Dropshiping', 'Geek', 'Hero', 'Eva'];
const currentTheme = window?.C_SETTINGS?.theme?.merchant_theme_name;
return allowThemeList.includes(currentTheme);
},
getSubscriptionIdInit() {
let defaultID;
const selectSubscriptionEnum = {
CLOSE: 1,
ACTIVE: 2,
}
const productDetail = getProductDetail();
const sellingPlan = "";
if (!sellingPlan || typeof sellingPlan !== "object") {
return null;
}
let sellingItems;
if (sellingPlan?.spu?.[productDetail?.product?.id]) {
sellingItems = sellingPlan.spu[productDetail?.product?.id]
}
if (sellingPlan?.sku?.[productDetail?.selected?.id]) {
sellingItems = sellingPlan.sku[productDetail?.product?.id]
}
if (sellingItems?.cycles === selectSubscriptionEnum.ACTIVE && sellingItems?.selected_selling_plan_option_id) {
defaultID = sellingItems?.selected_selling_plan_option_id
}
return defaultID ?? null
},
getSubscriptionId() {
const formData = _businessUtils.getThemeFormData();
const defaultID = _businessUtils.getSubscriptionIdInit();
console.log(`[paymentEC]订阅信息:form-${formData?.properties?._selling_plan_option_id},默认-${defaultID}`);
if (formData?.properties) {
return formData?.properties?._selling_plan_option_id
}
return defaultID ?? null;
},
isSubscription() {
return !!_businessUtils.getSubscriptionId();
},
isAllowSubscriptionPay(channel) {
if (!_businessUtils.isSubscription()) {
return true;
}
return [channelEnums.PAYPAL].includes(channel);
},
blockChannelHandler() {
const block_googlePay = false &&
"shoplazzagoogle";
const block_applePay = false &&
"shoplazzaapple";
const block_credit = false &&
"paypal";
const blockChannel = {
googlepay: (isPreview() || isChrome()) && block_googlePay,
applepay: (isPreview() || isSafari()) && block_applePay,
credit: block_credit
};
const sortList = ['credit', 'googlepay', 'applepay'];
const methodSort = Object.keys(blockChannel).filter(key => blockChannel[key] && key).sort((a, b) => {
const indexA = sortList.indexOf(a);
const indexB = sortList.indexOf(b);
return indexA - indexB;
}).map(key => blockChannel[key]);
const result = setBlockChannel(methodSort);
track('setBlockChannel', result);
return result;
},
showECButtonHandler() {
const {
paymentChannelList,
sdkErrorList,
disabledChannelList,
extraChannelList,
} = getExpressCheckoutList();
const showChannelList = paymentChannelList.filter((ecName) =>
!sdkErrorList.includes(ecName) && !disabledChannelList.includes(ecName) &&
!extraChannelList.includes(ecName)) || [];
const result = setShowChannel(showChannelList);
track('showECButton', result);
return result;
},
filterECButtonHandler({type}, cb) {
const {
paymentChannelList,
sdkErrorList,
disabledChannelList,
extraChannelList,
} = getExpressCheckoutList();
const showChannelList = paymentChannelList.filter((ecName) =>
!sdkErrorList.includes(ecName) && !disabledChannelList.includes(ecName) &&
!extraChannelList.includes(ecName)) || [];
const result = setShowChannel(showChannelList.filter((ecName) => ecName !== type) || []);
cb && cb();
track('filterECButton', result);
return result;
},
loadSDKErrorHandler(type) {
const {sdkErrorList} = getExpressCheckoutList();
const result = setSdkErrorList([...sdkErrorList, type]);
track('loadSDKError', result);
return result;
},
extraFilterShowHandler(channel) {
const {extraChannelList} = getExpressCheckoutList();
const result = setExtraChannelList(extraChannelList.filter(ecName => ecName !== channel));
track('extraFilterEvent_show', result);
return result;
},
extraFilterHideHandler(channel) {
const {extraChannelList} = getExpressCheckoutList();
const result = setExtraChannelList([...extraChannelList, channel]);
track('extraFilterEvent_hide', result);
return result;
},
disabledChannelListHandler(checkoutData = {}, cb) {
const {paymentChannelList} = getExpressCheckoutList();
const productDetail = getProductDetail();
const disabledChannelList = paymentChannelList.filter(ecName => {
let mustDisable = false;
if (!isRequiresShipping() && ecName !== channelEnums.PAYPAL) {
mustDisable = true;
}
if (!_businessUtils.isAllowSubscriptionPay(ecName)) {
mustDisable = true;
}
if (!productDetail?.selected?.available) {
mustDisable = true;
}
const {payment_due} = checkoutData?.prices;
const paymentDueNum = Number(payment_due || 0) * 100;
const showFlag = paymentDueNum > 0;
return mustDisable || !showFlag;
})
const result = setDisabledChannelList(disabledChannelList)
result?.disabledChannelList?.forEach(ecName => {
cb && cb(ecName);
})
track('disabledChannelListEvent', result);
},
async getCheckoutData() {
const formData = _businessUtils.getProductFormData();
const totalPrice = multiply(getProductPrice(), formData?.[0]?.quantity || 0);
return {
prices: {payment_due: totalPrice, subtotal_price: totalPrice},
orderParams: _businessUtils.getOrderFetchParams(_businessUtils.getProductFormData()),
containerDOMIdEnums: containerDomId,
ecGlobalVarEnums
}
},
}
return _businessUtils
}
dom.businessUtilsFn = businessUtils;
document.dispatchEvent(new CustomEvent('payment_ec_core_ready', {
detail: {
businessUtils: true
}
}))
} catch (e) {
}
// 通用渲染方法
try {
const dom = document.getElementById('pm-payment-express-button-1539149753700-12');
const containerDOM = 'pm-payment-express-button-container-1539149753700-12';
const commonRenderUtils = function () {
return {
addChildrenDOM(id, allowShow, options = {}) {
if (!id) {
return;
}
const paymentEl = document.getElementById(containerDOM);
const childrenEL = document.getElementById(id);
if (paymentEl && childrenEL) {
childrenEL.style.display = allowShow ? 'block' : 'none';
return;
}
if (paymentEl && !childrenEL) {
const dom = document.createElement('div');
dom.id = id;
dom.style.display = allowShow ? 'block' : 'none';
if (options?.style) {
Object.keys(options?.style).forEach(key => {
dom.style[key] = options.style[key];
})
}
if (Array.isArray(options?.classList)) {
dom.classList.add(...options.classList)
}
paymentEl.appendChild(dom);
}
},
removeChildrenDOM(id) {
if (!id) {
return;
}
const paymentEl = document.getElementById(containerDOM);
const childrenEL = document.getElementById(id);
if (paymentEl && childrenEL) {
// childrenEL.remove();
childrenEL.style.display = 'none';
}
},
mockAddChildrenDOM(id, allowShow, options = {}) {
if (!id) {
return;
}
const paymentEl = document.getElementById(containerDOM);
const childrenEL = document.getElementById(id);
if (paymentEl && childrenEL) {
childrenEL.style.display = allowShow ? 'flex' : 'none';
return;
}
if (paymentEl && !childrenEL) {
const dom = document.createElement('div');
dom.id = id;
dom.style.display = allowShow ? 'flex' : 'none';
if (options?.style) {
Object.keys(options?.style).forEach(key => {
dom.style[key] = options.style[key];
})
}
if (Array.isArray(options?.classList)) {
dom.classList.add(...options.classList)
}
dom.classList.add('mock-img');
const img = document.createElement('img');
img.src = `//static.staticdj.com/${options?.url}`;
dom.appendChild(img);
paymentEl.appendChild(dom);
}
},
resetRenderDOM() {
const resetStyleList = [
"pm-payment-express-error-tips-1539149753700-12",
"pm-payment-express-more-button-1539149753700-12",
"pm-payment-express-mock-tips-1539149753700-12",
"pm-payment-express-skeletonLayer-1539149753700-12",
]
const resetHtmlList = [
"pm-payment-express-skeletonLayer-title-content-1539149753700-12",
"pm-payment-express-skeletonLayer-content-1539149753700-12",
"pm-payment-express-mock-tips-1539149753700-12",
"pm-payment-express-error-tips-1539149753700-12",
"pm-payment-express-button-container-1539149753700-12",
"pm-payment-express-more-button-1539149753700-12",
]
resetStyleList.forEach(domID => {
const content = document.getElementById(domID);
if (content) {
content.style.display = 'none';
}
})
resetHtmlList.forEach(domID => {
const content = document.getElementById(domID);
if (content) {
content.innerHTML = '';
}
})
}
}
}
dom.commonRenderUtilsFn = commonRenderUtils;
document.dispatchEvent(new CustomEvent('payment_ec_core_ready', {
detail: {
commonRenderUtils: true
}
}))
} catch (e) {
}
// 错误提示渲染
try {
const dom = document.getElementById('pm-payment-express-button-1539149753700-12');
const renderTipsUtils = function () {
const {i18n} = dom;
const {isPreview} = dom.commonUtils;
const {channelEnums} = dom.coreData;
return {
showChannelNotOpenTips(channelList) {
const tipsDom = document.getElementById('pm-payment-express-error-tips-1539149753700-12');
if (!isPreview()) {
return;
}
if (!tipsDom) {
return;
}
tipsDom.style.display = channelList.length > 0 ? 'block' : 'none';
const channelName = {
[channelEnums.SHOPLAZZA_GOOGLE]: "ShoplazzaPayments - GooglePay",
[channelEnums.SHOPLAZZA_APPLE]: "ShoplazzaPayments - ApplePay",
[channelEnums.PAYPAL]: "PayPal",
}
channelList.forEach(ecName => {
const id = `pm-payment-express-error-tips-1539149753700-12-${ecName}`;
const hasDom = document.getElementById(id)
if (!hasDom) {
const dom = document.createElement('div');
dom.id = id;
dom.innerHTML = i18n('ec.not_active_channel', {channelName: channelName[ecName]});
tipsDom.appendChild(dom);
}
})
},
disabledThemTips() {
const tipsDom = document.getElementById('pm-payment-express-error-tips-1539149753700-12');
if (!isPreview()) {
return;
}
if (!tipsDom) {
return;
}
tipsDom.style.display = 'block';
const id = 'pm-payment-express-error-tips-1539149753700-12-theme';
const hasDom = document.getElementById(id);
if (!hasDom) {
const dom = document.createElement('div');
dom.id = id;
dom.innerHTML = i18n('ec.not_support_theme');
tipsDom.appendChild(dom);
}
},
notFindFormTips() {
const tipsDom = document.getElementById('pm-payment-express-error-tips-1539149753700-12');
if (!isPreview()) {
return;
}
if (!tipsDom) {
return;
}
tipsDom.style.display = 'block';
const id = 'pm-payment-express-error-tips-1539149753700-12-theme';
const hasDom = document.getElementById(id);
if (!hasDom) {
const dom = document.createElement('div');
dom.id = id;
dom.innerHTML = i18n('ec.not_find_form_tips');
tipsDom.appendChild(dom);
}
},
showSkeletonLayerTips() {
const skeletonLayerDOMId = 'pm-payment-express-skeletonLayer-1539149753700-12';
const skeletonLayerDOM = document.getElementById(skeletonLayerDOMId);
const titleDOM = document.getElementById('pm-payment-express-skeletonLayer-title-content-1539149753700-12');
const contentDOM = document.getElementById('pm-payment-express-skeletonLayer-content-1539149753700-12');
if (!skeletonLayerDOM || !titleDOM || !contentDOM) {
return;
}
skeletonLayerDOM.style.display = 'block';
titleDOM.innerHTML = i18n('ec.skeleton_layer_tips_title');
contentDOM.innerHTML = i18n('ec.skeleton_layer_tips_content');
},
showMockTips() {
const tipsDOM = document.getElementById('pm-payment-express-mock-tips-1539149753700-12');
if (!tipsDOM) {
return;
}
tipsDOM.style.display = 'block';
tipsDOM.innerHTML = i18n('ec.mock_tips');
}
}
}
dom.renderTipsUtilsFn = renderTipsUtils;
document.dispatchEvent(new CustomEvent('payment_ec_core_ready', {
detail: {
renderTipsUtils: true
}
}))
} catch (e) {
}
// 更多信息渲染
try {
const dom = document.getElementById('pm-payment-express-button-1539149753700-12');
const moreDOM = document.getElementById('pm-payment-express-more-button-1539149753700-12');
const moreButtonConfig = {
firstClick: true,
maxSize: isNaN(1) ? 1 : 1
};
const renderMoreUtils = function () {
const {i18n} = dom;
const {getExpressCheckoutList} = dom.coreData;
function moreButtonEvent(cb) {
if (!moreDOM) {
return;
}
moreDOM.style.display = 'none';
moreButtonConfig.firstClick = false;
cb && cb();
}
return {
getMoreButtonConfig() {
return moreButtonConfig
},
showMoreButton(cb) {
if (!moreDOM) {
return;
}
const {showChannelList} = getExpressCheckoutList();
const showLength = showChannelList.length;
const {firstClick, maxSize} = moreButtonConfig;
moreDOM.style.display = (firstClick && showLength > 0 && showLength > maxSize) ? 'block' : 'none';
moreDOM.innerHTML = i18n('ec.more_button');
moreDOM.onclick = () => moreButtonEvent(cb);
},
}
}
dom.renderMoreUtilsFn = renderMoreUtils;
document.dispatchEvent(new CustomEvent('payment_ec_core_ready', {
detail: {
renderMoreUtils: true
}
}))
} catch (e) {
}
try {
const dom = document.getElementById('pm-payment-express-button-1539149753700-12');
function start() {
const {
getExtUrl,
loadFilly,
delayCallback,
ecEvent,
track,
loadScript,
debounce
} = dom.commonUtils;
const {
blockChannelHandler,
getAttributeConfig,
showECButtonHandler,
filterECButtonHandler,
loadSDKErrorHandler,
extraFilterShowHandler,
extraFilterHideHandler,
disabledChannelListHandler,
getECConfig,
isAllowTheme,
getCheckoutData,
getThemeFormData
} = dom.businessUtils;
const {addChildrenDOM, removeChildrenDOM} = dom.commonRenderUtils;
const {getMoreButtonConfig, showMoreButton} = dom.renderMoreUtils;
const {
ecGlobalVarEnums,
getExpressCheckoutList,
getProductPrice,
getProductDetail,
setProductDetail,
containerDomId,
channel2ProviderEnums,
getChannelThemeConfig
} = dom.coreData;
function getFilly() {
const fillyTag = getExtUrl('filly');
if (fillyTag) {
loadFilly(fillyTag, init);
}
}
function extraFilterEvent(e) {
const {channel, domId, allowShow} = e?.detail || {};
if (channel && domId) {
if (allowShow) {
extraFilterShowHandler(channel);
} else {
extraFilterHideHandler(channel);
filterECButtonHandler({type: channel},
() => removeChildrenDOM(domId)
);
}
renderEC();
}
}
const renderEC = () => {
showECButtonHandler();
const {showChannelList} = getExpressCheckoutList();
const {firstClick, maxSize} = getMoreButtonConfig();
if (showChannelList.length === 0) {
showMoreButton(renderEC);
}
showChannelList.forEach((ecName, index) => {
const disableShow = firstClick && index >= maxSize;
addChildrenDOM(containerDomId[channel2ProviderEnums[ecName]], !disableShow, getChannelThemeConfig(ecName));
showMoreButton(renderEC);
});
}
const loadErrorEvent = (type) => {
const domID = containerDomId[type];
if (!domID) {
return;
}
loadSDKErrorHandler(type);
filterECButtonHandler({type},
() => removeChildrenDOM(domID)
);
showMoreButton(renderEC);
};
async function loadEC() {
const themeFormData = getThemeFormData?.() || {};
if (!themeFormData?.product_id || !themeFormData?.variant_id) {
console.log('[paymentEC]hide:未找到form表单或必要信息')
return;
}
const ecConfig = await getECConfig();
const expressCheckoutList = getExpressCheckoutList();
track('loadEC', expressCheckoutList);
if (ecConfig) {
const checkoutData = await getCheckoutData();
disabledChannelListHandler(checkoutData, (ecName) => {
filterECButtonHandler({type: ecName},
() => removeChildrenDOM(containerDomId[channel2ProviderEnums[ecName]])
);
});
renderEC();
window.PaymentEC.handleEcPluginsLoad =
({
channelInfos = [],
loadedCbFn = () => {
}
}) => {
const expressCheckoutLoadList = [];
channelInfos.map((channelInfo) => {
const {ecGlobalVar, ecName = '', sdkPath = '', datasets} = channelInfo;
if (!document.getElementById(containerDomId[ecName])) {
return;
}
const attributeConfig = getAttributeConfig(channelInfo) || {};
expressCheckoutLoadList.push(
loadScript(() => window[ecGlobalVar], ecGlobalVar, sdkPath, datasets, () => {
loadErrorEvent(ecName);
}, attributeConfig)
);
});
Promise.all(expressCheckoutLoadList).then(() => {
loadedCbFn(checkoutData);
});
};
// 通知外部数据变更
ecEvent.emit('tc_payment_ec_data_change', {
ecGlobalVarEnums,
containerDOMIdEnums: containerDomId
});
}
}
const loadECDebounce = debounce(loadEC, 300)
async function refreshEC(data = {}, sources) {
if (!sources) {
console.warn('[paymentEC]hide: sources is null');
return;
}
if (data?.detail?.selected?.price) {
setProductDetail(data?.detail)
}
loadECDebounce();
}
function init() {
ecEvent.on('shoplazza_express_channels_change', extraFilterEvent, false);
ecEvent.on('shoplazza_express_channels_change_ready', extraFilterEvent, false);
if (typeof window.PaymentEC === 'object') {
window.PaymentEC.getCheckoutData = getCheckoutData;
} else {
console.warn("[payment]window.PaymentEC is null");
}
document.addEventListener('dj.variantChange', (data) => refreshEC(data, 'variantChange'));
document.addEventListener('payment_ec_refresh', (data) => refreshEC(data, data?.detail?.sources));
refreshEC({}, 'init');
}
if (isAllowTheme()) {
blockChannelHandler();
if (document.readyState === 'complete') {
delayCallback(getFilly);
return;
}
window.addEventListener('load', () => delayCallback(getFilly), {once: true});
}
}
dom.startFn = start;
document.dispatchEvent(new CustomEvent('payment_ec_core_ready', {
detail: {
start: true
}
}))
} catch (e) {
console.log(e);
}
// 预览模式
try {
const dom = document.getElementById('pm-payment-express-button-1539149753700-12');
function start() {
const {track} = dom.commonUtils;
const {showMoreButton, getMoreButtonConfig} = dom.renderMoreUtils;
const {
showECButtonHandler,
getECConfig,
blockChannelHandler,
isAllowTheme,
getThemeFormData
} = dom.businessUtils;
const {
disabledThemTips,
showChannelNotOpenTips,
showSkeletonLayerTips,
showMockTips,
notFindFormTips
} = dom.renderTipsUtils;
const {mockAddChildrenDOM, resetRenderDOM} = dom.commonRenderUtils;
const {
channelEnums,
getChannelThemeConfig,
getExpressCheckoutList,
getOpenChannelType
} = dom.coreData;
const mockDomId = {
[channelEnums.PAYPAL]: channelEnums.PAYPAL,
[channelEnums.SHOPLAZZA_GOOGLE]: channelEnums.SHOPLAZZA_GOOGLE,
[channelEnums.SHOPLAZZA_APPLE]: channelEnums.SHOPLAZZA_APPLE,
[channelEnums.STRIPE_GOOGLE]: channelEnums.STRIPE_GOOGLE,
[channelEnums.STRIPE_APPLE]: channelEnums.STRIPE_APPLE,
}
const renderNotOpenTips = () => {
const {blockChannelList, paymentChannelList} = getExpressCheckoutList();
const notOpenChannel = blockChannelList.filter(ecName => !paymentChannelList.includes(ecName));
showChannelNotOpenTips(notOpenChannel);
}
const renderMockTips = () => {
const {hasApplepay, hasGooglepay} = getOpenChannelType();
if (hasApplepay || hasGooglepay) {
showMockTips();
}
}
const renderEC = () => {
showECButtonHandler();
const {showChannelList} = getExpressCheckoutList();
const {firstClick, maxSize} = getMoreButtonConfig();
if (showChannelList.length === 0) {
showMoreButton(renderEC);
}
showChannelList.forEach((ecName, index) => {
const disableShow = firstClick && index >= maxSize;
mockAddChildrenDOM(mockDomId[ecName], !disableShow, getChannelThemeConfig(ecName));
showMoreButton(renderEC);
});
}
async function loadEC() {
const date = new Date().getTime();
dom.loadEC_timestamp = date
const ecConfig = await getECConfig();
if (date !== dom.loadEC_timestamp) {
return;
}
const expressCheckoutList = getExpressCheckoutList();
track('preview-loadEC', expressCheckoutList);
resetRenderDOM();
// 初始化时没有事件推送
if (ecConfig) {
renderNotOpenTips();
renderEC();
renderMockTips();
}
}
const init = () => {
blockChannelHandler();
const {blockChannelList} = getExpressCheckoutList();
if (!isAllowTheme()) {
disabledThemTips()
return;
}
const themeFormData = getThemeFormData?.() || {};
if (!themeFormData?.product_id || !themeFormData?.variant_id) {
notFindFormTips();
return;
}
if (blockChannelList.length > 0) {
loadEC();
} else {
showSkeletonLayerTips()
}
}
init();
}
dom.mockStartFn = start;
document.dispatchEvent(new CustomEvent('payment_ec_core_ready', {
detail: {
start: true
}
}))
} catch (e) {
}
try {
const dom = document.getElementById('pm-payment-express-button-1539149753700-12');
window.PaymentEC = {}
const delayCallback = (cb) => {
window.requestIdleCallback ? requestIdleCallback(cb, {timeout: 50}) : setTimeout(cb, 50);
}
const checkReady = function (data) {
const {
i18n,
commonUtilsFn,
coreDataFn,
businessUtilsFn,
commonRenderUtilsFn,
renderTipsUtilsFn,
renderMoreUtilsFn,
startFn,
mockStartFn
} = dom
let readyData = {
commonUtils: !!(commonUtilsFn) || false,
coreData: !!(coreDataFn) || false,
businessUtils: !!(businessUtilsFn) || false,
commonRenderUtils: !!(commonRenderUtilsFn) || false,
renderTipsUtils: !!(renderTipsUtilsFn) || false,
renderMoreUtils: !!(renderMoreUtilsFn) || false,
start: !!(startFn) || false,
mockStart: !!(mockStartFn) || false,
i18n: !!(i18n) || false
}
if (data?.detail) {
Object.keys(data.detail).forEach(key => {
readyData[key] = data.detail[key]
})
}
let isReady = true;
Object.keys(readyData).forEach(key => {
if (!readyData[key]) {
isReady = false
}
})
return isReady
}
const readyFn = () => {
if (!checkReady()) {
return;
}
document.removeEventListener('payment_ec_core_ready', readyFn);
dom.commonUtils = dom.commonUtilsFn();
dom.coreData = dom.coreDataFn();
dom.businessUtils = dom.businessUtilsFn();
dom.commonRenderUtils = dom.commonRenderUtilsFn();
dom.renderTipsUtils = dom.renderTipsUtilsFn();
dom.renderMoreUtils = dom.renderMoreUtilsFn();
const productData = dom?.commonUtils?.getProduct?.() || {};
if (JSON.stringify(productData) === '{}') {
console.log('[paymentEC]hide: product data is {}')
return;
}
if (dom?.commonUtils?.isPreview()) {
dom.mockStartFn()
} else {
dom.startFn();
}
}
const init = () => {
if (checkReady()) {
readyFn();
} else {
document.addEventListener('payment_ec_core_ready', readyFn)
}
}
if (document.readyState === 'complete') {
delayCallback(init);
} else {
window.addEventListener('load', () => delayCallback(init), {once: true});
}
} catch (e) {
}
Mops and scrapes at the same time Dust and hair on the floor can be easily absorbed when dry mopping. Water stains on the glass can be quickly removed by scraping
PROPERTIES
Independent drainage scraper The mop is equipped with a drainage scraper. You only need to move the scraper up and down to drain the mop. The scraper is equipped with a toothed comb that can scrape hair and other debris off the mop, which is very convenient and practical. Avoid touching the mop directly with your hands to make it cleaner and more hygienic.
Long stainless steel handle Consists of 3 sections of stainless steel bars with a total length of 137 cm. The long handle is suitable for most people's height, reduces the frequency of bending and squatting, and effectively saves your body strength, avoiding back pain caused by frequent bending. And the stainless steel is very sturdy so you don't have to worry about it suddenly breaking during use, making it suitable for long-term use.
360° freely rotatable mop head The mop head is flexible and can be rotated 360°. The mop can go in and out of the underside of the bed, the underside of the sofa and other hard to clean places, avoids dust accumulation, leaves no dead corners and cleans your house in all directions. At the top of the handle there is a hook that can be hung vertically on the wall when the mop is not in use. It doesn't take up too much space and is very practical for storage.
2 Microfibre pads Equipped with 2 microfibre pads (one of which is already installed), it has a strong water absorption capacity, can absorb many times its own weight in water, can effectively absorb hair, dust and dirt on the floor and helps you clean your floor quickly . After use, you can put the microfibre mat directly into the washing machine. It can be machine washed more than a hundred times without deforming or damaging, saving you the hassle of buying it again and again.
Suitable for a wide range of floors Made from high-quality materials, this mop is suitable for cleaning most hard floors, including tiles, wood, laminate, resin, etc. It can meet your needs in different situations. Don't worry about scratches on the floor or insufficient cleaning very suitable for daily use.
SPECIFICATIONS
PACKAGE
1 * Large flat mop in new style
NOTE
Please allow slight measurement deviation due to manual measurement.
Due to the different monitor and lighting effect, the actual colour of the item may vary slightly from the colour shown in the pictures.