Last active
October 24, 2022 03:00
-
-
Save tobiasdalhof/ca0484abc8c1e8cee26d8c375f1caef2 to your computer and use it in GitHub Desktop.
Shopify variant listener
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This class contains general helper methods. | |
*/ | |
class Helper { | |
/** | |
* @param {String} name | |
* @returns {String|null} | |
*/ | |
static getQueryParameter(name) { | |
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]') | |
const regex = new RegExp('[\\?&]' + name + '=([^&#]*)') | |
const results = regex.exec(location.search) | |
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')) | |
} | |
} | |
/** | |
* This class contains Shopify related helper methods. | |
*/ | |
class ShopifyHelper { | |
/** | |
* @returns {String|null} | |
*/ | |
static getSelectedVariantId() { | |
// Try to get variant id from form element with name id | |
const addToCartForm = document.querySelector('form[action^="/cart/add"]') | |
if (addToCartForm) { | |
const input = addToCartForm.querySelector('[name="id"]') | |
const submitButton = addToCartForm.querySelector('[type="submit"]') | |
// If the submit button is disabled, the input value is most likely wrong | |
// because it got autofilled on initial page load with the first available product variant id. | |
if ( | |
(!submitButton || submitButton.disabled !== true) && | |
input && | |
input.value | |
) { | |
return input.value | |
} | |
} | |
// Try to get variant id from "variant" query parameter. | |
const queryParameter = Helper.getQueryParameter('variant') | |
if (queryParameter) { | |
return queryParameter | |
} | |
// Try to get variant id from ShopifyAnalytics.meta object | |
if ( | |
self.ShopifyAnalytics && | |
self.ShopifyAnalytics.meta && | |
self.ShopifyAnalytics.meta.selectedVariantId | |
) { | |
return self.ShopifyAnalytics.meta.selectedVariantId | |
} | |
// No variant id found | |
return null | |
} | |
/** | |
* @returns {Array<Element>} | |
*/ | |
static getAddToCartFormElements() { | |
const foundElements = [] | |
const elementTypes = ['select', 'input'] | |
for (let elementType of elementTypes) { | |
let elements = document.querySelectorAll(`form[action^="/cart/add"] ${elementType}`) | |
for (let element of elements) { | |
foundElements.push(element) | |
} | |
} | |
return foundElements | |
} | |
/** | |
* @param {Function} eventHandler | |
*/ | |
static addVariantListeners(eventHandler) { | |
for (let element of ShopifyHelper.getAddToCartFormElements()) { | |
element.addEventListener('change', eventHandler) | |
} | |
} | |
/** | |
* @param {Function} eventHandler | |
*/ | |
static removeVariantListeners(eventHandler) { | |
for (let element of ShopifyHelper.getAddToCartFormElements()) { | |
element.removeEventListener('change', eventHandler) | |
} | |
} | |
} | |
const initApp = () => { | |
let selectedVariantId = ShopifyHelper.getSelectedVariantId() | |
console.log('selected variant id is', selectedVariantId) | |
const variantHandler = (event) => { | |
const variantId = ShopifyHelper.getSelectedVariantId() | |
if (selectedVariantId !== variantId) { | |
selectedVariantId = variantId | |
console.log('selected variant id changed to', selectedVariantId) | |
} | |
} | |
ShopifyHelper.addVariantListeners(variantHandler) | |
} | |
if (document.readyState !== 'loading') { | |
setTimeout(initApp, 0) | |
} else { | |
document.addEventListener('DOMContentLoaded', initApp) | |
} |
I've noticed that putting the query handler above everything else works better off for most themes, might be a good option here.
Thanks @patrickbolle
Why is that? I'm not using it in production yet but the thought behind getting the variant id from the add to cart form element with name id first was that id
is required by the cart api.
Not 100% sure. I'm testing it on the free Shopify Supply theme, and it wasn't registering the proper variant ID on page load. I think the free Shopify themes use similar systems that change the query before anything else?
I'm honestly not sure! But it worked for me :P
…On Thu, Jun 6, 2019, at 1:18 PM, Tobi wrote:
> I've noticed that putting the query handler above everything else works better off for most themes, might be a good option here.
Thanks @patrickbolle <https://github.com/patrickbolle>
Why is that? I'm not using it in production yet but the thought behind getting the variant id from the add to cart form element with name id first was that `id` is required by the cart api.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub <https://gist.github.com/ca0484abc8c1e8cee26d8c375f1caef2?email_source=notifications&email_token=ACUARXMXCKLMZRAJVR6C3X3PZFPG5A5CNFSM4HVHNQE2YY3PNVWWK3TUL52HS4DFVNDWS43UINXW23LFNZ2KUY3PNVWWK3TUL5UWJTQAFTIQ6#gistcomment-2937103>, or mute the thread <https://github.com/notifications/unsubscribe-auth/ACUARXIY3L6DO5E5ODVP5GLPZFPG5ANCNFSM4HVHNQEQ>.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've noticed that putting the query handler above everything else works better off for most themes, might be a good option here.
Thanks for making this available, super helpful.