@nguyenmv2/buy-button
Version:
BuyButton.js allows merchants to build Shopify interfaces into any website
1,005 lines (868 loc) • 31.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _merge2 = _interopRequireDefault(require("../utils/merge"));
var _component = _interopRequireDefault(require("../component"));
var _template = _interopRequireDefault(require("../template"));
var _checkout = _interopRequireDefault(require("./checkout"));
var _windowUtils = _interopRequireDefault(require("../utils/window-utils"));
var _money = _interopRequireDefault(require("../utils/money"));
var _normalizeConfig = _interopRequireDefault(require("../utils/normalize-config"));
var _detectFeatures = _interopRequireDefault(require("../utils/detect-features"));
var _unitPrice = _interopRequireDefault(require("../utils/unit-price"));
var _product = _interopRequireDefault(require("../views/product"));
var _product2 = _interopRequireDefault(require("../updaters/product"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
function isFunction(obj) {
return Boolean(obj && obj.constructor && obj.call && obj.apply);
}
function isPseudoSelector(key) {
return key.charAt(0) === ':';
}
function isMedia(key) {
return key.charAt(0) === '@';
}
var ENTER_KEY = 13;
var propertiesWhitelist = ['background', 'background-color', 'border', 'border-radius', 'color', 'border-color', 'border-width', 'border-style', 'transition', 'text-transform', 'text-shadow', 'box-shadow', 'font-size', 'font-family'];
function whitelistedProperties(selectorStyles) {
return Object.keys(selectorStyles).reduce(function (filteredStyles, propertyName) {
if (isPseudoSelector(propertyName) || isMedia(propertyName)) {
filteredStyles[propertyName] = whitelistedProperties(selectorStyles[propertyName]);
return filteredStyles;
}
if (propertiesWhitelist.indexOf(propertyName) > -1) {
filteredStyles[propertyName] = selectorStyles[propertyName];
}
return filteredStyles;
}, {});
}
/**
* Renders and fetches data for product embed.
* @extends Component.
*/
var Product =
/*#__PURE__*/
function (_Component) {
_inheritsLoose(Product, _Component);
/**
* create Product.
* @param {Object} config - configuration object.
* @param {Object} props - data and utilities passed down from UI instance.
*/
function Product(config, props) {
var _this;
// eslint-disable-next-line no-param-reassign
config = (0, _normalizeConfig.default)(config);
_this = _Component.call(this, config, props) || this;
_this.typeKey = 'product';
_this.defaultStorefrontVariantId = config.storefrontVariantId;
_this.cachedImage = null;
_this.childTemplate = new _template.default(_this.config.option.templates, _this.config.option.contents, _this.config.option.order);
_this.cart = null;
_this.modal = null;
_this.imgStyle = '';
_this.selectedQuantity = 1;
_this.selectedVariant = {};
_this.selectedOptions = {};
_this.selectedImage = null;
_this.updater = new _product2.default(_assertThisInitialized(_this));
_this.view = new _product.default(_assertThisInitialized(_this));
return _this;
}
/**
* determines when image src should be updated
* @return {Boolean}
*/
var _proto = Product.prototype;
/**
* prevent events from bubbling if entire product is being treated as button.
*/
_proto.stopPropagation = function stopPropagation(evt) {
if (this.isButton) {
evt.stopImmediatePropagation();
}
}
/**
* get HTML for product options selector.
* @return {String} HTML
*/
;
/**
* determines whether an option can resolve to an available variant given current selections
* @return {Boolean}
*/
_proto.optionValueCanBeSelected = function optionValueCanBeSelected(selections, name, value) {
var variants = this.variantArray;
var selectableValues = Object.assign({}, selections, _defineProperty({}, name, value));
var satisfactoryVariants = variants.filter(function (variant) {
var matchingOptions = Object.keys(selectableValues).filter(function (key) {
return variant.optionValues[key] === selectableValues[key];
});
return matchingOptions.length === Object.keys(selectableValues).length;
});
var variantSelectable = false;
variantSelectable = satisfactoryVariants.reduce(function (variantExists, variant) {
var variantAvailable = variant.available;
if (!variantExists) {
return variantAvailable;
}
return variantExists;
}, false);
return variantSelectable;
}
/**
* get options for product with selected value.
* @return {Array}
*/
;
/**
* open online store in new tab.
*/
_proto.openOnlineStore = function openOnlineStore() {
this._userEvent('openOnlineStore');
window.open(this.onlineStoreURL);
}
/**
* initializes component by creating model and rendering view.
* Creates and initalizes cart if necessary.
* @param {Object} [data] - data to initialize model with.
* @return {Promise} promise resolving to instance.
*/
;
_proto.init = function init(data) {
var _this2 = this;
return this.createCart().then(function (cart) {
_this2.cart = cart;
return _Component.prototype.init.call(_this2, data).then(function (model) {
if (model) {
_this2.view.render();
}
return model;
});
});
}
/**
* creates cart if necessary.
* @return {Promise}
*/
;
_proto.createCart = function createCart() {
var cartConfig = Object.assign({}, this.globalConfig, {
node: this.globalConfig.cartNode,
options: this.config
});
return this.props.createCart(cartConfig);
}
/**
* fetches data if necessary.
* Sets default variant for product.
* @param {Object} [data] - data to initialize model with.
*/
;
_proto.setupModel = function setupModel(data) {
var _this3 = this;
return _Component.prototype.setupModel.call(this, data).then(function (model) {
return _this3.setDefaultVariant(model);
});
}
/**
* fetch product data from API.
* @return {Promise} promise resolving to model data.
*/
;
_proto.sdkFetch = function sdkFetch() {
if (this.storefrontId && Array.isArray(this.storefrontId) && this.storefrontId[0]) {
return this.props.client.product.fetch(this.storefrontId[0]);
} else if (this.storefrontId && !Array.isArray(this.storefrontId)) {
return this.props.client.product.fetch(this.storefrontId);
} else if (this.handle) {
return this.props.client.product.fetchByHandle(this.handle).then(function (product) {
return product;
});
}
return Promise.reject(new Error('SDK Fetch Failed'));
}
/**
* call sdkFetch and set selected quantity to 0.
* @throw 'Not Found' if model not returned.
* @return {Promise} promise resolving to model data.
*/
;
_proto.fetchData = function fetchData() {
var _this4 = this;
return this.sdkFetch().then(function (model) {
if (model) {
_this4.storefrontId = model.id;
_this4.handle = model.handle;
return model;
}
throw new Error('Not Found');
});
};
_proto.onButtonClick = function onButtonClick(evt, target) {
evt.stopPropagation();
if (isFunction(this.options.buttonDestination)) {
this.options.buttonDestination(this);
} else if (this.options.buttonDestination === 'cart') {
this.props.closeModal();
this._userEvent('addVariantToCart');
this.props.tracker.trackMethod(this.cart.addVariantToCart.bind(this), 'Update Cart', this.selectedVariantTrackingInfo)(this.selectedVariant, this.selectedQuantity);
if (this.iframe) {
this.props.setActiveEl(target);
}
} else if (this.options.buttonDestination === 'modal') {
this.props.setActiveEl(target);
this.props.tracker.track('Open modal', this.productTrackingInfo);
this.openModal();
} else if (this.options.buttonDestination === 'onlineStore') {
this.openOnlineStore();
} else {
this._userEvent('openCheckout');
this.props.tracker.track('Direct Checkout', {});
var checkoutWindow;
if (this.config.cart.popup && _detectFeatures.default.windowOpen()) {
var params = new _checkout.default(this.config).params;
checkoutWindow = window.open('', 'checkout', params);
} else {
checkoutWindow = window;
}
var input = {
lineItems: [{
variantId: this.selectedVariant.id,
quantity: this.selectedQuantity
}]
};
this.props.client.checkout.create(input).then(function (checkout) {
checkoutWindow.location = checkout.webUrl;
});
}
};
_proto.onBlockButtonKeyup = function onBlockButtonKeyup(evt, target) {
if (evt.keyCode === ENTER_KEY) {
this.onButtonClick(evt, target);
}
};
_proto.onOptionSelect = function onOptionSelect(evt) {
var target = evt.target;
var value = target.options[target.selectedIndex].value;
var name = target.getAttribute('name');
this.updateVariant(name, value);
};
_proto.onQuantityBlur = function onQuantityBlur(evt, target) {
this.updateQuantity(function () {
return parseInt(target.value, 10);
});
};
_proto.onQuantityIncrement = function onQuantityIncrement(qty) {
this.updateQuantity(function (prevQty) {
return prevQty + qty;
});
};
_proto.closeCartOnBgClick = function closeCartOnBgClick() {
if (this.cart && this.cart.isVisible) {
this.cart.close();
}
};
_proto.onCarouselItemClick = function onCarouselItemClick(evt, target) {
evt.preventDefault();
var selectedImageId = target.getAttribute('data-image-id');
var imageList = this.model.images;
var foundImage = imageList.find(function (image) {
return image.id === selectedImageId;
});
if (foundImage) {
this.selectedImage = foundImage;
this.cachedImage = foundImage;
}
this.view.render();
};
_proto.nextIndex = function nextIndex(currentIndex, offset) {
var nextIndex = currentIndex + offset;
if (nextIndex >= this.model.images.length) {
return 0;
}
if (nextIndex < 0) {
return this.model.images.length - 1;
}
return nextIndex;
};
_proto.onCarouselChange = function onCarouselChange(offset) {
var _this5 = this;
var imageList = this.model.images;
var currentImage = imageList.filter(function (image) {
return image.id === _this5.currentImage.id;
})[0];
var currentImageIndex = imageList.indexOf(currentImage);
this.selectedImage = imageList[this.nextIndex(currentImageIndex, offset)];
this.cachedImage = this.selectedImage;
this.view.render();
}
/**
* create modal instance and initialize.
* @return {Promise} promise resolving to modal instance
*/
;
_proto.openModal = function openModal() {
if (!this.modal) {
var modalConfig = Object.assign({}, this.globalConfig, {
node: this.globalConfig.modalNode,
options: Object.assign({}, this.config, {
product: this.modalProductConfig,
modal: Object.assign({}, this.config.modal, {
googleFonts: this.options.googleFonts
})
})
});
this.modal = this.props.createModal(modalConfig, this.props);
}
this._userEvent('openModal');
return this.modal.init(this.model);
}
/**
* update quantity of selected variant and rerender.
* @param {Function} fn - function which returns new quantity given current quantity.
*/
;
_proto.updateQuantity = function updateQuantity(fn) {
var quantity = fn(this.selectedQuantity);
if (quantity < 0) {
quantity = 0;
}
this.selectedQuantity = quantity;
this._userEvent('updateQuantity');
this.view.render();
}
/**
* Update variant based on option value.
* @param {String} optionName - name of option being modified.
* @param {String} value - value of selected option.
* @return {Object} updated option object.
*/
;
_proto.updateVariant = function updateVariant(optionName, value) {
var _this6 = this;
var updatedOption = this.model.options.find(function (option) {
return option.name === optionName;
});
if (updatedOption) {
this.selectedOptions[updatedOption.name] = value;
this.selectedVariant = this.props.client.product.helpers.variantForOptions(this.model, this.selectedOptions);
}
if (this.variantExists) {
this.cachedImage = this.selectedVariant.image;
if (this.selectedVariant.image) {
this.selectedImage = null;
} else {
this.selectedImage = this.model.images[0]; // get cached image
}
} else {
this.selectedImage = this.model.images.find(function (image) {
return image.id === _this6.cachedImage.id;
});
}
this.view.render();
this._userEvent('updateVariant');
return updatedOption;
}
/**
* set default variant to be selected on initialization.
* @param {Object} model - model to be modified.
*/
;
_proto.setDefaultVariant = function setDefaultVariant(model) {
var _this7 = this;
var selectedVariant;
if (this.defaultStorefrontVariantId) {
selectedVariant = model.variants.find(function (variant) {
return variant.id === _this7.defaultStorefrontVariantId;
});
} else {
this.defaultStorefrontVariantId = model.variants[0].id;
selectedVariant = model.variants[0];
this.selectedImage = model.images[0];
}
if (!selectedVariant) {
selectedVariant = model.variants[0];
}
this.selectedOptions = selectedVariant.selectedOptions.reduce(function (acc, option) {
acc[option.name] = option.value;
return acc;
}, {});
this.selectedVariant = selectedVariant;
return model;
};
_proto.imageAltText = function imageAltText(altText) {
return altText || this.model.title;
};
_createClass(Product, [{
key: "shouldUpdateImage",
get: function get() {
return !this.cachedImage || this.image && this.image.src !== this.cachedImage;
}
/**
* get image for product and cache it. Return caches image if shouldUpdateImage is false.
* @return {Object} image objcet.
*/
}, {
key: "currentImage",
get: function get() {
if (this.shouldUpdateImage) {
this.cachedImage = this.image;
}
return this.cachedImage;
}
/**
* get image for selected variant and size based on options or layout.
* @return {Object} image object.
*/
}, {
key: "image",
get: function get() {
var DEFAULT_IMAGE_SIZE = 480;
var MODAL_IMAGE_SIZE = 550;
if (!(this.selectedVariant || this.options.contents.imgWithCarousel)) {
return null;
}
var imageSize;
if (this.options.width && this.options.width.slice(-1) === '%') {
imageSize = 1000;
} else {
imageSize = parseInt(this.options.width, 10) || DEFAULT_IMAGE_SIZE;
}
var id;
var src;
var srcLarge;
var srcOriginal;
var altText;
var imageOptions = {
maxWidth: imageSize,
maxHeight: imageSize * 1.5
};
var imageOptionsLarge = {
maxWidth: MODAL_IMAGE_SIZE,
maxHeight: MODAL_IMAGE_SIZE * 1.5
};
if (this.selectedImage) {
id = this.selectedImage.id;
src = this.props.client.image.helpers.imageForSize(this.selectedImage, imageOptions);
srcLarge = this.props.client.image.helpers.imageForSize(this.selectedImage, imageOptionsLarge);
srcOriginal = this.selectedImage.src;
altText = this.imageAltText(this.selectedImage.altText);
} else if (this.selectedVariant.image == null && this.model.images[0] == null) {
id = null;
src = '';
srcLarge = '';
srcOriginal = '';
altText = '';
} else if (this.selectedVariant.image == null) {
id = this.model.images[0].id;
src = this.model.images[0].src;
srcLarge = this.props.client.image.helpers.imageForSize(this.model.images[0], imageOptionsLarge);
srcOriginal = this.model.images[0].src;
altText = this.imageAltText(this.model.images[0].altText);
} else {
id = this.selectedVariant.image.id;
src = this.props.client.image.helpers.imageForSize(this.selectedVariant.image, imageOptions);
srcLarge = this.props.client.image.helpers.imageForSize(this.selectedVariant.image, imageOptionsLarge);
srcOriginal = this.selectedVariant.image.src;
altText = this.imageAltText(this.selectedVariant.image.altText);
}
return {
id: id,
src: src,
srcLarge: srcLarge,
srcOriginal: srcOriginal,
altText: altText
};
}
/**
* get formatted cart subtotal based on moneyFormat
* @return {String}
*/
}, {
key: "formattedPrice",
get: function get() {
if (!this.selectedVariant) {
return '';
}
return (0, _money.default)(this.selectedVariant.priceV2.amount, this.globalConfig.moneyFormat);
}
/**
* get formatted cart subtotal based on moneyFormat
* @return {String}
*/
}, {
key: "formattedCompareAtPrice",
get: function get() {
if (!this.hasCompareAtPrice) {
return '';
}
return (0, _money.default)(this.selectedVariant.compareAtPriceV2.amount, this.globalConfig.moneyFormat);
}
/**
* get whether unit price string should be displayed
* @return {Boolean}
*/
}, {
key: "showUnitPrice",
get: function get() {
if (!this.selectedVariant || !this.selectedVariant.unitPrice || !this.options.contents.unitPrice) {
return false;
}
return true;
}
/**
* get formatted variant unit price amount based on moneyFormat
* @return {String}
*/
}, {
key: "formattedUnitPrice",
get: function get() {
if (!this.showUnitPrice) {
return '';
}
return (0, _money.default)(this.selectedVariant.unitPrice.amount, this.globalConfig.moneyFormat);
}
/**
* get formatted variant unit price base unit
* @return {String}
*/
}, {
key: "formattedUnitPriceBaseUnit",
get: function get() {
if (!this.showUnitPrice) {
return '';
}
var unitPriceMeasurement = this.selectedVariant.unitPriceMeasurement;
return (0, _unitPrice.default)(unitPriceMeasurement.referenceValue, unitPriceMeasurement.referenceUnit);
}
/**
* get data to be passed to view.
* @return {Object} viewData object.
*/
}, {
key: "viewData",
get: function get() {
return Object.assign({}, this.model, this.options.viewData, {
classes: this.classes,
contents: this.options.contents,
text: this.options.text,
optionsHtml: this.optionsHtml,
decoratedOptions: this.decoratedOptions,
currentImage: this.currentImage,
buttonClass: this.buttonClass,
hasVariants: this.hasVariants,
buttonDisabled: !this.buttonEnabled,
selectedVariant: this.selectedVariant,
selectedQuantity: this.selectedQuantity,
buttonText: this.buttonText,
imgStyle: this.imgStyle,
quantityClass: this.quantityClass,
priceClass: this.priceClass,
formattedPrice: this.formattedPrice,
priceAccessibilityLabel: this.priceAccessibilityLabel,
hasCompareAtPrice: this.hasCompareAtPrice,
formattedCompareAtPrice: this.formattedCompareAtPrice,
compareAtPriceAccessibilityLabel: this.compareAtPriceAccessibilityLabel,
showUnitPrice: this.showUnitPrice,
formattedUnitPrice: this.formattedUnitPrice,
formattedUnitPriceBaseUnit: this.formattedUnitPriceBaseUnit,
carouselIndex: 0,
carouselImages: this.carouselImages
});
}
}, {
key: "carouselImages",
get: function get() {
var _this8 = this;
return this.model.images.map(function (image) {
return {
id: image.id,
src: image.src,
carouselSrc: _this8.props.client.image.helpers.imageForSize(image, {
maxWidth: 100,
maxHeight: 100
}),
isSelected: image.id === _this8.currentImage.id,
altText: _this8.imageAltText(image.altText)
};
});
}
}, {
key: "buttonClass",
get: function get() {
var disabledClass = this.buttonEnabled ? '' : this.classes.product.disabled;
var quantityClass = this.options.contents.buttonWithQuantity ? this.classes.product.buttonBesideQty : '';
return "".concat(disabledClass, " ").concat(quantityClass);
}
}, {
key: "quantityClass",
get: function get() {
return this.options.contents.quantityIncrement || this.options.contents.quantityDecrement ? this.classes.product.quantityWithButtons : '';
}
}, {
key: "buttonText",
get: function get() {
if (this.options.buttonDestination === 'modal') {
return this.options.text.button;
}
if (!this.variantExists) {
return this.options.text.unavailable;
}
if (!this.variantInStock) {
return this.options.text.outOfStock;
}
return this.options.text.button;
}
}, {
key: "buttonEnabled",
get: function get() {
return this.options.buttonDestination === 'modal' || this.buttonActionAvailable && this.variantExists && this.variantInStock;
}
}, {
key: "variantExists",
get: function get() {
var _this9 = this;
return this.model.variants.some(function (variant) {
if (_this9.selectedVariant) {
return variant.id === _this9.selectedVariant.id;
} else {
return false;
}
});
}
}, {
key: "variantInStock",
get: function get() {
return this.variantExists && this.selectedVariant.available;
}
}, {
key: "hasVariants",
get: function get() {
return this.model.variants.length > 1;
}
}, {
key: "requiresCart",
get: function get() {
return this.options.buttonDestination === 'cart';
}
}, {
key: "buttonActionAvailable",
get: function get() {
return !this.requiresCart || Boolean(this.cart);
}
}, {
key: "hasQuantity",
get: function get() {
return this.options.contents.quantityInput;
}
}, {
key: "priceClass",
get: function get() {
return this.hasCompareAtPrice ? this.classes.product.loweredPrice : '';
}
}, {
key: "isButton",
get: function get() {
return this.options.isButton && !(this.options.contents.button || this.options.contents.buttonWithQuantity);
}
/**
* get events to be bound to DOM.
* @return {Object}
*/
}, {
key: "DOMEvents",
get: function get() {
var _merge;
return (0, _merge2.default)({}, (_merge = {
click: this.closeCartOnBgClick.bind(this)
}, _defineProperty(_merge, "click ".concat(this.selectors.option.select), this.stopPropagation.bind(this)), _defineProperty(_merge, "focus ".concat(this.selectors.option.select), this.stopPropagation.bind(this)), _defineProperty(_merge, "click ".concat(this.selectors.option.wrapper), this.stopPropagation.bind(this)), _defineProperty(_merge, "click ".concat(this.selectors.product.quantityInput), this.stopPropagation.bind(this)), _defineProperty(_merge, "click ".concat(this.selectors.product.quantityButton), this.stopPropagation.bind(this)), _defineProperty(_merge, "change ".concat(this.selectors.option.select), this.onOptionSelect.bind(this)), _defineProperty(_merge, "click ".concat(this.selectors.product.button), this.onButtonClick.bind(this)), _defineProperty(_merge, "click ".concat(this.selectors.product.blockButton), this.onButtonClick.bind(this)), _defineProperty(_merge, "keyup ".concat(this.selectors.product.blockButton), this.onBlockButtonKeyup.bind(this)), _defineProperty(_merge, "click ".concat(this.selectors.product.quantityIncrement), this.onQuantityIncrement.bind(this, 1)), _defineProperty(_merge, "click ".concat(this.selectors.product.quantityDecrement), this.onQuantityIncrement.bind(this, -1)), _defineProperty(_merge, "blur ".concat(this.selectors.product.quantityInput), this.onQuantityBlur.bind(this)), _defineProperty(_merge, "click ".concat(this.selectors.product.carouselItem), this.onCarouselItemClick.bind(this)), _defineProperty(_merge, "click ".concat(this.selectors.product.carouselNext), this.onCarouselChange.bind(this, 1)), _defineProperty(_merge, "click ".concat(this.selectors.product.carouselPrevious), this.onCarouselChange.bind(this, -1)), _merge), this.options.DOMEvents);
}
}, {
key: "optionsHtml",
get: function get() {
var _this10 = this;
if (!this.options.contents.options) {
return '';
}
return this.decoratedOptions.reduce(function (acc, option) {
var data = (0, _merge2.default)(option, _this10.options.viewData);
data.classes = _this10.classes;
data.onlyOption = _this10.model.options.length === 1;
return acc + _this10.childTemplate.render({
data: data
});
}, '');
}
/**
* get product variants with embedded options
* @return {Array} array of variants
*/
}, {
key: "variantArray",
get: function get() {
delete this.variantArrayMemo;
this.variantArrayMemo = this.model.variants.map(function (variant) {
var betterVariant = {
id: variant.id,
available: variant.available,
optionValues: {}
};
variant.optionValues.forEach(function (optionValue) {
betterVariant.optionValues[optionValue.name] = optionValue.value;
});
return betterVariant;
});
return this.variantArrayMemo;
}
}, {
key: "decoratedOptions",
get: function get() {
var _this11 = this;
return this.model.options.map(function (option) {
return {
name: option.name,
values: option.values.map(function (value) {
return {
name: value.value,
selected: _this11.selectedOptions[option.name] === value.value
};
})
};
});
}
/**
* get info about product to be sent to tracker
* @return {Object}
*/
}, {
key: "trackingInfo",
get: function get() {
var variant = this.selectedVariant || this.model.variants[0];
var contents = this.options.contents;
var contentString = Object.keys(contents).filter(function (key) {
return contents[key];
}).toString();
return {
id: this.model.id,
name: this.model.title,
variantId: variant.id,
variantName: variant.title,
price: variant.priceV2.amount,
destination: this.options.buttonDestination,
layout: this.options.layout,
contents: contentString,
checkoutPopup: this.config.cart.popup,
sku: null
};
}
/**
* get info about variant to be sent to tracker
* @return {Object}
*/
}, {
key: "selectedVariantTrackingInfo",
get: function get() {
var variant = this.selectedVariant;
return {
id: variant.id,
name: variant.title,
productId: this.model.id,
productName: this.model.title,
quantity: this.selectedQuantity,
price: variant.priceV2.amount,
sku: null
};
}
/**
* get info about product to be sent to tracker
* @return {Object}
*/
}, {
key: "productTrackingInfo",
get: function get() {
return {
id: this.model.id
};
}
/**
* get configuration object for product details modal based on product config and modalProduct config.
* @return {Object} configuration object.
*/
}, {
key: "modalProductConfig",
get: function get() {
var _this12 = this;
var modalProductStyles;
if (this.config.product.styles) {
modalProductStyles = (0, _merge2.default)({}, Object.keys(this.config.product.styles).reduce(function (productStyles, selectorKey) {
productStyles[selectorKey] = whitelistedProperties(_this12.config.product.styles[selectorKey]);
return productStyles;
}, {}), this.config.modalProduct.styles);
} else {
modalProductStyles = {};
}
return Object.assign({}, this.config.modalProduct, {
styles: modalProductStyles
});
}
/**
* get params for online store URL.
* @return {Object}
*/
}, {
key: "onlineStoreParams",
get: function get() {
return {
channel: 'buy_button',
referrer: encodeURIComponent(_windowUtils.default.location()),
variant: atob(this.selectedVariant.id).split('/')[4]
};
}
/**
* get query string for online store URL from params
* @return {String}
*/
}, {
key: "onlineStoreQueryString",
get: function get() {
var _this13 = this;
return Object.keys(this.onlineStoreParams).reduce(function (string, key) {
return "".concat(string).concat(key, "=").concat(_this13.onlineStoreParams[key], "&");
}, '?');
}
/**
* get URL to open online store page for product.
* @return {String}
*/
}, {
key: "onlineStoreURL",
get: function get() {
return "".concat(this.model.onlineStoreUrl).concat(this.onlineStoreQueryString);
}
}, {
key: "priceAccessibilityLabel",
get: function get() {
return this.hasCompareAtPrice ? this.options.text.salePriceAccessibilityLabel : this.options.text.regularPriceAccessibilityLabel;
}
}, {
key: "compareAtPriceAccessibilityLabel",
get: function get() {
return this.hasCompareAtPrice ? this.options.text.regularPriceAccessibilityLabel : '';
}
}, {
key: "hasCompareAtPrice",
get: function get() {
return Boolean(this.selectedVariant && this.selectedVariant.compareAtPriceV2);
}
}]);
return Product;
}(_component.default);
exports.default = Product;