Classic Boater Panama Hat

$71.09
FRESH DEAL: Buy 2 get 2nd for 50% off,discount applied in cart
class SpzCustomDiscountFlashsale extends SPZ.BaseElement { constructor(element) { super(element); this.xhr_ = SPZServices.xhrFor(this.win); this.getFlashSaleApi = "\/api\/storefront\/promotion\/flashsale\/display_setting\/product_setting"; this.timer = null; this.variantId = "bf0a038b-8297-4381-83db-726c354551c8"; // 促销活动数据 this.flashsaleData = {} } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } buildCallback() { this.templates_ = SPZServices.templatesForDoc(); this.viewport_ = this.getViewport(); // 挂载bind函数 解决this指向问题 this.render = this.render.bind(this); this.resize = this.resize.bind(this); this.switchVariant = this.switchVariant.bind(this); } mountCallback() { // 获取数据 this.getData(); this.element.onclick = (e) => { const cur = this.win.document.querySelector(".app_discount_flashsale_desc"); const setting = this.flashsaleData.product_setting; const landingUrl = `/promotions/discount-default/${this.flashsaleData.discount_info.id}`; const finalUrl = appDiscountUtils.resolveDiscountHref(setting, landingUrl); if (finalUrl && appDiscountUtils.inProductBody(this.element) && e.target !== cur) { this.win.open(finalUrl, '_blank', 'noopener'); } } // 绑定 this.viewport_.onResize(this.resize); // 监听子款式切换,重新渲染 this.win.document.addEventListener('dj.variantChange', this.switchVariant); } unmountCallback() { // 解绑 this.viewport_.removeResize(this.resize); this.win.document.removeEventListener('dj.variantChange', this.switchVariant); // 清除定时器 if (this.timer) { clearTimeout(this.timer); this.timer = null; } } resize() { if (this.timer) { clearTimeout(this.timer) this.timer = null; } this.timer = setTimeout(() => { this.render(); }, 200) } switchVariant(event) { const variant = event.detail.selected; if (variant.product_id == 'a620d0de-b5fe-4584-9b59-1e50f4888d05' && variant.id != this.variantId) { this.variantId = variant.id; this.getData(); } } getData() { const reqBody = { product_id: "a620d0de-b5fe-4584-9b59-1e50f4888d05", product_type: "default", variant_id: this.variantId } this.flashsaleData = {}; this.win.fetch(this.getFlashSaleApi, { method: "POST", body: JSON.stringify(reqBody), headers: { "Content-Type": "application/json" } }).then(async (response) => { if (response.ok) { this.flashsaleData = await response.json(); this.render(); } else { this.clearDom(); } }).catch(err => { this.clearDom(); }); } clearDom() { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); } render() { this.templates_ .findAndRenderTemplate(this.element, { isMobile: appDiscountUtils.judgeMobile(), isRTL: appDiscountUtils.judgeRTL(), inProductDetail: appDiscountUtils.inProductBody(this.element), flashsaleData: this.flashsaleData, image_domain: this.win.SHOPLAZZA.image_domain, }) .then((el) => { this.clearDom(); this.element.appendChild(el); }) } } SPZ.defineElement('spz-custom-discount-flashsale', SpzCustomDiscountFlashsale);
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.)
var theme = window.C_SETTINGS && C_SETTINGS.theme && C_SETTINGS.theme.merchant_theme_name; var isFlash = /Flash/gi.test(theme); var isGeek = /Geek/gi.test(theme); var isNova23 = /Nova 2023/gi.test(theme); var isWind = /Wind/gi.test(theme); var isOnePage = /OnePage/gi.test(theme); var isHero = /Hero/gi.test(theme); var isBoost = /Boost/gi.test(theme); var isEva = /Eva/gi.test(theme); var isFarida = /Farida/gi.test(theme); var isPluto = /Pluto/gi.test(theme); var isLifeStyle = /Life Style/gi.test(theme); 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; this.initData = this.getProductJson(data); if (this.initData && this.initData.product && data.product && this.initData.product.id === data.product.id) { this.initRebate(this.initData, true); } else { 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(); setTimeout(()=>{ if (document.querySelector(".plugin-container__bottom-fixed")) { this.showDiscountPopupsInfoBar(); } else { this.win.addEventListener("extloaded", () => { this.showDiscountPopupsInfoBar(); }); } },1000) } getProductJson = (mergeData = {}) => { const productJson = document.querySelector("#product-json"); let productJsonData = {}; if (productJson && productJson.textContent) { try { productJsonData = JSON.parse(productJson.textContent); } catch (e) {} } // 深度合并函数 const deepMerge = (target, source) => { if (source === null || source === undefined) { return target; } if (typeof source !== 'object' || Array.isArray(source)) { return source; } const result = { ...target }; for (const key in source) { if (source.hasOwnProperty(key)) { if ( typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key]) && typeof target[key] === 'object' && target[key] !== null && !Array.isArray(target[key]) ) { result[key] = deepMerge(target[key], source[key]); } else { result[key] = source[key]; } } } return result; }; return deepMerge(productJsonData, mergeData); } getProduct = (() => { document.addEventListener("dj.variantChange", e => { if (!e.detail || !e.detail.product) return; let productJsonData = getProductJson(e.detail); if (this.win.jQuery && this.win.jQuery.fn && this.win.jQuery(document).data("djproduct") && productJsonData) { this.win.jQuery(document).data("djproduct", productJsonData); } }); 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; }; })(); clearRebateInfoDom = () => { // 1. 清除 apis.render 渲染的 DOM (app_rebate_section) const rebateSection = document.getElementById('app_rebate_section'); if (rebateSection) { const rebateRuleSection = rebateSection.querySelector('.rebate_rule_section'); if (rebateRuleSection) { rebateRuleSection.remove(); } } // 2. 清除 templates_.renderTemplate 渲染的 DOM (app_rebate_block) const rebateBlock = document.getElementById('app_rebate_block'); if (rebateBlock) { const appRebateList = rebateBlock.querySelector('.app_rebate_list'); if (appRebateList) { appRebateList.remove(); } } // 3. 清除 insertProductDetailRebateTag 插入的 DOM // 清除所有 rebate-tag 元素 document.querySelectorAll('.slider-discount-tag.dj_skin_product_title.rebate-tag').forEach(tag => { tag.remove(); }); // 移除 data-rebate-tag 属性 const productContainer = document.querySelector('.product-details, .product-details, .page_container, .product-images, [data-section-type="product"]'); if (productContainer && productContainer.hasAttribute('data-rebate-tag')) { productContainer.removeAttribute('data-rebate-tag'); } }; initRebate = this.win.SPZCore.Types.debounce( this.win, (async (data) => { 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)) { this.clearRebateInfoDom(); 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.insertProductDetailRebateTag(this.rebateInfo.tag); 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) || []; }; insertProductDetailRebateTag = (tag) => { if (!tag) return // 旧判断逻辑 const productSelectModal = document.querySelector('#product-select-modal'); if (productSelectModal && productSelectModal.classList.contains('show')) { return; } setTimeout(() => { var $tag_container = []; if (isNova23) { $tag_container = document.querySelectorAll('.product-details .product-images-container'); } else if (isFlash) { $tag_container = document.querySelectorAll('.product-detail .product-images .product-main-images-container'); } else if (isGeek) { $tag_container = document.querySelectorAll('.product-images #product-images-inner-container spz-carousel .i-spzhtml-slide-item'); } else if (isWind) { $tag_container = document.querySelectorAll('.product-detail .product-images-container .i-spzhtml-slides-container'); } else if (isOnePage) { $tag_container = document.querySelectorAll('.product-details .product-main-images'); } else if (isHero) { $tag_container = document.querySelectorAll('.product-detail #product-images-container #product-images-carousel .spz-carousel-slide'); } else if (isBoost) { $tag_container = document.querySelectorAll('.boost-product-detail .product-image__layout-list .slides .slides-item .product-info__slide .slider-zoom'); } else if (isEva) { $tag_container = document.querySelectorAll('.page_container [data-section-type="product"] .support-slick'); } else if (isFarida) { $tag_container = document.querySelectorAll('.product-details .product-images-container'); } else if (isLifeStyle) { $tag_container = document.querySelectorAll('.page_container [data-section-type="product_detail"] .sep-slider,.support-slick'); } else if (isPluto) { $tag_container = document.querySelectorAll('.page_container [data-section-type="product_detail"] .sep-slider,.support-slick'); } if($tag_container.length === 0) return; // 给商祥页添加满送插件的标识属性 const $product_container = document.querySelector('.product-details, .product-details, .page_container, .product-images, [data-section-type="product"]') if($product_container) { $product_container.setAttribute('data-rebate-tag', 'true'); } // 部分主题需要调整样式 if (isWind) { Array.from($tag_container).forEach(container => { container.style.position = 'relative'; }); } document.querySelectorAll('.slider-discount-tag.dj_skin_product_title.rebate-tag').forEach(tag => tag.remove()); // 遍历所有容器并插入标签 Array.from($tag_container).forEach(container => { container.insertAdjacentHTML('beforeend', `<div class="slider-discount-tag dj_skin_product_title rebate-tag">${tag}</div>`); }); }, 1000) }; fetchInfoBar = async () => { 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(); const { cart } = await this.xhr_.fetchJson('/api/cart') return this.xhr_.fetchJson("\/api\/discount-rebate\/global-text", { method: "POST", body: { product_type: productObj && productObj.product && productObj.product.product_type, line_items: (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; document.querySelector(".discount__info-bar")?.remove(); 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);
Size:  S
Quantity
/** * 优惠码组件模型类 * 处理优惠码的显示和交互逻辑 */ class SpzCustomDiscountCodeModel extends SPZ.BaseElement { constructor(element) { super(element); // 复制按钮和内容的类名 this.copyBtnClass = "discount_code_btn" this.copyClass = "discount_code_value" } isLayoutSupported(layout) { return layout == SPZCore.Layout.LOGIC; } buildCallback() { // 初始化服务 this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); } /** * 渲染优惠码组件 * @param {Object} data - 渲染数据 */ doRender_(data) { return this.templates_ .findAndRenderTemplate(this.element, Object.assign(this.getDefaultData(), data) ) .then((el) => { this.clearDom(); this.element.appendChild(el); // 绑定复制代码功能 this.copyCode(el, data); }); } /** * 获取渲染模板 * @param {Object} data - 渲染数据 */ getRenderTemplate(data) { const renderData = Object.assign(this.getDefaultData(), data); return this.templates_ .findAndRenderTemplate(this.element, renderData) .then((el) => { this.clearDom(); return el; }); } /** * 清除DOM内容 */ clearDom() { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); } /** * 获取默认数据 * @returns {Object} 默认数据对象 */ getDefaultData() { return { isMobile: appDiscountUtils.judgeMobile(), isRTL: appDiscountUtils.judgeRTL(), image_domain: this.win.SHOPLAZZA.image_domain, copyBtnClass: this.copyBtnClass, copyClass: this.copyClass } } /** * 复制优惠码功能 * @param {Element} el - 当前元素 */ copyCode(el) { const copyBtnList = el.querySelectorAll(`.${this.copyBtnClass}`); if (copyBtnList.length > 0) { copyBtnList.forEach(item => { item.onclick = async () => { // 确保获取正确的元素和内容 const codeElement = item.querySelector(`.${this.copyClass}`); if (!codeElement) return; // 获取纯文本内容 const textToCopy = codeElement.innerText.trim(); // 尝试使用现代API,如果失败则使用备用方案 try { if (navigator.clipboard && navigator.clipboard.writeText) { await navigator.clipboard.writeText(textToCopy); } else { throw new Error('Clipboard API not available'); } // 显示复制成功提示 this.showCopySuccessToast(textToCopy, el); } catch (err) { console.error('Modern clipboard API failed, trying fallback...', err); // 使用备用复制方案 this.fallbackCopy(textToCopy, el); } const discountId = item.dataset["discountId"]; // 跳转决策: is_redirection + link(可选覆盖) const setting = { is_redirection: item.dataset["redirection"] === "true", link: item.dataset["link"], }; const landingUrl = `/promotions/discount-default/${discountId}`; const finalUrl = appDiscountUtils.resolveDiscountHref(setting, landingUrl); if (finalUrl && appDiscountUtils.inProductBody(this.element)) { this.win.open(finalUrl, '_blank', 'noopener'); } } }) } } /** * 使用 execCommand 的复制方案 * @param {string} codeText - 要复制的文本 * @param {Element} el - 当前元素 */ fallbackCopy(codeText, el) { const textarea = this.win.document.createElement('textarea'); textarea.value = codeText; // 设置样式使文本框不可见 textarea.style.position = 'fixed'; textarea.style.left = '-9999px'; textarea.style.top = '0'; // 添加 readonly 属性防止移动端虚拟键盘弹出 textarea.setAttribute('readonly', 'readonly'); this.win.document.body.appendChild(textarea); textarea.focus(); textarea.select(); try { this.win.document.execCommand('copy'); // 显示复制成功提示 this.showCopySuccessToast(codeText, el); } catch (err) { console.error('Copy failed:', err); } this.win.document.body.removeChild(textarea); } /** * 创建 Toast 元素 * @returns {Element} 创建的 Toast 元素 */ createToastEl_() { const toast = document.createElement('ljs-toast'); toast.setAttribute('layout', 'nodisplay'); toast.setAttribute('hidden', ''); toast.setAttribute('id', 'discount-code-toast'); toast.style.zIndex = '1051'; return toast; } /** * 挂载 Toast 元素到 body * @returns {Element} 挂载的 Toast 元素 */ mountToastToBody_() { const existingToast = this.win.document.getElementById('discount-code-toast'); if (existingToast) { return existingToast; } const toast = this.createToastEl_(); this.win.document.body.appendChild(toast); return toast; } /** * 复制成功的提醒 * @param {string} codeText - 要复制的文本 * @param {Element} el - 当前元素 */ showCopySuccessToast(codeText, el) { const $toast = this.mountToastToBody_(); SPZ.whenApiDefined($toast).then(toast => { toast.showToast("Discount code copied !"); this.codeCopyInSessionStorage(codeText); }); } /** * 复制优惠码成功后要存一份到本地存储中,购物车使用 * @param {string} codeText - 要复制的文本 */ codeCopyInSessionStorage(codeText) { try { sessionStorage.setItem('other-copied-coupon', codeText); } catch (error) { console.error(error) } } } // 注册自定义元素 SPZ.defineElement('spz-custom-discount-code-model', SpzCustomDiscountCodeModel);
/** * Custom discount code component that handles displaying and managing discount codes * @extends {SPZ.BaseElement} */ class SpzCustomDiscountCode extends SPZ.BaseElement { constructor(element) { super(element); // API endpoint for fetching discount codes this.getDiscountCodeApi = "\/api\/storefront\/promotion\/code\/list"; // Debounce timer for resize events this.timer = null; // Current variant ID this.variantId = "bf0a038b-8297-4381-83db-726c354551c8"; // Store discount code data this.discountCodeData = {} } /** * Check if layout is supported * @param {string} layout - Layout type * @return {boolean} */ isLayoutSupported(layout) { return layout == SPZCore.Layout.LOGIC; } /** * Initialize component after build */ buildCallback() { this.templates_ = SPZServices.templatesForDoc(); this.viewport_ = this.getViewport(); // Bind methods to maintain context this.render = this.render.bind(this); this.resize = this.resize.bind(this); this.switchVariant = this.switchVariant.bind(this); } /** * Setup component when mounted */ mountCallback() { this.getData(); // Add event listeners this.viewport_.onResize(this.resize); this.win.document.addEventListener('dj.variantChange', this.switchVariant); } /** * Cleanup when component is unmounted */ unmountCallback() { this.viewport_.removeResize(this.resize); this.win.document.removeEventListener('dj.variantChange', this.switchVariant); // 清除定时器 if (this.timer) { clearTimeout(this.timer); this.timer = null; } } /** * Handle resize events with debouncing */ resize() { if (this.timer) { clearTimeout(this.timer) this.timer = null; } this.timer = setTimeout(() => { if (appDiscountUtils.inProductBody(this.element)) { this.render(); } else { this.renderSkeleton(); } }, 200); } /** * Handle variant changes * @param {Event} event - Variant change event */ switchVariant(event) { const variant = event.detail.selected; if (variant.product_id == 'a620d0de-b5fe-4584-9b59-1e50f4888d05' && variant.id != this.variantId) { this.variantId = variant.id; this.getData(); } } /** * Fetch discount code data from API */ getData() { if (appDiscountUtils.inProductBody(this.element)) { const reqBody = { product_id: "a620d0de-b5fe-4584-9b59-1e50f4888d05", variant_id: this.variantId, product_type: "default", } if (!reqBody.product_id || !reqBody.variant_id) return; this.discountCodeData = {}; this.win.fetch(this.getDiscountCodeApi, { method: "POST", body: JSON.stringify(reqBody), headers: { "Content-Type": "application/json" } }).then(async (response) => { if (response.ok) { let data = await response.json(); if (data.list && data.list.length > 0) { data.list[0].product_setting.template_config = JSON.parse(data.list[0].product_setting.template_config); // Format timestamps to local timezone const zone = this.win.SHOPLAZZA.shop.time_zone; data.list = data.list.map(item => { if(+item.ends_at !== -1) { item.ends_at = appDiscountUtils.convertTimestampToFormat(+item.ends_at, zone); } item.starts_at = appDiscountUtils.convertTimestampToFormat(+item.starts_at, zone); return item; }); } this.discountCodeData = data; this.render(); } else { this.clearDom(); } }).catch(err => { console.error("discount_code", err) this.clearDom(); }); } else { this.renderSkeleton(); } } /** * Clear component DOM except template */ clearDom() { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); } /** * Render discount codes with formatted dates */ render() { // Render using discount code model SPZ.whenApiDefined(document.querySelector('#spz_custom_discount_code_model')).then(renderApi => { renderApi.doRender_({ discountCodeData: this.discountCodeData }) }).catch(err => { this.clearDom(); }) } renderSkeleton() { // Render template for non-product pages this.templates_ .findAndRenderTemplate(this.element, { isMobile: appDiscountUtils.judgeMobile() }) .then((el) => { this.clearDom(); this.element.appendChild(el); }) .catch(err => { this.clearDom(); }); } } // Register custom element SPZ.defineElement('spz-custom-discount-code', SpzCustomDiscountCode);
Shipping

Description

HOW TO DETERMINE YOUR HAT SIZE

Use a tape measure (or a length of string that you will have to hold up to a tape measure) to determine the length. Place the string or tape around your head about 1/8″ above your ear, across the mid-forehead, completely circling your head. Hold the tape firmly, but not too tightly. Basically you need to measure your head exactly where the hat will sit. If your measurement falls between sizes, choose the next largest size.
Learn more:https: //www.tiendahat.com/pages/style-size-advice


TIPS: Our goods are authentic, with genuine patents, counterfeit must be investigated! Customers, please identify our products!

  • Fast refund>>100% Money Back Guarantee
  • Secure Payments Via PayPal®
  • Buy 2 or more items Free Shipping

Perfect finishing touch to every attire. Dress it up with a top coat and a suit or dress it down with a t-shirt and sneakers. This hat will instantly have you looking your best on every occasion.

Product Details

  • Made of 100% wool felt
  • Unfinished Stiff Brim
  • 2.5″ Wide Brim
  • 4″ Crown

HAT SIZING CHART

GENERAL SIZE

US HAT SIZE

HEAD MEASUREMENT
(IN INCHES)

M

7.12

22.4

L

7.37

23.2

XL

7.62

24.0

About transport:
Many businesses choose to use plastic bags in order to save costs. This will make the hat produce creases. Our packages are packed in cardboard boxes to protect them from distortion

exceptional CRAFTSMANSHIP
Making hats never gets old, only the folks making them. With this comes generations of experience at our craft. We combine old world methods with a modern mindset because quality people deserve quality hats.

carefully CURATED DETAILS
There is deep intention behind every design. We cut fabric and textiles, but never corners. Always an art; never just a hat.

sourcing THE BEST MATERIALS
The best hats come from the best materials and only the finest will do. From 100% merino wool, hand woven toquilla straw, premium furs, and more. Start at the top.

About transport:

  • Many businesses choose to use plastic bags in order to save costs. This will make the hat produce creases. Our packages are packed in cardboard boxes to protect them from distortion

MONEY BACK GUARANTEE
We want you to be 100% satisfied with the products you buy from us. If for ANY reason you are not satisfied with your purchase, we offer iron-clad money back guarantee.

Insured Worldwide Shipping: Each order includes real-time tracking details and insurance coverage in the unlikely event that a package gets lost or stolen in transit.

Money-Back Guarantee: If your items arrive damaged or become defective within 30 days of normal usage, we will gladly issue out a replacement or refund.

✉️ 24/7 Customer Support: We have a team of live reps ready to help and answer any questions you have within a 24-hour time frame, 7 days a week.

Safe & Secure Checkouts: We use state-of-the-art SSL Secure encryption to keep your personal and financial information 100% protected.

Alt

Hat Care Guide

Tumahy Hat Care Guide (Felt & Straw)

Proper hat care is the first step to keeping your Tumahy hat looking its best. With the right handling, cleaning, drying, and storage habits, you can help preserve the shape, finish, and lifespan of both felt hats and straw hats.

1) Handle with care (how to pick up your hat)

  • Avoid repeatedly picking up your hat from the front by pinching the dents. Over time, this can reshape the crown, and prolonged stress may eventually damage felt.
  • If you lift your hat by the brim, do so as close to the crown as possible to reduce brim distortion.
  • Ideally, handle your hat by the crown, which generally holds its shape better than the brim.

2) Protect the shape (storage best practices)

  • Store each hat on a wide peg or hook that won’t leave dimples.
  • If storing on a flat surface (e.g., a closet shelf), place the hat upside down so the brim doesn’t flatten.
  • For long-term storage, use a supportive hatbox to protect both crown and brim while keeping dust and moisture away.

3) Use the correct brush

Regular brushing can make a big difference—just choose the right tool:

  • Felt hats (fur felt / wool): use a soft bristle brush.
  • Straw hats (including Sinamay-style materials): gently dust with a small whisk broom or soft brush.

4) Avoid water (and dry properly if it gets wet)

No hat enjoys heavy rain. If your hat gets wet:

  • Shake off excess water immediately.
  • Don’t use high heat to dry (no hairdryer, radiator, or clothes dryer). Heat can shrink, warp, or weaken materials.
  • Straw hats: you may gently wipe surface moisture.
  • Felt hats: avoid rubbing with a towel; allow to air-dry naturally and brush when dry if needed.

5) Use steam to remove dents or bends

If your felt or straw hat gets dented or bent:

