HEX
Server: Apache/2.4.57 (Debian)
System: Linux web-server-k8s-e92jnr3j-6f99bff6b6-rp2wg 6.1.0-22-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.94-1 (2024-06-21) x86_64
User: apache (48)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,
Upload Files
File: /var/www/sites/1250.info/wp-content/themes/savoy/assets/js/dev/nm-shop.js
(function($) {
	
	'use strict';
	
	// Extend core script
	$.extend($.nmTheme, {
		
		/**
		 *	Initialize scripts
		 */
		shop_init: function() {
			var self = this;
			
			
			// Shop select config
			self.shopSelectConfig = {
				onOpen: function() {
                    var $this = $(this);
                    
                    $this.closest('tr').addClass('open');
                    
                    // Set options-menu width
                    var menuWidth = $this.closest('tr')[0].getBoundingClientRect().width; // Get menu-width including sub-pixel value (to avoid 1px gap)
                    $this.children('.sod_list_wrapper').css('width', menuWidth+'px');
                    
                    // Trigger "focusin" event on original select element to make sure WooCommerce updates the options
					$this.children('select').trigger('focusin');
				},
				onChange: function() {
                    $(this).closest('tr').removeClass('open');
				},
				onClose: function() {
                    $(this).closest('tr').removeClass('open');
				}
			};
			
			
			/* Shop */
			if (self.isShop) {
                // Shop vars and elements
				self.shopAjax = false;
				self.scrollOffsetDesktop = parseInt(nm_wp_vars.shopScrollOffset);
                self.scrollOffsetTablet = parseInt(nm_wp_vars.shopScrollOffsetTablet);
                self.scrollOffsetMobile = parseInt(nm_wp_vars.shopScrollOffsetMobile);
                self.infloadScroll = false;
				self.categoryClicked = false;
				self.shopLoaderSpeed = 300;
				self.shopScrollSpeed = 410;
				self.$shopBrowseWrap = $('#nm-shop-browse-wrap');
				self.imageLazyLoading = (nm_wp_vars.shopImageLazyLoad != '0') ? true : false;
				if (nm_wp_vars.shopFiltersAjax != '0') {
					// Check if AJAX should be disabled on mobile devices
					self.filtersEnableAjax = (self.isTouch && nm_wp_vars.shopFiltersAjax != '1') ? false : true;
				} else {
					self.filtersEnableAjax = false;
				}
				
				
                // Set page-scroll offset
                self.shopSetScrollOffset();
                // Set shop min-height (keep above "shopSetScrollOffset()")
				self.shopSetMinHeight();
				
				
				/* Bind: Window resize */
				var timer = null;
                self.$window.on('resize', function() {
					if (timer) { clearTimeout(timer); }
					timer = setTimeout(function() {
						// Set shop min-height
						self.shopSetMinHeight();
                        // Set page-scroll offset
                        self.shopSetScrollOffset();
					}, 250);
				});
				
				
				if (self.$pageIncludes.hasClass('banner-slider')) {
					// Wait for "banner-slider-loaded" event (banner slider changes height)
					self.$document.on('banner-slider-loaded', function() {
						self.shopUrlHashScroll();
					});
				} else {
					self.shopUrlHashScroll();
				}
                
                // Lazyload: Add class to fade-in product images
                if (self.imageLazyLoading) {
                    setTimeout(function() {
                        self.$shopWrap.addClass('images-show');
                    }, 50);
                }
                
                if (self.filtersEnableAjax) {
                    /* Bind: Back button "popstate" event */
                    self.$window.on('popstate.nmshop', function(e) {
                        // Return if no "popstate" tag/id is set
                        if (!e.originalEvent.state) { return; }
                        
                        // Make sure the "popstate" event is ours (nmShop)
                        if (e.originalEvent.state.nmShop) {
                            // Load full page from saved "pushState" url
                            self.shopGetPage(window.location.href, true);
                        }
                    });
                }
				
				
				/* 
				 * Bind: Header main menu shop link 
				 * Note: "shop-link" class is added manually in WP admin
				 */
				$('#nm-main-menu-ul').children('.shop-link').find('> a').on('click', function(e) {
					e.preventDefault();
					self.shopScrollToTop(); // Smooth-scroll to shop
				});
				
                
                /* Bind: Results bar - Filters reset link */
                self.$shopWrap.on('click.nmShopFiltersReset', '#nm-shop-filters-reset', function(e) {
                    e.preventDefault();
                    self.shopFiltersReset(this);
                });
                
                /* Bind: Results bar - Search/taxonomy reset link */
                self.$shopWrap.on('click.nmShopSearchTaxonomyReset', '#nm-shop-search-taxonomy-reset', function(e) {
                    e.preventDefault();
                    self.shopSearchTaxonomyReset(this);
                });
			}
			
			
			/* 
			 * Variation selects - Bind: Product variations updated event - Triggered from "add-to-cart-variation.js"
			 * Note: See "self.shopSelectConfig" for related "focusin" event
			 */
            self.$document.on('woocommerce_update_variation_values', '.variations_form', function() {
                self.singleProductVariationsUpdate();
            });
			
			
			if (typeof wc_add_to_cart_params !== 'undefined' && wc_add_to_cart_params.cart_redirect_after_add !== 'yes') { // Only bind if add-to-cart redirect is disabled
				/* Add-to-cart event: Show mini cart with loader overlay */
                self.$body.on('adding_to_cart', function(event, $button, data) {
					// Is widget/cart panel enabled?
					if (self.$widgetPanel.length) {
                        if (!self.quickviewIsOpen()) {
                            self.widgetPanelShow(true, true); // Args: showLoader, addingToCart
						}
					} else {
						// Show page overlay
                        self.$pageOverlay.addClass('nm-loader');
                        self.pageOverlayShow();
					}
				});
				/* Add-to-cart event: Hide mini cart loader overlay */
                self.$body.on('added_to_cart', function(event, fragments, cartHash) {
					// Is widget/cart panel enabled?
					if (self.$widgetPanel.length) {
                        if (!self.quickviewIsOpen()) {    
							self.widgetPanelCartHideLoader();
						}
					} else {
						// Hide page overlay
                        self.pageOverlayHide();
                        self.$pageOverlay.removeClass('nm-loader');
					}
				});
			} else {
				// Disable default WooCommerce AJAX add-to-cart event if redirect is enabled
				self.$document.off( 'click', '.add_to_cart_button' );
			}
			
			
			// Load extension scripts
			self.shopLoadExtension();
		},
		
		
		/**
		 *	Shop: Load extension scripts
		 */		
		shopLoadExtension: function() {
			var self = this;
			
			// Extension: Add to cart
			if ($.nmThemeExtensions.add_to_cart) {
				$.nmThemeExtensions.add_to_cart.call(self);
			}
			
			if (self.isShop) {
				// Extension: Infinite load
				if ($.nmThemeExtensions.infload) {
					$.nmThemeExtensions.infload.call(self);
				}
				
				// Extension: Filters
				if ($.nmThemeExtensions.filters) {
					$.nmThemeExtensions.filters.call(self);
				}
			}
			
			// Extension: Quickview
			if (self.$pageIncludes.hasClass('quickview')) {
				if ($.nmThemeExtensions.quickview) {
					$.nmThemeExtensions.quickview.call(self);
				}
			}
		},
        
        
		/**
		 *	Shop: Check for URL #hash and scroll/jump to shop if added
		 */
		shopUrlHashScroll: function() {
			var self = this;
			
			if (window.location.hash === '#shop') {
				self.shopScrollToTop(true); // Arg: (jumpTo)
			}
		},
		
		
        /**
		 *	Shop/Single-product: Check variation details (hide if empty)
		 */
		shopCheckVariationDetails: function($variationDetailsWrap) {
            var $variationDetailsChildren = $variationDetailsWrap.children(),
			    variationDetailsEmpty = true;
            
			if ($variationDetailsChildren.length) {
                // Check for variation detail elements
				for (var i = 0; i < $variationDetailsChildren.length; i++) {
                    if ($variationDetailsChildren.eq(i).children().length) {
						variationDetailsEmpty = false;
						break;
					}
				}
			}
            
            if (variationDetailsEmpty) {
				$variationDetailsWrap.hide();
			} else {
                $variationDetailsWrap.show();
            }
		},
		
        
        /**
		 *	Shop: Set page-scroll offset
		 */
		shopSetScrollOffset: function() {
			var self = this,
                pageWidth = self.$body.width();
            
            // Desktop
            if (pageWidth > 863) {
                self.scrollOffset = (self.$header.hasClass('static-on-scroll')) ? self.$header.outerHeight() : self.scrollOffsetDesktop;
            }
            // Tablet
            else if (pageWidth > 383) {
                self.scrollOffset = self.scrollOffsetTablet;
            } 
            // Mobile
            else {
                self.scrollOffset = self.scrollOffsetMobile;
            }
		},
        
		
		/**
		 *	Shop: Set shop min-height
		 */
		shopSetMinHeight: function() {
			var self = this,
				footerHeight = $('#nm-footer').outerHeight(true);
            
            self.$shopWrap.css('min-height', (self.$window.height() - (footerHeight + self.scrollOffset))+'px');
		},
		
		
		/**
		 *	Shop: Scroll to shop-top (directly below header)
         *        - Returns variable "to" with the smooth-scroll animation speed so "setTimeout()" can be used
		 */
		shopScrollToTop: function(setHeight, jumpTo) {
			var self = this,
                to = 0;
            
            if (self.$window.width() > 399) {
                var shopPosition = Math.round(self.$shopWrap.offset().top - self.scrollOffset);
            } else {
                var shopPosition = Math.round($('#nm-shop-products').offset().top - 24 - self.scrollOffset);
            }
			
            // Cancel scroll if current scroll position is within the scrollTolerance range
            var scrollTolerance = 50;
            if (Math.abs(shopPosition - self.$html.scrollTop()) < scrollTolerance) {
                return to;
            }
            
            if (setHeight) {
                // Set shop min-height
                self.shopSetMinHeight();
            }
            
			if (jumpTo) {
				$('html, body').scrollTop(shopPosition);
			} else {
                to = self.shopScrollSpeed;
                
				$('html, body').animate({'scrollTop': shopPosition}, self.shopScrollSpeed);
			}
            
            return to;
		},
		
        
        /**
		 *	Shop: Show any visible notices
		 */
		shopShowNotices: function() {
            var self = this;
            self.$body.addClass('nm-woocommerce-message-show');
            if (self.isShop && nm_wp_vars.cartPanelHideOnAtcScroll != '0') {
                self.shopScrollToTop(); // Smooth-scroll to shop-top
            }
        },
        
		
		/**
		 *	Shop: Remove any visible shop notices
		 */
		shopRemoveNotices: function() {
			$('#nm-shop-notices-wrap').empty();
		},
		
		
		/**
		 *	Shop: Show "loader" overlay
		 */
		shopShowLoader: function(disableAnimation) {
			var self = this,
                $shopLoader = $('#nm-shop-products-overlay');
			
			if (disableAnimation) {
				$shopLoader.addClass('no-anim');
			}
							
			$shopLoader.addClass('show');
            self.$shopWrap.addClass('loading');
		},
		
		
		/**
		 *	Shop: Hide "loader" overlay
		 */
		shopHideLoader: function(disableAnimation) {
			var self = this,
				$shopLoader = $('#nm-shop-products-overlay');
			
			if (!disableAnimation) {
				$shopLoader.removeClass('no-anim');
			}
			
			$shopLoader.removeClass('nm-loader').addClass('fade-out');
			setTimeout(function() {
				$shopLoader.removeClass('show fade-out').addClass('nm-loader'); 
			}, self.shopLoaderSpeed);
			
			if (self.infloadScroll) {
				self.infscrollLock = false; // "Unlock" infinite scroll
				self.$window.trigger('scroll'); // Load next page (if correct scroll position)
			}
            
            self.$shopWrap.removeClass('loading');
		},
        
        
        /**
		 *	Shop: Filters - Reset
		 */
		shopFiltersReset: function(resetBtn) {
            var self = this,
                $resetButton = $(resetBtn),
                // Get URL from "override" data attribute (used on preview), or from current URL without query-strings
                resetUrl = ($resetButton.data('shop-override-url')) ? $resetButton.data('shop-override-url') : location.href.replace(location.search, '');
            
            if (self.filtersEnableAjax) {
                self.shopGetPage(resetUrl);
            } else {
                window.location.href = resetUrl;
            }
        },
        
        
        /**
		 *	Shop: Filters - Reset search or taxonomy
		 */
		shopSearchTaxonomyReset: function(resetBtn) {
            var self = this,
                $resetButton = $(resetBtn);
            
            if ($resetButton.closest('.nm-shop-results-bar').hasClass('is-search')) {
                // Search
                var urlSearchParam = self.urlGetParameter('s'), // Check for the "s" parameter in the current page URL
                    // Search from external page: Get default/main shop URL (current URL may not be the default shop URL)
                    // Search from shop page: Get current URL without query-strings (current URL is a shop URL)
                    resetUrl = (urlSearchParam) ? $resetButton.data('shop-url') : location.href.replace(location.search, '');
            } else {
                // Category or tag
                var resetUrl = $resetButton.data('shop-url'); // Get default/main shop URL
            }

            if (self.filtersEnableAjax) {
                self.shopGetPage(resetUrl);
            } else {
                window.location.href = resetUrl;
            }
        },
        
        
        /**
		 *	Single product: Variations
         *
         *  Note: This function is placed here so it's available to the Quick-view
		 */
		singleProductVariationsInit: function($variationsForm) {
			var self = this,
                $variationsWrap = $variationsForm.children('.variations'),
                $variationDetailsWrap = $variationsForm.children('.single_variation_wrap').children('.single_variation');
            
            
			// Custom select boxes
            if (self.shopCustomSelect) {
                var $selectBoxes = $variationsWrap.find('select'), $selectBox;
                for (var i = 0; i < $selectBoxes.length; i++) {
                    $selectBox = $selectBoxes.eq(i);
                    // Make sure the select-box isn't hidden
                    if (! $selectBox.parent().hasClass('nm-select-hidden')) {
                        $selectBox.selectOrDie(self.shopSelectConfig);
                    }
                }
            }
            
            
            // Custom variation controls: Bind
            var clickThrottle = null;
            $variationsWrap.find('.nm-variation-control').children('li').on('click', function() {
                if (clickThrottle) { return; } // Prevent selection before variation-image has changed
                
                var $this = $(this),
                    $container = $this.parent(),
                    $select = $container.parent().children('.nm-select-hidden').find('select'),
                    value = $this.data('value');
                
                // Toggle variation control
                if ($this.hasClass('selected')) {
                    $this.removeClass('selected');
                    $select.val('').trigger('change'); // Empty value and trigger "change" event on hidden select
                } else {
                    $container.children('.selected').removeClass('selected');
                    $this.addClass('selected');
                    $select.val(value).trigger('change'); // Change value and trigger "change" event on hidden select
                }
                
                clickThrottle = setTimeout(function() { clickThrottle = null; }, 300);
            });
            
            
            // Variation details
            self.shopCheckVariationDetails($variationDetailsWrap);
            // Variation details: Bind WooCommerce "show_variation" event
			$variationDetailsWrap.on('show_variation', function() {
                self.shopCheckVariationDetails($(this));
            });
            // Variation details: Bind WooCommerce "hide_variation" event
			$variationDetailsWrap.on('hide_variation', function() {
                $variationDetailsWrap.css('display', 'none'); // Add "display:none" to skip default animation
            });
		},
        
        
        /**
		 *	Single product: Variations - Update variation controls on select change (options may have been added/enabled or removed/disabled by WooCommerce)
         *
         *  Note: This function is placed here so it's available to the Quick-view
		 */
		singleProductVariationsUpdate: function() {
            var self = this;
            
            $('.variations_form').find('select').each(function() {
                var $select = $(this);

                // Update custom selects
                if (self.shopCustomSelect) {
                    $select.selectOrDie('update');
                }

                // Update custom variation controls
                if ($select.parent('.nm-select-hidden').length) {
                    var $controls = $select.closest('.value').children('.nm-variation-control').children('li'),
                        $control,
                        controlValue,
                        $optionMatch,
                        optionDisabledAttr;
                    
                    for (var i = 0; i < $controls.length; i++) {
                        $control = $($controls[i]);
                        controlValue = $control.data('value');
                        $optionMatch = $select.children('[value="' + controlValue + '"]');
                        
                        // Is a matching option found in the controls hidden select?
                        if ($optionMatch.length) {
                            optionDisabledAttr = $optionMatch.attr('disabled');
                            
                            if ($optionMatch.hasClass('enabled')) {
                                $control.removeClass('hidden disabled'); // Show matching custom control
                            } else if (typeof optionDisabledAttr !== typeof undefined && optionDisabledAttr !== false) {
                                $control.removeClass('hidden').addClass('disabled'); // "Gray out" matching custom control (option disabled)
                            }
                        } else {
                            $control.removeClass('disabled').addClass('hidden'); // Hide custom control (no matching option found)
                        }
                    };
                }
            });
        },
		
		
		/**
		 *	Quick view: Check if quick view modal is open
		 */
		quickviewIsOpen: function() {
            return $('#nm-quickview').is(':visible');
		}
		
	});
	
	// Add extension so it can be called from $.nmThemeExtensions
	$.nmThemeExtensions.shop = $.nmTheme.shop_init;
	
})(jQuery);