Tutorial on editing existing theme to use products with multiple options

From Shopify Wiki

Jump to: navigation, search

Contents

Product Options Liquid Tutorial

Please review the new additional liquid parameters available for the Product and its variants.

All current default themes support products with multiple options by default. If you apply one of these themes as your new theme, no further action is needed to support multiple options.

This tutorial discusses how to update an existing theme to use Shopify's new multiple option javascript helper. This javascript helper will build multiple select dropdown boxes for a given product, so that users can easily select a product variant by selecting different values for each product option. A callback mechanism allows designers to provide a callback action to enable/disable their 'add to cart' button, update price field, etc.

While designers can create their own selector methods as they see fit, using the built-in javascript helper is an easy way to implement multiple select boxes as a way to select product variants.

Quick Overview of Steps

  1. Include new options javascript helper to theme.liquid
  2. Update product.liquid to use <select> tag and use unique ids
  3. Define a callback
  4. Instantiate javascript with valid parameters


1. Update theme.liquid to include OptionSelector javascript

Each theme must include the following code in the header of their theme.liquid file.

Insert into the head section
{{ 'option_selection.js' | shopify_asset_url | script_tag }}
If you are using prototype.js, ensure you are using the prototype version 1.6, by including the following (update lightbox.js if you are using this as well)
{{ 'prototype/1.6/prototype.js' | global_asset_url  | script_tag }}
{{ 'lightbox/v2/lightbox.css'   | global_asset_url  | stylesheet_tag }}
{{ 'lightbox/v2/lightbox.js'    | global_asset_url  | script_tag }}


for example
...
...
<head>
<title>{{ shop.name }} — {{ page_title }}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

{{ 'stylesheet.css' | asset_url | stylesheet_tag }}

<!-- Additional colour schemes for this theme. If you want to use them, just replace the above line with one of these
{{ 'caramel.css' | asset_url | stylesheet_tag }}
{{ 'sea.css' | asset_url | stylesheet_tag }}
-->

{{ 'mootools.js'        | global_asset_url  | script_tag }}
{{ 'slimbox.js'         | global_asset_url  | script_tag }}
{{ 'option_selection.js' | shopify_asset_url | script_tag }}

{{ content_for_header }}
</head>
...
...
  

2. Update Product.liquid

Inside your product.liquid file, ensure you have a <form> element that posts to the /cart/add action, and that contains a <select> element that contains all the variants for your given product.

For example:

<form action="/cart/add" method="post">
  <div id="product-variants">
      <div id="price-field"></div>

      <select id="product-select" name='id'>
        {% for variant in product.variants %}
          <option value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money }}</option>
        {% endfor %}
      </select>
  </div>

    <input type="image" src="{{ 'purchase.png' | asset_url }}" name="add" value="Purchase" id="purchase" />
</form>

You need to ensure the following elements are in place in your <form> to use Shopify's JavaScript helper:

  • use a <select> element as the selection method for your variants
  • the <select> element requires a unique id. For example, <select id='product-12-selector' name='id'>
  • there should be a DOM element for messages when selecting different variants. This is used for updating the price of the product, or setting a 'unavailable' or 'sold out' message
  • the add to cart button should have a unique id. This is to allow the callback to enable/disable the button.

