Untitled
unknown
plain_text
8 months ago
12 kB
11
Indexable
{% comment %}
Simple and Clean Bundle Selector - Fixed
{% endcomment %}
<div class="simple-bundle-selector">
<div class="simple-options-container">
{% for variant in product.variants %}
{% if variant.title contains 'Pack' %}
<div class="simple-option-item" id="option-item-{{ variant.id }}">
<input
type="radio"
value="{{ variant.id }}"
name="simple_bundle_variant"
id="simple_bundle_variant_{{ forloop.index }}"
class="simple-variant-selector"
data-variant-id="{{ variant.id }}"
data-regular-price="{{ variant.price }}"
data-compare-price="{{ variant.compare_at_price }}"
{% if forloop.first %}checked{% endif %}
>
<label for="simple_bundle_variant_{{ forloop.index }}">
<div class="simple-option-content">
<div class="simple-option-header">
{% case variant.title %}
{% when '2 Pack' or '2 pack' %}{% when '4 Pack' or '4 pack' %}<span class="best-seller">Best Seller</span>{% when '6 Pack' or '6 pack' %}<span class="best-value">Best Value</span>
{% endcase %}
</div>
<div class="simple-circle">
{% case variant.title %}
{% when '2 Pack' or '2 pack' %}2{% when '4 Pack' or '4 pack' %}4{% when '6 Pack' or '6 pack' %}6
{% endcase %}
</div>
<div class="simple-option-price">
{{ variant.price | money }}
</div>
{% if variant.compare_at_price > 0 %}
<div class="simple-option-compare">
{{ variant.compare_at_price | money }}
</div>
{% endif %}
</div>
</label>
</div>
{% endif %}
{% endfor %}
</div>
</div>
<style>
/* Base styles */
.simple-bundle-selector {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
margin: 20px auto;
max-width: 600px;
perspective: 1000px;
}
.simple-options-container {
display: flex;
justify-content: center;
gap: 10px;
}
.simple-option-item {
position: relative;
flex: 1;
min-width: 0;
flex-basis: 33.333%;
transition: all 0.3s ease;
}
.simple-option-item input[type="radio"] {
position: absolute;
opacity: 0;
}
.simple-option-item label {
display: block;
cursor: pointer;
border: 1px solid #e8e8e8;
border-radius: 10px;
padding: 15px 10px;
background-color: #fff;
transition: all 0.3s ease;
height: 100%;
}
/* Selected state and hover effects */
.simple-option-item.selected label,
.simple-option-item input[type="radio"]:checked + label {
border-color: #de96b8;
background-color: #fdf6fa;
transform: translateY(-3px);
box-shadow: 0 4px 12px rgba(222, 150, 184, 0.15);
}
.simple-option-item label:hover {
transform: translateY(-2px);
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.05);
}
.simple-option-content {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.simple-option-header {
font-size: 14px;
font-weight: 600;
margin-bottom: 8px;
min-height: 18px;
}
.best-seller, .best-value {
display: inline-block;
padding: 1px 5px;
border-radius: 3px;
font-weight: 500;
font-size: 10px;
background-color: #faeaf3;
color: #d76ea3;
transition: all 0.3s ease;
}
.simple-circle {
width: 50px;
height: 50px;
border-radius: 50%;
background-color: #f6e9f2;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: 600;
color: #8e5c7b;
margin-bottom: 12px;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.simple-option-item input[type="radio"]:checked + label .simple-circle {
transform: scale(1.08);
box-shadow: 0 0 15px rgba(222, 150, 184, 0.2);
}
.simple-option-price {
font-size: 16px;
font-weight: 600;
color: #333;
margin-top: 4px;
transition: all 0.3s ease;
}
.simple-option-item input[type="radio"]:checked + label .simple-option-price {
color: #000;
transform: scale(1.05);
}
.simple-option-compare {
font-size: 14px;
text-decoration: line-through;
color: #999;
margin-top: 2px;
transition: opacity 0.3s ease;
}
/* Responsive styles */
@media (max-width: 480px) {
.simple-option-header {
font-size: 12px;
margin-bottom: 6px;
}
.best-seller, .best-value {
padding: 1px 4px;
font-size: 9px;
}
.simple-circle {
width: 40px;
height: 40px;
font-size: 20px;
}
.simple-option-price {
font-size: 14px;
}
.simple-option-compare {
font-size: 12px;
}
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.15); }
100% { transform: scale(1.08); }
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize the bundle selector right away
initBundleSelector();
// Also initialize after a short delay to ensure everything is loaded
setTimeout(initBundleSelector, 500);
function initBundleSelector() {
// Get all option items and radio buttons
const bundleItems = document.querySelectorAll('.simple-variant-selector');
const allOptionItems = document.querySelectorAll('.simple-option-item');
// Cart form elements
const variantIdInputs = document.querySelectorAll('input[name="id"]');
// Find subscription elements
const subscribeElement = document.querySelector('input[id*="subscribe"], [id*="subscription-option"]');
const oneTimeElement = document.querySelector('input[id*="one-time"]');
// Get subscription discount percentage
const discountText = document.querySelector('[class*="save"]');
let discountPercent = 10; // Default 10%
if (discountText) {
const match = discountText.textContent.match(/\d+/);
if (match) {
discountPercent = parseInt(match[0], 10);
}
}
// Function to update displayed prices
function updatePrices() {
const isSubscription = subscribeElement && subscribeElement.checked;
bundleItems.forEach(item => {
const priceElement = item.closest('.simple-option-item').querySelector('.simple-option-price');
const compareElement = item.closest('.simple-option-item').querySelector('.simple-option-compare');
const regularPrice = parseFloat(item.getAttribute('data-regular-price'));
const comparePrice = parseFloat(item.getAttribute('data-compare-price')) || 0;
if (priceElement && !isNaN(regularPrice)) {
let finalPrice;
if (isSubscription) {
// Apply discount for subscription
finalPrice = regularPrice * (1 - discountPercent / 100);
} else {
finalPrice = regularPrice;
}
// Format using Shopify's currency converter
priceElement.textContent = formatMoney(finalPrice);
// Update compare price if present
if (compareElement && comparePrice > 0) {
compareElement.textContent = formatMoney(comparePrice);
}
}
});
}
// Helper function to format money using Shopify's currency converter
function formatMoney(cents) {
if (typeof Shopify !== 'undefined' && Shopify.formatMoney) {
return Shopify.formatMoney(cents);
}
// Simple fallback if Shopify formatter isn't available
return '$' + (cents / 100).toFixed(2);
}
// Function to update the visual selection state
function updateSelectionState() {
// Remove selected class from all items
allOptionItems.forEach(item => {
item.classList.remove('selected');
});
// Find the checked radio button and add selected class to its parent
const checkedRadio = document.querySelector('.simple-variant-selector:checked');
if (checkedRadio) {
checkedRadio.closest('.simple-option-item').classList.add('selected');
}
}
// Update all variant inputs on the page
function updateVariantSelection(variantId) {
variantIdInputs.forEach(input => {
input.value = variantId;
});
// Find main product form
const mainProductForm = document.querySelector('form[action="/cart/add"]');
if (mainProductForm) {
const mainFormVariantInput = mainProductForm.querySelector('input[name="id"]');
if (mainFormVariantInput) {
mainFormVariantInput.value = variantId;
mainFormVariantInput.dispatchEvent(new Event('change', { bubbles: true }));
}
}
// Get the subscription app dropdown if it exists and update it
const subscriptionDropdown = document.querySelector('.rc_widget__option_selector, [id*="purchase-options"]');
if (subscriptionDropdown) {
subscriptionDropdown.value = variantId;
subscriptionDropdown.dispatchEvent(new Event('change', { bubbles: true }));
}
}
// Handle bundle selection
bundleItems.forEach(item => {
item.addEventListener('change', function() {
const variantId = this.value;
// Update the form
updateVariantSelection(variantId);
// Update visual selection state
updateSelectionState();
// Add pulse animation to the circle
const circle = this.closest('.simple-option-item').querySelector('.simple-circle');
circle.style.animation = 'none';
setTimeout(() => {
circle.style.animation = 'pulse 0.6s';
}, 10);
});
});
// Listen for subscription option changes
if (subscribeElement) {
subscribeElement.addEventListener('change', updatePrices);
}
if (oneTimeElement) {
oneTimeElement.addEventListener('change', updatePrices);
}
// Watch for DOM changes that might affect pricing
document.addEventListener('click', function() {
setTimeout(updatePrices, 100);
});
// Monitor the subscription app elements for changes
const subscriptionContainer = document.querySelector('.rc_container, .purchase-options-container, [class*="subscription"]');
if (subscriptionContainer) {
const subscriptionObserver = new MutationObserver(function(mutations) {
updatePrices();
});
subscriptionObserver.observe(subscriptionContainer, {
childList: true,
subtree: true,
characterData: true,
attributes: true
});
}
// Also listen for variant changes from the subscription app
const subscriptionDropdown = document.querySelector('.rc_widget__option_selector, [id*="purchase-options"]');
if (subscriptionDropdown) {
subscriptionDropdown.addEventListener('change', function() {
// Find corresponding bundle variant
const selectedVariantId = this.value;
bundleItems.forEach(item => {
if (item.value === selectedVariantId) {
item.checked = true;
updateSelectionState();
}
});
});
}
// When a product variant selection changes outside our bundle
document.addEventListener('variant:changed', function(event) {
if (event.detail && event.detail.variant) {
const newVariantId = event.detail.variant.id.toString();
bundleItems.forEach(item => {
if (item.value === newVariantId) {
item.checked = true;
updateSelectionState();
}
});
}
});
// Initial setup
updateSelectionState();
updatePrices();
}
});
</script>Editor is loading...
Leave a Comment