{"version":3,"file":"js/chunks/image.js","sources":["webpack:///./org_colony/cartridge/js/pages/product/image.js"],"sourcesContent":["const qs = require('qs');\nconst url = require('url');\nconst assignIn = require('lodash.assignin');\nconst util = require('../../util');\nconst ajax = require('../../ajax');\n\nlet wistiaThumbInit = false;\n\nconst zoomMediaQuery = matchMedia('(min-width: 768px)');\nlet productPage = false;\n\nif (window.pageContext.ns === 'product') {\n productPage = true;\n}\n\n/**\n * @description Enables the zoom viewer on the product detail page\n * @param zmq {Media Query List}\n */\nfunction loadZoom(zmq) {\n const $imgZoom = $('#pdpMain .slick-current .main-image');\n const zoomImageCurrent = $('#pdpMain .slick-current .main-image .zoomImg');\n const attrImage = $('#pdpMain .slick-current .main-image img').data('lgimg');\n\n if (zoomImageCurrent.length > 0) {\n $(zoomImageCurrent).each((index, element) => {\n $(element).remove();\n });\n }\n\n if (!zmq) {\n // eslint-disable-next-line\n zmq = zoomMediaQuery;\n }\n\n if ($imgZoom.length === 0 || !productPage || util.isMobile() || !zoomMediaQuery.matches) {\n // remove zoom\n $imgZoom.trigger('zoom.destroy');\n return;\n }\n\n const hiresUrl = $imgZoom.attr('href');\n if (hiresUrl && hiresUrl !== 'null' && hiresUrl.indexOf('noimagelarge') === -1 && zoomMediaQuery.matches && attrImage.zoom !== 'false') {\n $imgZoom.zoom({\n url: hiresUrl,\n on: 'grab',\n });\n }\n\n $('body').on('mouseenter mouseup', '#pdpMain .product-image-container .slick-current', () => {\n $('.zoom-text').show();\n });\n\n $('body').on('mouseleave mousedown', '#pdpMain .product-image-container .slick-current', () => {\n $('.zoom-text').hide();\n });\n\n $('body').bind('mousemove', '#pdpMain .product-image-container .slick-current', (e) => {\n $('.zoom-text').offset({\n left: e.pageX + 5,\n top: e.pageY + 20,\n });\n });\n}\n\nzoomMediaQuery.addListener(loadZoom);\n\n/**\n * @function\n * @desc Updates the Pinterest button URL to the newly selected main image\n * @param imageUrl {string} URL used to update the Pinterest button\n */\nfunction updatePinButton(imageUrl) {\n const pinButton = document.querySelector('.share-icon[data-share=pinterest]');\n if (!pinButton) {\n return;\n }\n let newUrl = imageUrl;\n if (!imageUrl) {\n newUrl = document.querySelector('#pdpMain .primary-image').getAttribute('src');\n }\n const href = url.parse(pinButton.href);\n const query = qs.parse(href.query);\n query.media = url.resolve(window.location.href, newUrl);\n query.url = window.location.href;\n const newHref = url.format(assignIn({}, href, {\n query, // query is only used if search is absent\n search: qs.stringify(query),\n }));\n pinButton.href = newHref;\n}\n\n/**\n * @function\n * @description Replaces the images in the image container, for eg. when a different color was clicked.\n */\nfunction replaceImages() {\n const $newImages = $('.update-images');\n const $imageContainer = $('#pdpMain .product-image-container');\n if ($newImages.length === 0) { return; }\n\n $imageContainer.html($newImages.html());\n $newImages.remove();\n loadZoom();\n picturefill();\n}\n\n/**\n * Initialize Wistia video player and set the thumbnail image. This does\n * not need to be done inside window.wistiaInit; doing it immediately\n * so we are not depending on timers. We'll use the wistiaThumbInit flag\n * to make sure it only executes once.\n *\n * There is a lot of crazy things happening in the Wistia library involving\n * timers and asynchronous functions, and depending on when this code executes,\n * certain elements could be in unpredictable states. We'll change the thumbnail image\n * if possible, but if it isn't in the DOM at this point, use mutation observers\n * to detect when it is added and set it then.\n */\nfunction wistiaThumbmail() {\n if (wistiaThumbInit) {\n return;\n }\n\n const wistiaThumb = $('#pdpMain').find('.wistia_thumb');\n\n if (wistiaThumb.length > 0) {\n wistiaThumbInit = true;\n\n const videoKey = $('#pdpMain').find('.wistia_thumb').data('apivideokey');\n const regex = /\\w+$/;\n const apiKey = regex.exec(videoKey);\n\n /* eslint-disable no-underscore-dangle */\n window._wq = window._wq || [];\n window._wq.push({\n id: apiKey,\n options: {\n videoFoam: {\n maxWidth: 768,\n },\n },\n });\n /* eslint-enable no-underscore-dangle */\n\n wistiaThumb.addClass('active');\n\n if (productPage && videoKey) {\n ajax.getJson({\n url: videoKey,\n callback(data) {\n if (!data || !data.thumbnail_url) {\n return false;\n }\n\n const thumbnailUrl = `${data.thumbnail_url.substring(0, data.thumbnail_url.indexOf('?'))}?image_crop_resized=130x95`;\n if (wistiaThumb.find('img').length > 0) {\n wistiaThumb.find('img').attr('src', thumbnailUrl);\n return true;\n }\n\n // If the img element was not found in wistiaThumb, it is because the Wistia library\n // is currently modifying the wistiaThumb element asynchronously. Watch the element\n // with a mutation observer, and change the src to thumbnailUrl when the img is added.\n const wistiaObserver = new MutationObserver(() => {\n const wistiaThumbImg = wistiaThumb.find('img');\n if (wistiaThumbImg.length > 0) {\n wistiaThumbImg.attr('src', thumbnailUrl);\n wistiaObserver.disconnect();\n }\n });\n\n wistiaObserver.observe(wistiaThumb.get(0), {childList: true, subtree: true});\n return true;\n },\n });\n }\n }\n}\n\n/**\n * @function\n * @description Change main image on thumb hover.\n */\nfunction mainImageHoverChange() {\n if (!util.isMobile()) {\n const currentMainImage = $('.product-primary-image .slick-current a .primary-image');\n const currentMainImageUrl = currentMainImage.attr('src');\n $('.product-thumbnails-list li').each((index, element) => {\n $(element).hover(\n (e) => {\n currentMainImage.attr('src', $(e.currentTarget).find('.productthumbnail').data('lgimg').url);\n },\n () => {\n currentMainImage.attr('src', currentMainImageUrl);\n },\n );\n });\n }\n}\n\n/**\n * @description Sets the main image attributes and the href for the surrounding tag\n * @param {Object} atts Object with url, alt, title and hires properties\n */\nfunction setMainImage(atts) {\n $('#pdpMain .slick-current .primary-image').attr({\n src: atts.url,\n alt: atts.alt,\n title: atts.title,\n });\n\n updatePinButton(atts.url);\n\n if (productPage && !util.isMobile()) {\n $('#pdpMain .slick-current .main-image').attr('href', atts.hires);\n }\n\n mainImageHoverChange();\n loadZoom();\n}\n\n/**\n * @function\n * @description Thumbnail slider for different viewports.\n */\nfunction heroCarousel() {\n if ($('#pdpMain #thumbnails').length > 0) {\n const primaryImageContainer = $('.product-primary-image');\n const thumbImages = $('#thumbnails .slick-slider img');\n const allImages = primaryImageContainer.find('img').add(thumbImages);\n\n const handleImageLoad = (resolve) => {\n let imagesLoaded = 0;\n allImages.each((index, image) => {\n if (image.complete && image.naturalHeight !== 0) {\n imagesLoaded += 1;\n if (imagesLoaded === allImages.length) {\n resolve();\n }\n } else {\n $(image).on('load', () => {\n imagesLoaded += 1;\n if (imagesLoaded === allImages.length) {\n resolve();\n }\n });\n }\n });\n };\n\n const imagesLoadedPromise = new Promise((resolve) => {\n handleImageLoad(resolve);\n });\n\n imagesLoadedPromise.then(() => {\n // Initialize Slick sliders after all images have loaded\n primaryImageContainer.on('init', (e) => {\n $(e.currentTarget).find('.slick-arrow').removeAttr('style');\n const currentImg = $(e.currentTarget).find('.slick-current img');\n if (currentImg.data('lgimg')) {\n setMainImage(currentImg.data('lgimg'));\n }\n }).slick({\n slidesToShow: 1,\n slidesToScroll: 1,\n infinite: false,\n fade: true,\n speed: 300,\n dots: true,\n asNavFor: '#thumbnails .slick-slider',\n responsive: [\n {\n breakpoint: util.getViewports('md'),\n settings: {\n fade: false,\n arrows: false,\n },\n },\n ],\n }).on('afterChange', (e) => {\n const currentImg = $(e.currentTarget).find('.slick-current img');\n if (currentImg.data('lgimg')) {\n setMainImage(currentImg.data('lgimg'));\n }\n });\n\n const thumbCarousel = $('#thumbnails .slick-slider');\n const thumbsToShow = 4;\n thumbCarousel.on('init', () => {\n if (thumbCarousel.find('.thumb').length > thumbsToShow) {\n thumbCarousel.addClass('with-nav');\n }\n }).slick({\n speed: 300,\n slidesToShow: thumbsToShow,\n slidesToScroll: 1,\n vertical: true,\n infinite: false,\n centerMode: true,\n asNavFor: '.product-primary-image',\n focusOnSelect: true,\n slide: '.thumb',\n });\n });\n }\n}\n\n/**\n * @description by default, this function sets up zoom and event handler for thumbnail click\n * */\nmodule.exports = function setupZoom() {\n if (!productPage || util.isMobile()) {\n $('#pdpMain .main-image').removeAttr('href');\n }\n\n updatePinButton();\n heroCarousel();\n loadZoom();\n mainImageHoverChange();\n wistiaThumbmail();\n\n // handle product thumbnail click event\n $('#pdpMain').on('click', '.productthumbnail', (e) => {\n // switch indicator\n $(e.currentTarget).closest('.product-thumbnails').find('.thumb.selected').removeClass('selected');\n $(e.currentTarget).closest('.thumb').addClass('selected');\n\n const zoomImageCurrent = $('#pdpMain .main-image .zoomImg');\n\n if (zoomImageCurrent.length > 0) {\n $(zoomImageCurrent).each((index, element) => {\n $(element).remove();\n });\n }\n\n setMainImage($(e.currentTarget).data('lgimg'));\n });\n\n /**\n * @listener\n * @description Listens for the click event on the main product image and prevents the link from being followed\n */\n $('#pdpMain').on('click', '.main-image', (e) => {\n e.preventDefault();\n });\n};\nmodule.exports.loadZoom = loadZoom;\nmodule.exports.setMainImage = setMainImage;\nmodule.exports.replaceImages = replaceImages;\nmodule.exports.heroCarousel = heroCarousel;\nmodule.exports.wistiaThumbmail = wistiaThumbmail;\n"],"mappings":";;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AAEA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;A","sourceRoot":""}