diff --git a/.github/workflow-examples/automatic_deployment_production.yml b/.github/workflow-examples/automatic_deployment_production.yml index 3565324e91..5f3c18e73d 100644 --- a/.github/workflow-examples/automatic_deployment_production.yml +++ b/.github/workflow-examples/automatic_deployment_production.yml @@ -39,6 +39,8 @@ jobs: # # You must configure store credentials as secrets on your GitHub repo for automatic deployment via GitHub Actions +# This defaults to pushing the theme to channel ID 1, which is the default storefront. If you wish to push to an +# Alternate storefront, use a different channel ID # - name: Connect to store @@ -48,4 +50,4 @@ jobs: run: stencil init -u $URL -t $TOKEN -p 3000 - name: Push theme live, automatically deleting oldest theme if necessary - run: stencil push -a -d + run: stencil push -a -d -c 1 diff --git a/.github/workflow-examples/poll_for_changed_configuration.yml b/.github/workflow-examples/poll_for_changed_configuration.yml index 3bba3e3fe6..714d9d69cc 100644 --- a/.github/workflow-examples/poll_for_changed_configuration.yml +++ b/.github/workflow-examples/poll_for_changed_configuration.yml @@ -49,8 +49,8 @@ jobs: TOKEN: ${{ secrets.STENCIL_ACCESS_TOKEN_PRODUCTION }} run: stencil init -u $URL -t $TOKEN -p 3000 - - name: Check for an updated configuration on the live store - run: stencil pull + - name: Check for an updated configuration on the live default storefront (channel ID 1) + run: stencil pull -c 1 - name: Create Pull Request id: cpr diff --git a/CHANGELOG.md b/CHANGELOG.md index 32425b7443..0714295018 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,21 @@ # Changelog ## Draft +- Fixed displaying swatch name for multiple swatch options on page. [#2040](https://github.com/bigcommerce/cornerstone/pull/2040) +- Added settings for payment banners. [#2021](https://github.com/bigcommerce/cornerstone/pull/2021) +- Use https:// for schema markup. [#2039](https://github.com/bigcommerce/cornerstone/pull/2039) +- Update focus tooltip styles contrast to achieve accessibility AA Complaince. [#2047](https://github.com/bigcommerce/cornerstone/pull/2047) +- Apple pay button displaying needs to be fixed. [#2043](https://github.com/bigcommerce/cornerstone/pull/2043) + +## 5.4.0 (04-26-2021) +- Incorrect focus order for product carousels. [#2034](https://github.com/bigcommerce/cornerstone/pull/2034) +- Removed duplicates of main tag.[#2032](https://github.com/bigcommerce/cornerstone/pull/2032) +- Hamburger Menu Icon missing on Google AMP Pages. [#2022](https://github.com/bigcommerce/cornerstone/pull/2022) +- Wish List drop down is truncated on product page. [#2001](https://github.com/bigcommerce/cornerstone/pull/2001) +- Improve performance of analyzing homepage carousel images. [#2027](https://github.com/bigcommerce/cornerstone/pull/2027) +- Added keyboard support on radio buttons. [#2028](https://github.com/bigcommerce/cornerstone/pull/2028) +- Replace SSL settings in Page builder with global region for SSL certificate. [#2026](https://github.com/bigcommerce/cornerstone/pull/2026) +- fixed email address validation in forms. [#2029](https://github.com/bigcommerce/cornerstone/pull/2029) - Fixed unnecessary horizontal scroll on swatch options on PDP. [#2023](https://github.com/bigcommerce/cornerstone/pull/2023) - Always showing product counts for Category facet in the faceted search results page. [#2035](https://github.com/bigcommerce/cornerstone/pull/2035) diff --git a/assets/js/theme/cart.js b/assets/js/theme/cart.js index 01268687e9..c13b165cae 100644 --- a/assets/js/theme/cart.js +++ b/assets/js/theme/cart.js @@ -10,6 +10,7 @@ import CartItemDetails from './common/cart-item-details'; export default class Cart extends PageManager { onReady() { this.$modal = null; + this.$cartPageContent = $('[data-cart]'); this.$cartContent = $('[data-cart-content]'); this.$cartMessages = $('[data-cart-status]'); this.$cartTotals = $('[data-cart-totals]'); @@ -18,9 +19,16 @@ export default class Cart extends PageManager { this.$activeCartItemId = null; this.$activeCartItemBtnAction = null; + this.setApplePaySupport(); this.bindEvents(); } + setApplePaySupport() { + if (window.ApplePaySession) { + this.$cartPageContent.addClass('apple-pay-supported'); + } + } + cartUpdate($target) { const itemId = $target.data('cartItemid'); this.$activeCartItemId = itemId; diff --git a/assets/js/theme/common/aria/radioOptions.js b/assets/js/theme/common/aria/radioOptions.js index f65eb29827..5a32129994 100644 --- a/assets/js/theme/common/aria/radioOptions.js +++ b/assets/js/theme/common/aria/radioOptions.js @@ -9,6 +9,7 @@ const setCheckedRadioItem = (itemCollection, itemIdx) => { } $item.attr('aria-checked', true).prop('checked', true).focus(); + $item.trigger('change'); }); }; @@ -31,21 +32,18 @@ const handleItemKeyDown = itemCollection => e => { } switch (keyCode) { - case ariaKeyCodes.RETURN: - case ariaKeyCodes.SPACE: { - setCheckedRadioItem(itemCollection, itemIdx); - break; - } case ariaKeyCodes.LEFT: case ariaKeyCodes.UP: { const prevItemIdx = calculateTargetItemPosition(lastCollectionItemIdx, itemIdx - 1); itemCollection.get(prevItemIdx).focus(); + setCheckedRadioItem(itemCollection, itemIdx - 1); break; } case ariaKeyCodes.RIGHT: case ariaKeyCodes.DOWN: { const nextItemIdx = calculateTargetItemPosition(lastCollectionItemIdx, itemIdx + 1); itemCollection.get(nextItemIdx).focus(); + setCheckedRadioItem(itemCollection, itemIdx + 1); break; } diff --git a/assets/js/theme/common/carousel/constants.js b/assets/js/theme/common/carousel/constants.js new file mode 100644 index 0000000000..9db53bebe6 --- /dev/null +++ b/assets/js/theme/common/carousel/constants.js @@ -0,0 +1 @@ +export const FOCUSABLE_ELEMENTS_SELECTOR = '[href], button, input, textarea, select, details, [contenteditable="true"], [tabindex]'; diff --git a/assets/js/theme/common/carousel/index.js b/assets/js/theme/common/carousel/index.js index 1cdc858699..a687f11035 100644 --- a/assets/js/theme/common/carousel/index.js +++ b/assets/js/theme/common/carousel/index.js @@ -2,62 +2,61 @@ import 'slick-carousel'; import { activatePlayPauseButton, + analizeSlides, arrowAriaLabling, dotsSetup, getActiveSlideIdxAndSlidesQuantity, handleImageAspectRatio, handleImageLoad, - setTabindexes, - tooltipSetup, + refreshFocus, updateTextWithLiveData, } from './utils'; -/** - * returns activeSlideIdx and slidesQuantity - * based on provided carousel settings - * @param {Object} $slickSettings - * @returns {Object} - */ -const extractSlidesDetails = ({ - slideCount, $slides, options: { slidesToShow, slidesToScroll }, -}) => getActiveSlideIdxAndSlidesQuantity( - slideCount, - slidesToShow, - slidesToScroll, - $slides, -); +export const setCarouselState = ({ delegateTarget }, carouselObj) => { + const carouselObjCurrent = carouselObj || delegateTarget.slick; + const { $slider } = carouselObjCurrent; + + $slider.data('state', getActiveSlideIdxAndSlidesQuantity(carouselObjCurrent)); +}; export const onUserCarouselChange = ({ data }, context, $slider) => { const $activeSlider = $slider || data; - const $parentContainer = $activeSlider.hasClass('productView-thumbnails') ? $('.productView-images') : $activeSlider; - const { activeSlideIdx, slidesQuantity } = extractSlidesDetails($activeSlider[0].slick); + const $parentContainer = $activeSlider.hasClass('productView-thumbnails') ? $activeSlider.parent('.productView-images') : $activeSlider; + const { activeSlideIdx, slidesQuantity } = $activeSlider.data('state'); const $carouselContentElement = $('[data-carousel-content-change-message]', $parentContainer); const carouselContentAnnounceMessage = updateTextWithLiveData(context.carouselContentAnnounceMessage, (activeSlideIdx + 1), slidesQuantity); $carouselContentElement.text(carouselContentAnnounceMessage); }; -export const onSlickCarouselChange = (e, carousel, context) => { +export const onSlickCarouselChange = (e, carouselObj, context) => { const { $dots, $slider, $prevArrow, $nextArrow, - } = carousel; + options: { infinite }, + } = carouselObj; - const { activeSlideIdx, slidesQuantity } = extractSlidesDetails(carousel); + const { activeSlideIdx, slidesQuantity } = $slider.data('state') || getActiveSlideIdxAndSlidesQuantity(carouselObj); dotsSetup($dots, activeSlideIdx, slidesQuantity, context); - arrowAriaLabling($prevArrow, $nextArrow, activeSlideIdx, slidesQuantity, context.carouselArrowAndDotAriaLabel); - setTabindexes($slider.find('.slick-slide')); - tooltipSetup($prevArrow, $nextArrow, $dots); - activatePlayPauseButton(carousel, slidesQuantity, context); + arrowAriaLabling($prevArrow, $nextArrow, activeSlideIdx, slidesQuantity, infinite, context.carouselArrowAndDotAriaLabel); + analizeSlides($slider.find('.slick-slide')); + refreshFocus($prevArrow, $nextArrow, $dots, $slider, activeSlideIdx, slidesQuantity, infinite); + + $slider.data('state', null); }; export default function (context) { $('[data-slick]').each((idx, carousel) => { // getting element using find to pass jest test const $carousel = $(document).find(carousel); + + $carousel.on('init breakpoint swipe', setCarouselState); + $carousel.on('click', '.slick-arrow, .slick-dots', setCarouselState); + + $carousel.on('init breakpoint', (e, carouselObj) => activatePlayPauseButton(e, carouselObj, context)); $carousel.on('init afterChange', (e, carouselObj) => onSlickCarouselChange(e, carouselObj, context)); $carousel.on('click', '.slick-arrow, .slick-dots', $carousel, e => onUserCarouselChange(e, context)); $carousel.on('swipe', (e, carouselObj) => onUserCarouselChange(e, context, carouselObj.$slider)); @@ -65,7 +64,7 @@ export default function (context) { if ($carousel.hasClass('heroCarousel')) { $carousel.on('init afterChange', handleImageLoad); $carousel.on('swipe', handleImageAspectRatio); - $carousel.on('click', '.slick-arrow, .slick-dots', $carousel, handleImageAspectRatio); + $carousel.on('click', '.slick-arrow, .slick-dots', handleImageAspectRatio); // Alternative image styling for IE, which doesn't support objectfit if (typeof document.documentElement.style.objectFit === 'undefined') { diff --git a/assets/js/theme/common/carousel/utils/activatePlayPauseButton.js b/assets/js/theme/common/carousel/utils/activatePlayPauseButton.js index 7405369771..71f4d8be5e 100644 --- a/assets/js/theme/common/carousel/utils/activatePlayPauseButton.js +++ b/assets/js/theme/common/carousel/utils/activatePlayPauseButton.js @@ -2,18 +2,7 @@ import { throttle } from 'lodash'; const PLAY_ACTION = 'slickPlay'; const PAUSE_ACTION = 'slickPause'; -const IS_ACTIVATED_DATA_ATTR = 'is-activated'; - -export default (carousel, slidesQuantity, context) => { - const { $slider, $dots, speed } = carousel; - const $playPauseButton = $slider.find('[data-play-pause-button]'); - - if ($playPauseButton.length === 0) return; - - $playPauseButton.css('display', slidesQuantity < 2 ? 'none' : 'block'); - - if ($playPauseButton.data(IS_ACTIVATED_DATA_ATTR)) return; - +const updateButtonLabels = (context) => { const { carouselPlayPauseButtonPlay, carouselPlayPauseButtonPause, @@ -21,30 +10,43 @@ export default (carousel, slidesQuantity, context) => { carouselPlayPauseButtonAriaPause, } = context; - const updateLabels = action => { - $playPauseButton + return ($button, action) => { + $button .text(action === PLAY_ACTION ? carouselPlayPauseButtonPause : carouselPlayPauseButtonPlay) .attr('aria-label', action === PLAY_ACTION ? carouselPlayPauseButtonAriaPause : carouselPlayPauseButtonAriaPlay); }; +}; +let updateButtonLabelsWithContext; - const onPlayPauseClick = () => { - const action = carousel.paused ? PLAY_ACTION : PAUSE_ACTION; +export default (e, carouselObj, context) => { + const { $slider, $dots, options: { speed } } = carouselObj; + const $playPauseButton = $slider.find('[data-play-pause-button]'); - $slider.slick(action); - updateLabels(action); - }; + if ($playPauseButton.length === 0) return; // for correct carousel controls focus order if ($dots) { $playPauseButton.insertBefore($dots); } else $slider.append($playPauseButton); - $playPauseButton.on('click', throttle(onPlayPauseClick, speed, { trailing: false })); - $playPauseButton.data(IS_ACTIVATED_DATA_ATTR, true); + const { slidesQuantity } = $slider.data('state'); + $playPauseButton.css('display', slidesQuantity > 1 ? 'block' : 'none'); - if (carousel.breakpoints.length) { - $slider.on('breakpoint', () => updateLabels(PLAY_ACTION)); + if (e.type === 'init') updateButtonLabelsWithContext = updateButtonLabels(context); + + if (e.type === 'breakpoint') { + updateButtonLabelsWithContext($playPauseButton, PLAY_ACTION); + return; } + + const onPlayPauseClick = () => { + const action = carouselObj.paused ? PLAY_ACTION : PAUSE_ACTION; + + $slider.slick(action); + updateButtonLabelsWithContext($playPauseButton, action); + }; + + $playPauseButton.on('click', throttle(onPlayPauseClick, speed, { trailing: false })); }; diff --git a/assets/js/theme/common/carousel/utils/setTabindexes.js b/assets/js/theme/common/carousel/utils/analizeSlides.js similarity index 76% rename from assets/js/theme/common/carousel/utils/setTabindexes.js rename to assets/js/theme/common/carousel/utils/analizeSlides.js index 892b2ca0c4..7b1d38c57d 100644 --- a/assets/js/theme/common/carousel/utils/setTabindexes.js +++ b/assets/js/theme/common/carousel/utils/analizeSlides.js @@ -1,4 +1,4 @@ -const FOCUSABLE_ELEMENTS_SELECTOR = '[href], button, input, textarea, select, details, [contenteditable="true"], [tabindex]'; +import { FOCUSABLE_ELEMENTS_SELECTOR } from '../constants'; export default ($slides) => { $slides.each((idx, slide) => { diff --git a/assets/js/theme/common/carousel/utils/arrowAriaLabling.js b/assets/js/theme/common/carousel/utils/arrowAriaLabling.js index 1751262d1d..dc96c2b77a 100644 --- a/assets/js/theme/common/carousel/utils/arrowAriaLabling.js +++ b/assets/js/theme/common/carousel/utils/arrowAriaLabling.js @@ -1,6 +1,7 @@ import updateTextWithLiveData from './updateTextWithLiveData'; +import tooltipSetup from './tooltipSetup'; -export default ($prevArrow, $nextArrow, activeSlideIdx, slidesQuantity, ariaLabel) => { +export default ($prevArrow, $nextArrow, activeSlideIdx, slidesQuantity, isInfinite, ariaLabel) => { if (slidesQuantity < 2 || !$prevArrow || !$nextArrow) return; const activeSlideNumber = activeSlideIdx + 1; @@ -8,10 +9,18 @@ export default ($prevArrow, $nextArrow, activeSlideIdx, slidesQuantity, ariaLabe const prevSlideNumber = activeSlideIdx === 0 ? slidesQuantity : activeSlideNumber - 1; const arrowLeftText = updateTextWithLiveData(ariaLabel, prevSlideNumber, slidesQuantity); - $prevArrow.attr('aria-label', arrowLeftText); + $prevArrow.attr({ + 'aria-label': arrowLeftText, + tabindex: !isInfinite && activeSlideIdx === 0 ? -1 : 0, + }); + tooltipSetup($prevArrow); const nextSlideNumber = activeSlideIdx === slidesQuantity - 1 ? 1 : activeSlideNumber + 1; const arrowRightText = updateTextWithLiveData(ariaLabel, nextSlideNumber, slidesQuantity); - $nextArrow.attr('aria-label', arrowRightText); + $nextArrow.attr({ + 'aria-label': arrowRightText, + tabindex: !isInfinite && activeSlideIdx === slidesQuantity - 1 ? -1 : 0, + }); + tooltipSetup($nextArrow); }; diff --git a/assets/js/theme/common/carousel/utils/dotsSetup.js b/assets/js/theme/common/carousel/utils/dotsSetup.js index 9db5927d7d..109f1847e5 100644 --- a/assets/js/theme/common/carousel/utils/dotsSetup.js +++ b/assets/js/theme/common/carousel/utils/dotsSetup.js @@ -1,4 +1,5 @@ import updateTextWithLiveData from './updateTextWithLiveData'; +import tooltipSetup from './tooltipSetup'; export default ($dots, activeSlideIdx, slidesQuantity, { carouselArrowAndDotAriaLabel, carouselActiveDotAriaLabel }) => { if (!$dots) return; @@ -14,7 +15,8 @@ export default ($dots, activeSlideIdx, slidesQuantity, { carouselArrowAndDotAria const dotLabelText = updateTextWithLiveData(carouselArrowAndDotAriaLabel, idx + 1, slidesQuantity); const dotSlideStatusText = idx === activeSlideIdx ? `, ${carouselActiveDotAriaLabel}` : ''; const dotAriaLabel = `${dotLabelText}${dotSlideStatusText}`; + const $dotButton = $(dot).find('[data-carousel-dot]'); - $(dot).find('[data-carousel-dot]').attr('aria-label', dotAriaLabel); + tooltipSetup($dotButton.attr('aria-label', dotAriaLabel)); }); }; diff --git a/assets/js/theme/common/carousel/utils/getActiveSlideIdxAndSlidesQuantity.js b/assets/js/theme/common/carousel/utils/getActiveSlideIdxAndSlidesQuantity.js index 352a82dc80..83f1cccef2 100644 --- a/assets/js/theme/common/carousel/utils/getActiveSlideIdxAndSlidesQuantity.js +++ b/assets/js/theme/common/carousel/utils/getActiveSlideIdxAndSlidesQuantity.js @@ -1,4 +1,4 @@ -export default (slideCount, slidesToShow, slidesToScroll, $slides) => { +export default ({ slideCount, $slides, options: { slidesToShow, slidesToScroll } }) => { const lastVisibleIdx = $slides.get().reduce((acc, curr, idx) => { if ($(curr).hasClass('slick-active')) return idx; return acc; diff --git a/assets/js/theme/common/carousel/utils/getActiveSlideInfo.js b/assets/js/theme/common/carousel/utils/getActiveSlideInfo.js index c5b67c770e..3cdf46b7df 100644 --- a/assets/js/theme/common/carousel/utils/getActiveSlideInfo.js +++ b/assets/js/theme/common/carousel/utils/getActiveSlideInfo.js @@ -5,16 +5,12 @@ export default ({ $slider }, isAnalyzedDataAttr) => { if (isAnalyzedSlide) return { isAnalyzedSlide }; const $activeSlideImg = $activeSlide.find('.heroCarousel-image'); - - const attrsObj = { - src: $activeSlideImg.attr('src'), - srcset: $activeSlideImg.attr('srcset'), - sizes: $activeSlideImg.attr('sizes'), - }; + const activeSlideImgNode = $activeSlideImg[0]; return { - attrsObj, $slider, $activeSlide, + $activeSlideImg, + activeSlideImgNode, }; }; diff --git a/assets/js/theme/common/carousel/utils/handleImageAspectRatio.js b/assets/js/theme/common/carousel/utils/handleImageAspectRatio.js index ef163e433e..f10ab2cdd6 100644 --- a/assets/js/theme/common/carousel/utils/handleImageAspectRatio.js +++ b/assets/js/theme/common/carousel/utils/handleImageAspectRatio.js @@ -6,7 +6,7 @@ const IMAGE_CLASSES = { }; const IS_ANALYZED_DATA_ATTR = 'image-ratio-analyzed'; -const defineClass = (imageAspectRatio) => { +const defineAspectRatioClass = (imageAspectRatio) => { switch (true) { case imageAspectRatio > 0.8 && imageAspectRatio <= 1.2: return IMAGE_CLASSES.square; @@ -17,13 +17,21 @@ const defineClass = (imageAspectRatio) => { } }; -export default ({ delegateTarget }, carousel) => { +const setAspectRatioClass = (imageNode, $slides) => { + if (imageNode.naturalHeight <= 1) return; + + const imageAspectRatio = imageNode.naturalHeight / imageNode.naturalWidth; + $slides.each((idx, slide) => $(slide).addClass(defineAspectRatioClass(imageAspectRatio))); +}; + +export default ({ delegateTarget }, carouselObj) => { const { isAnalyzedSlide, - attrsObj, $slider, $activeSlide, - } = getActiveSlideInfo(carousel || delegateTarget.slick, IS_ANALYZED_DATA_ATTR); + $activeSlideImg, + activeSlideImgNode, + } = getActiveSlideInfo(carouselObj || delegateTarget.slick, IS_ANALYZED_DATA_ATTR); if (isAnalyzedSlide) return; @@ -32,15 +40,12 @@ export default ({ delegateTarget }, carousel) => { if ($activeSlide.find('.heroCarousel-content').length) return; - $('') - .on('load', function getImageSizes() { - const imageHeight = this.height; - const imageWidth = this.width; - - if (imageHeight < 2 || imageWidth < 2) return; - - const imageAspectRatio = imageHeight / imageWidth; - $activeSlideAndClones.each((idx, slide) => $(slide).addClass(defineClass(imageAspectRatio))); - }) - .attr(attrsObj); + if (activeSlideImgNode.complete) { + if (activeSlideImgNode.naturalHeight === 1) { + // only base64 image from srcset was loaded + $activeSlideImg.on('load', () => setAspectRatioClass(activeSlideImgNode, $activeSlideAndClones)); + } else if (activeSlideImgNode.naturalHeight > 1) { + setAspectRatioClass(activeSlideImgNode, $activeSlideAndClones); + } + } else $activeSlideImg.on('load', () => setAspectRatioClass(activeSlideImgNode, $activeSlideAndClones)); }; diff --git a/assets/js/theme/common/carousel/utils/handleImageLoad.js b/assets/js/theme/common/carousel/utils/handleImageLoad.js index 66572db108..9a9f5383a8 100644 --- a/assets/js/theme/common/carousel/utils/handleImageLoad.js +++ b/assets/js/theme/common/carousel/utils/handleImageLoad.js @@ -1,20 +1,47 @@ +import { isBrowserIE } from '../../utils/ie-helpers'; import getActiveSlideInfo from './getActiveSlideInfo'; const IMAGE_ERROR_CLASS = 'is-image-error'; const IS_ANALYZED_DATA_ATTR = 'image-load-analyzed'; -export default (e, carousel) => { +const generateImage = ($slide, $image) => { + $('') + .on('error', () => $slide.addClass(IMAGE_ERROR_CLASS)) + .attr('src', $image.attr('src')); +}; + +export default (e, carouselObj) => { const { isAnalyzedSlide, - attrsObj, $activeSlide, - } = getActiveSlideInfo(carousel, IS_ANALYZED_DATA_ATTR); + $activeSlideImg, + activeSlideImgNode, + } = getActiveSlideInfo(carouselObj, IS_ANALYZED_DATA_ATTR); if (isAnalyzedSlide) return; $activeSlide.data(IS_ANALYZED_DATA_ATTR, true); - $('') - .on('error', () => $activeSlide.addClass(IMAGE_ERROR_CLASS)) - .attr(attrsObj); + if (activeSlideImgNode.complete) { + if (activeSlideImgNode.naturalHeight === 0) { + $activeSlide.addClass(IMAGE_ERROR_CLASS); + } else if (activeSlideImgNode.naturalHeight === 1) { + // only base64 image from srcset was loaded + $activeSlideImg.on('error', () => $activeSlide.addClass(IMAGE_ERROR_CLASS)); + } + + return; + } + + if (!$activeSlideImg.attr('src')) { + $activeSlide.addClass(IMAGE_ERROR_CLASS); + return; + } + + if (isBrowserIE) { + generateImage($activeSlide, $activeSlideImg); + return; + } + + $activeSlideImg.on('error', () => $activeSlide.addClass(IMAGE_ERROR_CLASS)); }; diff --git a/assets/js/theme/common/carousel/utils/index.js b/assets/js/theme/common/carousel/utils/index.js index 3e7e2dd0a0..f6ad26c659 100644 --- a/assets/js/theme/common/carousel/utils/index.js +++ b/assets/js/theme/common/carousel/utils/index.js @@ -1,9 +1,9 @@ export { default as activatePlayPauseButton } from './activatePlayPauseButton'; +export { default as analizeSlides } from './analizeSlides'; export { default as arrowAriaLabling } from './arrowAriaLabling'; export { default as dotsSetup } from './dotsSetup'; export { default as getActiveSlideIdxAndSlidesQuantity } from './getActiveSlideIdxAndSlidesQuantity'; export { default as handleImageAspectRatio } from './handleImageAspectRatio'; export { default as handleImageLoad } from './handleImageLoad'; -export { default as setTabindexes } from './setTabindexes'; -export { default as tooltipSetup } from './tooltipSetup'; +export { default as refreshFocus } from './refreshFocus'; export { default as updateTextWithLiveData } from './updateTextWithLiveData'; diff --git a/assets/js/theme/common/carousel/utils/refreshFocus.js b/assets/js/theme/common/carousel/utils/refreshFocus.js new file mode 100644 index 0000000000..dad85f3d56 --- /dev/null +++ b/assets/js/theme/common/carousel/utils/refreshFocus.js @@ -0,0 +1,20 @@ +import { FOCUSABLE_ELEMENTS_SELECTOR } from '../constants'; + +export default ($prevArrow, $nextArrow, $dots, $slider, activeSlideIdx, slidesQuantity, isInfinite) => { + if (isInfinite || !$prevArrow || !$nextArrow) return; + + if (activeSlideIdx === 0 && $prevArrow.is(':focus')) { + $nextArrow.focus(); + } else if (activeSlideIdx === slidesQuantity - 1 && $nextArrow.is(':focus')) { + if ($dots) { + $dots.children().first().find('[data-carousel-dot]').focus(); + return; + } + + const $firstActiveSlide = $slider.find('.slick-active').first(); + + if ($firstActiveSlide.is(FOCUSABLE_ELEMENTS_SELECTOR)) { + $firstActiveSlide.focus(); + } else $firstActiveSlide.find(FOCUSABLE_ELEMENTS_SELECTOR).first().focus(); + } +}; diff --git a/assets/js/theme/common/carousel/utils/tooltipSetup.js b/assets/js/theme/common/carousel/utils/tooltipSetup.js index da4af37856..c2a6003ba0 100644 --- a/assets/js/theme/common/carousel/utils/tooltipSetup.js +++ b/assets/js/theme/common/carousel/utils/tooltipSetup.js @@ -2,7 +2,7 @@ const TOOLTIP_DATA_SELECTOR = 'data-carousel-tooltip'; const TOOLTIP_CLASS = 'carousel-tooltip'; const TOOLTIP_NODE = ``; -const setupTooltipAriaLabel = ($node) => { +export default ($node) => { const $existedTooltip = $node.find(`[${TOOLTIP_DATA_SELECTOR}]`); if ($existedTooltip.length) { $existedTooltip.attr('aria-label', $node.attr('aria-label')); @@ -11,21 +11,3 @@ const setupTooltipAriaLabel = ($node) => { $node.append($tooltip); } }; - -const setupArrowTooltips = (...arrowNodes) => { - arrowNodes.forEach($arrow => setupTooltipAriaLabel($arrow)); -}; - -const setupDotTooltips = ($dots) => { - $dots.children().each((idx, dot) => setupTooltipAriaLabel($('[data-carousel-dot]', dot))); -}; - -export default ($prevArrow, $nextArrow, $dots) => { - if ($prevArrow && $nextArrow) { - setupArrowTooltips($prevArrow, $nextArrow); - } - - if ($dots) { - setupDotTooltips($dots); - } -}; diff --git a/assets/js/theme/common/models/forms.js b/assets/js/theme/common/models/forms.js index c4870e68dd..ddb7dfc846 100644 --- a/assets/js/theme/common/models/forms.js +++ b/assets/js/theme/common/models/forms.js @@ -1,6 +1,6 @@ const forms = { email(value) { - const re = /^.+@.+\..+/; + const re = /^\S+@\S+\.\S+/; return re.test(value); }, diff --git a/assets/js/theme/common/product-details.js b/assets/js/theme/common/product-details.js index b698f15d77..326767d4e8 100644 --- a/assets/js/theme/common/product-details.js +++ b/assets/js/theme/common/product-details.js @@ -18,7 +18,9 @@ export default class ProductDetails extends ProductDetailsBase { this.imageGallery.init(); this.listenQuantityChange(); this.$swatchOptionMessage = $('.swatch-option-message'); - this.swatchOptionMessageInitText = this.$swatchOptionMessage.text(); + this.swatchInitMessageStorage = {}; + this.swatchGroupIdList = $('[id^="swatchGroup"]').map((_, group) => $(group).attr('id')); + this.storeInitMessagesForSwatches(); const $form = $('form[data-cart-item-add]', $scope); const $productOptionsElement = $('[data-product-option-change]', $form); @@ -43,10 +45,17 @@ export default class ProductDetails extends ProductDetailsBase { if (context.showSwatchNames) { this.$swatchOptionMessage.removeClass('u-hidden'); - $productSwatchGroup.on('change', ({ target }) => this.showSwatchNameOnOption($(target))); + + $productSwatchGroup.on('change', ({ target }) => { + const swatchGroupElement = target.parentNode.parentNode; + + this.showSwatchNameOnOption($(target), $(swatchGroupElement)); + }); $.each($productSwatchGroup, (_, element) => { - if ($(element).is(':checked')) this.showSwatchNameOnOption($(element)); + const swatchGroupElement = element.parentNode.parentNode; + + if ($(element).is(':checked')) this.showSwatchNameOnOption($(element), $(swatchGroupElement)); }); } @@ -76,6 +85,16 @@ export default class ProductDetails extends ProductDetailsBase { this.previewModal = modalFactory('#previewModal')[0]; } + storeInitMessagesForSwatches() { + if (this.swatchGroupIdList.length && isEmpty(this.swatchInitMessageStorage)) { + this.swatchGroupIdList.each((_, swatchGroupId) => { + if (!this.swatchInitMessageStorage[swatchGroupId]) { + this.swatchInitMessageStorage[swatchGroupId] = $(`#${swatchGroupId} ~ .swatch-option-message`).text().trim(); + } + }); + } + } + setProductVariant() { const unsatisfiedRequiredFields = []; const options = []; @@ -218,12 +237,14 @@ export default class ProductDetails extends ProductDetailsBase { * if this setting is enabled in Page Builder * show name for swatch option */ - showSwatchNameOnOption($swatch) { + showSwatchNameOnOption($swatch, $swatchGroup) { const swatchName = $swatch.attr('aria-label'); + const activeSwatchGroupId = $swatchGroup.attr('aria-labelledby'); + const $swatchOptionMessage = $(`#${activeSwatchGroupId} ~ .swatch-option-message`); - $('[data-product-attribute="swatch"] [data-option-value]').text(swatchName); - this.$swatchOptionMessage.text(`${this.swatchOptionMessageInitText} ${swatchName}`); - this.setLiveRegionAttributes(this.$swatchOptionMessage, 'status', 'assertive'); + $('[data-option-value]', $swatchGroup).text(swatchName); + $swatchOptionMessage.text(`${this.swatchInitMessageStorage[activeSwatchGroupId]} ${swatchName}`); + this.setLiveRegionAttributes($swatchOptionMessage, 'status', 'assertive'); } setLiveRegionAttributes($element, roleType, ariaLiveStatus) { @@ -376,6 +397,10 @@ export default class ProductDetails extends ProductDetailsBase { if (this.previewModal) { this.previewModal.open(); + if (window.ApplePaySession) { + this.previewModal.$modal.addClass('apple-pay-supported'); + } + if ($addToCartBtn.parents('.quickView').length === 0) this.previewModal.$preModalFocusedEl = $addToCartBtn; this.updateCartContent(this.previewModal, response.data.cart_item.id, () => this.previewModal.setupFocusTrap()); } else { diff --git a/assets/js/theme/common/utils/ie-helpers.js b/assets/js/theme/common/utils/ie-helpers.js index c65b0c1275..cde421dc48 100644 --- a/assets/js/theme/common/utils/ie-helpers.js +++ b/assets/js/theme/common/utils/ie-helpers.js @@ -1,3 +1,3 @@ -export const isBrowserIE = navigator.userAgent.includes('Trident'); +export const isBrowserIE = !!document.documentMode; export const convertIntoArray = collection => Array.prototype.slice.call(collection); diff --git a/assets/js/theme/global/cart-preview.js b/assets/js/theme/global/cart-preview.js index 0fc5138c7d..b5c79f086f 100644 --- a/assets/js/theme/global/cart-preview.js +++ b/assets/js/theme/global/cart-preview.js @@ -15,6 +15,10 @@ export default function (secureBaseUrl, cartId) { const $body = $('body'); + if (window.ApplePaySession) { + $cartDropdown.addClass('apple-pay-supported'); + } + $body.on('cart-quantity-update', (event, quantity) => { $cart.attr('aria-label', (_, prevValue) => prevValue.replace(/\d+/, quantity)); diff --git a/assets/js/theme/global/quick-view.js b/assets/js/theme/global/quick-view.js index 85b13bcdd7..907282f1c8 100644 --- a/assets/js/theme/global/quick-view.js +++ b/assets/js/theme/global/quick-view.js @@ -4,7 +4,7 @@ import utils from '@bigcommerce/stencil-utils'; import ProductDetails from '../common/product-details'; import { defaultModal } from './modal'; import 'slick-carousel'; -import { onSlickCarouselChange, onUserCarouselChange } from '../common/carousel'; +import { setCarouselState, onSlickCarouselChange, onUserCarouselChange } from '../common/carousel'; export default function (context) { const modal = defaultModal(); @@ -24,7 +24,10 @@ export default function (context) { const $carousel = modal.$content.find('[data-slick]'); if ($carousel.length) { - $carousel.on('init afterChange', (e, carousel) => onSlickCarouselChange(e, carousel, context)); + $carousel.on('init breakpoint swipe', setCarouselState); + $carousel.on('click', '.slick-arrow, .slick-dots', setCarouselState); + + $carousel.on('init afterChange', (e, carouselObj) => onSlickCarouselChange(e, carouselObj, context)); $carousel.on('click', '.slick-arrow, .slick-dots', $carousel, e => onUserCarouselChange(e, context)); $carousel.on('swipe', (e, carouselObj) => onUserCarouselChange(e, context, carouselObj.$slider)); diff --git a/assets/js/theme/search.js b/assets/js/theme/search.js index f022231cdb..8467de01e5 100644 --- a/assets/js/theme/search.js +++ b/assets/js/theme/search.js @@ -204,9 +204,15 @@ export default class Search extends CatalogPage { } }); - setTimeout(() => { - $('[data-search-aria-message]').removeClass('u-hidden'); - }, 100); + const $searchResultsMessage = $(`