There are two components to the required JavaScript script:

  • Define a callback (which is called whenever a user changes one of the newly created <select> elements
  • Instantiate the JavaScript OptionSelectors model

3. Define a callback

A callback is called whenever a user changes one of the new multiple <select> dropdown boxes. You can define a callback to perform whatever actions you need (for example, update the price, enable/disable the add to cart button if the particular option is not valid, etc.)

The format of the callback is:

var selectCallback = function(variant, selector) {
  <your code goes here>
}

Where: 
  variant : object of the selected variant (if exists). It will have the following attributes:
    { id              : id of the product variant,
      title           : concatenation of option values with ' / '. ie: Large / Blue / Cotton
      price           : price in cents
      compare_at_price: compare_at_price in cents (or null)
      weight          : weight in grams (or null)
      available       : true / false
      option1         : value of option1 
      option2         : value of option2 (or null if not used)
      option3         : value of option3 (or null if not used)
      sku             : sku (or null)
    } 
  selector : object of the calling OptionSelector. 
  

This callback will be called when any of the new <select> elements is changed by a user. Your callback should handle the following cases:

  • When variant passed in is null (no valid variant with the selected options was found)
  • When variant passed in is not available (there is a variant with the selected options, but available = false)
  • when variant passed in is available


Here's a sample callback for prototype:

  var selectCallback = function(variant, selector) {
    if (variant && variant.available == true) {
      // selected a valid variant
      $('add').disabled = false;           // reenable add-to-cart button
      $('price-field').innerHTML = Shopify.formatMoney(variant.price, "{{shop.money_with_currency_format}}");  // update price field
    } else {
      // variant doesn't exist
      $('add').disabled = true;              // disable add-to-cart button      
      $('price-field').innerHTML = (variant) ? "Sold Out" : "Unavailable"; // update price-field message
    }
  };
  


Here's a sample callback function for mootools:

  var selectCallback = function(variant, selector) {
    if (variant && variant.available == true) {
      // selected a valid variant
      $('purchase').removeClass('disabled'); // remove unavailable class from add-to-cart button
      $('purchase').disabled = false;           // reenable add-to-cart button
      $('price-field').innerHTML = Shopify.formatMoney(variant.price, "{{shop.money_with_currency_format}}");  // update price field
    } else {
      // variant doesn't exist
      $('purchase').addClass('disabled');      // set add-to-cart button to unavailable class
      $('purchase').disabled = true;              // disable add-to-cart button      
      $('price-field').innerHTML = (variant) ? "Sold Out" : "Unavailable"; // update price-field message
    }
  };
  

Here's a sample callback function for jquery:

  var selectCallback = function(variant, selector) {
    if (variant && variant.available == true) {
      // selected a valid variant
      jQuery('#purchase').removeClass('disabled').removeAttr('disabled'); // remove unavailable class from add-to-cart button, and re-enable button
      jQuery('#price-field').html(Shopify.formatMoney(variant.price, "{{shop.money_with_currency_format}}"));  // update price field
    } else {
      // variant doesn't exist
      jQuery('#purchase').addClass('disabled').attr('disabled', 'disabled');      // set add-to-cart button to unavailable class and disable button
      var message = variant ? "Sold Out" : "Unavailable";    
      jQuery('#price-field').text(message); // update price-field message
    }
  };
  

4. Instantiate Shopify.OptionSelectors javascript

To use Shopify's javascript helper, you must instantiate Shopify.OptionSelectors with the id of the <select>, a javascript representation of the product, and a callback. This will hide the existing <select> element, build new <select> elements for each product option, and bind the callback to each selector.

To instantiate javascript using prototype:

  Event.observe(document, 'dom:loaded', function() {  
    new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback }); 
  });
  

To instantiate javascript using mootools:

  window.addEvent('domready', function() {
    new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback }); 
  });
  

To instantiate javascript using jquery:

  jQuery(function() {
    new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback });
  });
  


Format of javascript is:

    new Shopify.OptionSelectors(<domid of select>, { product: <product>, onVariantSelected: <callback>}); 

Where:
  <domid of select> : id of the existing <select> element for the product. Must be a <select> tag.
  <product> : javascript object that represents the product. Shopify has liquid functionality to do this automatically.
              Pass in the following liquid tag {{ product | json }}

  <callback> : the callback function that will be called whenever one of the new <select> elements is changed

  

Here's a complete prototype script that call the Shopify javascript helper to enabled multiple options for a product:

<script type="text/javascript">
// <![CDATA[  
  // prototype callback for multi variants dropdown selector
  var selectCallback = function(variant, selector) {
    if (variant && variant.available == true) {
      // selected a valid variant
      $('add').disabled = false;           // reenable add-to-cart button
      $('price-field').innerHTML = Shopify.formatMoney(variant.price, "{{shop.money_with_currency_format}}");  // update price field
    } else {
      // variant doesn't exist
      $('add').disabled = true;              // disable add-to-cart button      
      $('price-field').innerHTML = (variant) ? "Sold Out" : "Unavailable"; // update price-field message
    }
  };

  // initialize multi selector for product
  Event.observe(document, 'dom:loaded', function() {  
    new Shopify.OptionSelectors("variants", { product: {{ product | json }}, onVariantSelected: selectCallback }); 
  });
// ]]>
</script>

  

Here's a complete jquery script that calls the Shopify javascript helper to enabled multiple options for a product:

<script type="text/javascript">
// <![CDATA[  
var selectCallback = function(variant, selector) {
  if (variant && variant.available == true) {
    // selected a valid variant
    jQuery('#purchase').removeClass('disabled').removeAttr('disabled'); // remove unavailable class from add-to-cart button, and re-enable button
    jQuery('#price-field').html(Shopify.formatMoney(variant.price, "{{shop.money_with_currency_format}}"));  // update price field
  } else {
    // variant doesn't exist
    jQuery('#purchase').addClass('disabled').attr('disabled', 'disabled');      // set add-to-cart button to unavailable class and disable button
    var message = variant ? "Sold Out" : "Unavailable";    
    jQuery('#price-field').text(message); // update price-field message
  }
};

// initialize multi selector for product
jQuery(function() {
  new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback });
});
// ]]>
</script>

  

Full example using jQuery can be found here (fake store): http://writertoolbox.myshopify.com/products/stock-it . The 5 by 8 inches white notebook is sold out.