Variant images not updating with dropdown

New Member
2 0 0

I'm using the Plain shopify theme and manually updated it to add the ability to use variant images using Shopify's article. I have a problem with the product page, however. I've successfully got the variant to change in the URL according to what's selected in the options dropdown, but the image does not change with the selection. Here are the relevant sections in product.liquid:

 

<div class="eight columns">
          	{% assign featured_image = product.selected_or_first_available_variant.featured_image | default: product.featured_image %}
			{% if product.images.size == 0 %}
			    <div id="product-large-img">
			      <img src="{{ '' | img_url: 'grande' }}" alt="" />
			      {% if on_sale %}<div class="product-mark sale">Sale</div>{% endif %}
			    
			    </div>
			{% else %}
				<div id="product-large-img">
					<img src="{{ featured_image | img_url: 'grande' }}" alt="{{ featured_image.alt | escape }}" id="large-img" />
					{% if on_sale %}<div class="product-mark sale">Sale</div>{% endif %}
				</div>
				
				{% if product.images.size > 1 %}
				<div id="thumbs" class="clearfix">
					{% for image in product.images %}
						<img src="{{ image.src | img_url: 'grande' }}" alt="" class="two columns scale-with-grid {% cycle 'product-img-align': 'alpha', '', '', 'omega'%}">
					{% endfor %}
				</div>
				{% endif %}
			{% endif %}
			
      </div>
<script>
var selectCallback = function(variant, selector) {
  if (variant) {
    // Selected a valid variant that is available.
    if (variant.available) {
      // Enabling add to cart button.
      jQuery('#add').removeClass('disabled').removeAttr('disabled').val('{{ settings.add_to_cart_text }}').fadeTo(200,1);
      // If item is backordered yet can still be ordered, we'll show special message.
      if (variant.inventory_management && variant.inventory_quantity <= 0) {
        jQuery('#selected-variant').html({{ product.title | json }}{% unless hide_default_title %} + ' - ' + variant.title{% endunless %});
        jQuery('#backorder').removeClass("hidden");
      } else {
        jQuery('#backorder').addClass("hidden");
      }
    } else {
      // Variant is sold out.
      jQuery('#backorder').addClass('hidden');
      jQuery('#add').val('Sold Out').addClass('disabled').attr('disabled', 'disabled').fadeTo(200,0.5);
    }
    // Whether the variant is in stock or not, we can update the price and compare at price.
    if ( variant.compare_at_price > variant.price ) {
      jQuery('#product-price').html('<span class="product-price on-sale">'+ Shopify.formatMoney(variant.price, "{{ shop.money_format }}") +'</span>'+'<br /><span class="product-compare-price">Was '+Shopify.formatMoney(variant.compare_at_price, "{{ shop.money_format }}")+ '</span>');
    } else {
      jQuery('#product-price').html('<span class="product-price">'+ Shopify.formatMoney(variant.price, "{{ shop.money_format }}") + '</span>' );
    }        
  } else {
    // variant doesn't exist.
    jQuery('#backorder').addClass('hidden');
    jQuery('#add').val('Unavailable').addClass('disabled').attr('disabled', 'disabled').fadeTo(200,0.5);
  }
  if (variant && variant.featured_image) {
        var originalImage = $(".product-large-img img");
        var newImage = variant.featured_image;
        var element = originalImage[0];
        Shopify.Image.switchImage(newImage, element, function (newImageSizedSrc, newImage, element) {
            $(element).parents('a').attr('href', newImageSizedSrc);
            $(element).attr('src', newImageSizedSrc);
        });
    }
};
  
jQuery(function($) {
  new Shopify.OptionSelectors('product-select', { product: {{ product | json }}, onVariantSelected: selectCallback, enableHistoryState: true });
  
  // Add label if only one product option and it isn't 'Title'.
  {% if product.options.size == 1 and product.options.first != 'Title' %}
    $('.selector-wrapper:eq(0)').prepend('<label>{{ product.options.first }}</label>');
  {% endif %}
  
  // Auto-select first available variant on page load.
  {% assign found_one_in_stock = false %}
  {% for variant in product.variants %}
    {% if variant.available and found_one_in_stock == false %}
      {% assign found_one_in_stock = true %}
      {% for option in product.options %}
      $('.single-option-selector:eq({{ forloop.index0 }})').val({{ variant.options[forloop.index0] | json }}).trigger('change');
      {% endfor %}
    {% endif %}
  {% endfor %}
});
</script>

<script>
  jQuery(function($) {
    Shopify.Image.preload({{ product.images | json }}, '1024x1024');
  });
</script>

 

0 Likes
Shopify Expert
9807 92 1560

