How to properly display custom inventory message and update when each new variation is selected?

Highlighted
New Member
1 0 1

Background:
I am currently helping a company move their current website to Shopify and am trying to add a custom feature to the product page. I am a web designer, not a developer so I am having trouble implementing this. We are currently using the Warehouse theme.

 

Here is my situation:
At this point, our theme allows us to display an "In stock & ready to ship" or an "Out of stock" message on our product page based on a several product conditions. Here is the original code snippet on the product-info.liquid section:

 

{%- if selected_variant.available -%}
  {%- if selected_variant.inventory_management and selected_variant.inventory_policy == 'deny' and section.settings.low_inventory_threshold > 0 -%}
    {%- if selected_variant.inventory_quantity <= section.settings.low_inventory_threshold -%}
      <span class="product-form__inventory inventory inventory--low">{{ 'product.form.low_stock_with_quantity_count' | t: count: selected_variant.inventory_quantity }}</span>
    {%- else -%}
      <span class="product-form__inventory inventory inventory--high">{{ 'product.form.in_stock_with_quantity_count' | t: count: selected_variant.inventory_quantity }}</span>
    {%- endif -%}
  {%- else -%}
    <span class="product-form__inventory inventory inventory--high">{{ 'product.form.in_stock' | t }}</span>
  {%- endif -%}
{%- else -%}
  <span class="product-form__inventory inventory">{{ 'product.form.sold_out' | t }}</span>
{%- endif -%}

 

As such, this code does exactly as you would expect; if a variation is available, it will display an "In stock" message. If it is unavailable, it will display a "Out of stock" message. This theme also allows an option to show the quantity if you so choose, but I am not worried about that snippet.

 

There is one other option I would like to add to this code: our company sells a lot of items that we don't keep in stock but are able to special order for customers, so instead of emailing each customer individually to let them know it will take longer to ship, I would like to add another option to this code to display a message indicating the previously stated.

 

At this point, I have added a variable (product.form.no_stock_special_order) to the en.default.json with the exact string value: "Special order: this product will take 7-10 business days to arrive." Using said variable, I have created the following code in an attempt to display the correct message for each variable: 

 

{%- if selected_variant.available -%}
  {%- if selected_variant.inventory_management and selected_variant.inventory_policy == 'deny' and section.settings.low_inventory_threshold > 0 -%}
    {%- if selected_variant.inventory_quantity <= section.settings.low_inventory_threshold -%}
      <span class="product-form__inventory inventory inventory--low">{{ 'product.form.low_stock_with_quantity_count' | t: count: selected_variant.inventory_quantity }}</span>
    {%- else -%}
      <span class="product-form__inventory inventory inventory--high">{{ 'product.form.in_stock_with_quantity_count' | t: count: selected_variant.inventory_quantity }}</span>
    {%- endif -%}
  {%- elsif section.settings.show_special_order_option and selected_variant.inventory_management and selected_variant.inventory_policy == 'continue' -%}
    {%- if selected_variant.inventory_quantity == 0 -%}
      <span class="product-form__inventory inventory inventory--special-order">{{ 'product.form.no_stock_special_order' | t }}</span>
    {%- else -%}
      <span class="product-form__inventory inventory inventory--high">{{ 'product.form.in_stock' | t }}</span>
    {%- endif -%}
  {%- else -%}
    <span class="product-form__inventory inventory inventory--high">{{ 'product.form.in_stock' | t }}</span>
  {%- endif -%}              
{%- else -%}
  <span class="product-form__inventory inventory">{{ 'product.form.sold_out' | t }}</span>
{%- endif -%}

 

In this case, section.settings.show_special_order_option is a checkbox option I created that when checked allows this custom message to be displayed. At this point, the code works, but not exactly how I want it to, which I will explain in a bit.

 

Also, the Warehouse theme has a theme.js file with a collection of AJAX functions that execute whenever a new variation is selected. I have successfully piggybacked off of this file so as to not mess with the core functions, and have made it so that this special message receives an extra CSS class when it is active in order to give it the proper color.

 

Here is the JS snippet (keep in mind that .inventory--low gives the message a red color, .inventory--high gives the message a green color and .inventory--special-order gives the message an orange color):

 

