Last active
September 15, 2015 07:21
-
-
Save DanWebb/f6afc0a7ed2c1b141200 to your computer and use it in GitHub Desktop.
Variant option selection with tabs instead of select boxes and no need to initialise it in the product template.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Product page variant option selection | |
var VariantSelect = (function() { | |
var $variantSelection; | |
// The selection filters from top to bottom. Only the 2nd and 3rd option | |
// variants can become unavailable | |
function setUnavailable(index) { | |
var option1 = $variantSelection.find('.active[data-index="0"]').data('option1'); | |
if(index===0) { | |
// we need to set the unavailable items in indexes 1 & 2 (remember it's 0 index) | |
$variantSelection.find('span[data-index="1"]:not([data-option1="'+option1+'"]), span[data-index="2"]:not([data-option1="'+option1+'"])').addClass('unavailable').removeClass('active'); | |
$variantSelection.find('span[data-index="1"][data-option1="'+option1+'"], span[data-index="2"][data-option1="'+option1+'"]').removeClass('unavailable'); | |
} | |
else if(index===1) { | |
// we need to set the unavailable items in index 2 | |
var option2 = $variantSelection.find('.active[data-index="1"]').data('option2'); | |
$variantSelection.find('span[data-index="2"]:not([data-option1="'+option1+'"][data-option2="'+option2+'"])').addClass('unavailable').removeClass('active'); | |
$variantSelection.find('span[data-index="2"][data-option1="'+option1+'"][data-option2="'+option2+'"]').removeClass('unavailable'); | |
} | |
} | |
// make sure we still have an active option in each section and that all options | |
// are showing that should be | |
function setActive() { | |
$variantSelection.each(function() { | |
if(!$(this).find('span.active').length) $(this).find('span:not(.unavailable):first').addClass('active'); | |
// make sure the active item is showing | |
if(!$(this).find('span.active:visible').length) { | |
var $activeItem = $(this).find('span.active'); | |
var activeValue = $activeItem.data('val'); | |
$(this).find('span[data-val="'+activeValue+'"]:visible').hide().after($activeItem); | |
$activeItem.show(); | |
} | |
// make sure items that are not unavailable which have same name variants that | |
// are unavailable are swapped out | |
$(this).find('span.unavailable:visible').each(function() { | |
var itemText = $(this).data('val'); | |
var $validItem = $(this).siblings('span[data-val="'+itemText+'"]:not(.unavailable):first'); | |
if($validItem.length) { | |
$(this).hide().after($validItem); | |
$validItem.show(); | |
} | |
}); | |
}); | |
} | |
function getActive() { | |
if($variantSelection.find('span.active[data-index="2"]').length) return $variantSelection.find('span.active[data-index="2"]'); | |
if($variantSelection.find('span.active[data-index="1"]').length) return $variantSelection.find('span.active[data-index="1"]'); | |
if($variantSelection.find('span.active[data-index="0"]').length) return $variantSelection.find('span.active[data-index="0"]'); | |
} | |
// the last index will always hold the correct id | |
function setVariant() { | |
var $active = getActive(); | |
$('[name="id"]').val($active.data('id')); | |
$('#ProductPrice').html($active.data('price')) | |
} | |
function selectItem() { | |
if($(this).hasClass('unavailable')) return; | |
$(this).toggleClass('active').siblings('span').removeClass('active'); | |
var index = $(this).data('index'); | |
setUnavailable(index); | |
setActive(); | |
setId(); | |
} | |
function init() { | |
if(!$('.variant-selection').length) return; | |
$variantSelection = $('.variant-selection'); | |
$variantSelection.find('span').click(selectItem); | |
setActive(); | |
setVariant(); | |
} | |
return function() { | |
$(init); | |
}; | |
})(); | |
// initialise it | |
VariantSelect(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<form action="/cart/add" method="post" enctype="multipart/form-data" id="AddToCartForm" class="form-vertical"> | |
<!-- Product Price ===================== --> | |
<div itemprop="price" class="product-price"> | |
<span id="ProductPrice">{{ current_variant.price | money }}</span> | |
<!-- on sale --> | |
{% if current_variant.compare_at_price > current_variant.price %} | |
<span class="h2">was</span> <span class="h2 line-through">{{ current_variant.compare_at_price | money }}</span> | |
{% endif %} | |
</div> | |
<!-- //Product Price --> | |
<!-- | |
Variant Selection ===================== | |
Generate a set of tags for each of the variant options. | |
-- option_list ensures we don't list the same variant option twice. | |
-- class="active" represents the currently selected option | |
-- class="unavailable" greys out the options preventing it from being selected | |
-- when an option is selected each data-option(1/2/3) is checked in the VariantSelect js to | |
ensure only compatible matches can be selected | |
--> | |
{% if product.available %} | |
{% for option in product.options %} | |
{% assign option_index = forloop.index0 %} | |
{% assign option_list = '' %} | |
{% assign selected_variant = product.selected_or_first_available_variant %} | |
<div class="variant-selection"> | |
<h4>{{ option }}:</h4> | |
{% for variant in product.variants %} | |
{% if variant.available %} | |
{% if option_list contains variant.options[option_index] %} | |
<!-- hidden tags (get swapped out when a relevant option is chosen) --> | |
{% if option_index != 0 %}<span style="display:none;" data-id="{{ variant.id }}" data-index="{{ option_index }}" data-option1="{{ variant.options[0] }}" data-option2="{{ variant.options[1] }}" data-option3="{{ variant.options[2] }}" data-val="{{ variant.options[option_index] }}" data-price="{{ variant.price | money }}">{{ variant.options[option_index] }}</span>{% endif %} | |
{% else %} | |
{% assign option_list = option_list | append: variant.options[option_index] | append: ', ' %} | |
<span | |
class="{% if variant == selected_variant %}active{% endif %} {% unless variant.options[0] == selected_variant.options[0] %}{% if option_index != 0 %}unavailable{% endif %}{% endunless %}" | |
data-id="{{ variant.id }}" | |
data-index="{{ option_index }}" | |
data-option1="{{ variant.options[0] }}" | |
data-option2="{{ variant.options[1] }}" | |
data-option3="{{ variant.options[2] }}" | |
data-val="{{ variant.options[option_index] }}" | |
data-price="{{ variant.price | money }}" | |
>{{ variant.options[option_index] }}</span> | |
{% endif %} | |
{% endif %} | |
{% endfor %} | |
</div> | |
{% endfor %} | |
{% endif %} | |
<!-- //Variant Select --> | |
<!-- Form Controls ===================== --> | |
<label for="Quantity" class="quantity-selector">{{ 'products.product.quantity' | t }}</label> | |
<input type="number" id="Quantity" name="quantity" value="1" min="1" class="quantity-selector"> | |
<!-- the current variant id is stored here and submitted with the form --> | |
<input type="hidden" data-id="{{ product.selected_or_first_available_variant.id }}" name="id"> | |
<button type="submit" name="add" id="AddToCart" class="btn"> | |
<span id="AddToCartText">{{ 'products.product.add_to_cart' | t }}</span> | |
</button> | |
<!-- //Form Controls --> | |
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.variant-selection { | |
margin: 10px -10px 10px -10px; | |
h4 { margin: 0 0 3px 10px; } | |
span { | |
display: inline-block; | |
border-radius: 20px; | |
border: 1px solid $dark-shade; | |
color: $dark-shade; | |
padding: 8px 10px; | |
font-weight: 300; | |
margin: 5px 10px; | |
background: #fff; | |
cursor: pointer; | |
} | |
span.active { background: $primary-4; border-color: $primary-4; color: #fff; } | |
span.unavailable { background: $light-shade; border-color: $light-shade; color: $mid-shade; cursor: default; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment