Date Caramel Coffee Cake Recipe (2024)

Cart ()

You're away from free shipping
+
Our 5 Day Reset Health Program

Congrats! You unlocked FREE shipping
+
Qualified for a FREE copy of our 5-Day Reset Health Program
(sent to your inbox on purchase)

CUSTOMERS WHO BOUGHT THIS ITEM ALSO GOT...

Date Caramel Coffee Cake Recipe (3)

Organic Plant Protein + Superfood Smoothie Mix (Sample Box)

$35

Date Caramel Coffee Cake Recipe (4)

Organic Protein + Superfood Bars Sample Pack (9 Bars)

$35

Date Caramel Coffee Cake Recipe (6)

Organic Protein + Superfood Bars Sample Pack (12 Bars)

$45

Date Caramel Coffee Cake Recipe (7)

Organic Superfood Latte Mix

$35

Cart updated ()

0
    • Build My Own Box Sample Box

      Our most popular smoothie box - designed to work in synergy to boost immunity, promote weight loss, stimulate collagen, increase energy and leave you with glowing skin.

    • Achieve a healthier weight, improved gut health, boosted energy, and stronger immunity faster with TUSOL's research-backed smoothies, packed with superfoods for ultimate health support.

      Date Caramel Coffee Cake Recipe (9)

      Healthy Weight Smoothie Box

      Packed with protein, fiber, & nutrients for sustainable weight loss.

      SHOP NOW

      Date Caramel Coffee Cake Recipe (10)

      Gut Healing Smoothie Box

      Smoothie with probiotics, prebiotics, and enzymes for a healthy, happy gut.

      SHOP NOW

      Date Caramel Coffee Cake Recipe (11)

      Energizing Smoothie Box

      Jumpstart your day, power through a workout with smoothies packed with superfoods.

      SHOP NOW

      Date Caramel Coffee Cake Recipe (12)

      Metabolism Smoothie Box

      Filled with ingredients designed to naturally support your body's metabolism.

      SHOP NOW

      • Organic Superfood Latte Mix

        TUSOL superfood Lattes are low in calories, sugar, and fat. Our Latte Mixes are formulated with superfoods to nourish the body. The organic ingredients promote energy, metabolism, focus, and immunity and leave you in control of the morning.

      • TUSOL Wellness Essentials Kit Full Body Reset Kit Starter Kit

        Effortlessly optimize your health from the inside out - The full body reset kit combines our best-selling superfood formulas to optimize your health.

      • Organic Superfood Protein Bar Assorted Box Sample Pack

        Our three organic superfood bars are the new best way to get real nutrition on the go. They are the only bars backed by a 3 Michelin Star Chef and are Certified Organic, Dairy-Free, and Gluten-Free.

      • Health programs
      • Research
      • Ingredients
      • Sustainability
      • Wholesale

    ★ ★ ★ ★ ★

    “I absolutely love this product. I'm a working Mom on the go and every morning I look forward to a quiet moment drinking my TUSOL, before rushing out the door. My skin and hair look better than ever, I've had less stomach bloat and my stress level and clarity of mind has improved.” - Martina K

    SHOP SMOOTHIES

Date Caramel Coffee Cake Recipe (16)

I Ilana Friedman

Nov 4, 2021

This one is a keeper. It's completely comforting, easy to whip up for yourself or friends, ready in the time it takes to run an errand or FT with your trainer, perfect for any occasion, so light and wonderful and plant-based!

So, what are we waiting for? Let's do this.

Prep Time:

8minutes

Cook Time:

20minutes

Ingredients:

¾ cup almond milk

1/3 cup honey

2 cups almond flour

1 flax egg

½ teaspoon vanilla extract

1 pack TUSOL Banana Smoothie blend

6 medjool dates

1/3 cup coconut butter

Pinch of seal salt

Frosting: optional

First, pit the dates and then pop them in the blender with the honey, seal salt, coconut butter, vanilla extract and slowly add in the almond flour — and last, the flax egg and almond milk.

  • Pre-heat oven to 180°C (conventional) / 356°F or 160°C (fan-forced or convection) / 320°F
  • Line a 22cm (9inch) round cake pan with baking paper.

Nourish your body with our NEW organic superfood latte blends designed to work in synergy to support metabolism, immunity, energy and focus.

Link to share

Use this link to share this article

Share Tweet Pin it

Related Blog Posts