if (newVariant['available']) {
  if (null !== variantInventoryManagement && variantInventoryPolicy === 'deny' && this.options['lowInventoryThreshold'] > 0) {
    if (variantInventoryQuantity <= this.options['lowInventoryThreshold']) {
      productFormInventoryElement.classList.add('inventory--low');
    } else {
      productFormInventoryElement.classList.add('inventory--high');
    }
  } else {
    if (variantInventoryQuantity === 0) {
      productFormInventoryElement.classList.add('inventory--special-order');
    } else {
      productFormInventoryElement.classList.add('inventory--high');
    }	  
}

This code works and changes the color of the message by changing its CSS class using AJAX. So, whenever a new variation is selected, it updates the color correctly. However, it does not update the message unless the page is manually refreshed. After doing some more digging, I also noticed that this theme uses a JSON script to display certain product information, including the inventory message. Here is the original JSON script:

 

<script type="application/json" data-product-json>
  {
    "product": {{ product | json }},
    "options_with_values": {{ product.options_with_values | json }},
    "selected_variant_id": {{ selected_variant.id }}
    {%- if section.settings.show_inventory_quantity -%}
      ,"inventories": {
        {%- for variant in product.variants -%}
          {%- if variant.available -%}
            {%- if variant.inventory_management and variant.inventory_policy == 'deny' and section.settings.low_inventory_threshold > 0 -%}
              {%- if variant.inventory_quantity <= section.settings.low_inventory_threshold -%}
                {%- capture inventory_message -%}{{ 'product.form.low_stock_with_quantity_count' | t: count: variant.inventory_quantity }}{%- endcapture -%}
              {%- else -%}
                {%- capture inventory_message -%}{{ 'product.form.in_stock_with_quantity_count' | t: count: variant.inventory_quantity }}{%- endcapture -%}
              {%- endif -%}
            {%- else -%}
              {%- capture inventory_message -%}{{ 'product.form.in_stock' | t }}{%- endcapture -%}
            {%- endif -%}
          {%- else -%}
            {%- capture inventory_message -%}{{ 'product.form.sold_out' | t }}{%- endcapture -%}
          {%- endif -%}

          "{{ variant.id }}": {
            "inventory_management": {{ variant.inventory_management | json }},
            "inventory_policy": {{ variant.inventory_policy | json }},
            "inventory_quantity": {{ variant.inventory_quantity | json }},
            "inventory_message": {{ inventory_message | json }}
          }{% unless forloop.last %},{% endunless %}
        {%- endfor -%}
      }
    {%- endif -%}
  }
</script>

And here is my updated JSON script altered to fit my new inventory message function on product-info.liquid:

 

<script type="application/json" data-product-json>
{
  "product": {{ product | json }},
  "options_with_values": {{ product.options_with_values | json }},
  "selected_variant_id": {{ selected_variant.id }}
  {%- if section.settings.show_inventory_quantity -%}
    ,"inventories": {
      {%- for variant in product.variants -%}
        {%- if variant.available -%}
          {%- if variant.inventory_management and variant.inventory_policy == 'deny' and section.settings.low_inventory_threshold > 0 -%}
            {%- if variant.inventory_quantity <= section.settings.low_inventory_threshold -%}
              {%- capture inventory_message -%}{{ 'product.form.low_stock_with_quantity_count' | t: count: variant.inventory_quantity }}{%- endcapture -%}
            {%- else -%}
              {%- capture inventory_message -%}{{ 'product.form.in_stock_with_quantity_count' | t: count: variant.inventory_quantity }}{%- endcapture -%}
            {%- endif -%}
          {%- elsif section.settings.show_special_order_option and selected_variant.inventory_management and selected_variant.inventory_policy == 'continue' -%}
            {%- if selected_variant.inventory_quantity == 0 -%}  
              {%- capture inventory_message -%}{{ 'product.form.no_stock_special_order' | t }}{%- endcapture -%}
            {%- else -%}
              {%- capture inventory_message -%}{{ 'product.form.in_stock' | t }}{%- endcapture -%}
            {%- endif -%}
          {%- else -%}
            {%- capture inventory_message -%}{{ 'product.form.in_stock' | t }}{%- endcapture -%}
          {%- endif -%}
        {%- else -%}
          {%- capture inventory_message -%}{{ 'product.form.sold_out' | t }}{%- endcapture -%}
        {%- endif -%}

        "{{ variant.id }}": {
          "inventory_management": {{ variant.inventory_management | json }},
          "inventory_policy": {{ variant.inventory_policy | json }},
          "inventory_quantity": {{ variant.inventory_quantity | json }},
          "inventory_message": {{ inventory_message | json }}
        }{% unless forloop.last %},{% endunless %}
      {%- endfor -%}
    }
  {%- endif -%}
}
</script>

When I view the page source for a variation with stock count > 0 versus the page source for a variation with stock count < 0, the message is correctly displayed in the JSON script for each respective variation. Example:

 

The source for an available variation with stock count > 0:

 

"inventories": {"34011454013485": {
              "inventory_management": "shopify",
              "inventory_policy": "continue",
              "inventory_quantity": 5,
              "inventory_message": "In stock \u0026amp; ready to ship"
            },
"34011463876653": {
              "inventory_management": "shopify",
              "inventory_policy": "continue",
              "inventory_quantity": 0,
              "inventory_message": "In stock \u0026amp; ready to ship"
            },

Vs. the source for an available variation with stock count < 0:

 

"inventories": {"34011454013485": {
              "inventory_management": "shopify",
              "inventory_policy": "continue",
              "inventory_quantity": 5,
              "inventory_message": "Special order: this product will take 7-10 business days to arrive."
            },
"34011463876653": {
              "inventory_management": "shopify",
              "inventory_policy": "continue",
              "inventory_quantity": 0,
              "inventory_message": "Special order: this product will take 7-10 business days to arrive."
            },

However, this message does not update in the product page when changing variations without manually reloading the page, which tells me it might be a problem with my JS/AJAX script. Again, I am a web designer not a developer, so I am very unfamiliar with JS. I provided a snippet of my updated JS/AJAX code previously, but here is the full version that is executed whenever a variation change is detected:

 

function _updateInventory(newVariant) {
        if (!this.options['showInventoryQuantity'] || !newVariant) {
          return;
        }

        var productFormInventoryElement = this.element.querySelector('.product-form__inventory'),
            variantInventoryManagement = this.variantsInventories[newVariant['id']]['inventory_management'],
            variantInventoryPolicy = this.variantsInventories[newVariant['id']]['inventory_policy'],
            variantInventoryQuantity = this.variantsInventories[newVariant['id']]['inventory_quantity'],
            variantInventoryMessage = this.variantsInventories[newVariant['id']]['inventory_message'];

        productFormInventoryElement.classList.remove('inventory--high');
        productFormInventoryElement.classList.remove('inventory--low');
		productFormInventoryElement.classList.remove('inventory--special-order');

        if (newVariant['available']) {
          if (null !== variantInventoryManagement && variantInventoryPolicy === 'deny' && this.options['lowInventoryThreshold'] > 0) {
            if (variantInventoryQuantity <= this.options['lowInventoryThreshold']) {
              productFormInventoryElement.classList.add('inventory--low');
            } else {
              productFormInventoryElement.classList.add('inventory--high');
            }
          } else {
			if (variantInventoryQuantity === 0) {
			  productFormInventoryElement.classList.add('inventory--special-order');
		    } else {
			  productFormInventoryElement.classList.add('inventory--high');
			}
		  }
        }

        // We also need to update the stock countdown if setup
        var stockCountdown = this.element.querySelector('.inventory-bar');

        if (stockCountdown) {
          var stockCountdownProgress = Math.min(Math.max(variantInventoryQuantity / parseInt(stockCountdown.getAttribute('data-stock-countdown-max')) * 100.0, 0), 100);

          stockCountdown.classList.toggle('inventory-bar--hidden', stockCountdownProgress === 0);
          stockCountdown.firstElementChild.style.width = stockCountdownProgress + '%';
        }

        productFormInventoryElement.innerHTML = variantInventoryMessage;
      }

You'll notice that variantInventoryMessage is the inventory message and is updated each time this code is executed, but for some reason it does not change asynchronously when the user selects a new variation, only the actual color of the message does. 

 

Please view this product page to get a better understanding of the problem (website password is rtiabe): https://kandb-sportswear.myshopify.com/products/tyr-womens-lambent-cutoutfit-swimsuit-1

 

Please also note that the size 26 suit in Green has a stock count of 3 and the size 26 in titanium has a stock count of 5; all other variations have a stock count of 0.

 

When refreshing the page with a new variation selected (one that should display a different message from the one loaded on the original page load) you'll notice the message does update. 

 

My question:
Assuming I have provided all the necessary information, I am in need of some guidance as to correct my functions/scripts to display the proper inventory message live on the product page for each variation as the user selects different variations. Could someone please help me solve this problem? Please let me know if you need any additional information from me.

 

Thank you so much in advance and I am hoping someone will be able to help me solve this.

 

Best regards,

Matt G.

Highlighted
New Member
1 0 0

I have the same question and a similar need for product page messages that change asynchronously based on variant. We're using the Warehouse theme as well, although I've run into this issue in the past with other themes. If anyone has insights, I'd be most appreciative.

0 Likes
Highlighted
Tourist
23 0 2

Hi Matt

I have the same requirement and don't want to give this a go unless I know it's going to work properly - were you ever able to sort this out?

 

Thanks

Mark

0 Likes
Highlighted
Tourist
23 0 2

OK I gave it a go and have exactly the same result you had - I see the live store is working correctly, please could you share the solution?

 

Thanks in advance.

0 Likes