Buy More Save More Custom Template
Overview¶
This allows developers the ability to add custom functionality that is currently not achievable by the buy more save more widget settings. These templates can use any globally accessible functions. Developers can add additional Vue.js/HTML to these templates as needed. As these templates are written in Vue.js they accept any Vue.js attributes such as v-if for conditional rendering.
Setting up Custom Templates¶
There are a couple of ways these templates can be used. They can target all widgets of that widget type or, they can target a specific widget if you do not want the custom work to be applied to all widgets of that specific widget type.
Typically developers will create a new snippet named something like "rebuy-templates.liquid" and paste the contents of the code in that file. Then render that snippet in the associated file or in the theme.liquid file if they want the template to be globally accessible.
Buy More Save More Default Template¶
<script id="rebuy-buy-more-save-more-template" type="text/template">
<div
class="rebuy-widget rebuy-buy-more-save-more rebuy-buy-more-save-more__widget"
v-cloak
:id="'rebuy-widget-' + id"
:class="[visible ? 'is-visible' : 'is-hidden']"
role="region"
aria-label="Buy More Save More Widget"
>
<div
class="rebuy-buy-more-save-more__layout"
:class="['rebuy-buy-more-save-more__layout--' + config.layout.type]">
<!-- Header -->
<div class="rebuy-buy-more-save-more__header">
<h1
v-if="getConfigLanguage('super_title')"
class="super-title rebuy-buy-more-save-more__header-super-title"
v-html="getConfigLanguage('super_title')">
</h1>
<h2
v-if="getConfigLanguage('title')"
class="primary-title rebuy-buy-more-save-more__header-title"
v-html="getConfigLanguage('title')">
</h2>
<p
v-if="getConfigLanguage('description')"
class="description rebuy-buy-more-save-more__header-description"
v-html="getConfigLanguage('description')">
</p>
</div>
<!-- /Header -->
<!-- Main -->
<div class="rebuy-buy-more-save-more__main">
<!-- Subscribe and Save Container - Above Position -->
<div
v-if="shouldShowSwitchToSubscription() && getSubscriptionLayoutPosition() === 'above'"
class="rebuy-buy-more-save-more__subscribe-and-save-container"
:class="['rebuy-buy-more-save-more__subscribe-and-save-container--' + getSubscriptionLayoutType(), 'rebuy-buy-more-save-more__subscribe-and-save-container--above']"
>
<!-- Purchase Type Tabs -->
<div class="rebuy-buy-more-save-more__purchase-type-tabs">
<div
class="rebuy-buy-more-save-more__purchase-type-tab rebuy-buy-more-save-more__purchase-type-tab--subscribe"
:class="{ 'rebuy-buy-more-save-more__purchase-type-tab--active': isSubscriptionPurchaseType() }"
@click="selectPurchaseType('subscription')"
role="button"
tabindex="0"
:aria-pressed="isSubscriptionPurchaseType() ? 'true' : 'false'"
@keydown.enter.prevent="selectPurchaseType('subscription')"
@keydown.space.prevent="selectPurchaseType('subscription')"
>
<div class="rebuy-buy-more-save-more__purchase-type-tab-content">
<span
v-html="getConfigLanguage('subscribe_and_save_label')"
class="rebuy-buy-more-save-more__purchase-type-tab-title">
</span>
<select
id="rebuy-subscription-frequency-select"
class="rebuy-select rebuy-buy-more-save-more__subscription-frequency-select"
v-model="selected_interval"
@change="updateSubscriptionInterval(selected_interval)"
@click.stop
:aria-label="getConfigLanguage('subscribe_and_save_label')"
>
<option
v-for="(interval, interval_index) in selling_plan_interval_list"
v-bind:key="'rebuy-buy-more-save-more-subscription-interval--' + interval_index"
v-bind:value="interval">
{{ interval }}
</option>
</select>
</div>
</div>
<div
v-if="shouldShowSwitchToOneTime()"
class="rebuy-buy-more-save-more__purchase-type-tab rebuy-buy-more-save-more__purchase-type-tab--one-time"
:class="{ 'rebuy-buy-more-save-more__purchase-type-tab--active': !isSubscriptionPurchaseType() }"
@click="selectPurchaseType('one-time')"
role="button"
tabindex="0"
:aria-pressed="!isSubscriptionPurchaseType() ? 'true' : 'false'"
@keydown.enter.prevent="selectPurchaseType('one-time')"
@keydown.space.prevent="selectPurchaseType('one-time')"
>
<div class="rebuy-buy-more-save-more__purchase-type-tab-content">
<span
v-html="getConfigLanguage('one_time_label')"
class="rebuy-buy-more-save-more__purchase-type-tab-title">
</span>
</div>
</div>
</div>
<!-- /Purchase Type Tabs -->
</div>
<!-- /Subscribe and Save Container - Above Position -->
<!-- Blocks Type -->
<div
v-if="!isProgressBarLayout()"
class="rebuy-buy-more-save-more__blocks-container"
role="radiogroup"
aria-label="Select a tier option"
:class="[
'rebuy-buy-more-save-more__blocks-container--' + config.layout.type,
'rebuy-buy-more-save-more__blocks-container--align-' + getLayoutThemeContentAlignment(),
layoutBlocksClasses
]">
<div
v-for="(tier, tier_index) in getConfigTiers()"
:key="tier_index + '-' + getTierLanguage(tier, 'label')"
:class="[
'rebuy-buy-more-save-more__block',
'rebuy-buy-more-save-more__block--' + tier_index,
'rebuy-buy-more-save-more__block--' + (selected_tier_index === tier_index ? 'active' : 'inactive')
]"
@click="selectTier(tier_index)"
@keydown.enter.prevent="selectTier(tier_index)"
@keydown.space.prevent="selectTier(tier_index)"
role="radio"
:aria-checked="selected_tier_index === tier_index ? 'true' : 'false'"
:aria-labelledby="'rebuy-tier-label-' + tier_index"
tabindex="0"
>
<div class="rebuy-buy-more-save-more__block-info-container">
<div class="rebuy-buy-more-save-more__block-info">
<div class="rebuy-buy-more-save-more__block-info-utility">
<label v-if="hasRadioButtonEnabled()" class="rebuy-radio-label">
<input
type="radio"
name="rebuy-buy-more-save-more-tier"
:id="'rebuy-buy-more-save-more-tier-' + tier_index"
v-model="selected_tier_index"
:value="tier_index"
class="radio-input rebuy-radio rebuy-buy-more-save-more__radio-input"
tabindex="-1"
:aria-label="getTierLanguage(tier, 'label') + ' - ' + formatMoney(tier.price)"
/>
<span class="radio-label sr-only" :aria-label="getTierLanguage(tier, 'label')"></span>
</label>
<div v-if="getTierImage(tier)" class="rebuy-buy-more-save-more__block-info-image">
<img
:src="getTierImage(tier)"
:alt="getTierLanguage(tier, 'label')"
class="rebuy-buy-more-save-more__block-info-image-img"
/>
</div>
</div>
<div class="rebuy-buy-more-save-more__block-info-header">
<h3
:id="'rebuy-tier-label-' + tier_index"
class="rebuy-product-title rebuy-buy-more-save-more__block-info-title"
v-html="getTierLanguage(tier, 'label')">
</h3>
<p
:id="'rebuy-tier-desc-' + tier_index"
class="rebuy-product-description rebuy-buy-more-save-more__block-info-description"
v-html="getTierLanguage(tier, 'description')">
</p>
</div>
</div>
<div class="rebuy-buy-more-save-more__block-info-body">
<div v-if="tierOnSale(tier)" class="rebuy-buy-more-save-more__block-info-price-container">
<span class="rebuy-money sale rebuy-buy-more-save-more__block-price-text rebuy-buy-more-save-more__block-info-price">
<span class="sr-only">Sale tier price: </span>
<span aria-hidden="false" v-html="formatMoney(tier.price)"></span>
</span>
<span class="rebuy-money compare-at rebuy-buy-more-save-more__block-price-text rebuy-buy-more-save-more__block-info-compare-at-price">
<span class="sr-only">Original price: </span>
<span aria-hidden="false" v-html="formatMoney(tier.compare_at_price)"></span>
</span>
</div>
<div v-if="!(tierOnSale(tier))">
<span class="rebuy-money rebuy-buy-more-save-more__block-price-text rebuy-buy-more-save-more__block-info-price">
<span class="sr-only">Price: </span>
<span aria-hidden="false" v-html="formatMoney(tier.price)"></span>
</span>
</div>
<p v-if="shouldShowUnitPriceForTier(tier)" class="rebuy-product-unit rebuy-buy-more-save-more__block-price-text rebuy-buy-more-save-more__block-info-unit">
<span class="sr-only">Unit price: </span>
<span class="rebuy-money" v-html="formatMoney(tier.unit_price)"></span>/<span class="rebuy-product-unit-text" v-html="tier.unit_label"></span>
</p>
</div>
</div>
<!-- Custom Variant Selector For Vertical/Horizontal Layout Type Only -->
<div
v-if="!isProgressBarLayout() && shouldShowVariantOptionsForTier(tier_index)"
class="rebuy-buy-more-save-more__block-info-variants">
<div
v-for="(product, product_index) in getTierSelectedProducts(tier_index)"
v-if="!productHasDefaultVariantTitle(product)"
class="rebuy-buy-more-save-more__block-info-variant"
:class="['rebuy-buy-more-save-more__block-info-variant--' + getTierSelectedProducts(tier_index).length]"
:key="product_index + '-' + product.id"
>
<label
class="rebuy-buy-more-save-more__block-info-variant-label"
:for="id + '-' + 'select' + '-' + product.id + '-' + product_index"
>
<span
v-html="getCustomSelectProductLabel(tier_index, product_index)"
class="rebuy-buy-more-save-more__block-info-variant-label-text">
</span>
</label>
<!-- Variant Selector -->
<select
v-if="isProductOptionVariantSelect()"
title="Select product variant"
:id="id + '-' + 'select' + '-' + product.id + '-' + product_index"
:class="{ hide : !isProductOptionVariantSelect() }"
class="rebuy-select"
v-bind:aria-label="'variant of ' + product.title"
v-model="product.selected_variant_id"
v-on:change="selectVariantForSelectedProduct(product, tier_index)"
>
<option
v-for="(variant, variant_index) in getVariantsOnSelectedProduct(product)"
:key="variant_index + '-' + variant.id"
class="rebuy-product-options__option"
:class="{ 'rebuy-product-options__option--oos' : !variantAvailable(variant) }"
v-bind:value="variant.id"
:disabled="!variantAvailable(variant)"
v-html="formatVariantOptionTitle(variant)">
</option>
</select>
<!-- /Variant Selector -->
<!-- Swatch Selector -->
<div
v-if="!isProductOptionVariantSelect()"
class="rebuy-product-options__button-swatches-container rebuy-buy-more-save-more__button-swatches-container"
:class="{ 'rebuy-style__hidden-block' : isProductOptionVariantSelect() }"
>
<div
v-for="option in product.options"
:key="'option-' + product.id + '-' + option.name"
class="rebuy-product-options__button-swatches rebuy-size-swatches"
>
<div
v-for="(value, value_index) in getSelectedProductOptions(option, product)"
:key="'value-' + product.id + '-' + option.name + '-' + value + '-' + value_index"
>
<div v-if="displayColorSwatches(option)" class="rebuy-product-options__button-swatch rebuy-color-swatch">
<input
:name="id + '-color-' + product_index"
:id="id + '-color-' + product_index + '-' + value + '-' + value_index"
:checked="hasSwatchOptionSelected(product, value, value_index, 'color')"
:value="value"
type="radio"
class="rebuy-color-input hide"
v-on:change="selectVariantByOption(product, option.name, value)"
:disabled="isDisabledOptionValue(product, option.name, value)"
/>
<label
:for="id + '-color-' + product_index + '-' + value + '-' + value_index"
:style="getMerchantThemeColorAssetStyle(value)"
:title="value"
class="rebuy-color-label"
:class="{ 'rebuy-product-options__button-swatch-label--disabled' : isDisabledOptionValue(product, option.name, value) }"
>
</label>
</div>
<div v-if="!displayColorSwatches(option)" class="rebuy-product-options__button-swatch rebuy-size-swatch">
<input
:name="id + '-' + option.name + '-' + product_index"
:id="id + '-' + option.name + '-' + product_index + '-' + value"
:checked="hasSwatchOptionSelected(product, value, value_index, option.name)"
:value="value"
type="radio"
class="rebuy-size-input hide"
v-on:change="selectVariantByOption(product, option.name, value)"
:disabled="isDisabledOptionValue(product, option.name, value)"
/>
<label
:for="id + '-' + option.name + '-' + product_index + '-' + value"
class="rebuy-size-label"
:class="{ 'rebuy-product-options__button-swatch-label--disabled' : isDisabledOptionValue(product, option.name, value) }"
>
{{ value }}
</label>
</div>
</div>
</div>
</div>
<!-- /Swatch Selector -->
</div>
</div>
<!-- /Custom Variant Selector For Vertical/Horizontal Layout Type Only -->
</div>
</div>
<!-- /Blocks Type -->
<!-- Progress Bar Type -->
<div
v-if="isProgressBarLayout()"
class="rebuy-buy-more-save-more__dragger-container"
:class="['rebuy-buy-more-save-more__dragger-container--' + config.layout.type]">
<div
class="rebuy-buy-more-save-more__dragger-labels"
:class="['rebuy-buy-more-save-more__dragger-labels--align-' + getLayoutThemeContentAlignment()]"
role="list"
aria-label="Available tiers"
>
<div
v-for="(tier, tier_index) in getConfigTiers()"
class="rebuy-buy-more-save-more__dragger-label"
:key="tier_index + '-' + getTierLanguage(tier, 'label')"
:class="[
'rebuy-buy-more-save-more__dragger-label--' + tier_index,
selected_tier_index >= tier_index ? 'rebuy-buy-more-save-more__dragger-label--active' : ''
]"
role="listitem"
@click="selectTier(tier_index)"
>
<div class="rebuy-buy-more-save-more__dragger-header">
<div
class="rebuy-buy-more-save-more__dragger-image-title-container"
:class="['rebuy-buy-more-save-more__dragger-image-title-container--' + getProductQuantityPosition()]"
>
<div v-if="getTierImage(tier)" class="rebuy-buy-more-save-more__dragger-image">
<img
:src="getTierImage(tier)"
:alt="getTierLanguage(tier, 'label')"
class="rebuy-buy-more-save-more__dragger-image-img"
/>
</div>
<h3
:id="'rebuy-tier-title-' + tier_index"
class="rebuy-product-title rebuy-buy-more-save-more__block-info-title"
v-html="getTierLanguage(tier, 'label')">
</h3>
</div>
<p
:id="'rebuy-tier-description-' + tier_index"
class="rebuy-product-description rebuy-buy-more-save-more__block-info-description"
v-html="getTierLanguage(tier, 'description')">
</p>
</div>
<div class="rebuy-buy-more-save-more__dragger-body">
<div v-if="tierOnSale(tier)" class="rebuy-buy-more-save-more__dragger-price-container">
<span class="rebuy-money sale rebuy-buy-more-save-more__block-price-text rebuy-buy-more-save-more__block-info-price">
<span class="sr-only">Sale tier price: </span>
<span aria-hidden="false" v-html="formatMoney(tier.price)"></span>
</span>
<span class="rebuy-money compare-at rebuy-buy-more-save-more__block-price-text rebuy-buy-more-save-more__block-info-compare-at-price">
<span class="sr-only">Original price: </span>
<span aria-hidden="false" v-html="formatMoney(tier.compare_at_price)"></span>
</span>
</div>
<div v-if="!tierOnSale(tier)">
<span class="rebuy-money rebuy-buy-more-save-more__block-price-text rebuy-buy-more-save-more__block-info-price">
<span class="sr-only">Price: </span>
<span aria-hidden="false" v-html="formatMoney(tier.price)"></span>
</span>
</div>
<p v-if="tier.should_display_unit" class="rebuy-product-unit rebuy-buy-more-save-more__block-price-text rebuy-buy-more-save-more__block-info-unit">
<span class="sr-only">Unit price: </span>
<span class="rebuy-money" v-html="formatMoney(tier.unit_price)"></span>/<span class="rebuy-product-unit-text" v-html="tier.unit"></span>
</p>
</div>
</div>
</div>
<div class="rebuy-buy-more-save-more__dragger-track-container">
<div
class="rebuy-buy-more-save-more__dragger-track-fill"
:style="{ width: getProgressBarFillPercentage() }"
></div>
<input
type="range"
v-model.number="selected_tier_index"
:min="0"
:max="getConfigTiersLastIndex()"
:step="1"
aria-label="Select tier"
:aria-valuetext="'Tier ' + (selected_tier_index + 1) + ' of ' + getConfigTiersLength()"
:aria-valuenow="selected_tier_index"
:aria-valuemin="0"
:aria-valuemax="getConfigTiersLastIndex()"
/>
</div>
<!-- Custom Variant Selector For Progress Bar Layout Type Only -->
<div
v-if="isProgressBarLayout() && shouldShowVariantOptionsForTier(selected_tier_index)"
class="rebuy-buy-more-save-more__block-info-variants">
<div
v-for="(product, product_index) in getTierSelectedProducts(selected_tier_index)"
v-if="!productHasDefaultVariantTitle(product)"
class="rebuy-buy-more-save-more__block-info-variant"
:class="['rebuy-buy-more-save-more__block-info-variant--' + getTierSelectedProducts(selected_tier_index).length]"
:key="product_index + '-' + product.id"
>
<label
class="rebuy-buy-more-save-more__block-info-variant-label"
:for="id + '-' + 'select' + '-' + product.id + '-' + product_index"
>
<span
v-html="getCustomSelectProductLabel(selected_tier_index, product_index)"
class="rebuy-buy-more-save-more__block-info-variant-label-text">
</span>
</label>
<!-- Variant Selector -->
<select
v-if="isProductOptionVariantSelect()"
title="Select product variant"
:id="id + '-' + 'select' + '-' + product.id + '-' + product_index"
:class="{ hide : !isProductOptionVariantSelect() }"
class="rebuy-select"
v-bind:aria-label="'variant of ' + product.title"
v-model="product.selected_variant_id"
v-on:change="selectVariantForSelectedProduct(product, selected_tier_index)"
>
<option
v-for="(variant, variant_index) in getVariantsOnSelectedProduct(product)"
:key="variant_index + '-' + variant.id"
class="rebuy-product-options__option"
:class="{ 'rebuy-product-options__option--oos' : !variantAvailable(variant) }"
v-bind:value="variant.id"
:disabled="!variantAvailable(variant)"
v-html="formatVariantOptionTitle(variant)">
</option>
</select>
<!-- /Variant Selector -->
<!-- Swatch Selector -->
<div
v-if="!isProductOptionVariantSelect()"
class="rebuy-product-options__button-swatches-container rebuy-buy-more-save-more__button-swatches-container"
:class="{ 'rebuy-style__hidden-block' : isProductOptionVariantSelect() }"
>
<div
v-for="option in product.options"
:key="'option-' + product.id + '-' + option.name"
class="rebuy-product-options__button-swatches rebuy-size-swatches"
>
<div
v-for="(value, value_index) in getSelectedProductOptions(option, product)"
:key="'value-' + product.id + '-' + option.name + '-' + value + '-' + value_index"
>
<div v-if="displayColorSwatches(option)" class="rebuy-product-options__button-swatch rebuy-color-swatch">
<input
:name="id + '-color-' + product_index"
:id="id + '-color-' + product_index + '-' + value + '-' + value_index"
:checked="hasSwatchOptionSelected(product, value, value_index, 'color')"
:value="value"
type="radio"
class="rebuy-color-input hide"
v-on:change="selectVariantByOption(product, option.name, value)"
:disabled="isDisabledOptionValue(product, option.name, value)"
/>
<label
:for="id + '-color-' + product_index + '-' + value + '-' + value_index"
:style="getMerchantThemeColorAssetStyle(value)"
:title="value"
class="rebuy-color-label"
:class="{ 'rebuy-product-options__button-swatch-label--disabled' : isDisabledOptionValue(product, option.name, value) }"
>
</label>
</div>
<div v-if="!displayColorSwatches(option)" class="rebuy-product-options__button-swatch rebuy-size-swatch">
<input
:name="id + '-' + option.name + '-' + product_index"
:id="id + '-' + option.name + '-' + product_index + '-' + value"
:checked="hasSwatchOptionSelected(product, value, value_index, option.name)"
:value="value"
type="radio"
class="rebuy-size-input hide"
v-on:change="selectVariantByOption(product, option.name, value)"
:disabled="isDisabledOptionValue(product, option.name, value)"
/>
<label
:for="id + '-' + option.name + '-' + product_index + '-' + value"
class="rebuy-size-label"
:class="{ 'rebuy-product-options__button-swatch-label--disabled' : isDisabledOptionValue(product, option.name, value) }"
>
{{ value }}
</label>
</div>
</div>
</div>
</div>
<!-- /Swatch Selector -->
</div>
</div>
<!-- /Custom Variant Selector For Progress Bar Layout Type Only -->
</div>
<!-- /Progress Bar Type -->
<!-- Subscribe and Save Container - Below Position -->
<div
v-if="shouldShowSwitchToSubscription() && getSubscriptionLayoutPosition() === 'below'"
class="rebuy-buy-more-save-more__subscribe-and-save-container"
:class="['rebuy-buy-more-save-more__subscribe-and-save-container--' + getSubscriptionLayoutType(), 'rebuy-buy-more-save-more__subscribe-and-save-container--below']"
>
<!-- Purchase Type Tabs -->
<div class="rebuy-buy-more-save-more__purchase-type-tabs">
<div
class="rebuy-buy-more-save-more__purchase-type-tab rebuy-buy-more-save-more__purchase-type-tab--subscribe"
:class="{ 'rebuy-buy-more-save-more__purchase-type-tab--active': isSubscriptionPurchaseType() }"
@click="selectPurchaseType('subscription')"
role="button"
tabindex="0"
:aria-pressed="isSubscriptionPurchaseType() ? 'true' : 'false'"
@keydown.enter.prevent="selectPurchaseType('subscription')"
@keydown.space.prevent="selectPurchaseType('subscription')"
>
<div class="rebuy-buy-more-save-more__purchase-type-tab-content">
<span
v-html="getConfigLanguage('subscribe_and_save_label')"
class="rebuy-buy-more-save-more__purchase-type-tab-title">
</span>
<select
id="rebuy-subscription-frequency-select-below"
class="rebuy-select rebuy-buy-more-save-more__subscription-frequency-select"
v-model="selected_interval"
@change="updateSubscriptionInterval(selected_interval)"
@click.stop
:aria-label="getConfigLanguage('subscribe_and_save_label')"
>
<option
v-for="(interval, interval_index) in selling_plan_interval_list"
v-bind:key="'rebuy-buy-more-save-more-subscription-interval-below--' + interval_index"
v-bind:value="interval">
{{ interval }}
</option>
</select>
</div>
</div>
<div
v-if="shouldShowSwitchToOneTime()"
class="rebuy-buy-more-save-more__purchase-type-tab rebuy-buy-more-save-more__purchase-type-tab--one-time"
:class="{ 'rebuy-buy-more-save-more__purchase-type-tab--active': !isSubscriptionPurchaseType() }"
@click="selectPurchaseType('one-time')"
role="button"
tabindex="0"
:aria-pressed="!isSubscriptionPurchaseType() ? 'true' : 'false'"
@keydown.enter.prevent="selectPurchaseType('one-time')"
@keydown.space.prevent="selectPurchaseType('one-time')"
>
<div class="rebuy-buy-more-save-more__purchase-type-tab-content">
<span
v-html="getConfigLanguage('one_time_label')"
class="rebuy-buy-more-save-more__purchase-type-tab-title">
</span>
</div>
</div>
</div>
<!-- /Purchase Type Tabs -->
</div>
<!-- /Subscribe and Save Container - Below Position -->
</div>
<!-- /Main -->
</div>
</div>
</script>