đŸ”Crochet Punch Monkey Keychain

$20.99
$30.99
Save $10.00
/** * äŒ˜æƒ ç ç»„ä»¶æšĄćž‹ç±» * ć€„ç†äŒ˜æƒ ç çš„æ˜Ÿç€ș撌äș€äș’逻蟑 */ 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 = "3293562f-9ab0-4195-bf3e-495c9149fbea"; // 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 == 'b347e27e-0495-497f-ab4b-28243a4f1717' && 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: "b347e27e-0495-497f-ab4b-28243a4f1717", 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);
Quantity
Quantity
Share the love
Description

Description

Product description

Handmade Crochet Monkey Keychain - Your Tiny Companion Inspired by Punch the Monkey

🐒 Product Introduction

Meet your new heartwarming tiny companion — a meticulously handmade crochet monkey keychain designed to carry warmth, comfort, and a beautiful reminder that no one is ever truly alone. Just like the beloved viral star Punch the Monkey from Ichikawa City Zoo, who found solace and courage in his plush companion amid life’s challenges, this little monkey keychain embodies the spirit of friendship, reassurance, and quiet emotional support đŸ„ș. It’s not just an accessory; it’s a small, tangible symbol of love that you can carry everywhere, just as Punch carries his beloved plush with unwavering trust.
Inspired by the gentle bonds we witness in nature and the simple comfort of holding something soft and familiar, this keychain pays homage to Punch’s touching journey of resilience and connection. Whether you’re navigating a busy workday, exploring a new city, or simply needing a little pick-me-up, this adorable crochet monkey is here to wrap you in warmth, just like the comfort Punch finds in his toy.

✹ Why You’ll Adore It

🌟 Inspired by the Viral Punch the Monkey Phenomenon

This keychain draws direct inspiration from the global heartwarming story of Punch the Monkey — the abandoned baby macaque who stole millions of hearts worldwide with his unwavering bond to his plush companion. Just as Punch’s story taught us about courage in loneliness and the beauty of finding comfort in small things, this keychain serves as a daily reminder that friendship and support exist in the tiniest, most unexpected places. It’s a wearable tribute to resilience, love, and the power of connection that resonates with anyone who fell in love with Punch’s touching journey 🌍.

đŸ§¶ Perfectly Pocket-Sized & Versatile for Every Scene

  • Daily Carry: Clip it onto your keys, and let this little monkey greet you every time you grab your bag — a sweet, constant companion for your morning commute, office runs, or grocery trips.

  • Accessory Upgrade: Attach it to your backpack, tote bag, or purse to instantly elevate your style with cozy-cute charm. It’s the perfect pop of warmth for your everyday carry, just like Punch’s plush brightens his days.

  • Travel Buddy: Take it on your adventures! Whether you’re hiking a mountain, strolling through a park, or exploring a new cafĂ©, this tiny companion will be by your side, turning ordinary moments into memorable ones filled with soft comfort.

  • Sentimental Gift: It’s not just a keychain — it’s a heartfelt gift for friends, family, or loved ones. Just as Punch’s story unites people in empathy, this little monkey lets someone special know you’re thinking of them, no matter the distance.

đŸ„° Irresistibly Soft & Durable

Crafted with smooth, high-quality yarn and filled with premium PP cotton, this keychain strikes the perfect balance: it’s squishy and huggable enough to squeeze during stressful moments, yet structured enough to stay adorable and hold its shape. The sturdy metal keychain attachment ensures your mini companion stays securely by your side without feeling bulky — lightweight enough to carry anywhere, just like Punch carries his plush with ease.

📌 Core Product Details

SpecificationDetails
MaterialSoft yarn exterior + premium PP cotton stuffing (safe, skin-friendly, and ultra-soft)
Size3.15 inches / 8x8 cm (handmade item, slight variations may occur, making each one uniquely charming)
DesignAdorable double-monkey hugging design, mirroring the tender companionship of Punch and his plush toy
AttachmentSturdy metal keychain with a smooth finish, easy to clip on and durable for long-term use

💖 A Little Note on Meaning

Every stitch of this handmade crochet keychain is filled with love — just like the care zookeepers pour into raising Punch, and just like the love we hold for the people and things that matter. When you carry this keychain, you’re not just carrying a cute accessory; you’re carrying a piece of warmth, a reminder of friendship, and a tribute to the beautiful spirit of Punch the Monkey. It’s a small thing, but it has the power to make your days a little softer, your heart a little fuller, and to remind you that you’re never alone 💛.

🎁 Perfect for Every Occasion

Whether you’re treating yourself to a daily dose of comfort, gifting a sentimental token to a loved one, or adding a unique touch to your own accessory collection, this handmade crochet monkey keychain is the ideal choice. It’s more than a keychain — it’s a symbol of love, resilience, and the quiet companionship we all need, inspired by one of the most heartwarming viral stories of 2026: Punch the Monkey.

âšĄïžStock Sells Fast!âšĄïž

Click On "ADD TO CART" To Get Yours Now!

Certification

WHY US?

  • We work directly with manufacturers all over the world to ensure the best quality of our products. We have Quality Control department which help us to keep our promise!
  • Price is always competitive.
  • Awesome Customer Service
  • Amazing products along with High Quality
  • Read reviews from our lovely customers


OUR 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, 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.

🔒 100% Risk-Free Purchase: If you bought it and felt that it is not for you, don't worry. Just hit the Contact us button and send us a message, and we will make it right by offering you a replacement or refund. 100% Simple & Risk-Free process.

Â