import $ from 'jquery' import ctEvents from 'ct-events' let originalImageUpdate = null const store = {} function isTouchDevice() { try { document.createEvent('TouchEvent') return true } catch (e) { return false } } const cachedFetch = (url) => store[url] ? new Promise((resolve) => { resolve(store[url]) store[url] = store[url].clone() }) : new Promise((resolve) => fetch(url).then((response) => { resolve(response) store[url] = response.clone() }) ) const makeUrlFor = ({ variation, productId, isQuickView }) => { let url = new URL(ct_localizations.ajax_url) let params = new URLSearchParams(url.search.slice(1)) params.append('action', 'blocksy_get_product_view_for_variation') params.append('variation_id', variation.variation_id) params.append('product_id', productId) params.append('is_quick_view', isQuickView) url.search = `?${params.toString()}` return url.toString() } const replaceFirstImage = ({ container, image }) => { if (!image) { return } const containersToReplace = [] const selectorsToTry = [ '.woocommerce-product-gallery .ct-product-gallery-container > .ct-media-container', '.woocommerce-product-gallery .ct-stacked-gallery-container > .ct-media-container:first-child', '.woocommerce-product-gallery .flexy-items > *:first-child > *', '.woocommerce-product-gallery .flexy-pills > ol > *:first-child > *', ] selectorsToTry.map((selector) => { if (container.parentNode.querySelector(selector)) { containersToReplace.push( container.parentNode.querySelector(selector) ) } }) containersToReplace.map((imgContainer) => { if (imgContainer.href) { imgContainer.href = image.full_src } if (imgContainer.dataset.src) { imgContainer.dataset.src = image.full_src } if (imgContainer.dataset.height) { imgContainer.dataset.height = image.full_src_h } if (imgContainer.dataset.width) { imgContainer.dataset.width = image.full_src_w } ;[...imgContainer.querySelectorAll('.zoomImg')].map((img) => { img.remove() }) ;[...imgContainer.querySelectorAll('img, source')].map((img) => { if (img.matches('.zoomImg')) { return } if (img.getAttribute('width')) { img.width = image.width || (img.closest('.flexy-pills') ? image.gallery_thumbnail_src_w : image.src_w) } if (img.getAttribute('height')) { img.height = image.height || (img.closest('.flexy-pills') ? image.gallery_thumbnail_src_h : image.src_h) } img.src = img.closest('.flexy-pills') ? image.gallery_thumbnail_src : image.src if (image.srcset && img.srcset && image.srcset !== 'false') { img.srcset = image.srcset } else { img.removeAttribute('srcset') } }) if ($.fn.zoom) { if ( (window.wp && wp.customize && wp.customize('has_product_single_zoom') && wp.customize('has_product_single_zoom')() === 'yes') || !window.wp || !wp.customize ) { const rect = imgContainer.getBoundingClientRect() if ( parseFloat(imgContainer.getAttribute('data-width')) > imgContainer .closest('.woocommerce-product-gallery') .getBoundingClientRect().width ) { $(imgContainer).zoom({ url: imgContainer.href, touch: false, duration: 50, ...(rect.width > parseFloat(imgContainer.dataset.width) || rect.height > parseFloat(imgContainer.dataset.height) ? { magnify: 2, } : {}), ...(isTouchDevice() ? { on: 'toggle', } : {}), }) } } } }) } const performInPlaceUpdate = ({ container, currentVariationObj, nextVariationObj, }) => { const currentImage = currentVariationObj ? { id: currentVariationObj.image_id, ...currentVariationObj.image } : (nextVariationObj || {}).blocksy_original_image const nextImage = nextVariationObj ? { id: nextVariationObj.image_id, ...nextVariationObj.image } : (currentVariationObj || {}).blocksy_original_image if (!nextImage) { return } if ( currentImage && parseFloat(nextImage.id) === parseFloat(currentImage.id) ) { return } // Attempt slide to image if (container.querySelector(`.flexy-pills > *`)) { let maybePillImage = container.querySelector( `.flexy-items [srcset*="${nextImage.src}"]` ) || container.querySelector(`.flexy-items [src*="${nextImage.src}"]`) if (maybePillImage) { let pillIndex = [ ...container.querySelector(`.flexy-items`).children, ].indexOf(maybePillImage.closest('div')) const pill = container.querySelector(`.flexy-pills > *`).children[pillIndex] if (pill) { if ( container .querySelector('[data-flexy]') .dataset.flexy.indexOf('no') > -1 ) { if (container.querySelector('[data-flexy]').forcedMount) { container.querySelector('[data-flexy]').forcedMount() } setTimeout(() => { if (nextVariationObj) { replaceFirstImage({ container, image: nextVariationObj.blocksy_original_image, }) } pill.click() }, 500) return } else { if (nextVariationObj) { replaceFirstImage({ container, image: nextVariationObj.blocksy_original_image, }) } pill.click() return } } } } // Replace 1st image replaceFirstImage({ container, image: nextImage }) if (container.querySelector(`.flexy-pills > *`)) { const pill = container.querySelector(`.flexy-pills > *`).children[0] if (pill) { pill.click() } } } export const mount = (el) => { if (!$ || !$.fn || !$.fn.wc_variations_image_update) { return } originalImageUpdate = $.fn.wc_variations_image_update $.fn.wc_variations_image_update = function (variation) { const currentElement = this[0] if ( currentElement.closest('.woobt-products') || currentElement.closest('.upsells') || currentElement.closest('.related') ) { return } const currentVariation = el .closest('.product') .querySelector('.woocommerce-product-gallery') let productContainer = currentVariation.closest('.type-product') let isQuickView = 'no' let productId = productContainer.id.replace('product-', '') if (!productId) { productId = currentVariation .closest('[class*="ct-quick-view"]') .querySelector('[data-product_id]').dataset.product_id if (productId) { isQuickView = 'yes' } } const allVariations = JSON.parse(el.dataset.product_variations) let nextVariationObj = false let currentVariationObj = false if (allVariations) { nextVariationObj = variation.variation_id ? allVariations.find( ({ variation_id }) => parseInt(variation_id) === parseInt(variation.variation_id) ) : false currentVariationObj = currentVariation.dataset.currentVariation ? allVariations.find( ({ variation_id }) => parseInt(variation_id) === parseInt(currentVariation.dataset.currentVariation) ) : false } let defaultCanDoInPlaceUpdate = '__DEFAULT__' if ( variation && !variation.variation_id && currentElement.querySelector('.wcpa_form_outer') ) { defaultCanDoInPlaceUpdate = true nextVariationObj = variation } if ( defaultCanDoInPlaceUpdate === '__DEFAULT__' && !variation.variation_id && !currentVariation.dataset.currentVariation ) { return } if ( defaultCanDoInPlaceUpdate === '__DEFAULT__' && parseInt(variation.variation_id) === parseInt(currentVariation.dataset.currentVariation) ) { return } if ( variation.variation_id || defaultCanDoInPlaceUpdate === '__DEFAULT__' ) { currentVariation.dataset.currentVariation = variation.variation_id || '0' } else { currentVariation.removeAttribute('data-current-variation') } const canDoInPlaceUpdate = defaultCanDoInPlaceUpdate === '__DEFAULT__' ? allVariations && [nextVariationObj, currentVariationObj].every((variation) => { if (!variation) { return true } return variation.blocksy_gallery_source === 'default' }) : defaultCanDoInPlaceUpdate if (canDoInPlaceUpdate) { performInPlaceUpdate({ container: currentVariation, nextVariationObj, currentVariationObj, }) return } const acceptHtml = (html, style) => { const div = document.createElement('div') div.innerHTML = html ;[...div.firstElementChild.children].map((el, index) => { if ( !el.matches( '.flexy-container, .ct-product-gallery-container' ) ) { el.remove() } }) let didInsert = false ;[...currentVariation.children].map((el, index) => { if ( el.matches( '.flexy-container, .ct-product-gallery-container' ) ) { if (!didInsert) { didInsert = true el.insertAdjacentHTML( 'beforebegin', div.firstElementChild.innerHTML ) } } if ( el.matches( '.flexy-container, .ct-product-gallery-container' ) ) { el.remove() } }) currentVariation .closest('.product') .classList.remove('thumbs-left', 'thumbs-bottom') if (currentVariation.querySelector('.flexy-container')) { currentVariation.closest('.product').classList.add(style) } currentVariation.hasLazyLoadClickHoverListener = false setTimeout(() => { ctEvents.trigger('blocksy:frontend:init') currentVariation.removeAttribute('data-state') }, 10) } if (variation.blocksy_gallery_html) { acceptHtml( variation.blocksy_gallery_html, variation.blocksy_gallery_style ) return } currentVariation.removeAttribute('style') requestAnimationFrame(() => { currentVariation.dataset.state = 'loading' }) let maybeLoadedVariation = allVariations ? allVariations.find( (nestedVariation) => store[ makeUrlFor({ variation: nestedVariation, productId, isQuickView, }) ] && nestedVariation.image_id === variation.image_id && variation.blocksy_gallery_source === 'default' && nestedVariation.blocksy_gallery_source === 'default' ) : null cachedFetch( makeUrlFor({ variation: maybeLoadedVariation || variation, productId, isQuickView, }), { method: 'POST', } ) .then((response) => response.json()) .then(({ success, data }) => { if (!success) { return } acceptHtml(data.html, data.blocksy_gallery_style) }) } }