Pilates Fever: Unraveling the Obsession Sweeping the Nation Read More Recipe: Detoxifying Greens Smoothie Bowl Ingredients:⁠⁠1 cup fresh spinach leaves (rich in antioxidants and supports detoxification processes)⁠1/2 cucumber, peeled and sliced (hydrating and may help flush out toxins)⁠1/2 avocado (contains healthy fats and... Read More 10 Simple Swaps to Replace Sugary Products with Sugar-Free Alternatives Excessive sugar consumption has been linked to numerous health issues, from obesity to heart disease and diabetes. If you're looking to reduce your sugar intake, making simple swaps in... Read More
Preview
`; const $previewModelEl = document.createElement('div'); $previewModelEl.innerHTML = previewModeControlHtml; document.querySelector('body').appendChild($previewModelEl); // not removing this yet bc its set to be used in a v2 version of the preview mode controls const hidePreviewControl = function () { document .querySelector('#awt-preview-mode-control') .classList.add('hidden'); }; const closePreviewMode = function () { window.localStorage.removeItem(PREVIEW_MODE_STORAGE_KEY); insertUrlParam('bundleapp-preview'); window.location.reload(); }; // document // .querySelector('#awt-preview-mode-control__hide') // .addEventListener('click', hidePreviewControl); document .querySelector('#awt-preview-mode-control__close') .addEventListener('click', closePreviewMode); }; var getShopInfo = function () { const moneyFormat = window.moneyFormat || (window.theme && window.theme.moneyFormat) || (window.theme && window.theme.strings && window.theme.strings.moneyFormat) || (window.theme && window.theme.settings && window.theme.settings.moneyFormat) || (window.bundleapp && window.bundleapp.settings && window.bundleapp.settings.moneyFormat); if (moneyFormat) { window.bundleapp.settings = Object.assign({}, window.bundleapp.settings, { moneyFormat: moneyFormat, }); return Promise.resolve(); } return fetch(window.bundleapp.settings.proxy + '/shop-info') .then(function (res) { return res.json(); }) .then(function (data) { window.bundleapp.settings = Object.assign( {}, window.bundleapp.settings, data, ); }); }; var setCssVars = function (styleSettings) { if (styleSettings) { // update CSS vars var root = document.querySelector(':root'); for (var styleSettingsKey in STYLE_VAR_MAP) { styleSettings[styleSettingsKey] && root.style.setProperty( STYLE_VAR_MAP[styleSettingsKey].cssVar, styleSettings[styleSettingsKey], ); } } }; var insertUrlParam = function (key, value) { if (history.replaceState) { let searchParams = new URLSearchParams(window.location.search); if (value) { searchParams.set(key, value); } else { searchParams.delete(key); } let newurl = window.location.protocol + '//' + window.location.host + window.location.pathname + '?' + searchParams.toString(); window.history.replaceState({ path: newurl }, '', newurl); } }; var formatMoney = function (cents, format) { if (typeof cents == 'string') { cents = cents.replace('.', ''); } var value = ''; var placeholderRegex = /\{\{\s*(\w+)\s*\}\}/; var formatString = format || window.bundleapp.settings.moneyFormat; function defaultOption(opt, def) { return typeof opt == 'undefined' ? def : opt; } function formatWithDelimiters(number, precision, thousands, decimal) { precision = defaultOption(precision, 2); thousands = defaultOption(thousands, ','); decimal = defaultOption(decimal, '.'); if (isNaN(number) || number == null) { return 0; } number = (number / 100.0).toFixed(precision); var parts = number.split('.'), dollars = parts[0].replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1' + thousands, ), cents = parts[1] ? decimal + parts[1] : ''; return dollars + cents; } switch (formatString.match(placeholderRegex)[1]) { case 'amount': value = formatWithDelimiters(cents, 2); break; case 'amount_no_decimals': value = formatWithDelimiters(cents, 0); break; case 'amount_with_comma_separator': value = formatWithDelimiters(cents, 2, '.', ','); break; case 'amount_no_decimals_with_comma_separator': value = formatWithDelimiters(cents, 0, '.', ','); break; } return formatString.replace(placeholderRegex, value); }; // FIXME eslint error // eslint-disable-next-line no-undef debounce = function (func, wait, immediate) { var timeout; return function () { var context = this, args = arguments; var later = function () { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; // Method to get closes matching parent source: https://gomakethings.com/a-native-vanilla-javascript-way-to-get-the-closest-matching-parent-element/ if (window.Element && !Element.prototype.closest) { Element.prototype.closest = function (s) { var matches = (this.document || this.ownerDocument).querySelectorAll(s), i, el = this; do { i = matches.length; // FIXME eslint error // eslint-disable-next-line no-empty while (--i >= 0 && matches.item(i) !== el) {} } while (i < 0 && (el = el.parentElement)); return el; }; } var priceBadgeContainer = () => [ 'form.product__form--add-to-cart .product__price', // Boundless '.product-single__meta .price-container', //Brooklyn '.product__price .price__pricing-group', // Debut '.product__content .price__pricing-group', // Express '.product-single__prices', // Minimal, Simple '.product__content-header .product__price', // Narrative '.inline-list.product-meta', // Supply '.product-single__meta-list', // Venture ] .concat(window.bundleapp.settings.priceBadgeContainer || []) .join(', '); const priceContainerSel = () => [ '.price__regular', // debut, express '.product-single__price', // brooklin, minimal '.product__current-price', // narrative '#productPrice-product-template', // supply, venture '.product__price--reg', // boundless ] .concat(window.bundleapp.settings.priceContainerSel || []) .join(', '); const comparePriceContainerSel = () => [ '.price--on-sale .price__sale', // debut, express '.product-single__price--compare-at', // brooklin '.product-single__sale-price', // minimal '.product__compare-price', //narrative '.product-single__price--compare', // simple, venture '.product__price .product__price--sale', // boundless '.product-meta .sale-tag', // supply ] .concat(window.bundleapp.settings.comparePriceContainerSel || []) .join(', '); const planSelectorSel = '.bundleapp-plan-selector-plan'; const addToCartButtonSel = () => ['button[type=submit]'] .concat(window.bundleapp.settings.addToCartButtonSel || []) .join(', '); const PREVIEW_MODE_STORAGE_KEY = 'awtomatic-preview-mode'; /** * Awtomatic Selector Widget * */ function BundleAppWidget($selector, product) { this.product = product; this.$selector = $selector; this.$sellingPlanField = this.$selector.querySelector( 'input[name=selling_plan]', ); this.$wrapper = this.$selector.closest( 'div[data-section-type], .shopify-section, body', ); this.$planGroups = this.$selector.querySelectorAll( '.bundleapp-plan-selector-group_wrap', ); this.$form = this.$selector.closest('form'); this.$variantSelect = this.$form.querySelector('[name=id]'); this.$badgePriceEl = this.$wrapper.querySelector(priceBadgeContainer()); if (!this.$badgePriceEl) console.warn('Did not find a badge container element'); // FIXME eslint error // eslint-disable-next-line no-undef this.setPlansVisibility = debounce( this._baseSetPlansVisibility.bind(this), 50, ); this.init(); this.setPlansVisibility(); if (window.bundleapp.settings.onInit) { window.bundleapp.settings.onInit.call(this); } if (window.bundleapp.onInit) { console.warn( 'onInit will be deprecated soon. Please use bundleapp.settings.onInit instead', ); window.bundleapp.onInit.call(this); } } Object.assign(BundleAppWidget.prototype, { init: function () { this.$selector.style.display = 'block'; this.$planGroups.forEach( function (elem) { var $planGroupRadio = elem.querySelector( "input[name='bundleapp-plan-selector-group_wrap']", ); $planGroupRadio.addEventListener( 'change', this.handlePlanRadioChange.bind(this), ); elem .querySelector('select') .addEventListener( 'change', this.handlePlanOptionsChange.bind(this), ); var $radioButtonsfrequencySelector = elem.querySelectorAll( '.bundleapp-plan-selector-radio__input', ); for ( let index = 0; index < $radioButtonsfrequencySelector.length; index++ ) { $radioButtonsfrequencySelector[index].addEventListener( 'change', this.handlePlanOptionsChange.bind(this), ); } }.bind(this), ); //Ads an event listener to every element in the form const $selectorElements = Array.from( this.$selector.querySelectorAll('input, select'), ); Array.from(this.$form.elements).forEach( function (el) { if ( !$selectorElements.includes(el) && el.tagName !== 'BUTTON' && el.type !== 'hidden' ) { el.addEventListener('change', this.handleFormDomChanged.bind(this)); } }.bind(this), ); if (window.bundleapp.settings.formDomChangeElementsSel) { const $variantEls = document.querySelectorAll( window.bundleapp.settings.formDomChangeElementsSel, ); $variantEls.forEach( function (el) { el.addEventListener('click', this.handleFormDomChanged.bind(this)); }.bind(this), ); } }, getTranslation: function (key, fallback) { let translation = this.product?.translations[key]; if (translation.includes('ranslation missing')) { translation = fallback; } return translation; }, // This is marked as a private function because this is not intended to be used // directly. Use the debounced version of it this.setPlansVisibility() _baseSetPlansVisibility: function () { if (window.bundleapp.settings.hideIfUnavailable) { //If variant is not available hide the whole widget this.$selector.style.display = this.product.selected_variant.available ? 'block' : 'none'; } var selling_plan_group_ids = this.product.selected_variant.selling_plan_allocations.map( function (i) { return i.selling_plan_group_id; }, ); var planId = ''; const hasPlanWithMultipleDeliveries = this.product.selected_variant.selling_plan_allocations.some( (sp) => sp.price !== sp.per_delivery_price, ); // @TODO: translate suffix const suffix = hasPlanWithMultipleDeliveries ? this.getTranslation('delivery_suffix', '/delivery') : ''; this.$planGroups.forEach( function (elem) { var bundleAppSettings = window.bundleapp.settings || {}; var $planGroupRadio = elem.querySelector( "input[name='bundleapp-plan-selector-group_wrap']", ); var groupId = $planGroupRadio.value; elem.style.display = selling_plan_group_ids.includes(groupId) || !groupId ? 'block' : 'none'; var selectedPlanGroup = this.product.selling_plans_by_id[ this.product.selected_selling_plan ? this.product.selected_selling_plan.id : null ]; var isSelectedGroup = !!( selectedPlanGroup && selectedPlanGroup.selling_plan_group_id === groupId ); var $selectorPlan = elem.querySelector(planSelectorSel); $selectorPlan.style.display = isSelectedGroup ? 'block' : 'none'; if (!$planGroupRadio.value && !isSelectedGroup) { // If value is falsy a.k.a one-time purchase $planGroupRadio.checked = true; } else { $planGroupRadio.checked = isSelectedGroup; if (this.$planGroups.length === 1) { elem.classList.add('bundleapp-plan-selector-group--single-group'); } // if this is the selected group add the selected class if (isSelectedGroup) { elem.classList.add('bundleapp-plan-selector-group--selected'); if (bundleAppSettings.useRadioButtonFrequencySelector) { const selectedGroupPlans = elem .querySelector('.bundleapp-plan-selector-radio') .getElementsByTagName('input'); const isPlanChecked = Array.from(selectedGroupPlans).some( ({ checked }) => checked, ); if (!isPlanChecked) { // if no plan is checked, select the first one selectedGroupPlans[0].checked = true; elem .querySelector('.bundleapp-plan-selector-radio label') .classList.add( 'bundleapp-plan-selector-radio__label--selected', ); } } } } if (bundleAppSettings.useRadioButtonFrequencySelector) { let $radioButtonPlanSelector = elem.querySelector( '.bundleapp-plan-selector-radio', ); $radioButtonPlanSelector.style.display = isSelectedGroup ? 'block' : 'none'; let $selectPlanSelector = elem.querySelector( '.bundleapp-plan-selector-select', ); $selectPlanSelector.style.display = 'none'; } else { let $radioButtonPlanSelector = elem.querySelector( '.bundleapp-plan-selector-radio', ); $radioButtonPlanSelector.style.display = 'none'; let $selectPlanSelector = elem.querySelector( '.bundleapp-plan-selector-select', ); $selectPlanSelector.style.display = isSelectedGroup && $selectPlanSelector.options.length > 1 ? 'block' : 'none'; } if (isSelectedGroup) { const planSel = bundleAppSettings.useRadioButtonFrequencySelector ? `${planSelectorSel} .bundleapp-plan-selector-radio input:checked` : `${planSelectorSel} select`; planId = elem.querySelector(planSel) && elem.querySelector(planSel).value; } //update pricing label of each group const planGroup = this.product.selling_plan_groups.find( (p) => p.id === groupId, ); const $priceLabel = elem.querySelector( '.bundleapp-plan-selector-group-pricing', ); const currentVariant = this.product.variants.find( (variant) => variant.id === this.product.selected_variant.id, ); if (planGroup && $priceLabel) { const values = planGroup.selling_plans.map(function (i) { return parseInt(i.price_adjustments[0]?.value); }); const sellingPlansFromCurrentGroup = currentVariant.selling_plan_allocations.filter( (sp) => sp.selling_plan_group_id === planGroup.id, ); if (sellingPlansFromCurrentGroup && values) { const lowestPriceInGroup = Math.min.apply( null, sellingPlansFromCurrentGroup.map((sp) => sp.per_delivery_price), ); const isSame = values.every(function (val) { return val === values[0]; }); const prefix = isSame ? '' : this.getTranslation('from', 'from'); $priceLabel.innerHTML = `${prefix} ${formatMoney( lowestPriceInGroup, )}${suffix}`; $priceLabel.dataset.test = `planPriceInSelector-${ sellingPlansFromCurrentGroup?.selling_plan_group_id || sellingPlansFromCurrentGroup[0]?.selling_plan_group_id }`; } } if (this.product?.selling_plan_groups?.length === 1) { // check to see. IF just one selling plan group, and does not offer discount // then we wont display itemized prices. const $itemizedPrices = this.$selector.querySelectorAll( '.bundleapp-plan-selector-group-pricing', ); const oneTimePurchasePrice = currentVariant?.price; const pricesInSellingPlans = currentVariant.selling_plan_allocations.map( (sp) => sp.price, ); const allEqual = (arr) => arr.every((val) => val === arr[0]); if (allEqual([oneTimePurchasePrice, ...pricesInSellingPlans])) { $itemizedPrices.forEach((price) => { price.style.display = 'none'; }); } } }.bind(this), ); //check if theres a visible option selected //If not: check first if ( !Array.from(this.$planGroups).filter( (el) => el.offsetParent && el.querySelector('input').checked, ).length ) { // get first input that's visible const firstVisibleGroup = Array.from(this.$planGroups).filter( (el) => el.offsetParent, )[0]; if (firstVisibleGroup) { const $firstRadio = firstVisibleGroup.querySelector('input'); if (!$firstRadio.checked) { $firstRadio.checked = true; $firstRadio.dispatchEvent(new Event('change')); // if we are using radio buttons get the first plan and check it if (window.bundleapp.settings.useRadioButtonFrequencySelector) { let $radioButtonPlanSelector = firstVisibleGroup.querySelector( '.bundleapp-plan-selector-radio', ); const firstPlan = $radioButtonPlanSelector.querySelector('input'); if (!firstPlan.checked) { firstPlan.checked = true; firstPlan.dispatchEvent(new Event('change')); } } } } } //Updates input field if (this.$sellingPlanField) { this.$sellingPlanField.value = planId ? planId : ''; $("input[name=selling_plan]").trigger("change"); // adding this so that the input triggers a change events for the awt-box code to work as expected } //Update url only if we are in the product page if (window.location.pathname.includes('/products/')) { insertUrlParam('selling_plan', planId); } //Updates one-time purchase price const $oneTimePrice = this.$selector.querySelector( '[data-one-time].bundleapp-plan-selector-group_wrap .bundleapp-plan-selector-group-pricing', ); if ($oneTimePrice) { $oneTimePrice.innerHTML = `${formatMoney( this.product.selected_variant.price, )}${suffix}`; // data-test attribute for testing $oneTimePrice.dataset.test = 'oneTimePriceInSelector'; } // do not update prices if there are no selling plans groups on the product if (this.product?.selling_plan_groups?.length) { this.updatePrice(planId); this.updateBadgePrice(planId); } this.replaceAddBtnForBundles(); }, replaceAddBtnForBundles: function () { // only replace button on BaB bundle if ( !this.product?.metafields?.isBundle || this.product?.metafields?.type === 'shuffle' ) { return; } const $btn = this.$form.querySelector(addToCartButtonSel()); // remove "buy it now" button const $shopifyPaymentBtn = $btn.parentElement.querySelector( '.shopify-payment-button', ); if ($shopifyPaymentBtn) { $shopifyPaymentBtn.remove(); } let $clonedBtn = this.$form.querySelector('#awt-customize-box-btn'); if (!$clonedBtn) { $clonedBtn = $btn.cloneNode(true); $clonedBtn.id = 'awt-customize-box-btn'; $clonedBtn.type = 'button'; $clonedBtn.innerText = this.getTranslation( 'customize_my_box', 'Customize my box', ); $clonedBtn.classList.remove('btn--secondary-accent'); $clonedBtn.classList.add('btn--primary-accent'); // remove any href in case the theme has been customized and isn't a standard add-to-cart button $clonedBtn.removeAttribute('href'); $btn.style.display = 'none'; $btn.classList.add('awt-hidden-add-to-cart-button'); $btn.parentNode.insertBefore($clonedBtn, $btn.nextSibling); } else { // clone the previous clone and replace var secondClone = $clonedBtn.cloneNode(true); $clonedBtn.parentNode.replaceChild(secondClone, $clonedBtn); // reference new button so we can add event listener $clonedBtn = secondClone; } var handleCustomizeBoxButtonClick = function (event) { event.stopPropagation(); let params = new URLSearchParams(window.location.search); let search = window.location.search; // only use product.selected_variant.id arg if variant is not already in the // url params. Otherwise we might be overriding the latest selection if (!search.includes('variant') && this.product?.selected_variant?.id) { params.append('variant', this.product?.selected_variant?.id); } // only use selectedSellingPlanId arg if variant is not already in the // url params. Otherwise we might be overriding the latest selection let selectedSellingPlanId = this.product?.selected_selling_plan?.id; if (!selectedSellingPlanId) { // if selectedSellingPlanId wasn't on the product check for the hidden input selectedSellingPlanId = document.querySelector( 'input[name="selling_plan"]', )?.value; } if (!search.includes('selling_plan') && selectedSellingPlanId) { params.append('selling_plan', selectedSellingPlanId); } let priceAdjustments = this.product?.selected_selling_plan ?.price_adjustments; if ( priceAdjustments && priceAdjustments[0] && priceAdjustments[0].value ) { params.append( 'd', `${priceAdjustments[0].value}-${ priceAdjustments[0].value_type === 'percentage' ? 'p' : 'q' }`, ); } let url = new URL( `${window.location.origin}${window.bundleapp.settings.proxy}/bundle/${this.product.id}`, ); url.search = params.toString(); window.location.href = url.toString(); }; $clonedBtn.addEventListener( 'click', handleCustomizeBoxButtonClick.bind(this), ); }, updatePrice: function (planId) { // don't update the price if this is an awt box const awtBox = document.querySelector('#awt-box'); if (awtBox) { return; } var planAllocation = this.product.selected_variant.selling_plan_allocations.find( (allo) => allo.selling_plan_id == planId, ); // var planOption = this.product.selling_plans_by_id[planId]; let $comparePriceSpan = this.$wrapper.querySelector( '.bundleapp-compareAtPrice', ); const $priceRegular = this.$wrapper.querySelector(priceContainerSel()); const $priceSale = this.$wrapper.querySelector( comparePriceContainerSel(), ); if (!$priceRegular) console.warn('Did not find a price element'); if (!$priceSale) console.warn('Did not find a compare price element'); if (!$comparePriceSpan) { $comparePriceSpan = document.createElement('span'); $comparePriceSpan.classList.add('bundleapp-compareAtPrice'); if ($priceRegular) { const priceStyles = window.getComputedStyle($priceRegular); Array.from(priceStyles).forEach((key) => $comparePriceSpan.style.setProperty( key, priceStyles.getPropertyValue(key), priceStyles.getPropertyPriority(key), ), ); $priceRegular.after($comparePriceSpan); } $comparePriceSpan.style.textDecoration = 'line-through'; $comparePriceSpan.style.webkitTextDecorationLine = 'line-through'; $comparePriceSpan.style.marginLeft = '10px'; // for testing purpose if ($comparePriceSpan) $comparePriceSpan.dataset.test = 'bundlePriceOnSale'; } setTimeout( function () { // Since the theme wants to change the price we need to wait a bit to make our changes, // hence, the timeout if (planAllocation) { if ($priceRegular) { $priceRegular.innerHTML = `${formatMoney(planAllocation.price)}`; if ( planAllocation.compare_at_price && planAllocation.compare_at_price !== planAllocation.price ) { $comparePriceSpan.innerHTML = `${formatMoney( planAllocation.compare_at_price, )}`; $comparePriceSpan.style.display = 'inline'; } else { $comparePriceSpan.style.display = 'none'; } } } else { if ($priceRegular) { $priceRegular.innerHTML = `${formatMoney( this.product.selected_variant.price, )}`; } if (this.product.selected_variant.compare_at_price) { $comparePriceSpan.innerHTML = formatMoney( this.product.selected_variant.compare_at_price, ); $comparePriceSpan.style.display = 'inline'; } else { $comparePriceSpan.style.display = 'none'; } } // make sure theme did not try to display=block if ($priceRegular) $priceRegular.style.display = 'inline'; //for testing purposes if ($priceRegular) $priceRegular.dataset.test = 'priceRegular'; // hide this because we are not longer using this elements. if ($priceSale) $priceSale.style.display = 'none'; //for testing purposes if ($priceSale) $priceSale.dataset.test = 'priceOnSale'; // make sure theme did not tried to decorate text if ($priceRegular) $priceRegular.style.textDecoration = 'none'; if ( this.product?.selected_variant?.compare_at_price === this.product.selected_variant.price || this.product?.selected_variant?.compare_at_price === planAllocation?.price || this.product?.selected_variant?.price === planAllocation?.price ) { if ($comparePriceSpan) $comparePriceSpan.style.display = 'none'; } }.bind(this), 100, ); }, updateBadgePrice: function (planId) { var planAllocation = this.product.selected_variant.selling_plan_allocations.find( (allo) => allo.selling_plan_id == planId, ); var planOption = this.product.selling_plans_by_id[planId]; var $priceAdjustment = this.$wrapper.querySelector( '.bundleapp-price-adjustment', ); if (planAllocation) { var value_type = planOption.price_adjustments[0].value_type; var value = planOption.price_adjustments[0].value; var symbol = value_type === 'percentage' ? '%' : ''; var strValue = value_type === 'percentage' ? value : formatMoney(value); var discount = value > 0 ? `${strValue}${symbol}` : ''; // find out if this selling plan is part of a selling plan group with multiple selling plans/frequencies const planAllocationBrothers = this.product.selected_variant.selling_plan_allocations.reduce( (acc, curr) => { if ( curr.selling_plan_group_id === planAllocation.selling_plan_group_id && curr.selling_plan_id !== planAllocation.selling_plan_id ) { acc.brothers = acc.brothers + 1; if (curr.price !== planAllocation.price) { acc.dynamicSavings = acc.dynamicSavings + 1; } } return acc; }, { brothers: 0, dynamicSavings: 0 }, ); const subscriptionLabel = `${this.getTranslation( 'subscription', 'SUBSCRIPTION', )}`; const dotSeparatorLabel = ' · '; const saveLabel = `${this.getTranslation( 'save', 'Save', )} ${discount}`; const extraDiscountLabel = `${this.getTranslation( 'extra', 'Extra', )} ${discount} ${this.getTranslation('off', 'off')}`; let badgeLabel = subscriptionLabel + dotSeparatorLabel + saveLabel; if (!discount) { badgeLabel = subscriptionLabel; } if ( this.product.selected_variant.compare_at_price && this.product.selected_variant.price != planAllocation.price ) { badgeLabel = extraDiscountLabel; } const html = `${badgeLabel}`; if (this.$badgePriceEl) { if ($priceAdjustment) { $priceAdjustment.innerHTML = html; } else { var div = document.createElement('div'); div.classList.add('bundleapp-price-adjustment'); div.innerHTML = html; this.$badgePriceEl.appendChild(div); } } } else { if ($priceAdjustment) { $priceAdjustment.remove(); } } }, setSupportInformation: function () { var $description = this.$selector.querySelector( '.bundleapp-plan-selector-description', ); if ($description) { if ( this.product.selected_selling_plan && this.product.selected_selling_plan.description ) { $description.innerHTML = `${this.product.selected_selling_plan.description}`; } else { $description.innerHTML = ''; } } }, handlePlanRadioChange: function (e) { var target = e.currentTarget || e.target; var $planGroup = target.closest('.bundleapp-plan-selector-group_wrap'); // remove selected class from previously selected group var $previouslySelected = document.querySelectorAll( '.bundleapp-plan-selector-group--selected', ); $previouslySelected.forEach((selectedGroup) => selectedGroup.classList.remove( 'bundleapp-plan-selector-group--selected', ), ); // add selected class to newly selected group $planGroup.classList.add('bundleapp-plan-selector-group--selected'); var $planSelect = $planGroup.querySelector('select'); var planId = $planSelect.value; this.product.selected_selling_plan = this.product.selling_plans_by_id[ planId ]; this.setPlansVisibility(); this.setSupportInformation(); }, handlePlanOptionsChange: function (e) { var target = e.currentTarget || e.target; var planId = target.value; if (window.bundleapp.settings.useRadioButtonFrequencySelector) { // remove selected class from previously selected plan label var $previouslySelectedLabels = document.querySelectorAll( '.bundleapp-plan-selector-radio__label--selected', ); $previouslySelectedLabels.forEach((selectedLabel) => selectedLabel.classList.remove( 'bundleapp-plan-selector-radio__label--selected', ), ); // add selected class to selected label var $label = document.querySelector( `.bundleapp-plan-selector-radio__label[for="${planId}"]`, ); if ($label) { $label.classList.add( 'bundleapp-plan-selector-radio__label--selected', ); } } this.product.selected_selling_plan = this.product.selling_plans_by_id[ planId ]; this.setPlansVisibility(); }, handleFormDomChanged: function (e) { setTimeout( function () { var variantId = this.$form.querySelector('[name=id]').value; this.product.selected_variant = this.product.variants.find( (v) => v.id == variantId, ); this.setPlansVisibility(); }.bind(this), 20, ); }, }); //Validates app is public const inPreviewMode = !!( window.location.search.includes('bundleapp-preview') || window.localStorage.getItem(PREVIEW_MODE_STORAGE_KEY) === 'true' ); // make sure preview mode is set in local storage if in preview mode inPreviewMode && window.localStorage.setItem(PREVIEW_MODE_STORAGE_KEY, inPreviewMode); // if we're in preview mode we can get rid of the URL param inPreviewMode && insertUrlParam('bundleapp-preview'); // show preview control if !appPublic and inPreviewMode if (inPreviewMode && !window.bundleapp.settings.appPublic) { showPreviewModeControl(); } // update CSS vars setCssVars(window.bundleapp.settings.shopStyleSettings); if (window.bundleapp.settings.appPublic || inPreviewMode) { window.bundleapp.BundleAppWidget = BundleAppWidget; document.dispatchEvent(new Event('bundleapp:ready')); } /** * Iterating over forms */ var shopInfoPromise = getShopInfo(); window.bundleapp.initializeForms = function () { var $forms = document.querySelectorAll("form[action='/cart/add']"); $forms.forEach(function (el) { // if we found more than one form, lets make sure we're adding only to the // forms that we want to.. if (el.getAttribute('id') == null) { } else if ($forms.length > 1) { // check if this is the installments form (from Dawn theme) before // initializing the plan selector widget if (el.getAttribute('id').includes('product-form-installment')) { return; } // additional checks will go here } var settings = window.bundleapp.settings; var $variantEl = el.querySelector('[name=id]'); // Checking if the widget has been initialized already if (el.querySelector('[data-bundleapp-wrapper]')) { console.warn('Bundleapp: Form already initialized'); return; } if ($variantEl) { var pathname = window.location.pathname; var search = window.location.search; var searchParams = new URLSearchParams(search); var reqParams = new URLSearchParams(); //gets product handle if in a product page let productHandle = pathname.includes('/products/') ? pathname.split('/').filter(Boolean).pop() : null; // If there is a container selector we want to try to get the handle from it. // This because in collection pages or product pages with recommended products it // will be easier: ie var $containerSel = el.querySelector( settings.containerSel || '[data-bundleapp-widget]', ); if ( $containerSel && $containerSel.dataset && $containerSel.dataset.bundleappWidget ) { productHandle = $containerSel.dataset.bundleappWidget; } if (productHandle) { reqParams.append('productHandle', productHandle); } var getProductSelector = function () { return; return fetch( settings.productSelectorUrl ? settings.productSelectorUrl + productHandle + '?view=selector&' + reqParams.toString() : settings.proxy + '/product-selector?' + reqParams.toString(), ).then(function (res) { if (!res.ok) { throw new Error(res.statusText); } return res.text(); }); }; // gets selected variant var variantId = $variantEl.value; if (variantId) { reqParams.append('variant', variantId); } // gets selected selling plan var sellingPlan = searchParams.get('selling_plan'); if (sellingPlan) { reqParams.append('selling_plan', sellingPlan); } var compareHtmlStrings = function (html1, html2) { // We need to remove this uuid from the string since it is always different // This is used to uniquely identify each widget. and it cannot be any product related // attribute because we could have multiple selectors for the same product var regexWrapperIdHtml = /data-bundleapp-wrapper=["|']\d+["|']/gm; var regexWrapperIdJs = /"widget_id":\s?"\d+"/gm; var str1 = (html1 || '') .replace(regexWrapperIdHtml, '') .replace(regexWrapperIdJs, ''); var str2 = (html2 || '') .replace(regexWrapperIdHtml, '') .replace(regexWrapperIdJs, ''); return str1 === str2; }; var cachedSelector; var selectorStorageKey = `bundleSelector1${productHandle + variantId}`; // We check first if there is a cached selector in local storage // to speed the render time try { cachedSelector = window.localStorage.getItem(selectorStorageKey); if (cachedSelector) { Promise.all([shopInfoPromise]).then(function () { if (window.bundleapp.settings.appPublic || inPreviewMode) { addAndInitiateSelector( cachedSelector, window.bundleapp.settings.shopStyleSettings, ); } }); } } catch (err) { console.error(err); } // we want to store the selector in a cache // in case there is a new version we can remove it and // create and initiate a new one var cachedDivContainer; var addAndInitiateSelector = function (htmlString, styleSettings) { var addSelector = function ($el) { // if selector style is selected use that if (styleSettings && styleSettings.SelectorStyle) { $el.classList.add(styleSettings.SelectorStyle); } // if a container class has been set in the settings this means // that we've manually set them up, use this class else if (settings.containerClass) { $el.classList.add(settings.containerClass); } // if styleSettings exist but no selector style has been chosen, default to awt-style-1 else if (styleSettings && !styleSettings.SelectorStyle) { $el.classList.add('awt-style-1'); } // final default is bundleapp-container else { $el.classList.add('bundleapp-container'); } $el.innerHTML = htmlString.trim(); var $renderBeforeEl, $renderAfterEl, $renderInsideEl; if ( settings.renderAfterSel || (styleSettings && styleSettings.RenderAfterSel) ) { $renderAfterEl = el.querySelector( settings.renderAfterSel || styleSettings.RenderAfterSel, ); } else if ( settings.renderBeforeEl || (styleSettings && styleSettings.RenderBeforeSel) ) { $renderBeforeEl = el.querySelector( settings.renderBeforeEl || styleSettings.RenderBeforeSel, ); } else if ( settings.renderInsideSel || (styleSettings && styleSettings.RenderInsideSel) ) { $renderInsideEl = el.querySelector( settings.renderInsideSel || styleSettings.RenderInsideSel, ); } // If there is a custom selector to render the widget if ($renderInsideEl) { $renderInsideEl.append($el); } else if ($containerSel) { // if the default container selector is available $containerSel.append($el); } else if ($renderAfterEl) { // else if renderAfterSel is set, render widget after that $renderAfterEl.parentNode.insertBefore( $el, $renderAfterEl.nextSibling, ); } else if ($renderBeforeEl) { // else if renderBeforeSel is set, render widget after that $renderBeforeEl.parentNode.insertBefore($el, $renderBeforeEl); } else if ($variantEl) { // else render the widget after the input field $variantEl.parentNode.insertBefore($el, $variantEl.nextSibling); } }; if (cachedDivContainer) { var newEl = document.createElement('div'); addSelector(newEl); cachedDivContainer.parentNode.removeChild(cachedDivContainer); } else { cachedDivContainer = document.createElement('div'); addSelector(cachedDivContainer); } const scriptMatches = [ ...htmlString.matchAll(/
Date Caramel Coffee Cake Recipe (2024)
Top Articles
Latest Posts
Article information

Author: Kimberely Baumbach CPA

Last Updated:

Views: 6314

Rating: 4 / 5 (61 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Kimberely Baumbach CPA

Birthday: 1996-01-14

Address: 8381 Boyce Course, Imeldachester, ND 74681

Phone: +3571286597580

Job: Product Banking Analyst

Hobby: Cosplaying, Inline skating, Amateur radio, Baton twirling, Mountaineering, Flying, Archery

Introduction: My name is Kimberely Baumbach CPA, I am a gorgeous, bright, charming, encouraging, zealous, lively, good person who loves writing and wants to share my knowledge and understanding with you.