${this.context.searchResultsCount}

`) + .prependTo('body'); + + setTimeout(() => $searchResultsMessage.focus(), 100); } loadTreeNodes(node, cb) { diff --git a/assets/scss/common/_focus-tooltip.scss b/assets/scss/common/_focus-tooltip.scss index 9d1bd3ccbf..7a7fed7052 100644 --- a/assets/scss/common/_focus-tooltip.scss +++ b/assets/scss/common/_focus-tooltip.scss @@ -6,14 +6,14 @@ top: 50%; border-width: remCalc(10px); border-style: solid; - border-color: transparent transparent $adminBar-tooltip-bg-backgroundColor transparent; + border-color: transparent transparent $focusTooltip-backgroundColor transparent; } &:after { content: attr($attr); padding: remCalc(4px) remCalc(6px); - background-color: $adminBar-tooltip-bg-backgroundColor; - color: white; + background-color: $focusTooltip-backgroundColor; + color: $focusTooltip-textColor; position: absolute; font-size: 1rem; white-space: nowrap; diff --git a/assets/scss/components/stencil/applePay/_applePay.scss b/assets/scss/components/stencil/applePay/_applePay.scss index dbaf8a4a8c..c931dd0d63 100644 --- a/assets/scss/components/stencil/applePay/_applePay.scss +++ b/assets/scss/components/stencil/applePay/_applePay.scss @@ -25,23 +25,14 @@ } } -.cart-additionalCheckoutButtons { - .apple-pay-checkout-button { - margin-top: spacing("half"); - } -} - .apple-pay-supported { .apple-pay-checkout-button { display: block; float: right; } -} -.previewCartCheckout { - .apple-pay-checkout-button { + & .previewCartCheckout .apple-pay-checkout-button { display: inline-block; float: none; - margin-top: spacing("half"); } } diff --git a/assets/scss/components/stencil/cart/_cart.scss b/assets/scss/components/stencil/cart/_cart.scss index a119cf829b..7bdfebd6ea 100644 --- a/assets/scss/components/stencil/cart/_cart.scss +++ b/assets/scss/components/stencil/cart/_cart.scss @@ -43,18 +43,6 @@ $card-preview-zoom-bottom-offset: 6rem; float: right; } } - - .CheckoutButton { - margin-bottom: spacing("base"); - - &:first-child { - margin-top: spacing("single"); - } - - &:last-child { - margin-bottom: spacing("single"); - } - } } // Cart layout @@ -557,7 +545,8 @@ $card-preview-zoom-bottom-offset: 6rem; .previewCart-additionalCheckoutButtons { @extend %additionalCheckoutButtons; - padding-right: 1.5rem; + padding-right: spacing('single'); + padding-bottom: spacing('single'); } // Cart Preview @@ -608,7 +597,7 @@ $card-preview-zoom-bottom-offset: 6rem; } @include lazy-loaded-padding('productthumb_size'); - + &:after { @include breakpoint("xxsmall") { padding-bottom: 75%; diff --git a/assets/scss/components/stencil/heroCarousel/_heroCarousel.scss b/assets/scss/components/stencil/heroCarousel/_heroCarousel.scss index c109d870eb..10cff12547 100644 --- a/assets/scss/components/stencil/heroCarousel/_heroCarousel.scss +++ b/assets/scss/components/stencil/heroCarousel/_heroCarousel.scss @@ -33,6 +33,15 @@ } } + // for IE + @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { + opacity: 0; + + &.slick-initialized { + opacity: 1; + } + } + &:not(.slick-initialized) :not(.heroCarousel-slide--first).heroCarousel-slide { display: none; } diff --git a/assets/scss/components/stencil/previewCart/_previewCart.scss b/assets/scss/components/stencil/previewCart/_previewCart.scss index e8967df692..52bb04ca2d 100644 --- a/assets/scss/components/stencil/previewCart/_previewCart.scss +++ b/assets/scss/components/stencil/previewCart/_previewCart.scss @@ -56,10 +56,13 @@ width: 100%; // scss-lint:disable NestingDepth - + .button, + p { margin-top: spacing("half"); } + + &:not(:last-child) { + margin-bottom: spacing("half"); + } } } diff --git a/assets/scss/components/stencil/productView/_productView.scss b/assets/scss/components/stencil/productView/_productView.scss index ac5ffe9293..1d51469e38 100644 --- a/assets/scss/components/stencil/productView/_productView.scss +++ b/assets/scss/components/stencil/productView/_productView.scss @@ -119,17 +119,9 @@ // Details // ----------------------------------------------------------------------------- -// -// 1. for Androind Chrome and IE with zoom horizontal scroll fix -// -// ----------------------------------------------------------------------------- .productView-details { padding-bottom: spacing("single") + spacing("third"); - - &.product-options { - overflow: hidden; // 1 - } } diff --git a/assets/scss/settings/global/color/_color.scss b/assets/scss/settings/global/color/_color.scss index ae4dfaed6e..0269c3a4d9 100644 --- a/assets/scss/settings/global/color/_color.scss +++ b/assets/scss/settings/global/color/_color.scss @@ -67,3 +67,9 @@ $color-textSecondary-active: stencilColor("color-textSecondary--active"); $color-textLink: stencilColor("color-textLink"); $color-textLink-hover: stencilColor("color-textLink--hover"); $color-textLink-active: stencilColor("color-textLink--active"); + + +// Tooltips +// ----------------------------------------------------------------------------- +$focusTooltip-textColor: stencilColor("focusTooltip-textColor"); +$focusTooltip-backgroundColor: stencilColor("focusTooltip-backgroundColor"); \ No newline at end of file diff --git a/config.json b/config.json index b7771ee1b9..91114bc4eb 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "name": "Cornerstone", - "version": "5.3.0", + "version": "5.4.0", "template_engine": "handlebars_v4", "meta": { "price": 0, @@ -309,12 +309,12 @@ "color_badge_product_sold_out_badges": "#007dc6", "color_text_product_sold_out_badges": "#ffffff", "color_hover_product_sold_out_badges": "#000000", + "focusTooltip-textColor": "#ffffff", + "focusTooltip-backgroundColor": "#313440", "restrict_to_login": false, "swatch_option_size": "22x22", "social_icon_placement_top": false, "social_icon_placement_bottom": "bottom_none", - "geotrust_ssl_common_name": "", - "geotrust_ssl_seal_size": "M", "navigation_design": "simple", "price_ranges": true, "pdp-price-label": "", @@ -331,6 +331,13 @@ "paymentbuttons-paypal-label": "checkout", "paymentbuttons-paypal-tagline": false, "paymentbuttons-paypal-fundingicons": false, + "paymentbanners-homepage-color": "white", + "paymentbanners-homepage-ratio": "8x1", + "paymentbanners-cartpage-text-color": "black", + "paymentbanners-cartpage-logo-position": "left", + "paymentbanners-cartpage-logo-type": "primary", + "paymentbanners-proddetailspage-color": "white", + "paymentbanners-proddetailspage-ratio": "8x1", "supported_card_type_icons": [ "american_express", "diners", @@ -595,7 +602,9 @@ "color_hover_product_sale_badges": "#000000", "color_badge_product_sold_out_badges": "#007dc6", "color_text_product_sold_out_badges": "#ffffff", - "color_hover_product_sold_out_badges": "#000000" + "color_hover_product_sold_out_badges": "#000000", + "focusTooltip-textColor": "#666666", + "focusTooltip-backgroundColor": "#ffffff" } }, { @@ -803,7 +812,9 @@ "color_hover_product_sale_badges": "#000000", "color_badge_product_sold_out_badges": "#007dc6", "color_text_product_sold_out_badges": "#ffffff", - "color_hover_product_sold_out_badges": "#000000" + "color_hover_product_sold_out_badges": "#000000", + "focusTooltip-textColor": "#ffffff", + "focusTooltip-backgroundColor": "#313440" } } ] diff --git a/package-lock.json b/package-lock.json index 065e83913b..a6346d3754 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "bigcommerce-cornerstone", - "version": "5.2.0", + "version": "5.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index be74cbe6a5..9a98ed8724 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bigcommerce-cornerstone", "description": "The BigCommerce reference theme for the Stencil platform", - "version": "5.3.0", + "version": "5.4.0", "private": true, "author": "BigCommerce", "license": "MIT", diff --git a/schema.json b/schema.json index 60005a5e44..018499e13c 100644 --- a/schema.json +++ b/schema.json @@ -938,36 +938,6 @@ "label": "i18n.ShowKlarna", "force_reload": true, "id": "show_accept_klarna" - }, - { - "type": "heading", - "content": "i18n.GeoTrustSSL" - }, - { - "type": "paragraph", - "content": "i18n.IfYouvePurchasedAGeoTrust" - }, - { - "type": "text", - "label": "i18n.SSLCommonName", - "force_reload": true, - "id": "geotrust_ssl_common_name" - }, - { - "type": "select", - "label": "i18n.SealSize", - "id": "geotrust_ssl_seal_size", - "options": [ - { - "value": "M", - "label": "i18n.Medium" - }, - { - "value": "S", - "label": "i18n.Small" - } - ], - "force_reload": true } ] }, @@ -3062,5 +3032,199 @@ ] } ] + }, + { + "name": "i18n.PaymentBanners", + "enable": "paymentBanners", + "settings": [ + { + "type": "paragraph", + "content": "i18n.BannersMessaging" + }, + { + "type": "heading", + "content": "i18n.ProductPageBanner" + }, + { + "type": "select", + "label": "i18n.BannerStyleColor", + "id": "paymentbanners-proddetailspage-color", + "force_reload": true, + "options": [ + { + "value": "blue", + "label": "i18n.Blue" + }, + { + "value": "black", + "label": "i18n.Black" + }, + { + "value": "white", + "label": "i18n.White" + }, + { + "value": "white-no-border", + "label": "i18n.White-no-border" + }, + { + "value": "gray", + "label": "i18n.gray" + }, + { + "value": "monochrome", + "label": "i18n.monochrome" + }, + { + "value": "grayscale", + "label": "i18n.grayscale" + } + ] + }, + { + "type": "select", + "label": "i18n.BannerStyleRatio", + "id": "paymentbanners-proddetailspage-ratio", + "force_reload": true, + "options": [ + { + "value": "8x1", + "label": "i18n.8x1" + }, + { + "value": "20x1", + "label": "i18n.20x1" + } + ] + }, + { + "type": "heading", + "content": "i18n.HomePageBanner" + }, + { + "type": "select", + "label": "i18n.BannerStyleColor", + "id": "paymentbanners-homepage-color", + "force_reload": true, + "options": [ + { + "value": "blue", + "label": "i18n.Blue" + }, + { + "value": "black", + "label": "i18n.Black" + }, + { + "value": "white", + "label": "i18n.White" + }, + { + "value": "white-no-border", + "label": "i18n.White-no-border" + }, + { + "value": "gray", + "label": "i18n.gray" + }, + { + "value": "monochrome", + "label": "i18n.monochrome" + }, + { + "value": "grayscale", + "label": "i18n.grayscale" + } + ] + }, + { + "type": "select", + "label": "i18n.BannerStyleRatio", + "id": "paymentbanners-homepage-ratio", + "force_reload": true, + "options": [ + { + "value": "8x1", + "label": "i18n.8x1" + }, + { + "value": "20x1", + "label": "i18n.20x1" + } + ] + }, + { + "type": "heading", + "content": "i18n.CartPageBanner" + }, + { + "type": "select", + "label": "i18n.BannerTextStyleColor", + "id": "paymentbanners-cartpage-text-color", + "force_reload": true, + "options": [ + { + "value": "black", + "label": "i18n.Black" + }, + { + "value": "white", + "label": "i18n.White" + }, + { + "value": "monochrome", + "label": "i18n.monochrome" + }, + { + "value": "grayscale", + "label": "i18n.grayscale" + } + ] + }, + { + "type": "select", + "label": "i18n.BannerStyleLogoPosition", + "id": "paymentbanners-cartpage-logo-position", + "force_reload": true, + "options": [ + { + "value": "left", + "label": "i18n.left" + }, + { + "value": "right", + "label": "i18n.right" + }, + { + "value": "top", + "label": "i18n.top" + } + ] + }, + { + "type": "select", + "label": "i18n.BannerStyleLogoType", + "id": "paymentbanners-cartpage-logo-type", + "force_reload": true, + "options": [ + { + "value": "inline", + "label": "i18n.inline" + }, + { + "value": "primary", + "label": "i18n.primary" + }, + { + "value": "alternative", + "label": "i18n.alternative" + }, + { + "value": "none", + "label": "i18n.none" + } + ] + } + ] } ] diff --git a/schemaTranslations.json b/schemaTranslations.json index 66364f0ba1..fc98a816f1 100644 --- a/schemaTranslations.json +++ b/schemaTranslations.json @@ -866,34 +866,6 @@ "uk": "Показати Klarna", "zh": "显示 Klarna" }, - "i18n.GeoTrustSSL": { - "default": "GeoTrust SSL", - "fr": "SSL GeoTrust", - "it": "GeoTrust SSL", - "uk": "GeoTrust SSL", - "zh": "Geo信任SSL" - }, - "i18n.IfYouvePurchasedAGeoTrust": { - "default": "If you've purchased a GeoTrust SSL from BigCommerce, check your BigCommerce Account Dashboard for the correct Common Name to use here.", - "fr": "Si vous avez acheté un SSL GeoTrust auprès de BigCommerce, consultez le tableau de bord de votre compte BigCommerce pour le nom commun correct à utiliser ici.", - "it": "Sei hai acquistato un SSL GeoTrust da BigCommerce, verifica sulla Dashboard del tuo Account BigCommerce il corretto Nome Comune da utilizzare qui.", - "uk": "Якщо ви придбали GeoTrust SSL у BigCommerce, перевірте на панелі керування облікового запису BigCommerce правильну загальну назву, яку тут можна використовувати.", - "zh": "如果您有在Bigcommerce中购买Geo信任SSL,检查您的Bigcommerce账户的控制面板,获得在这里使用的正确的公共名称。" - }, - "i18n.SSLCommonName": { - "default": "SSL Common Name", - "fr": "Nom commun du SSL", - "it": "Nome Comune SSL", - "uk": "Загальна назва SSL", - "zh": "SSL公共名称" - }, - "i18n.SealSize": { - "default": "Seal size", - "fr": "Taille du sceau", - "it": "Dimensioni sigillo", - "uk": "Розмір печатки", - "zh": "标志尺寸" - }, "i18n.Medium": { "default": "Medium", "fr": "Moyen", @@ -2047,5 +2019,74 @@ }, "i18n.CheckoutPayPalButton": { "default": "Checkout PayPal Button" + }, + "i18n.ProductPageBanner": { + "default": "Product page banner" + }, + "i18n.BannerStyleColor": { + "default": "Banner style color" + }, + "i18n.White-no-border": { + "default": "White no border" + }, + "i18n.gray": { + "default": "Gray" + }, + "i18n.monochrome": { + "default": "Monochrome" + }, + "i18n.grayscale": { + "default": "Grayscale" + }, + "i18n.BannerStyleRatio": { + "default": "Banner style ratio" + }, + "i18n.8x1": { + "default": "8x1" + }, + "i18n.20x1": { + "default": "20x1" + }, + "i18n.HomePageBanner": { + "default": "Home page banner" + }, + "i18n.BannerTextStyleColor": { + "default": "Banner text style color" + }, + "i18n.BannerStyleLogoPosition": { + "default": "Banner style logo position" + }, + "i18n.left": { + "default": "Left" + }, + "i18n.right": { + "default": "Right" + }, + "i18n.top": { + "default": "Top" + }, + "i18n.BannerStyleLogoType": { + "default": "Banner style logo type" + }, + "i18n.inline": { + "default": "Inline" + }, + "i18n.alternative": { + "default": "Alternative" + }, + "i18n.none": { + "default": "None" + }, + "i18n.PaymentBanners": { + "default": "Payment Banners" + }, + "i18n.CartPageBanner": { + "default": "Cart page banner" + }, + "i18n.primary": { + "default": "Primary" + }, + "i18n.BannersMessaging": { + "default": "Please note that in order for the changes to apply, you need navigate to the PayPal Settings in BC Control Panel, disable an appropriate messaging banner(s), click \"Save\" button, enable the banner again and click \"Save\" button again" } } diff --git a/templates/components/amp/css/header.html b/templates/components/amp/css/header.html index b68c06ad5e..804a448426 100644 --- a/templates/components/amp/css/header.html +++ b/templates/components/amp/css/header.html @@ -1,6 +1,6 @@ .amp-menu-button { background-color: transparent; - background-image: url('data:image/svg+xml;utf8,'); + background-image: url('data:image/svg+xml;utf8,'); background-repeat: no-repeat; background-size: 2rem 1.8rem; background-position: center center; diff --git a/templates/components/amp/products/product-view-details.html b/templates/components/amp/products/product-view-details.html index 1a9cf6956e..3330cbb7e6 100644 --- a/templates/components/amp/products/product-view-details.html +++ b/templates/components/amp/products/product-view-details.html @@ -2,7 +2,7 @@

{{product.title}}

{{#if product.brand }} -

+

{{/if}} diff --git a/templates/components/amp/products/reviews.html b/templates/components/amp/products/reviews.html index 253e534592..a170886893 100644 --- a/templates/components/amp/products/reviews.html +++ b/templates/components/amp/products/reviews.html @@ -7,9 +7,9 @@

{{> components/common/payment-icons}} - {{#if theme_settings.geotrust_ssl_common_name}} - - {{/if}} {{#if settings.paypal_commerce_credit_message}} {{/if}}
+ {{{region name="ssl_site_seal--global"}}} diff --git a/templates/components/products/options/swatch.html b/templates/components/products/options/swatch.html index d3a5fb0a4e..8470a42f97 100644 --- a/templates/components/products/options/swatch.html +++ b/templates/components/products/options/swatch.html @@ -1,5 +1,5 @@ -
-
+
{{theme_settings.pdp-price-label}} {{price.price_range.min.with_tax.formatted}} - {{price.price_range.max.with_tax.formatted}} @@ -29,12 +29,12 @@ {{lang 'products.price_with_tax' tax_label=price.price_range.min.tax_label}} {{/and}} {{#if schema_org}} - - + + -
+
@@ -67,7 +67,7 @@ {{price.non_sale_price_without_tax.formatted}}
-
+
{{theme_settings.pdp-price-label}} {{price.price_range.min.without_tax.formatted}} - {{price.price_range.max.without_tax.formatted}} @@ -75,12 +75,12 @@ {{lang 'products.price_without_tax' tax_label=price.price_range.min.tax_label}} {{/and}} {{#if schema_org}} - - + + -
+
diff --git a/templates/components/products/price.html b/templates/components/products/price.html index 9eec517a63..d0cf44b737 100644 --- a/templates/components/products/price.html +++ b/templates/components/products/price.html @@ -20,7 +20,7 @@ {{price.non_sale_price_with_tax.formatted}}
-
+
{{theme_settings.pdp-price-label}} @@ -29,12 +29,12 @@ {{price.with_tax.formatted}} {{#if schema_org}} - - + + -
+
@@ -58,7 +58,7 @@ {{price.non_sale_price_without_tax.formatted}}
-
+
{{theme_settings.pdp-price-label}} @@ -67,12 +67,12 @@ {{price.without_tax.formatted}} {{#if schema_org}} - - + + -
+
diff --git a/templates/components/products/product-view.html b/templates/components/products/product-view.html index 3be04e722e..9ce3fe3255 100644 --- a/templates/components/products/product-view.html +++ b/templates/components/products/product-view.html @@ -75,7 +75,7 @@

{{product.title}}

{{#if product.brand}} -

+

{{/if}} @@ -92,7 +92,7 @@

{{{region name="product_below_price"}}} -
' 0}}{{#if schema}} itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating"{{/if}}{{/if}}> +
' 0}}{{#if schema}} itemprop="aggregateRating" itemscope itemtype="https://schema.org/AggregateRating"{{/if}}{{/if}}> {{#if settings.show_product_rating}} {{#if product.num_reviews '>' 0}} {{#if schema}} diff --git a/templates/components/products/reviews.html b/templates/components/products/reviews.html index ae2217ca27..8f8dee1a7c 100644 --- a/templates/components/products/reviews.html +++ b/templates/components/products/reviews.html @@ -17,9 +17,9 @@

    {{#each reviews.list}}
  • -
    +
    - + {{> components/products/ratings rating=rating}} {{ rating }} diff --git a/templates/pages/account/add-return.html b/templates/pages/account/add-return.html index 4566684b73..2dd81f5958 100644 --- a/templates/pages/account/add-return.html +++ b/templates/pages/account/add-return.html @@ -4,7 +4,7 @@

    {{lang 'account.returns.new_return' }}

    {{> components/account/navigation account_page='returns'}} -
    +
    +

{{/partial}} {{> layout/base}} diff --git a/templates/pages/account/inbox.html b/templates/pages/account/inbox.html index a7a576c5cb..ddb19d4ba4 100644 --- a/templates/pages/account/inbox.html +++ b/templates/pages/account/inbox.html @@ -4,7 +4,7 @@

{{lang 'account.messages.heading' }}

{{> components/account/navigation account_page='messages'}} -
+
+
{{/partial}} {{> layout/base}} diff --git a/templates/pages/account/orders/all.html b/templates/pages/account/orders/all.html index 524e2415ba..5a7aa8c744 100644 --- a/templates/pages/account/orders/all.html +++ b/templates/pages/account/orders/all.html @@ -10,7 +10,7 @@

{{lang 'account.orders.heading' }}

{{> components/account/navigation account_page='orders'}} -
+
+
{{/partial}} {{> layout/base}} diff --git a/templates/pages/account/returns.html b/templates/pages/account/returns.html index 15047bf7c1..375885f0a1 100644 --- a/templates/pages/account/returns.html +++ b/templates/pages/account/returns.html @@ -4,7 +4,7 @@

{{lang 'account.returns.heading' }}

{{> components/account/navigation account_page='returns'}} -
+
+
{{/partial}} {{> layout/base}} diff --git a/templates/pages/amp/category.html b/templates/pages/amp/category.html index a259ae071b..c4b10c91f4 100644 --- a/templates/pages/amp/category.html +++ b/templates/pages/amp/category.html @@ -28,13 +28,13 @@

{{category.name}}

-
+
{{#if category.products}} {{> components/amp/category/product-listing}} {{else}}

{{lang 'categories.no_products'}}

{{/if}} -
+
{{> components/amp/category/subcategories}} {{> components/amp/common/footer}} {{#if settings.amp_analytics_id}} diff --git a/templates/pages/amp/product.html b/templates/pages/amp/product.html index 55f74933ed..f8e8215733 100644 --- a/templates/pages/amp/product.html +++ b/templates/pages/amp/product.html @@ -23,7 +23,7 @@ {{/partial}} {{#partial "page"}} {{> components/amp/common/header }} -
{{/partial}} {{> layout/base}} diff --git a/templates/pages/blog.html b/templates/pages/blog.html index 2fc35a7bc9..0e07f6ee86 100644 --- a/templates/pages/blog.html +++ b/templates/pages/blog.html @@ -9,7 +9,7 @@ {{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} -
+
{{#unless theme_settings.hide_blog_page_heading }}

{{ blog.name }}

{{/unless}} @@ -19,7 +19,7 @@

{{ blog.name }}

{{/each}} {{> components/common/paginator pagination.blog}} -
+ {{/partial}} {{> layout/base}} diff --git a/templates/pages/brand.html b/templates/pages/brand.html index a9e8a67ebd..99b4af4160 100644 --- a/templates/pages/brand.html +++ b/templates/pages/brand.html @@ -31,7 +31,7 @@

{{brand.name}}

{{> components/brand/sidebar}} -
+
{{#if brand.search_error }}

{{lang 'search.errorMessage'}}

{{else}} @@ -42,7 +42,7 @@

{{brand.name}}

{{/if}} {{{region name="brand_below_content"}}} {{/if}} -
+
{{/partial}} diff --git a/templates/pages/brands.html b/templates/pages/brands.html index df8dd36d66..34e4cb51b1 100644 --- a/templates/pages/brands.html +++ b/templates/pages/brands.html @@ -6,7 +6,7 @@ {{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} -
+

{{lang 'brand.label'}}

{{{region name="brands_below_header"}}}
    @@ -37,6 +37,6 @@

{{> components/common/paginator pagination.brands}} {{{region name="brands_below_content"}}} -
+ {{/partial}} {{> layout/base}} diff --git a/templates/pages/cart.html b/templates/pages/cart.html index 2e56444b66..9831d27689 100644 --- a/templates/pages/cart.html +++ b/templates/pages/cart.html @@ -4,7 +4,7 @@ {{#partial "page"}}
-
+
{{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} {{> components/cart/page-title}} @@ -52,7 +52,7 @@

{{lang 'cart.checkout.empty_cart'}}

{{/if}} -
+
{{/partial}} {{> layout/base}} diff --git a/templates/pages/category.html b/templates/pages/category.html index a6334b05ab..570a093b9e 100644 --- a/templates/pages/category.html +++ b/templates/pages/category.html @@ -48,10 +48,10 @@

{{category.name}}

{{/if}} {{/if}} -
+
{{> components/category/product-listing}} {{{region name="category_below_content"}}} -
+
{{/partial}} diff --git a/templates/pages/compare.html b/templates/pages/compare.html index 05f518ce2c..707d15b042 100644 --- a/templates/pages/compare.html +++ b/templates/pages/compare.html @@ -4,7 +4,7 @@ {{> components/common/breadcrumbs breadcrumbs=breadcrumbs}}

{{lang 'compare.header' products=comparisons.length}}

-
+
@@ -136,7 +136,7 @@

-
+
{{/partial}} diff --git a/templates/pages/contact-us.html b/templates/pages/contact-us.html index 69d182a5ae..93ca3877f1 100644 --- a/templates/pages/contact-us.html +++ b/templates/pages/contact-us.html @@ -2,7 +2,7 @@ {{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} -
+
{{#unless theme_settings.hide_contact_us_page_heading }}

{{page.title}}

{{/unless}} @@ -27,7 +27,7 @@

{{page.title}}

- + {{/partial}} diff --git a/templates/pages/errors/403.html b/templates/pages/errors/403.html index 465347bb2a..c632d25f71 100644 --- a/templates/pages/errors/403.html +++ b/templates/pages/errors/403.html @@ -2,7 +2,7 @@ {{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} -
+

{{lang 'forbidden.page_heading'}}

@@ -12,7 +12,7 @@

{{lang 'forbidden.page_heading'}}

{{> components/common/search-box}}
-
+
{{/partial}} {{> layout/base}} diff --git a/templates/pages/errors/404.html b/templates/pages/errors/404.html index 25c60dec9f..582a714f3d 100644 --- a/templates/pages/errors/404.html +++ b/templates/pages/errors/404.html @@ -2,7 +2,7 @@ {{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} -
+

{{lang 'page_not_found.page_heading'}}

@@ -11,7 +11,7 @@

{{lang 'page_not_found.page_heading'}}

{{> components/common/search-box}}
-
+
{{/partial}} {{> layout/base}} diff --git a/templates/pages/errors/generic.html b/templates/pages/errors/generic.html index 84a05925ca..65f37caa27 100644 --- a/templates/pages/errors/generic.html +++ b/templates/pages/errors/generic.html @@ -1,13 +1,13 @@ {{#partial "page"}} -
+

{{lang 'server_error.page_heading'}}

{{lang 'server_error.message'}}

-
+
{{/partial}} {{> layout/base}} diff --git a/templates/pages/gift-certificate/balance.html b/templates/pages/gift-certificate/balance.html index ffbf701e7a..c340f431aa 100644 --- a/templates/pages/gift-certificate/balance.html +++ b/templates/pages/gift-certificate/balance.html @@ -4,7 +4,7 @@

{{lang 'gift_certificate.heading' }}

{{> components/gift-certificate/navigation gift_page='balance'}} -
+
- + {{/partial}} {{> layout/base}} diff --git a/templates/pages/gift-certificate/purchase.html b/templates/pages/gift-certificate/purchase.html index 3bb12bfb40..e210a1b214 100644 --- a/templates/pages/gift-certificate/purchase.html +++ b/templates/pages/gift-certificate/purchase.html @@ -4,7 +4,7 @@

{{lang 'gift_certificate.heading' }}

{{> components/gift-certificate/navigation gift_page='purchase'}} -
+
{{#each forms.gift_certificate.errors}} {{> components/common/alert/alert-error this}} @@ -120,6 +120,6 @@

{{lang 'gift_certificate.heading' }}

value="{{lang 'forms.gift_certificate.purchase.submit_value' }}">
-
+ {{/partial}} {{> layout/base}} diff --git a/templates/pages/gift-certificate/redeem.html b/templates/pages/gift-certificate/redeem.html index 9f426c2bd4..9d8b7e7334 100644 --- a/templates/pages/gift-certificate/redeem.html +++ b/templates/pages/gift-certificate/redeem.html @@ -4,7 +4,7 @@

{{lang 'gift_certificate.heading' }}

{{> components/gift-certificate/navigation gift_page='redeem'}} -
+

{{lang 'gift_certificate.redeem.heading'}}

{{lang 'gift_certificate.redeem.intro' store_name=settings.store_name }}

    @@ -13,6 +13,6 @@

    {{lang 'gift_certificate.redeem.heading'}}

  1. {{{lang 'gift_certificate.redeem.item3' cart_url=urls.cart }}}
  2. {{lang 'gift_certificate.redeem.item4' }}
-
+ {{/partial}} {{> layout/base}} diff --git a/templates/pages/page.html b/templates/pages/page.html index 9e65e24aaf..0572768dda 100644 --- a/templates/pages/page.html +++ b/templates/pages/page.html @@ -2,7 +2,7 @@ {{> components/common/breadcrumbs breadcrumbs=breadcrumbs}} -
+
{{#unless theme_settings.hide_page_heading }}

{{ page.title }}

{{/unless}} @@ -37,7 +37,7 @@
{{title}}
{{/each}} {{/if}} -
+ {{/partial}} diff --git a/templates/pages/product.html b/templates/pages/product.html index 5536b567e9..016db21c4f 100644 --- a/templates/pages/product.html +++ b/templates/pages/product.html @@ -19,7 +19,7 @@ {{> components/common/alert/alert-info message}} {{/each}} -
+
{{> components/products/product-view schema=true }} {{{region name="product_below_content"}}} diff --git a/templates/pages/search.html b/templates/pages/search.html index f4031a0d6b..416a57529f 100644 --- a/templates/pages/search.html +++ b/templates/pages/search.html @@ -4,6 +4,7 @@ --- {{inject 'categoryTree' forms.search.category_options}} {{inject 'searchProductsPerPage' theme_settings.searchpage_products_per_page}} +{{inject 'searchResultsCount' (lang 'search.results.count' count=result_count search_query=(sanitize forms.search.query))}} {{#partial "head"}} {{#if pagination.product_results.previous}} @@ -61,7 +62,7 @@ {{> components/faceted-search/index product_results}} {{/if}} -
+
{{#if forms.search.has_suggestions}}
@@ -125,14 +126,6 @@
{{lang 'forms.search.suggestions.title'}}
{{/if}} -

- {{{lang 'search.results.count' count=result_count search_query=(sanitize forms.search.query)}}} -

-
{{> components/search/content-listing}}
@@ -142,7 +135,7 @@
{{lang 'forms.search.suggestions.title'}}
{{{region name="search_below_content"}}} -
+
{{/partial}}