Ad

Using Javascript To Display Selected Name

- 1 answer

On my shopify theme I am trying to display the name of the color next to the color label. For example if green is selected "Color:" will change to "Color: Green" and if red is selected it will change to "Color: Red". I am currently using a theme called Basel.

**Basel theme product page - https://new-basel2.myshopify.com/collections/bag/products/vintage-cinch-backpack

I've tried adding several different lines of code to my liquid file but nothing has worked. I've now realized I need to use javascript to do this. So that when a swatch is clicked, its value is taken and put it into the label.

I'm not very proficient in javascript at all. If anyone could help write the code or provide any assistance I would be extremely grateful.

swatch.liquid -

{%- include 'check_not_feature_img' -%}
<table class="variations{%- if settings.swatch_design == '2' %} variant_square{%- elsif settings.swatch_design == '3' %} variant_simple{%- endif -%}" cellspacing="0">
   {%- assign option_index = 0 -%}
   {%- if settings.color_name_check != blank -%}{%- assign _gl_color_name = settings.color_name_check | replace: ' ,', ',' | replace: ', ', ',' | split: ',' -%}{%- assign gl_color_name = _gl_color_name | downcase -%}{%-else-%}{%- assign gl_color_name = '\nathan_dt\' -%}{%-endif-%}
   <tbody>
   {%- for option in product.options_with_values -%}
      {%- assign option_index = forloop.index0 -%}
      {%- assign downcased_option = option.name | downcase -%}
      {%- assign downcased_option_check = option.name | downcase | prepend: '"' | append: '"' | strip -%} 
      {%- if downcased_option == 'color' or downcased_option == 'colour' or gl_color_name contains downcased_option_check -%}
            <tr data-option-index="{{ option_index }}" id="gl_select_{{ option_index }}">
               <td class="label"><label for="{{ option_index }}">{{ option.name }}</label></td>
               <td class="value with-swatches">
                  <div class="swatches-select" data-id="{{ option_index }}" data-option-index="{{ option_index }}">
                     {%-assign index = 0 %}
                     {%- for value in option.values -%}
                        <div class="basel-swatch bg_color basel-tooltip swatch-size-{{settings.swatch_size}}{%- if settings.swatch_style == '1' %} colored-swatch{%- else %} image-swatch{%- endif %}{%- if first_available_variant and option.selected_value == value %} active-swatch{%- elsif forloop.first == true and product.selected_variant == blank and first_available_variant == false %} active-swatch{%- elsif option.selected_value == value and product.selected_variant != blank and first_available_variant == false %} active-swatch{%- endif %} bg_color_{{ value  | handleize  }} bg_{{ value  | handleize  }} swatch-enabled" data-value='{{ value | handleize }}' data-image-id="{{ featured_image_id[index] }}">
                           <span class="basel-tooltip-label">{{ value }}</span>{{ value }}
                        </div>
                        {%-assign index = index | plus: 1 %}
                     {%- endfor -%}
                  </div>
               </td>
            </tr>
      {%- else- %}
         <tr data-option-index="{{ option_index }}" id="gl_select_{{ option_index }}">
            <td class="label"><label for="{{ option_index }}">{{ option.name }}</label></td>
            <td class="value with-swatches">
               <div class="swatches-select" data-id="{{ option_index }}" data-option-index="{{ option_index }}">
                 {%- for value in option.values -%}
                     <div class="basel-swatch basel-tooltip text-only swatch-size-{{settings.swatch_size}}{%- if first_available_variant and option.selected_value == value %} active-swatch{%- elsif forloop.first == true and product.selected_variant == blank and first_available_variant == false %} active-swatch{%- elsif option.selected_value == value and product.selected_variant != blank and first_available_variant == false %} active-swatch{%- endif %} bg_{{ value | handleize  }} swatch-enabled" data-value='{{ value | handleize }}'>
                     <span class="basel-tooltip-label">{{ value }}</span>{{ value }}
                     </div>
                 {%- endfor -%}
               </div>
            </td>
         </tr>
      {%- endif -%}
   {%- endfor -%}
   </tbody>
</table>

I need javascript to change the name of the color after the label -

 <td class="label"><label for="{{ option_index }}">{{ option.name }}</label></td>

The 3 files that contain var selectCallback = function(variant, selector)

product.design_default.liquid - https://gist.github.com/lok343/9e3286aa262b915438c091bf820eebcf

snippets/product.json.liquid - https://gist.github.com/lok343/b7251646824b6a9f265b0d7e270f64cd

snippets/product_js.liquid - https://gist.github.com/lok343/8690d8a7fb8246f0ca6730899f736050

Updated code

      var selectCallback = function(variant, selector) {
        var selectedOptions = selector.selectedValues(); // This gives an array of all the selected options
var optionData = selector.product.options;  // This gives information about the options set up on the product
var form = selector.variantIdField.form; // This gives us the enclosing form element without needing to do any query-selecting

// Now lets loop through the options and update the elements
for(var i=0; i<selectedOptions.length; i++){
  var optionLabel = form.querySelector('[data-option-index="' + i + '"] label') // This reads, "Find the first <label> element inside the element with the specified data-option-index attribute inside my product form"

  // Let's make sure our code will not break and quickly check to make sure we found the element we were after. If it's blank, continue to the next option. Raising an appropriate error is left as an exercise for the reader.
  if(!optionLabel){
    continue;
  }

  var optionName = typeof optionData[i] === 'object' ? optionData[i].name : optionData[i];  // This is checking to see which of Shopify's 2 different option formats got fed into this function - it could have been either an array of titles or an array of objects that include both the name and an array of all the values. The ( check ? result_if_true : result_if_false ) syntax is called a ternary expression and is shorthand for if(check){ value_if_true } else { value_if_false }
          if (optionName.toLowerCase('Color')) {
  optionLabel.innerText = optionName + ': ' + selectedOptions[i]
          }

}

Ad

Answer

I took a look at the page you linked, and it looks like your theme is running a function named "selectCallback" whenever the shopper's selections change.

In your theme files, look for this piece of code:

var selectCallback = function(variant, selector)

which marks the beginning of your variant-change function. This function is being rendered in-line on the product page, so it's probably coming from one of the following files:

  • The base template file - templates/product.liquid
  • A section linked from the base template - if the above contains {% section 'some-section-name' %} look in your sections folder for a file named 'some-section-name.liquid'
  • If not in either of the above, try the snippet that renders the product form, often named product-form.liquid or similar
  • A few themes put this function directly into the base layout file, layout/theme.liquid

Once you find that function, you can add a line to the javascript there to update a label for the selected colour. The variable named variant will be the newly-selected variant object (or null if the combination of selected options does not match a variant in the product), and the variable named selector contains a bunch of useful information.

The variant object contains all the information that Shopify has to describe the variant, including variant.options (an array of all the option values describing the variant) as well as variant.option1, variant.option2 and variant.option3 (references to the option values at specific indices). In the linked product, colour is the first and only option dimension, so variant.options[0] or variant.option1 are two ways you can access the colour value of the currently-selected product.

If you need to find the colour option specifically in any arbitrary product and want to ignore any other option names, I'll point you towards selector.product, which will give you access to the full product object. This means that selector.product.options will let you access all of the option names on the current product so that you can identify which dimension is the colourful one.

Example Time!

Here's an example of what you might want to add to this function.

Looking at the selector object, I see a function called selectedValues that returns an array of all of the currently-selected options. This looks useful, since a more complicated product may not have a variant for every possible combination of option selections. [Footnote]

Looking at the document structure, I see that the rendered code looks like this:

<tr data-option-index="0" id="gl_select_0">
  <td class="label"><label for="0">Color</label></td>

  <!-- (option-selecting swatches) -->
</tr>

Without updating the document structure, we can add this to your selectCallback function, which should do roughly what you need:

var selectedOptions = selector.selectedValues(); // This gives an array of all the selected options
var optionData = selector.product.options;  // This gives information about the options set up on the product
var form = selector.variantIdField.form; // This gives us the enclosing form element without needing to do any query-selecting

// Now lets loop through the options and update the elements
for(var i=0; i<selectedOptions.length; i++){
  var optionLabel = form.querySelector('[data-option-index="' + i + '"] label') // This reads, "Find the first <label> element inside the element with the specified data-option-index attribute inside my product form"

  // Let's make sure our code will not break and quickly check to make sure we found the element we were after. If it's blank, continue to the next option. Raising an appropriate error is left as an exercise for the reader.
  if(!optionLabel){
    continue;
  }

  var optionName = typeof optionData[i] === 'object' ? optionData[i].name : optionData[i];  // This is checking to see which of Shopify's 2 different option formats got fed into this function - it could have been either an array of titles or an array of objects that include both the name and an array of all the values. The ( check ? result_if_true : result_if_false ) syntax is called a ternary expression and is shorthand for if(check){ value_if_true } else { value_if_false }

  optionLabel.innerText = optionName + ': ' + selectedOptions[i]
}

That above example code could be placed anywhere in your selectCallback function. I would recommend placing it either near the beginning or near the end, outside of any if() statements within the function, as we would want this to run regardless of whether there is a successfully-selected variant or not.

Good luck!

[Footnote]

To inspect Javascript objects to see what you can do with them, I often find it expedient to:

  • Add a breakpoint to your code inside the function you're interested in. (I found the spot manually using Chrome's dev tools, you can take a shortcut by adding the keyword debugger inside your function)
  • Navigating to the page
  • Opening your browser's dev tools (Keyboard shortcut is usually F12 for most browsers running on Windows)
  • Do something on the page that will trigger the function in question (eg: click on different colour swatches)
  • The browser will now pause when it hits your breakpoint.
  • In the console tab (sometimes named 'debug' on some browsers), you can type the name of a variable you're interested in and your dev tools should auto-complete the variable name. You can now play around in console to see what the different properties are, run functions to see what their output would be, etc.
  • Remember that if you add debugger to your source code, be sure to clean that up when you're done by removing your debugging code :)
Ad
source: stackoverflow.com
Ad