Everything is working but swatch selections are not updating once "Add to Cart" is clicked (whatever the originally selected swatch was is being selected. Please advise!
product.liquid
<div data-section-id="{{ section.id }}" data-section-type="product" data-enable-history-state="true"> <form action="/cart/add" method="post" enctype="multipart/form-data"> {%- assign current_variant = product.selected_or_first_available_variant -%} {%- assign featured_image = current_variant.featured_image | default: product.featured_image -%} {% capture productTitle %}{% include 'product-title' %}{% endcapture %} {% capture productPrice %}{% include 'product-price' %}{% endcapture %} {%- capture image_alt_text -%} {{ productTitle }} - {{ shop.name }} {%- endcapture -%} {% if product.images.size > 1 %} <ul class="productThumbs"> {% for image in product.images %} <li> <a href="{{ image.src | img_url: '480x480' }}" data-thumbnail-id="{{ image.id }}" data-product-single-thumbnail> <img class="product-single__thumbnail-image" src="{{ image.src | img_url: '50x' }}" alt="{{ image_alt_text }}"> </a> </li> {% endfor %} </ul> {% endif %} <div class="mobileOnly"> <div class="vendor">{{ product.vendor }}</div> <h1 class="title">{{ productTitle }}</h1> </div> <div class="mainImage"> {% assign counter = 0 %} {% for image in product.images %} {% capture wrapper_class %} {%- unless featured_image == image -%} hide {%- endunless -%} {% endcapture %} {% capture image_attributes %} data-product-featured-image data-large="{{ image | img_url: '2048x2048' }}" {% endcapture %} <div class="img-zoom-container {{ wrapper_class }}"> {% include 'responsive-image' with image: image, max_width: 2048, max_height: 2048, image_attributes: image_attributes, image_class: 'image-zoom', wrapper_class: wrapper_class, wrapper_attributes: "data-product-image-wrapper", image_alt: image_alt_text %} <div class="zoomedContainer secret"><div id="zoomed-Image-{{ image.id }}-{{ counter }}" class="img-zoom-result"></div></div> <span class="imageInstructions">Roll over image to zoom in</span> </div> {% assign counter = counter | plus: 1 %} {% endfor %} </div> <div class="quickInfo"> <h1 class="title desktopOnly">{{ productTitle }}</h1> <div class="vendor desktopOnly">by {{ product.vendor }}</div> {{ productPrice }} <div class="rte"> <div class="description desktopOnly"> {{ product.description }} </div> {% include 'product-variants' %} </div> </div> <div class="actionsBoxContainer"> {% if section.settings.show_share_buttons %} <div class="socialSharingBox desktopOnly"> <span class="shareButtonInstructions">Share</span> {% include 'social-sharing', share_title: productTitle, share_permalink: product.url, share_image: product %} </div> {% endif %} <div class="actionsBox"> {{ productPrice }} {% if product.available %} <div class="stock inStock">In Stock.</div> {% else %} <div class="stock noStock">Out of Stock.</div> {% endif %} <div class="shipsFrom desktopOnly"> Ships from and sold by {{ shop.name }}. </div> <div class="quantity visually-hidden"> <label for="Quantity">{{ 'products.product.quantity' | t }}</label> <input type="number" id="Quantity" name="quantity" value="1" min="1"> </div> <button type="submit" name="add" class="button" data-add-to-cart {% unless current_variant.available %}disabled="disabled"{% endunless %} {% unless current_variant.price != 0 %}disabled="disabled"{% endunless %}> <span data-add-to-cart-text> {% if current_variant.available %} <span class="icon">{% include 'icon-cart' %}</span> <span class="text">{{ 'products.product.add_to_cart' | t }}</span> {% else %} <span class="soldOut">{{ 'products.product.sold_out' | t }}</span> {% endif %} </span> </button> <div class="shipsFrom mobileOnly"> Ships from and sold by {{ shop.name }}. </div> {% include 'deliver-to' %} </div> <h2 class="about mobileOnly">About this item</h2> <div class="moreInfo mobileOnly"> <div class="description">{{ product.description }}</div> {% include 'product-variants' %} </div> {% if section.settings.show_share_buttons %} <div class="socialSharingBox mobileOnly"> <span class="shareButtonInstructions">Share</span> {% include 'social-sharing', share_title: productTitle, share_permalink: product.url, share_image: product %} </div> {% endif %} {% unless product == empty %} <script type="application/json" data-product-json> {{ product | json }} </script> {% endunless %} </form> </div> {% schema %} { "name": "Product pages", "settings": [ { "type": "checkbox", "id": "show_share_buttons", "label": "Show social sharing buttons", "default": true } ] } {% endschema %} {% javascript %} $( document ).ready(function() { function imageZooming() { var windowWidth = $(window).width(); if (windowWidth >= 1300) { $('.imageInstructions').show(); $('.img-zoom-container').on({ mouseenter: function () { $(this).children('.responsive-image__wrapper').children('.img-zoom-lens').removeClass('secret'); $(this).children('.zoomedContainer').removeClass('secret'); $('.imageInstructions').html('Click image to open expanded view'); }, mouseleave: function () { $(this).children('.responsive-image__wrapper').children('.img-zoom-lens').addClass('secret'); $(this).children('.zoomedContainer').addClass('secret'); $('.imageInstructions').html('Roll over image to zoom in'); } }); $('.img-zoom-container img.image-zoom').each(function() { var zoomedId = "zoomed-" + this.id; imageZoom(this.id, zoomedId); }); } else { $('.imageInstructions').hide(); } } $(window).resize(function(){ imageZooming(); }); imageZooming(); }); {% endjavascript %}
product-variants.liquid
<div class="variants"> {% unless product.has_only_default_variant %} {% for option in product.options_with_values %} {%- capture optionValuesSize -%}{{ option.values | size }}{%- endcapture -%} <div class="selector-wrapper js swatch option{% if optionValuesSize == '1' %} oneOption{% endif %}"> {%- assign i = forloop.index0 -%} <h5 class="name">{{ option.name }}</h5> <div class="values"> {% for value in option.values %} <input class="swatch-element" id="SingleOptionSelector-{{ i }}-{{ value | handle }}" data-single-option-selector data-index="option{{ option.position }}" type="radio" name="SingleOptionSelector-{{ i }}" value="{{ value | escape }}"{% if option.selected_value == value %} checked{% endif %} {% unless current_variant.available %}disabled="disabled"{% endunless %} > <label for="SingleOptionSelector-{{ i }}-{{ value | handle }}" {% if optionValuesSize == '1' %}class="onlyOption"{% endif %}><span>{{ value }}</span></label> {% endfor %} </div> </div> {% endfor %} {% endunless %} {% if current_variant.sku != blank %} <div class="option sku"> <h5 class="name">Item #</h5> <span class="value">{{ current_variant.sku }}</span> </div> {% endif %} <select name="id" class="no-js" data-product-select> {% for variant in product.variants %} <option {% if variant == current_variant %}selected="selected"{% endif %} {% unless variant.available %}disabled="disabled"{% endunless %} value="{{ variant.id }}"> {{ variant.title }} </option> {% endfor %} </select> </div>
product.js
/** * Product Template Script * ------------------------------------------------------------------------------ * A file that contains scripts highly couple code to the Product template. * * @namespace product */ import $ from 'jquery'; import Variants from '@shopify/theme-variants'; import {formatMoney} from '@shopify/theme-currency'; import {register} from '@shopify/theme-sections'; const selectors = { addToCart: '[data-add-to-cart]', addToCartText: '[data-add-to-cart-text]', comparePrice: '[data-compare-price]', comparePriceText: '[data-compare-text]', originalSelectorId: '[data-product-select]', priceWrapper: '[data-price-wrapper]', productImageWrapper: '[data-product-image-wrapper]', productFeaturedImage: '[data-product-featured-image]', productJson: '[data-product-json]', productPrice: '[data-product-price]', productThumbs: '[data-product-single-thumbnail]', singleOptionSelector: '[data-single-option-selector]', }; const cssClasses = { activeThumbnail: 'active-thumbnail', hide: 'hide', }; const keyboardKeys = { ENTER: 13, }; /** * Product section constructor. Runs on page load as well as Theme Editor * `section:load` events. * @param {string} container - selector for the section container DOM element */ register('product', { onLoad() { this.$container = $(this.container); this.namespace = `.${this.id}`; // Stop parsing if we don't have the product json script tag when loading // section in the Theme Editor if (!$(selectors.productJson, this.$container).html()) { return; } this.productSingleObject = JSON.parse( $(selectors.productJson, this.$container).html(), ); const options = { $container: this.$container, enableHistoryState: this.$container.data('enable-history-state') || false, singleOptionSelector: selectors.singleOptionSelector, originalSelectorId: selectors.originalSelectorId, product: this.productSingleObject, }; this.settings = {}; this.variants = new Variants(options); this.$featuredImage = $(selectors.productFeaturedImage, this.$container); this.$container.on( `variantChange${this.namespace}`, this.updateAddToCartState.bind(this), ); this.$container.on( `variantPriceChange${this.namespace}`, this.updateProductPrices.bind(this), ); if (this.$featuredImage.length > 0) { this.$container.on( `variantImageChange${this.namespace}`, this.updateImages.bind(this), ); } $( ".swatch input.swatch-element" ).click(function() { // console.log(this); // $(".swatch input.swatch-element").each(function() { // $(this).prop('checked', false); // }); // var checkbox = ".swatch input#" + this.id; // $(checkbox).prop('checked', !$(checkbox).prop('checked')); $(".swatch label.selectedOnLoad").each(function() { $(this).removeClass("selectedOnLoad"); }); }); this.highlightSelectedVariantOnLoad(); this.initImageSwitch(); }, highlightSelectedVariantOnLoad() { $(".swatch input.swatch-element:checked").each(function() { $(".swatch label[for='" + this.id + "']").addClass("selectedOnLoad"); }); }, initImageSwitch() { const $productThumbs = $(selectors.productThumbs, this.$container); if (!$productThumbs.length) { return; } $productThumbs .on('click', (evt) => { evt.preventDefault(); const imageId = $(evt.currentTarget).data('thumbnail-id'); this.switchImage(imageId); this.setActiveThumbnail(imageId); }) .on('keyup', this.handleImageFocus.bind(this)); }, handleImageFocus(evt) { if (evt.keyCode !== keyboardKeys.ENTER) { return; } this.$featuredImage.filter(':visible').focus(); }, setActiveThumbnail(imageId) { let newImageId = imageId; // If "imageId" is not defined in the function parameter, find it by the current product image if (typeof newImageId === 'undefined') { newImageId = $( `${selectors.productImageWrapper}:not('.${cssClasses.hide}')`, ).data('image-id'); } const $thumbnail = $( `${selectors.productThumbs}[data-thumbnail-id='${newImageId}']`, ); $(selectors.productThumbs) .removeClass(cssClasses.activeThumbnail) .removeAttr('aria-current'); $thumbnail.addClass(cssClasses.activeThumbnail); $thumbnail.attr('aria-current', true); }, switchImage(imageId) { const $newImage = $( `${selectors.productImageWrapper}[data-image-id='${imageId}']`, this.$container, ); const $otherImages = $( `${selectors.productImageWrapper}:not([data-image-id='${imageId}'])`, this.$container, ); $newImage.removeClass(cssClasses.hide); $otherImages.addClass(cssClasses.hide); }, /** * Updates the DOM state of the add to cart button * * @param {boolean} enabled - Decides whether cart is enabled or disabled * @param {string} text - Updates the text notification content of the cart */ updateAddToCartState(evt) { const variant = evt.variant; if (variant) { $(selectors.priceWrapper, this.$container).removeClass(cssClasses.hide); } else { $(selectors.addToCart, this.$container).prop('disabled', true); $(selectors.priceWrapper, this.$container).addClass(cssClasses.hide); return; } if (variant.available) { $(selectors.addToCart, this.$container).prop('disabled', false); } else { $(selectors.addToCart, this.$container).prop('disabled', true); } if (variant.price != 0) { $(selectors.addToCart, this.$container).prop('disabled', false); } else { $(selectors.addToCart, this.$container).prop('disabled', true); } }, updateImages(evt) { const variant = evt.variant; const imageId = variant.featured_image.id; this.switchImage(imageId); this.setActiveThumbnail(imageId); }, /** * Updates the DOM with specified prices * * @param {string} productPrice - The current price of the product * @param {string} comparePrice - The original price of the product */ updateProductPrices(evt) { const variant = evt.variant; const $comparePrice = $(selectors.comparePrice, this.$container); const $compareEls = $comparePrice.add( selectors.comparePriceText, this.$container, ); const freeText = $('.freeText').html(); if (variant.price == 0) { $(selectors.productPrice, this.$container).html( freeText, ); } else { $(selectors.productPrice, this.$container).html( formatMoney(variant.price, theme.moneyFormat), ); } if (variant.compare_at_price > variant.price) { $comparePrice.html( formatMoney(variant.compare_at_price, theme.moneyFormat), ); $compareEls.removeClass(cssClasses.hide); } else { $comparePrice.html(''); $compareEls.addClass(cssClasses.hide); } }, /** * Event callback for Theme Editor `section:unload` event */ onUnload() { this.$container.off(this.namespace); }, });
This is URGENT! Any help ASAP would be hugely appreciated. Compensation can be provided if necessary.
User | Count |
---|---|
24 | |
20 | |
17 | |
16 | |
15 |