Much harder to troubleshoot these sorts of things without a working link but one thing I noticed was that your image container is using an id:

<div id="product-large-img">

but your JavaScript is looking for a class instead:

var originalImage = $(".product-large-img img");

Either change the js to look for the id, or change to container to have a class. Now your theme might have other script running that needs that id so you could just add a class like so.

<div id="product-large-img" class="product-large-img">

See if that makes a difference.

 

★ Winning Partner of the Build a Business competition. ★ http://freakdesign.com.au
0 Likes
New Member
2 0 0

Thanks very much Jason, that worked. Glad it was so simple!

Is it possible to extend the switching functionality to the thumbnails as well, so that when the user clicks a variant thumbnail, the select option changes accordingly? Can foresee some confusion when adding to cart.

0 Likes
New Member
4 0 0

I'm having the same problem.  I sets the correct variant url, and has the correct picture in the cart, but doesn't dynamically change the picture on the product page.  Here is my product.liquid code.  Please help!!!  :)

 

<div itemscope itemtype="http://schema.org/Product"; class="product product-scope">
  
  <meta itemprop="url" content="{{ shop.url }}{{ product.url }}" />
  <meta itemprop="image" content="{{ product.featured_image.src | product_img_url: 'grande' }}" />

  <h1 itemprop="name" class="product_title">{{ product.title }}</h1> 
  {% assign product_vendor_handle = product.vendor | handle %}
  {% comment %}
  Do we have a collection that has the same name as our product vendor name?
  If we do, let's have the vendor link point to it.
  If not, we will point to the automatic vendor collection.
  {% endcomment %}
  {% if collections[product_vendor_handle].handle == product_vendor_handle %}
    {% assign vendor_url = collections[product_vendor_handle].url %}
  {% else %}
    {% assign vendor_url = product.vendor | url_for_vendor %}
  {% endif %}
  


<div class="product_wrap">
<div class="row-fluid">

    <div id="product_image-container" class="span5">
    
    {% if product.images.size == 0 %}    
      <div class="product_image">        
        <img src="{{ '' | product_img_url: 'large' }}" alt="" />
      </div>      
    {% else %}

      <div class="product_image">
      {% assign featured_image = product.selected_or_first_available_variant.featured_image | default: product.featured_image %}
       <a href='{{ featured_image | img_url: '1024x1024' }}' class = 'cloud-zoom' id='zoom1'
            rel="adjustX: 10, adjustY:-4, softFocus:false">
            <img src="{{ featured_image | img_url: 'large' }}" alt="{{ featured_image.alt | escape }}" align="left" />
        </a>
        <div class="clearfix"></div>
      </div>      
      {% if product.images.size > 1 %}
        <div class="product_images-additional">
          <ul id="product_image-carousel" >
            <li>
              <a href='{{ featured_image | img_url: '1024x1024' }}' class='cloud-zoom-gallery'
                rel="useZoom: 'zoom1', smallImage: '{{ featured_image | img_url: 'large' }}' ">
              <img src="{{ featured_image | img_url: 'small' }}" alt="{{ featured_image.alt | escape }}"/></a>
            </li>
            {% for image in product.images offset:1 %}

              <li>
                <a href='{{ image.src | product_img_url: '1024x1024' }}' class='cloud-zoom-gallery'
                  rel="useZoom: 'zoom1', smallImage: '{{ image.src | product_img_url: 'large' }}' ">
                <img src="{{ image.src | product_img_url: 'small' }}" alt="{{ image.alt | escape }}" /></a>
              </li>

            {% endfor %}
          </ul>
          <a class="prev" id="product_image-carousel_prev" href="#"><span><i class="icon-chevron-left"></i></span></a>
          <a class="next" id="product_image-carousel_next" href="#"><span><i class="icon-chevron-right"></i></span></a>
        </div>
      {% endif %}

      <div class="product_image-slider">
        <ul class="bxslider">
            <li>
                <a href='{{ featured_image | img_url: '1024x1024' }}' class='magnific-popup'>
                  <img src="{{ featured_image | img_url: 'large' }}" alt="{{ product.title | escape }}"/>
                </a>
            </li>
            {% for image in product.images offset:1 %}

              <li>
                <a href='{{ image.src | product_img_url: '1024x1024' }}' class='magnific-popup'>
                  <img src="{{ image.src | product_img_url: 'large' }}" alt="{{ product.title | escape }}"/>
                </a>
              </li>

            {% endfor %}
          </ul>
      </div>


    {% endif %}
    </div><!-- #product-photos -->

    <div class="span7">

        {% if product.available %}
        
          {% assign hide_default_title = false %}
          {% if product.variants.size == 1 and product.variants.first.title contains 'Default' %}
            {% assign hide_default_title = true %}
          {% endif %} 
          
          <form action="/cart/add" method="post" enctype="multipart/form-data" class='form-horizontal' id="product-actions">
            <div class="options clearfix"> 

              <div id="product_price"><p class="price product-price"></p>  </div> 

              <div class="variants-wrapper clearfix {% if hide_default_title %}visuallyhidden{% endif %}"> 
                <select id="product-select" name="id">
                  {% for variant in product.variants %}
                  <option {% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} value="{{ variant.id }}">{{ variant.title | escape }} - {{ variant.price | money }}</option>
                  {% endfor %}
                </select>
              </div>            
                
              <div id="purchase"> 
                <label for="quantity">Qty: </label><input min="1" type="number" id="quantity" name="quantity" value="1" class="input-small"/>    
                <input class="btn btn-primary" type="submit" name="add" id="add-to-cart" value="Add to Cart" />
              </div>


