Product Variant Selector on IMPACT Theme

Product Variant Selector on IMPACT Theme

CJHIV
Shopify Partner
1 0 0

Hey there! I have recently built a small function using javascript that hides/shows product variants and was curious if the way I am doing is correct, or if there might be a more optimal way to do such a thing. For some additional context, I am using the IMPACT theme built by Maestrooo.

 

It seemed that the easiest route to go down is to load product data via json using a script file and parse that data to do any further actions. I thought about trying to use AJAX API to live load the data, but the script route was much more appealing. There are also some other functions, such as one that looks through all of the product thumbnails to hide/show them. Another one that on load only shows the currently selected variant.

 

Regardless, I would love some feedback and or constructive criticism as I would like to continue improving my code.

 

// js/sections/variant-picker.js
document.addEventListener("DOMContentLoaded", function () {
  // Parse product data
  const productDataScript = document.querySelector("script[data-product]");
  if (!productDataScript) return;
  let productData;
  try {
	productData = JSON.parse(productDataScript.textContent);
  } catch (e) {
	console.error("Failed to parse product data:", e);
	return;
  }

  // Parse currently selected variant
  const variantPicker = document.querySelector("variant-picker");
  if (!variantPicker) return;
  const selectedVariant = JSON.parse(variantPicker.querySelector("script[data-variant]")?.textContent || "{}");
  const selectedID = selectedVariant?.featured_media?.id;

  // Gather variants and their media IDs as a Set
  const variantMediaIDs = new Set(
    productData
      .filter((variant) => variant.featured_media)
      .map((variant) => variant.featured_media.id)
  );

  // Group images by their associated variant ID
  const galleryImages = Array.from(document.querySelectorAll(".product-gallery__thumbnail"));
  const groupedImages = new Map();
  let currentVariantID = null;

  galleryImages.forEach((image) => {
    const imageMediaID = parseInt(image.id);

    if (variantMediaIDs.has(imageMediaID)) {
      currentVariantID = imageMediaID;
      if (!groupedImages.has(currentVariantID)) {
        groupedImages.set(currentVariantID, []);
      }
    }

    if (currentVariantID) {
      groupedImages.get(currentVariantID).push(image);
    }
  });

  // Show images for the selected variant
  function showImagesForVariant(selectedID) {
    galleryImages.forEach((image) => {
      const belongsToSelectedVariant = groupedImages.get(selectedID)?.includes(image);
      image.classList.toggle("hidden", !belongsToSelectedVariant);
    });
  }

  // Initial display for the currently selected variant
  if (selectedID) showImagesForVariant(selectedID);

  // Listen for variant changes and update the display
  document.addEventListener("variant:change", function (event) {
    const newSelectedVariant = event.detail.variant;
    const newSelectedID = newSelectedVariant?.featured_media?.id;
    if (newSelectedID) showImagesForVariant(newSelectedID);
  });
});

 

Replies 0 (0)