  • Hold it over steam (from a kettle) or near a garment steamer for about 30 seconds.
  • Gently reshape with your fingers and let it cool/set.
  • Straw hats only: if needed, you may lightly press with an iron on a low heat setting—too much heat can scorch the straw.

6) Treat grease stains with dry cornstarch

Cornstarch can help absorb oily marks:

  • Apply dry cornstarch to the stain, let it sit, then gently brush away.
  • Always check the care label inside your hat for any specific instructions.

Note: These tips are general best practices. If your hat includes specific care directions, please follow those first.

Size Guide

WHAT'S YOUR HEAD SIZE?

Everyone knows their shoe size. Hats? Not so much. But with a few quick measurements, you will know your hat size which, unlike your waist size, will stay the same for the rest of your life.

HOW TO MEASURE YOUR HEAD AND HAT SIZE USING STRING OR A MEASURING TAPE

This is the traditional way that you can use at home to find your hat size.

What You'll Need:

  • String or ribbon
  • Ruler
  • Hat sizing chart
  • Pen or marker
  • Standard Measuring Tape

 

Step 1: Use a Piece of String to Measure Your Head

With the piece of string in your hands, wrap it around the back of your head just slightly above your ears or about 1/8 of an inch higher than your ear tip.

Pull the string around to meet at the center of your forehead just above your eyebrows. If you like your hat to sit a bit higher, you can pull the string around your head exactly to match how your hat rests on your head.