<div id="_willet_buttons_app"></div>
     
            </div><!-- /.options -->

          </form>
      {% include 'willet-shopconnection' %}
      

        {% else %}
          <div id="product-actions" class="sold-out">
            <div id="purchase">
              <p class="price">Sold out.</p>      
            </div>
          </div>      
        {% endif %}


      <div class="product_details">
        <div class="product_type">type: {{ product.type | link_to_type }}</div>
        <div class="product_vendor">Vendor: {{ product.vendor | link_to_vendor }}</div>
      </div>

       <div id="product_description" class="rte" itemprop="description">
          <h3>Description:</h3>
          {{ product.description }}
        </div> 

       {% include 'snippet-addthis' %}
      {% include 'addthis' %}
      
    </div>
  


    <div class="row-fluid">
      <div class="span12">       
             

          {% if collection %}
            {% if collection.previous_product or collection.next_product %}
            <div class="pagination pagination__product"> 
              <ul>    
                {% if collection.previous_product %}
                  {% capture prev_url %}{{ collection.previous_product}}#content{% endcapture %}
                  <li class="left-arrow"><span class="left">{{ '&larr; Previous Product' | link_to: prev_url }}</span></li>
                {% endif %}
                {% if collection.next_product %}
                  {% capture next_url %}{{ collection.next_product}}#content{% endcapture %}
                  <li class="right-arrow"><span class="right">{{ 'Next Product &rarr;' | link_to: next_url }}</span></li>
                {% endif %}
              </ul>
            </div>
            {% endif %}
          {% endif %}
      </div>
    </div>    

</div>
</div>

</div>

  <!-- begin yotpo code  -->

<div class="yotpo yotpo-main-widget"
    data-product-id="{{ product.id }}"
    data-name="{{ product.title | escape }}"
    data-url="{{ page.url }}"
    data-image-url="{{ product.featured_image | product_img_url: "large" |replace: '?', '%3F' | replace: '&','%26'}}"
    data-description="{{ product.description | escape }}">
</div>
<!-- end yotpo code  -->

{% include 'snippet-related-products' %}

{{ 'magnific-popup.js' | asset_url | script_tag }}
{{ 'cloud-zoom.1.0.2.js' | asset_url | script_tag }}
{{ 'jquery.bxslider.min.js' | asset_url | script_tag }}
{{ 'jquery.caroufredsel.min.js' | asset_url | script_tag }}


<script>
jQuery(function($) {
  
  // Product images zoom

  $('.magnific-popup').magnificPopup({
    type: 'image',
    closeOnContentClick: true,
    mainClass: 'mfp-fade',
    image: {
      verticalFit: true
    }
  })

  $('.bxslider').bxSlider({
    mode: 'horizontal',
    captions: false,
    pager: false
  });


  $("#product_image-carousel").carouFredSel({
  responsive  : true,
  items   : {
    width   : 100,
    visible   : {
      min     : 1,
      max     : 3
    }
  },
  auto : false,
  prev : "#product_image-carousel_prev",
  next : "#product_image-carousel_next"
});

 

});

</script>

