Product Variants on Product lists (collections/homepage)
This will allow variants to show and be selected below products on product lists. Allows for adding product to the cart on homepage and collection pages.
add below to after pricing around line 42 - product-loop.liquid
{% include 'product-add-to-cart-form' with product-loop %}
replace code with below - products-list.liquid
<div class="row{% if thumbnail_layout == 'masonry' %} masonry-collection{% endif %}">
{% if template contains 'index' %}
{% if t_object != blank %}
{% assign product_collection = t_object %}
{% elsif products-list != blank %}
{% assign product_collection = products-list %}
{% else %}
{% assign product_collection = collections[settings.homepage-products-collection] %}
{% endif %}
{% elsif collection %}
{% assign product_collection = collection %}
{% endif %}
{% if template contains 'index' or products-list == 'limit' %}
{% if settings.homepage-products-limit contains 'unlimited' %}{% assign limit = nil %}{% else %}{% assign limit = settings.homepage-products-limit %}{% endif %}
{% endif %}
{% for p in product_collection.products | limit: limit %}
{% assign product_count = forloop.length %}
{% include 'product-loop' with p %}
{% endfor %}
</div>
<style>
#product-form > .product-variants{
margin: 0;
}
.swatch {
position: relative;
clear: both;
}
.swatch_dropdown-wrapper .swatch{
height: 85px;
}
.swatch .header{
font-size: 18px;
}
.swatch-container {
position: absolute;
}
.swatch-container select {
cursor: pointer;
border: 1px solid #CCC;
padding: 12px;
min-width: 250px;
font-size: 15px;
box-shadow: 2px 2px 0px 0px rgba(0, 0, 0, 0.2);
outline: none;
-webkit-appearance: none;
appearance: none;
}
.swatch-container::before {
content: "\f13a";
font-family: FontAwesome;
position: absolute;
top: 0;
right: 0;
width: 20%;
height: 100%;
text-align: center;
font-size: 20px;
line-height: 50px;
color: rgba(0, 0, 0, 0.5);
background-color: rgba(0, 0, 0, 0.1);
pointer-events: none;
}
.swatch-container:hover::before {
color: rgba(0, 0, 0, 0.6);
background-color: rgba(0, 0, 0, 0.2);
}
.swatch-container:hover select{
background: white;
}
.swatch-container select option {
padding: 30px;
}
.swatch_image-wrapper .swatch label{
height: auto!important;
}
</style>
<style>
/*
Swatches Styles
*/
{% assign width = '50px' %}
{% assign height = '35px' %}
.swatch {
margin:1em 0;
}
/* Label */
.swatch .header {
margin: 0.5em 0;
}
/* Hide radio buttons.*/
.swatch input {
display:none;
}
.swatch label {
/* Rounded corners */
-webkit-border-radius:2px;
-moz-border-radius:2px;
border-radius:2px;
/* To give width and height */
float:left;
/* Color swatches contain no text so they need to have a width. */
min-width:{{ width }} !important;
height:{{ height }} !important;
/* No extra spacing between them */
margin:0;
/* The border when the button is not selected */
border:#ccc 1px solid;
/* Background color */
background-color:#ddd;
/* Styling text */
font-size:13px;
text-align:center;
line-height:{{ height }};
white-space:nowrap;
text-transform:uppercase;
}
.swatch-element label { padding:0 10px; }
.color.swatch-element label { padding:0; }
/* Styling selected swatch */
/* Slightly raised */
.swatch input:checked + label {
-webkit-box-shadow:0px 1px 2px rgba(0,0,0,0.8);
-moz-box-shadow:0px 1px 2px rgba(0,0,0,0.8);
box-shadow:0px 1px 2px rgba(0,0,0,0.8);
border-color:transparent;
}
.swatch .swatch-element {
float:left;
-webkit-transform:translateZ(0); /* webkit flicker fix */
-webkit-font-smoothing:antialiased; /* webkit text rendering fix */
/* Spacing between buttons */
margin:0px 10px 10px 0;
/* To position the sold out graphic and tooltip */
position:relative;
}
/* Image with the cross in it */
.crossed-out { position:absolute; width:100%; height:100%; left:0; top:0; }
.swatch .swatch-element .crossed-out { display:none; }
.swatch .swatch-element.soldout .crossed-out { display:block; }
.swatch .swatch-element.soldout label {
filter: alpha(opacity=60); /* internet explorer */
-khtml-opacity: 0.6; /* khtml, old safari */
-moz-opacity: 0.6; /* mozilla, netscape */
opacity: 0.6; /* fx, safari, opera */
}
/* Tooltips */
.swatch .tooltip {
text-align:center;
background:gray;
color:#fff;
bottom:100%;
padding: 10px;
display:block;
position:absolute;
width:100px;
left:{{ width | remove: 'px' | to_number | divided_by: 2 | minus: 50 | plus: 2 }}px;
margin-bottom:15px;
/* Make it invisible by default */
filter:alpha(opacity=0);
-khtml-opacity: 0;
-moz-opacity: 0;
opacity:0;
visibility:hidden;
/* Animations */
-webkit-transform: translateY(10px);
-moz-transform: translateY(10px);
-ms-transform: translateY(10px);
-o-transform: translateY(10px);
transform: translateY(10px);
-webkit-transition: all .25s ease-out;
-moz-transition: all .25s ease-out;
-ms-transition: all .25s ease-out;
-o-transition: all .25s ease-out;
transition: all .25s ease-out;
-webkit-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
-moz-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
-ms-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
-o-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
z-index: 10000;
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
box-sizing:border-box;
}
.swatch .tooltip:before {
bottom:-20px;
content:" ";
display:block;
height:20px;
left:0;
position:absolute;
width:100%;
}
/* CSS triangle */
.swatch .tooltip:after {
border-left:solid transparent 10px;
border-right:solid transparent 10px;
border-top:solid gray 10px;
bottom:-10px;
content:" ";
height:0;
left:50%;
margin-left:-13px;
position:absolute;
width:0;
}
.swatch .swatch-element:hover .tooltip {
filter:alpha(opacity=100);
-khtml-opacity:1;
-moz-opacity:1;
opacity:1;
visibility:visible;
-webkit-transform:translateY(0px);
-moz-transform:translateY(0px);
-ms-transform:translateY(0px);
-o-transform:translateY(0px);
transform:translateY(0px);
}
.swatch.error {
background-color:#E8D2D2!important;
color:#333!important;
padding:1em;
border-radius:5px;
}
.swatch.error p {
margin:0.7em 0;
}
.swatch.error p:first-child {
margin-top:0;
}
.swatch.error p:last-child {
margin-bottom:0;
}
.swatch.error code {
font-family:monospace;
}
</style>
<script>
// Select Button product swatches options
$('.swatch-element').click( function(evt) {
var $this = $(this);
setTimeout(function(){
var $thisthis = $this.parent().parent().parent('.product-variants');
var $checker = $thisthis.find(".product--options-wrapper");
var s1 = $this.children("input:checked").val();
//console.log( s1+" ///// " );
$checker.find('.submit-radio-var').each( function() {
console.log( s1+" ///// " +$(this).text());
if( $(this).text() == s1){
$(this).prev('input').addClass('foo').trigger('click');
if( $(this).next('.submit-radio-qty').text() <= 0 && $(this).next('.submit-radio-qty').next('.submit-radio-inv_management').text() != '' && $(this).next('.submit-radio-qty').next('.submit-radio-inv_management').next('.submit-radio-inv_policy').text() != 'continue' ){
$thisthis.find('#soldout-message').fadeIn();
}
else{
$thisthis.find('#soldout-message').fadeOut();
}
}
});
var $changes = $thisthis.parent().parent();
var moneyFormat = "{% if settings.show-currency-with-prices == 'with-currency' %}{{ shop.money_with_currency_format }}{% else %}{{ shop.money_format }}{% endif %}";
var varPrice = $changes.find('.submit-radio-var-wrapper input:checked').parent().children('.submit-radio-var_price').text();
var formattedMoney = Shopify.formatMoney(varPrice, moneyFormat);
$changes.find('.product-price').html('<span class="money">'+formattedMoney+'</span>');
var compareAtPrice = $changes.find('.compare-at-price .compare-at-price-field');
var comparePrice = parseInt(compareAtPrice.text());
if(comparePrice > 0){
var compareAtFormattedMoney = Shopify.formatMoney(comparePrice, moneyFormat);
compareAtPrice.show().find('.compare-at-price-field').html('<span class="money">'+compareAtFormattedMoney+'</span>');
}
}, 100);
});
</script>
replace code with below - product-add-to-cart-form.liquid
{% assign product = product-loop %}
<form id="{% include '__advanced-layout-id' with 'product-form' %}" action="/cart/add" method="post" role="form" enctype="multipart/form-data">
<div class="product-variants">
<div class="swatch_button-wrapper">
{% if product.available and product.variants.size > 1 %}
{% for option in product.options %}
{% include 'swatch' with option %}
{% endfor %}
{% endif %}
<hr style="clear: both;" />
</div>
<div id="soldout-message" style="display:none;">Sorry, sold out</div>
<div id="product--options-wrapper-main" class="product--options-wrapper" style="display:none;">
{% for v in product.variants %}
<div class="submit-radio-var-wrapper" id="submit-radio-var_{{forloop.index}}">
<input {% if forloop.index == 1 %}checked{% endif %} type="radio" name="id" value="{{ v.id }}">
<span class="submit-radio-var">{{ v.title }}</span>
|-<span class="submit-radio-qty">{{v.inventory_quantity}}</span>-|
==<span class="submit-radio-inv_management">{{v.inventory_management}}</span>
==<span class="submit-radio-inv_policy">{{v.inventory_policy}}</span>
==<span class="submit-radio-var_price">{{v.price}}</span>
</div>
{% endfor %}
</div>
{% if product.metafields.properties.size > 0 %}
<div class="col-xs-12 col-lg-6">
{% for l_item in product.metafields.properties %}
{% assign key = l_item.first | split: ':' %}
{% assign key_type = key.last %}
{% assign key_title = key.first %}
{% assign value = l_item.last %}
<div class="form-group">
<label>{{ key_title }}</label>
{% if key_type == 'select' %}
{% assign value_array = value | split: ',' %}
<select class="form-control" name="properties[{{ key_title }}]">
{% for v in value_array %}
<option value="{{ v }}">{{ v }}</option>
{% endfor %}
</select>
{% elsif key_type == 'text' %}
<input type="text" class="form-control" name="properties[{{ key_title }}]" placeholder="{{ value }}" />
{% elsif key_type == 'checkbox' %}
<p><input type="checkbox" name="properties[{{ key_title }}]" value="{{ value }}" /> {{ value }}</p>
{% elsif key_type == 'file' %}
<p><input type="file" id="{{ key_title }}" name="properties[{{ key_title }}]"> <small><em>{{ value }}</em></small></p>
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}
</div>
{% if product.template_suffix == 'quantity-limit-1' %}
{% assign product_max_qty = 1 %}
{% for line_item in cart.items %}
{% if product.id == line_item.product_id %}
{% assign disable_btn = true %}
{% endif %}
{% endfor %}
{% elsif product.template_suffix == 'quantity-limit-2' %}
{% assign product_max_qty = 2 %}
{% for line_item in cart.items %}
{% if product.id == line_item.product_id %}
{% assign disable_btn = true %}
{% endif %}
{% endfor %}
{% elsif product.template_suffix == 'quantity-limit-3' %}
{% assign product_max_qty = 3 %}
{% for line_item in cart.items %}
{% if product.id == line_item.product_id %}
{% assign disable_btn = true %}
{% endif %}
{% endfor %}
{% elsif product.template_suffix == 'quantity-limit-4' %}
{% assign product_max_qty = 4 %}
{% for line_item in cart.items %}
{% if product.id == line_item.product_id %}
{% assign disable_btn = true %}
{% endif %}
{% endfor %}
{% elsif product.template_suffix == 'quantity-limit' %}
{% assign product_max_qty = settings.product-max-quantity %}
{% for line_item in cart.items %}
{% if product.id == line_item.product_id %}
{% assign disable_btn = true %}
{% endif %}
{% endfor %}
{% endif %}
<div class="row {% unless disable_btn == blank %} hidden{% endunless %}">
<div class="col-sm-4 quantity-wrap">
{% unless price_is_poa %}
<div class="form-group">
<input class="form-control input-lg" type="number" id="quantity" placeholder="Quantity" name="quantity" value="1" min="0"{% if product_max_qty %} max="{{ product_max_qty }}"{% endif %} />
</div>
{% endunless %}
</div>
<div class="col-sm-8 add-to-cart-button-wrap">
{% unless price_is_poa %}
<div class="form-group">
{% if product.template_suffix == 'preorder' %}
{% assign cart_label = 'Preorder' %}
{% else %}
{% assign cart_label = 'Add to cart' %}
{% endif %}
<input type="submit" name="add" value="{% include '__localize' with cart_label %}" id="purchase" class="btn-main purchase-btn {% if product.template_suffix == 'preorder' %}preorder-btn{% endif %}" />
</div>
{% endunless %}
{% if settings.secondary-call-to-action-url != blank %}
<p class="secondary-call-to-action"><br><em>{% include '__localize' with settings.secondary-call-to-action-text %}</em><br><a href="{{ settings.secondary-call-to-action-url }}?title={{ product.title | replace: ' ', '%20' }}&handle={{ product.handle }}"><strong>{% include '__localize' with settings.secondary-call-to-action-link-text %}</strong></a></p>
{% endif %}
{% comment %} {% if settings.show-social-share-links %}
<div class="share-icons">
{% capture tweet %}https://twitter.com/intent/tweet?text={% include '__localize' with 'Check out' %} {{ page_title }}—{{ canonical_url }}{% unless settings.social-links-twitter == blank %} (via @{{ settings.social-links-twitter | split: '/' | last }}){% endunless %}{% endcapture %}
{% capture email_subject %}{% include '__localize' with 'Check out' %} {{ page_title }}{% endcapture %}
{% capture email_body %}{% include '__localize' with 'Hey' %}, {% include '__localize' with 'I was just looking at' %} {{ page_title }} {% include '__localize' with 'on' %} {{ shop.name }} {% include '__localize' with 'and wanted to share it with you' %}. {% include '__localize' with 'Check out' %} {{ canonical_url }}{% endcapture %}
Share:
<a href="{{ tweet | replace: ' ','%20' }}" target="_blank"><i class="fa fa-twitter fa-fw"></i></a>
<a href="https://www.facebook.com/sharer/sharer.php?u={{ canonical_url }}" target="_blank"><i class="fa fa-facebook fa-fw"></i></a>
<a href="http://pinterest.com/pin/create/button/?url={{ canonical_url }}&media={{ product.featured_image.src | product_img_url: '2048x2048' }}&description={{ page_title | replace: ' ','%20' }}" target="_blank"><i class="fa fa-pinterest fa-fw"></i></a>
<a href="mailto:?subject={{ email_subject | replace: ' ','%20' }}&body={{ email_body }}" target="_blank"><i class="fa fa-envelope fa-fw"></i></a>
</div>
{% endif %} {% endcomment %}
</div>
</div>
</form>
{% if settings.show-notify-me %}
<div class="row notify-me-wrapper">
<div class="col-xs-12">
{% form 'contact' %}
<div class="notify-me-form well">
<h3>{{ product.title }} is unavailable</h3>
<p>{% include '__localize' with 'Leave your email address if you would like to be notified when it becomes available.' %}</p>
<div class="alert" style="display: none"></div>
<div class="form-group">
<input type="hidden" name="contact[body]" value="Please notify me when {{ product.title | escape }} becomes available." />
<div class="input-group">
<input class="form-control input-lg{% if form.errors contains 'email' %} error{% endif %}" id="{% include '__advanced-layout-id' with 'notify-input' %}" required="required" type="email" name="contact[email]" placeholder="your@email.com" value="{{ contact.fields.email }}" />
<span class="input-group-btn">
<input class="btn btn-primary btn-lg" type="submit" value="{% include '__localize' with 'Notify me' %}" >
</span>
</div>
</div>
</div>
{% endform %}
</div>
</div>
<hr>
{% endif %}
<script>
jQuery(function() {
// option selectors extended with boostrap markup and link options
//new Shopify.BootstrapifyOptionSelectors("{% include '__advanced-layout-id' with 'product-select' %}", { product: {{ product | json }}, onVariantSelected: selectCallback, enableHistoryState: true{% unless settings.show-unavailable-products %}, linkOptions: true {% endunless %}});
//{% for option in product.options %}
//$('.single-option-selector:eq({{ forloop.index0 }})').prepend('<option value="">Pick a {{ product.options[forloop.index0] }}</option>').val('').trigger('change');
//{% endfor %}
if( $('.compare-at-price .compare-at-price-field').text() == "" ){
$('.compare-at-price').hide();
}
{% if product.template_suffix == 'quantity-limit' %}
$('.purchase-btn').on('click', function() {
$('#product-form .row').hide();
});
{% endif %}
});
</script>