It's important that you don't pull the string too tight. Rather, the string should fit comfortably around your forehead so that it isn't too tight or loose. This should feel exactly the way you want your hat to feel as it rests on your head.

You can mark the distance where the string meets with a pen or marker.

Step 2: Measure the String with a Ruler

Once you have marked the point of circumference on the string, you can lay it flat and place a ruler underneath to find the circumference in inches. You will likely have to measure the size to the nearest 1/8 of an inch.

Step 3: Using a Measuring Tape 

If you have a measuring tape you can also wrap it around your head. To measure your head size correctly, wrap the tape snugly just above eyebrows and ears. Use our chart to convert the measurement to the correct hat size.

Step 4: Match the Circumference to the Hat Sizing Chart

 

Things to Keep in Mind

  • Hat sizing is really based on your comfort level as well. If you prefer that a hat fits snugly for certain designs or you want a cap that fits slightly loose, you should account for that in your sizing. Your comfort matters most of all when picking the true hat size.
  • In addition, there are other factors to consider, such as your hairstyle. A hat that is too tight can make your hair stick out in odd ways. Materials and brands can also fit differently. For example, wool and straw may not fit the same hat size.

About Tumahy

Tumahy is a brand dedicated to handcrafting a variety of hats, including Fedora, cowboy hats, and various other styles. With a focus on quality craftsmanship and unique designs, we aim to provide our customers with stylish and comfortable headwear options. Each hat is carefully crafted to embody our commitment to excellence and attention to detail. Explore the world of Tumahy and discover the perfect hat to complement your style.