问题
I am using the 'Loft' theme on Shopify. When I select a variant on the product page, the them updates the SKU and the price to that variant I need more functionality than this, as I would like to show the dimensions of each variant using metafields.
I have created a function and called it on variant select like this:
jQuery(function($) {
new Shopify.OptionSelectors('productSelect', {
product: {{ product | json }},
onVariantSelected: selectCallback,
enableHistoryState: true
});
});
My function is called and I can perform my desired actions. But this stops the default actions from happening, like updating the price and SKU. Is there a way I can call both?
回答1:
There are a number of ways to make this work.
Firstly you need to be aware of how your theme is natively handling variants. For loft it uses the theme.Variant object so custom variant selection is as easy as:
jQuery('#shopify-section-product-template').on('theme:variants:changed', function(evt, variantObj){
console.log('theme event for '+ variantObj.sku); // limited view of variant.
console.log(variantObj);
});
For themes that use the old Shopify.OptionSelectors you can either do this old school by overriding the selectCallback
global function like:
(function(){
var original_selectCallback = window.selectCallback;
window.selectCallback = function(variant, selector) {
original_selectCallback(variant, selector); // call the original function
myCustomHandler(variant); // called with the full jsonified variant object.
};
})();
Finally most modern themes that I've dealt with and themes that use Shopify.OptionSelectors with enableHistoryState: true
allow you to skip the messiness of overrides and install your own history handler. Here is where you'd need to have your own script/liquid assemble the JSON you'd need for getting variant and product properties:
document.addEventListener('DOMContentLoaded', function(){
function usePushState(handler){
//modern themes use pushstate to track variant changes without reload
function track (fn, handler, before) {
return function interceptor () {
if (before) {
handler.apply(this, arguments);
return fn.apply(this, arguments);
} else {
var result = fn.apply(this, arguments);
handler.apply(this, arguments);
return result;
}
};
}
var currentVariantId = null;
function variantHandler () {
var selectedVariantId = window.location.search.replace(/.*variant=(\d+).*/, '$1');
console.log('checking variant change to '+ selectedVariantId);
if(!selectedVariantId) return;
if(selectedVariantId != currentVariantId){
currentVariantId = selectedVariantId;
handler(selectedVariantId);
}
}
// Assign listeners
window.history.pushState = track(history.pushState, variantHandler);
window.history.replaceState = track(history.replaceState, variantHandler);
window.addEventListener('popstate', variantHandler);
}
usePushState(function(variantId){
console.log('variant: '+ variantId +' selected');
});
});
回答2:
The recipe for you is as follows. When the original Liquid renders (happens once), you save the product as json into some Javascript variable. You have the extra task of looping through the variants, and assigning each variant their metafields. To make your life easier, you could've selected to save the variant dimensions as a JSON_STRING metafield at the product level, where the variant ID is your key and the dimensions are the value.
Nonetheless, you save the dimensions keyed to the variant ID. Now when the selector change event occurs, you are handed the variant on a platter in the existing option selector callback. Write yourself a function that uses the provided variant ID to get the dimensions from your already saved object. With those values, update the DOM and you're done.
来源:https://stackoverflow.com/questions/56816402/shopify-trigger-function-on-variant-selection-but-dont-override-existing-functi