diff --git a/CHANGELOG.md b/CHANGELOG.md index 9631c959bf..87b8004e97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Draft Add support for Card Management: List, Delete, Edit, Add and Default Payment Method [#1376](https://github.com/bigcommerce/cornerstone/pull/1376) +Add support for declarative data tag analytics. [#1377](https://github.com/bigcommerce/cornerstone/pull/1377) ## 2.5.2 (2018-10-24) - Product review modal error message is now accurate. [#1370](https://github.com/bigcommerce/cornerstone/pull/1370) diff --git a/assets/js/theme/common/product-details.js b/assets/js/theme/common/product-details.js index fb8324bbda..4078756e73 100644 --- a/assets/js/theme/common/product-details.js +++ b/assets/js/theme/common/product-details.js @@ -27,6 +27,7 @@ export default class ProductDetails { $productOptionsElement.on('change', event => { this.productOptionsChanged(event); + this.setProductVariant(); }); $form.on('submit', event => { @@ -76,6 +77,103 @@ export default class ProductDetails { return formData; } + setProductVariant() { + const unsatisfiedRequiredFields = []; + const options = []; + + $.each($('[data-product-attribute]'), (index, value) => { + const optionLabel = value.children[0].innerText; + const optionTitle = optionLabel.split(':')[0].trim(); + const required = optionLabel.toLowerCase().includes('required'); + const type = value.getAttribute('data-product-attribute'); + + if ((type === 'input-file' || type === 'input-text' || type === 'input-number') && value.querySelector('input').value === '' && required) { + unsatisfiedRequiredFields.push(value); + } + + if (type === 'textarea' && value.querySelector('textarea').value === '' && required) { + unsatisfiedRequiredFields.push(value); + } + + if (type === 'date') { + const isSatisfied = Array.from(value.querySelectorAll('select')).every((select) => select.selectedIndex !== 0); + + if (isSatisfied) { + const dateString = Array.from(value.querySelectorAll('select')).map((x) => x.value).join('-'); + options.push(`${optionTitle}:${dateString}`); + + return; + } + + if (required) { + unsatisfiedRequiredFields.push(value); + } + } + + if (type === 'set-select') { + const select = value.querySelector('select'); + const selectedIndex = select.selectedIndex; + + if (selectedIndex !== 0) { + options.push(`${optionTitle}:${select.options[selectedIndex].innerText}`); + + return; + } + + if (required) { + unsatisfiedRequiredFields.push(value); + } + } + + if (type === 'set-rectangle' || type === 'set-radio' || type === 'swatch' || type === 'input-checkbox' || type === 'product-list') { + const checked = value.querySelector(':checked'); + if (checked) { + if (type === 'set-rectangle' || type === 'set-radio' || type === 'product-list') { + const label = checked.labels[0].innerText; + if (label) { + options.push(`${optionTitle}:${label}`); + } + } + + if (type === 'swatch') { + const label = checked.labels[0].children[0]; + if (label) { + options.push(`${optionTitle}:${label.title}`); + } + } + + if (type === 'input-checkbox') { + options.push(`${optionTitle}:Yes`); + } + + return; + } + + if (type === 'input-checkbox') { + options.push(`${optionTitle}:No`); + } + + if (required) { + unsatisfiedRequiredFields.push(value); + } + } + }); + + let productVariant = unsatisfiedRequiredFields.length === 0 ? options.sort().join(', ') : 'unsatisfied'; + const view = $('.productView'); + + if (productVariant) { + productVariant = productVariant === 'unsatisfied' ? '' : productVariant; + if (view.attr('data-event-type')) { + view.attr('data-product-variant', productVariant); + } else { + const productName = view.find('.productView-title')[0].innerText; + const card = $(`[data-name="${productName}"]`); + card.attr('data-product-variant', productVariant); + } + } + } + /** * Since $productView can be dynamically inserted using render_with, * We have to retrieve the respective elements diff --git a/assets/js/theme/product.js b/assets/js/theme/product.js index 56b430aab1..84aa74e1be 100644 --- a/assets/js/theme/product.js +++ b/assets/js/theme/product.js @@ -30,6 +30,7 @@ export default class Product extends PageManager { collapsibleFactory(); this.productDetails = new ProductDetails($('.productView'), this.context, window.BCData.product_attributes); + this.productDetails.setProductVariant(); videoGallery(); diff --git a/config.json b/config.json index 3077ef71c3..2bbf0c648f 100644 --- a/config.json +++ b/config.json @@ -31,7 +31,8 @@ "product_videos", "google_amp", "customized_checkout", - "account_payment_methods" + "account_payment_methods", + "enhanced_ecommerce" ] }, "css_compiler": "scss", diff --git a/templates/components/amp/products/grid.html b/templates/components/amp/products/grid.html index 0b58c4d515..c2ab04f4d9 100644 --- a/templates/components/amp/products/grid.html +++ b/templates/components/amp/products/grid.html @@ -1,7 +1,7 @@