{% if product.available %}
  <script>
    var selectCallback = function(variant, selector) {
      if (variant && variant.available) {
        // selected a valid variant
        $('#add-to-cart').removeClass('disabled').removeAttr('disabled'); // remove unavailable class from add-to-cart button, and re-enable button
        if(variant.compare_at_price == null){
          $('#product_price .price').html('<span class="money"><strong>'+Shopify.formatMoney(variant.price, "{{shop.money_with_currency_format}}")+'</strong></span>');
        } else {
          $('#product_price .price').html('<span class="money"><strong>'+Shopify.formatMoney(variant.price, "{{shop.money_with_currency_format}}") + '</strong></span> <span class="money compare_at_price">was <del>' + Shopify.formatMoney(variant.compare_at_price, "{{shop.money_with_currency_format}}") + '</del></span>');
        }
      } else {
        $('#add-to-cart').addClass('disabled').attr('disabled', 'disabled'); // set add-to-cart button to unavailable class and disable button
        var message = variant ? "Sold Out" : "Unavailable";
        $('#product_price .price').text(message); // update price-field message
      }
      if (variant && variant.featured_image) {
        var originalImage = $("product_image img");
        var newImage = variant.featured_image;
        var element = originalImage[0];
        Shopify.Image.switchImage(newImage, element, function (newImageSizedSrc, newImage, element) {
            $(element).parents('a').attr('href', newImageSizedSrc);
            $(element).attr('src', newImageSizedSrc);
        });
      }
    };

    // initialize multi selector for product
    $(function() {
      new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback, enableHistoryState: true });
      
      // Add label if only one product option and it isn't 'Title'.
      {% if product.options.size == 1 and product.options.first != 'Title' %}
      $('.selector-wrapper:eq(0)').prepend('<label>{{ product.options.first }}</label>');
      {% endif %}
  
      // Auto-select first available variant on page load.
      {% assign found_one_in_stock = false %}
      {% for variant in product.variants %}
        {% if variant.available and found_one_in_stock == false %}
          {% assign found_one_in_stock = true %}
          {% for option in product.options %}
            $('.single-option-selector:eq({{ forloop.index0 }})').val({{ variant.options[forloop.index0] | json }}).trigger('change');
          {% endfor %}
        {% endif %}
      {% endfor %}
      
    });
  </script>
  {% endif %}

 

0 Likes
Shopify Expert
9807 92 1560

In your js you're trying to find a selection that matches this:

var originalImage = $("product_image img");

It won't work, unless you have a custom element like <product_image>. Do you?
I'd guess that it should be either:

var originalImage = $("#product_image img"); /* or *?
var originalImage = $(".product_image img");

Hard to be sure without seeing these things in action.

★ Winning Partner of the Build a Business competition. ★ http://freakdesign.com.au
0 Likes
New Member
4 0 0

wow-you're amazing! it worked with $(".product_image img");

the only other minor thing is the last part of the manual conversion (linking to the variant).  it says:

Linking to the variant

The line item title in the cart page typically links to the product page. Since the line item is aware of what variant was added to the cart, it should deep-link to the product's variant instead.

To do this, replace the product.url attribute of the line item...

<a href="{{ item.product.url }}">
  ...
</a>
<!-- Output: http://example.myshopify.com/products/example-product -->
... with url.

<a href="{{ item.url }}">
  ...
</a>
<!-- Output: http://example.myshopify.com/products/example-product?variant=105065082 -->

---------------------------------------------

i didn't see how to fix that in the code.  if you don't know, it's not a big deal.

 

 

also, i put the following to lines in the theme.liquid file-just checking to see if that is the right place to put it to preload the images:

  {{ 'option_selection.js' | shopify_asset_url | script_tag }}   
  <script type="text/javascript"> Shopify.Image.preload({{ product.images | json }}, '1024x1024'); </script>

you have saved me!!!!!!!!

0 Likes
Shopify Expert
9807 92 1560

i didn't see how to fix that in the code.  if you don't know, it's not a big deal.

That should be in cart.liquid (somewhere). 

also, i put the following to lines in the theme.liquid file-just checking to see if that is the right place to put it to preload the images:

It might be fine, but every theme is different so it might not be in you case. You'd want to double check that you're needing getting any errors in the browser debug console.

 

★ Winning Partner of the Build a Business competition. ★ http://freakdesign.com.au
1 Like
New Member
4 0 0

paypal tip sent-thanks for your help!

0 Likes
Shopify Partner
2 0 0

OMG Jason, can you help me! Brad's is the closes message to mine that I could find. I'm having a variant issue too. My sitte is http://riccardo-colli.myshopify.com password is: soughp

Here's the issue (link to a product page for you to see) please and thank you http://riccardo-colli.myshopify.com/products/1621-dress-classic-moc-toe as you can see, if you click on another color, it doesn't populate the shoe in that color for whatever reason.  

This theme was created before shopify had this functionality. I followed Shopify's instructions on adding and removing a line from the product liquid. I'm not a coder/programmer/designer so I have no idea about terminolgy but I can follow instructions.

 

Ty so much in advance,

 

Casey

0 Likes
Shopify Expert
9807 92 1560

@CaseyNYC - Your site looks fine to me, but it doesn't look like the image you posted. Did you change themes?

★ Winning Partner of the Build a Business competition. ★ http://freakdesign.com.au
0 Likes