509318396 ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ /*global wc_single_product_params, PhotoSwipe, PhotoSwipeUI_Default */ jQuery( function( $ ) { // wc_single_product_params is required to continue. if ( typeof wc_single_product_params === 'undefined' ) { return false; } $( 'body' ) // Tabs .on( 'init', '.wc-tabs-wrapper, .woocommerce-tabs', function() { $( this ).find( '.wc-tab, .woocommerce-tabs .panel:not(.panel .panel)' ).hide(); var hash = window.location.hash; var url = window.location.href; var $tabs = $( this ).find( '.wc-tabs, ul.tabs' ).first(); if ( hash.toLowerCase().indexOf( 'comment-' ) >= 0 || hash === '#reviews' || hash === '#tab-reviews' ) { $tabs.find( 'li.reviews_tab a' ).trigger( 'click' ); } else if ( url.indexOf( 'comment-page-' ) > 0 || url.indexOf( 'cpage=' ) > 0 ) { $tabs.find( 'li.reviews_tab a' ).trigger( 'click' ); } else if ( hash === '#tab-additional_information' ) { $tabs.find( 'li.additional_information_tab a' ).trigger( 'click' ); } else { $tabs.find( 'li:first a' ).trigger( 'click' ); } } ) .on( 'click', '.wc-tabs li a, ul.tabs li a', function( e ) { e.preventDefault(); var $tab = $( this ); var $tabs_wrapper = $tab.closest( '.wc-tabs-wrapper, .woocommerce-tabs' ); var $tabs = $tabs_wrapper.find( '.wc-tabs, ul.tabs' ); $tabs.find( 'li' ).removeClass( 'active' ); $tabs .find( 'a[role="tab"]' ) .attr( 'aria-selected', 'false' ) .attr( 'tabindex', '-1' ); $tabs_wrapper.find( '.wc-tab, .panel:not(.panel .panel)' ).hide(); $tab.closest( 'li' ).addClass( 'active' ); $tab .attr( 'aria-selected', 'true' ) .attr( 'tabindex', '0' ); $tabs_wrapper.find( '#' + $tab.attr( 'href' ).split( '#' )[1] ).show(); } ) .on( 'keydown', '.wc-tabs li a, ul.tabs li a', function( e ) { var isRTL = document.documentElement.dir === 'rtl'; var direction = e.key; var next = isRTL ? 'ArrowLeft' : 'ArrowRight'; var prev = isRTL ? 'ArrowRight' : 'ArrowLeft'; var down = 'ArrowDown'; var up = 'ArrowUp'; var home = 'Home'; var end = 'End'; if ( ! [ next, prev, down, up, end, home ].includes( direction ) ) { return; } var $tab = $( this ); var $tabs_wrapper = $tab.closest( '.wc-tabs-wrapper, .woocommerce-tabs' ); var $tabsList = $tabs_wrapper.find( '.wc-tabs, ul.tabs' ); var $tabs = $tabsList.find( 'a[role="tab"]' ); var endIndex = $tabs.length - 1; var tabIndex = $tabs.index( $tab ); var targetIndex = direction === prev || direction === up ? tabIndex - 1 : tabIndex + 1; var orientation = 'horizontal'; /** * We don't know if the tabs are going to be vertical or horizontal, * so let's try to detect the orientation depending on the position of the tabs. */ if ( $tabs.length >= 2 ) { var firstTab = $tabs[0].getBoundingClientRect(); var secondTab = $tabs[1].getBoundingClientRect(); var orientation = Math.abs( secondTab.top - firstTab.top ) > Math.abs( secondTab.left - firstTab.left ) ? 'vertical' : 'horizontal'; } /** * If the tabs are vertical, we don't need to detect left/right keys * If the tabs are horizontal, we don't need to detect up/down keys */ if ( ( orientation === 'vertical' && ( direction === prev || direction === next ) ) || ( orientation === 'horizontal' && ( direction === up || direction === down ) ) ) { return; } e.preventDefault(); if ( ( direction === prev && tabIndex === 0 && orientation === 'horizontal' ) || ( direction === up && tabIndex === 0 && orientation === 'vertical' ) || direction === end ) { targetIndex = endIndex; } else if ( ( next === direction && tabIndex === endIndex && orientation === 'horizontal' ) || ( down === direction && tabIndex === endIndex && orientation === 'vertical' ) || direction === home ) { targetIndex = 0; } $tabs.eq( targetIndex ).trigger( 'focus' ); } ) // Review link .on( 'click', 'a.woocommerce-review-link', function() { $( '.reviews_tab a' ).trigger( 'click' ); return true; } ) // Star ratings for comments .on( 'init', '#rating', function() { $( this ) .hide() .before( '

\ \ ' + wc_single_product_params.i18n_rating_options[0] + '\ ' + wc_single_product_params.i18n_rating_options[1] + '\ ' + wc_single_product_params.i18n_rating_options[2] + '\ ' + wc_single_product_params.i18n_rating_options[3] + '\ ' + wc_single_product_params.i18n_rating_options[4] + '\ \

' ); } ) .on( 'click', '#respond p.stars a', function() { var $star = $( this ), starPos = $star.closest( 'p.stars' ).find( 'a' ).index( $star ) + 1, $rating = $( this ).closest( '#respond' ).find( '#rating' ), $container = $( this ).closest( '.stars' ); $rating.val( starPos ); $star.siblings( 'a' ) .removeClass( 'active' ) .attr( 'aria-checked', 'false' ) .attr( 'tabindex', '-1' ); $star .addClass( 'active' ) .attr( 'aria-checked', 'true' ) .attr( 'tabindex', '0' ); $container.addClass( 'selected' ); return false; } ) .on( 'click', '#respond #submit', function() { var $rating = $( this ).closest( '#respond' ).find( '#rating' ), rating = $rating.val(); if ( $rating.length > 0 && ! rating && wc_single_product_params.review_rating_required === 'yes' ) { window.alert( wc_single_product_params.i18n_required_rating_text ); return false; } } ) /** * Handle keyup events for tabs, tabs li a, and respond p.stars a. * The stopPropagation is used to prevent the keyup event from being triggered on the flexslider. */ .on( 'keyup', '.wc-tabs li a, ul.tabs li a, #respond p.stars a', function( e ) { var direction = e.key; var next = [ 'ArrowRight', 'ArrowDown' ]; var prev = [ 'ArrowLeft', 'ArrowUp' ]; var allDirections = next.concat( prev ); if ( ! allDirections.includes( direction ) ) { return; } e.preventDefault(); e.stopPropagation(); if ( next.includes( direction ) ) { $( this ).next().trigger( 'focus' ).click(); return; } $( this ).prev().trigger( 'focus' ).click(); } ); // Init Tabs and Star Ratings $( '.wc-tabs-wrapper, .woocommerce-tabs, #rating' ).trigger( 'init' ); var productGalleryElement; /** * Product gallery class. */ var ProductGallery = function( $target, args ) { this.$target = $target; this.$images = $( '.woocommerce-product-gallery__image', $target ); // No images? Abort. if ( 0 === this.$images.length ) { this.$target.css( 'opacity', 1 ); return; } // Make this object available. $target.data( 'product_gallery', this ); // Pick functionality to initialize... this.flexslider_enabled = 'function' === typeof $.fn.flexslider && wc_single_product_params.flexslider_enabled; this.zoom_enabled = 'function' === typeof $.fn.zoom && wc_single_product_params.zoom_enabled; this.photoswipe_enabled = typeof PhotoSwipe !== 'undefined' && wc_single_product_params.photoswipe_enabled; // ...also taking args into account. if ( args ) { this.flexslider_enabled = false === args.flexslider_enabled ? false : this.flexslider_enabled; this.zoom_enabled = false === args.zoom_enabled ? false : this.zoom_enabled; this.photoswipe_enabled = false === args.photoswipe_enabled ? false : this.photoswipe_enabled; } // ...and what is in the gallery. if ( 1 === this.$images.length ) { this.flexslider_enabled = false; } // Bind functions to this. this.initFlexslider = this.initFlexslider.bind( this ); this.initZoom = this.initZoom.bind( this ); this.initZoomForTarget = this.initZoomForTarget.bind( this ); this.initPhotoswipe = this.initPhotoswipe.bind( this ); this.initVideoThumbnailPreviews = this.initVideoThumbnailPreviews.bind( this ); this.syncVideoPlayback = this.syncVideoPlayback.bind( this ); this.getPhotoswipeVideoHtml = this.getPhotoswipeVideoHtml.bind( this ); this.syncPhotoswipeVideoPlayback = this.syncPhotoswipeVideoPlayback.bind( this ); this.onResetSlidePosition = this.onResetSlidePosition.bind( this ); this.getGalleryItems = this.getGalleryItems.bind( this ); this.openPhotoswipe = this.openPhotoswipe.bind( this ); this.trapFocusPhotoswipe = this.trapFocusPhotoswipe.bind( this ); this.handlePswpTrapFocus = this.handlePswpTrapFocus.bind( this ); if ( this.flexslider_enabled ) { this.initFlexslider( args.flexslider ); $target.on( 'woocommerce_gallery_reset_slide_position', this.onResetSlidePosition ); } else { this.$target.css( 'opacity', 1 ); this.syncVideoPlayback( 0 ); } if ( this.zoom_enabled ) { this.initZoom(); $target.on( 'woocommerce_gallery_init_zoom', this.initZoom ); } if ( this.photoswipe_enabled ) { this.initPhotoswipe(); } }; /** * Initialize flexSlider. */ ProductGallery.prototype.initFlexslider = function( args ) { var $target = this.$target, gallery = this; var options = $.extend( { selector: '.woocommerce-product-gallery__wrapper > .woocommerce-product-gallery__image', start: function( slider ) { $target.css( 'opacity', 1 ); gallery.syncVideoPlayback( slider.currentSlide ); gallery.syncVideoThumbnailPreviewOpacity(); }, after: function( slider ) { gallery.initZoomForTarget( gallery.$images.eq( slider.currentSlide ) ); gallery.syncVideoPlayback( slider.currentSlide ); gallery.syncVideoThumbnailPreviewOpacity(); } }, args ); $target.flexslider( options ); gallery.initVideoThumbnailPreviews(); $target .off( 'click.wcProductGalleryVideoThumbs', '.flex-control-thumbs img' ) .on( 'click.wcProductGalleryVideoThumbs', '.flex-control-thumbs img', function() { window.setTimeout( function() { gallery.syncVideoPlayback(); gallery.syncVideoThumbnailPreviewOpacity(); }, 0 ); } ); // Trigger resize after main image loads to ensure correct gallery size. $( '.woocommerce-product-gallery__wrapper .woocommerce-product-gallery__image:eq(0) .wp-post-image' ).one( 'load', function() { var $image = $( this ); if ( $image ) { setTimeout( function() { var setHeight = $image.closest( '.woocommerce-product-gallery__image' ).height(); var $viewport = $image.closest( '.flex-viewport' ); if ( setHeight && $viewport ) { $viewport.height( setHeight ); } }, 100 ); } } ).each( function() { if ( this.complete ) { $( this ).trigger( 'load' ); } } ); }; /** * Play only the active gallery video. */ ProductGallery.prototype.syncVideoPlayback = function( slideIndex ) { const $activeSlide = 'number' === typeof slideIndex ? this.$images.eq( slideIndex ) : this.$target.find( '.flex-active-slide' ).first(); this.$images.find( 'video.wp-post-video' ).each( function() { if ( $activeSlide.has( this ).length ) { const playPromise = this.play(); if ( playPromise && playPromise.catch ) { playPromise.catch( function() { return undefined; } ); } } else { this.pause(); } } ); }; /** * Show browser-rendered previews for video thumbnails without posters. */ ProductGallery.prototype.initVideoThumbnailPreviews = function() { const $thumbs = this.$target.find( '.flex-control-thumbs img' ); if ( ! $thumbs.length ) { return; } this.$images.each( function( index, slide ) { const videoSrc = $( slide ).attr( 'data-thumb-video-src' ); const $thumb = $thumbs.eq( index ); const $thumbItem = $thumb.closest( 'li' ); if ( ! videoSrc || ! $thumb.length || $thumb.siblings( 'video' ).length ) { return; } const video = $( '