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-search.js
(function($) {	
	
	'use strict';
	
	// Extend core script
	$.extend($.nmTheme, {
		
		/**
		 *	Initialize
		 */
		search_init: function() {
			var self = this;
            
            self.headerSearch = (nm_wp_vars.shopSearchHeader !== '0') ? true : false;
            self.searchCurrentQuery = '';
            
            if (self.headerSearch) {
                // Suggestions
                if (nm_wp_vars.searchSuggestions !== '0') {
                    self.instantSuggestions = (nm_wp_vars.searchSuggestionsInstant !== '0') ? true : false;
                    if (self.instantSuggestions) { self.instantSuggestionsLoad(); } // Load product data
                    
                    self.suggestions = true;
                    self.suggestionsAjax = null;
                    self.suggestionsCacheEnabled = true;
                    self.suggestionsCache = {};
                    self.suggestionsMaxResults = nm_wp_vars.searchSuggestionsMax;
                } else {
                    self.suggestions = false;
                }
                
                self.$searchPanel = $('#nm-header-search');
                
                // Hide search-panel scrollbar
                self.$searchPanel.css('margin-right', '-'+self.scrollbarWidth+'px');
                
                self.$searchBtn = $('#nm-menu-search-btn');
                self.$searchInput = $('#nm-header-search-input');
                self.$searchNotice = $('#nm-header-search-notice');
                
                self.headerSearchBind();
            } else if (self.isShop) {
                self.$searchBtn = $('#nm-shop-search-btn');
                self.$searchPanel = $('#nm-shop-search');
                self.$searchInput = $('#nm-shop-search-input');
                self.$searchNotice = $('#nm-shop-search-notice');
                self.searchAjax = null;
                self.currentSearch = '';
                
                self.shopSearchBind();
            }
		},
		
		
		/**
		 *	Search: Validate input string
		 */
		searchValidateInput: function(searchKey, enterPress) {
			// Make sure the search string has at least one character (not just whitespace) and minimum allowed characters are entered
			/*ORG: if ((/\S/.test(searchKey)) && searchKey.length > (nm_wp_vars.shopSearchMinChar - 1)) {
				return true;
			} else {
				return false;
			}*/
            var self = this,
                searchQueryNoWhitespace = searchKey.replace(/ /g,'');
            
            // Has the search-text (without whitespace) changed?
            if (! enterPress && self.searchCurrentQuery == searchQueryNoWhitespace) {
                return 'unchanged';
            }
            
			// Make sure the search string has at least one character (not just whitespace) and minimum allowed characters are entered
            if (searchQueryNoWhitespace.length > 0 && searchKey.length > (nm_wp_vars.shopSearchMinChar - 1)) {
				self.searchCurrentQuery = searchQueryNoWhitespace;
                
                return 'valid';
			} else {
				return 'invalid';
			}
		},
        
        
        /**
		 *	Search: Show notice
		 */
		searchShowNotice: function() {
			var self = this;
            self.$searchNotice.addClass('show');
		},
		
		
		/**
		 *	Search: Hide notice
		 */
		searchHideNotice: function() {
			var self = this;
            self.$searchNotice.removeClass('show');
		},
        
        
        /**
		 *	Header search: Bind
		 */
		headerSearchBind: function() {
			var self = this;
			
            /* Bind: Menu button/link */
            self.$searchBtn.on('click', function(e) {
                e.preventDefault();
                self.headerSearchTogglePanel();
            });

            /* Bind: Panel "close" button */
            $('#nm-header-search-close').on('click', function(e) {
                e.preventDefault();
                self.headerSearchTogglePanel();
            });
            
            /* Bind: Search input "input" event */
            self.$searchInput.on('input', function() {
                var $input = $(this),
                    searchKey = $input.val(),
                    validSearch = self.searchValidateInput(searchKey);
                
                if (validSearch === 'valid') {
                    if (self.suggestions) {
                        self.suggestionsGet(searchKey);
                    } else {
                        self.searchShowNotice();
                    }
                } else if (validSearch === 'invalid') {
                    if (self.suggestions) {
                        self.suggestionsHide();   
                    } else {
                        self.searchHideNotice();
                    }
                }
            }).trigger('input');
			
			/* Bind: Search input "keypress" event - "ENTER" press */
            self.$searchInput.on('keypress', function(e) {
                var $input = $(this),
                    keyCode = (e.keyCode ? e.keyCode : e.which);
                
                if (keyCode == '13') {
                    // Prevent default form submit
                    e.preventDefault();
                    
                    // Cancel suggestion AJAX
                    if (self.suggestionsAjax) {
                        self.suggestionsAjax.abort();
                    }
                    
                    self.headerSearchStaticSearch($input);
                }
			});
            
            /* Bind: Document "keydown" event - "ESC" press */
            self.$document.on('keydown', function(e) {
                var keyCode = (e.keyCode ? e.keyCode : e.which);
                if (keyCode == '27' && self.$body.hasClass(self.classSearchOpen)) {
                    self.headerSearchTogglePanel();
                }
            });
		},
        
        
        /**
		 *	Header search: Toggle panel
		 */
		headerSearchTogglePanel: function() {
            var self = this;
            
            self.$body.toggleClass(self.classSearchOpen);
            
            if (self.$body.hasClass(self.classSearchOpen)) {
                self.pageOverlayShow();
                
                // "Focus" search input
                $('#nm-header-search-input').trigger('focus');
            } else {
                self.pageOverlayHide()
                
                setTimeout(function() {
                    $('#nm-header-search-input').val(''); // Empty input value
                    if (self.suggestions) {
                        self.suggestionsHide();
                    }
                }, self.panelsAnimSpeed + 150);
            }
            
			// Hide search notice
			self.searchHideNotice();
		},
        
        
        /**
         *  Header search: Do static search
         */
        headerSearchStaticSearch: function($input) {
            var self = this,
                searchKey = $input.val(),
                validSearch = self.searchValidateInput(searchKey, true);
            
            // Make sure search is valid
            if (validSearch === 'valid') {
                self.searchHideNotice();
                
                if (self.suggestions) {
                    $('#nm-header-search-form').addClass('nm-loader');
                    $('.nm-header-search-wrap').addClass('redirecting');
                }
                
                /*Can be used to do AJAX search: if (self.isShop && self.filtersEnableAjax) {
                    self.headerSearchTogglePanel();
                    self.shopSearchAjaxSearch(searchKey);
                } else {*/
                var searchUrl = nm_wp_vars.shopSearchUrl.toString().replace('%%nmsearchkey%%', encodeURIComponent(searchKey));
                window.location.href = searchUrl;
                //}
            }
        },
        
        
        /**
		 *	Shop search: Bind
		 */
		shopSearchBind: function() {
			var self = this;
            
            /* Bind: Panel "close" button */
            $('#nm-shop-search-close').on('click', function(e) {
                e.preventDefault();
                self.$searchBtn.trigger('click');
            });
            
            
            /* Bind: Search input "input" event */
            $('#nm-shop-search-input').on('input', function() {
                var validSearch = self.searchValidateInput($(this).val());

                //if (validSearch) {
                if (validSearch === 'valid') {
                    self.searchShowNotice();
                //} else {
                } else if (validSearch === 'invalid') {
                    self.searchHideNotice();
                }
            }).trigger('input');
            
			
            if (self.filtersEnableAjax) {
                /* Bind: Input "keypress" event - "ENTER" press */
                self.$searchInput.on('keypress', function(e) {
                    var $input = $(this),
                        searchKey = $input.val(),
                        keyCode = (e.keyCode ? e.keyCode : e.which);
                    
                    if (keyCode == '13') {
                        // Prevent default form submit
                        e.preventDefault();
                        
                        //ORG: var validSearch = self.searchValidateInput(searchKey);
                        var validSearch = self.searchValidateInput(searchKey, true);

                        // Make sure search is valid and unique
                        //ORG: if (validSearch && self.currentSearch !== s) {
                        if (validSearch === 'valid' && self.currentSearch !== searchKey) {

                            if ($input.hasClass('nm-mobile-menu-search')) {
                                self.pageOverlayHide(); // Close mobile menu
                                setTimeout(function() {
                                    $('#nm-mobile-menu-shop-search-input').val(''); // Empty input value
                                    self.shopSearchAjaxSearch(searchKey);
                                }, self.panelsAnimSpeed);
                            } else {
                                if (nm_wp_vars.shopSearchAutoClose != '0') {
                                    // Close search-panel
                                    self.$searchBtn.trigger('click');
                                } else {
                                    self.searchHideNotice();
                                }

                                setTimeout(function() {
                                    self.shopSearchAjaxSearch(searchKey);
                                }, self.filterPanelSlideSpeed);
                            }

                        } else {
                            self.currentSearch = searchKey;
                        }
                    }
                });
            }
		},
        
        
        /**
		 *	Shop search: Toggle panel
		 */
		shopSearchTogglePanel: function() {
			var self = this,
				$searchInput = $('#nm-shop-search-input');
			
			self.$searchPanel.slideToggle(200, function() {
				self.$searchPanel.toggleClass('fade-in');
												
				if (self.$searchPanel.hasClass('fade-in')) {
					// "Focus" search input
					$searchInput.trigger('focus');
				} else {
					// Empty input value
					$searchInput.val('');
				}
				
				self.filterPanelSliding = false;
			});
			
			// Hide search notice
			self.searchHideNotice();
		},
		
		
		/**
		 *	Shop search: Perform AJAX search
		 */
		shopSearchAjaxSearch: function(searchKey) {
			var self = this;
			
			// Blur input to hide virtual mobile keyboards
			self.$searchInput.blur();
            
            if (self.shopSidebarLayout == 'popup' && nm_wp_vars.shopFiltersPopupAutoClose !== '0') {
                 // Hide filters popup
                self.shopFiltersPopupHide();
            }
            
            // Show 'loader' overlay
            self.shopShowLoader();
			
			self.currentSearch = searchKey;
			
            // Create search URL
            var searchUrl = nm_wp_vars.searchUrl.toString().replace('%%nmsearchkey%%', encodeURIComponent(searchKey)); // Note: Encoding the search string with "encodeURIComponent" to avoid breaking the AJAX url
            
			self.searchAjax = $.ajax({
				url: searchUrl,
                data: {
					shop_load: 'search',
					post_type: 'product',
                    shop_filters_layout: self.shopSidebarLayout
				},
				dataType: 'html',
				// Note: Disabling this to avoid the "_(random number)" query-string in pagination links
				//cache: false,
				//headers: {'cache-control': 'no-cache'},
				method: 'GET',
				error: function(XMLHttpRequest, textStatus, errorThrown) {
					console.log('NM: AJAX error - shopSearchAjaxSearch() - ' + errorThrown);
					
					// Hide 'loader' overlay
					self.shopHideLoader();
					
					self.searchAjax = null;
				},
				success: function(data) {
					// Update shop content
					self.shopUpdateContent(data);
					
					self.searchAjax = null;
				}
			});
		},
        
        
        /**
         * Suggestions: Get suggestions
         */
        suggestionsGet: function(searchKey) {
            var self = this;
            
            // Show instant suggestions?
            if (self.instantSuggestions) {
                self.instantSuggestionsGet(searchKey);
                return;
            }
            
            // Is an AJAX request already running?
            if (self.suggestionsAjax) {
                self.suggestionsAjax.abort();
            }
            
            // Get form elements
            var $searchForm = $('#nm-header-search-form'),
                $searchSuggestions = $('#nm-search-suggestions');
            
            var cacheKey = self.suggestionsEscapeQuery(searchKey);
            
            // Has the search results been cached?
            if (self.suggestionsCacheEnabled && self.suggestionsCache[cacheKey]) {
                self.suggestionsShow(self.suggestionsCache[cacheKey], null, $searchSuggestions);
            } else {
                $searchForm.addClass('nm-loader');
                
                // Add class if suggestions are showing
                if ($searchSuggestions.children('.nm-search-suggestions-inner').children().length) {
                    $searchSuggestions.addClass('doing-search');
                }
                
                // Use WooCommerce AJAX endpoint URL
                var ajaxUrl = (typeof wc_add_to_cart_params !== 'undefined') ? wc_add_to_cart_params.wc_ajax_url : nm_wp_vars.woocommerceAjaxUrl;
                ajaxUrl = ajaxUrl.toString().replace('%%endpoint%%', 'nm_shop_search');

                // Get search results via AJAX
                self.suggestionsAjax = $.ajax({
                    type: 'POST',
                    url: ajaxUrl,
                    data: {
                        s: searchKey
                    },
                    dataType: 'html',
                    success: function(response) {
                        // Cache results
                        if (self.suggestionsCacheEnabled) {
                            self.suggestionsCacheResults(searchKey, response);
                        }
                        
                        self.suggestionsShow(response, null, $searchSuggestions);
                    },
                    complete: function() {
                        $searchForm.removeClass('nm-loader');

                        self.suggestionsAjax = null; // Reset AJAX state
                    }
                });
            }
        },
        
        
        /**
		 *	Suggestions: Make search-query URL safe (so it can be used as an object key)
		 */
        suggestionsEscapeQuery: function(searchQuery) {
            //var escapedQuery = $.param({s: searchQuery});
            var escapedQuery = encodeURIComponent(searchQuery);
            return escapedQuery;
        },
        
        
        /**
		 *	Suggestions: Cache results
		 */
        suggestionsCacheResults: function(searchKey, response) {
            var self = this,
                cacheKey = self.suggestionsEscapeQuery(searchKey);
            
            self.suggestionsCache[cacheKey] = response;
        },
        
        
        /**
		 *	Suggestions: Show
		 */
		suggestionsShow: function(productsHTML, resultCount, $searchSuggestions) {
            var self = this,
                $productList = $('#nm-search-suggestions-product-list');
            
            $productList.html(productsHTML);
            $searchSuggestions.removeClass('doing-search');
            $searchSuggestions.addClass('show');
            
            resultCount = (resultCount) ? resultCount : $productList.children().length;
            
            // Show notice
            if (resultCount == 0) {
                var noticeTxtClass = 'no-results';
            } else {
                var noticeTxtClass = (resultCount == self.suggestionsMaxResults) ? 'press-enter' : 'has-results';
            }
            $('#nm-search-suggestions-notice').removeClass().addClass('show ' + noticeTxtClass);
        },
        
        
        /**
		 *	Suggestions: Hide
		 */
		suggestionsHide: function() {
            var self = this;
            
            // Is an AJAX request running?
            if (self.suggestionsAjax) {
                self.suggestionsAjax.abort();
            }
            
            $('#nm-search-suggestions-product-list').html('');
            $('#nm-search-suggestions').removeClass();
            $('#nm-search-suggestions-notice').removeClass();
            
            self.searchCurrentQuery = '';
        },
        
        
        /**
		 *	Instant suggestions: Load product data
		 */
        instantSuggestionsLoad: function() {
            var self = this;
            
            self.productDataJSON = null;
            
            // Use WooCommerce AJAX endpoint URL
            var ajaxUrl = (typeof wc_add_to_cart_params !== 'undefined') ? wc_add_to_cart_params.wc_ajax_url : nm_wp_vars.woocommerceAjaxUrl;
            ajaxUrl = ajaxUrl.toString().replace('%%endpoint%%', 'nm_suggestions_product_data');
            
            // Get product data via AJAX
            $.ajax({
                type: 'post',
                url: ajaxUrl,
                dataType: 'json',
                error: function(XMLHttpRequest, textStatus, errorThrown) {
					console.log('NM: AJAX error - instantSuggestionsLoad() - ' + errorThrown);
				},
                success: function(response) {
                    self.productDataJSON = response;
                }
            });
        },
        
        
        /**
		 *	Instant suggestions: Search product data
		 */
        instantSuggestionsSearchData: function(searchKey) {
            // Converting accent characters so searching "ãbç" will match "abc" (product title is also converted in "../includes/woocommerce/search-suggestions-php")
            // - Source: https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
            if (searchKey.normalize) { // .normalize() not supported in IE
                searchKey = searchKey.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
            }
            
            var self = this,
                product,
                regexKeyword = new RegExp(searchKey, "i"),
                regexSKU = new RegExp("^" + searchKey + "$"), // Find exact match
                i = 0,
                matches = [];
            
            for (var key in self.productDataJSON) {
                if (self.productDataJSON.hasOwnProperty(key)) {
                    product = self.productDataJSON[key];
                    if (product['title'].search(new RegExp(regexKeyword)) != -1) { // Search by title
                        i++;
                        matches.push(product);
                    } else if (product['categories'] && product['categories'].search(new RegExp(regexKeyword)) != -1) { // Search by Categories
                        i++;
                        matches.push(product);
                    } else if (product['tags'] && product['tags'].search(new RegExp(regexKeyword)) != -1) { // Search by Tags
                        i++;
                        matches.push(product);
                    } else if (product['sku'] && regexSKU.test(product['sku'])) { // Search by SKU (exact match)
                        i++;
                        matches.push(product);
                    }
                    
                    if (i == self.suggestionsMaxResults) { break; } // Break loop when max results are reached
                }
            }
            
            return matches;
        },
        
        
        /**
		 *	Instant suggestions: Get suggestions from cached product data
		 */
        instantSuggestionsGet: function(searchKey) {
            var self = this,
                searchResults = self.instantSuggestionsSearchData(searchKey),
                productsHTML = '';
            
            if (searchResults.length > 0) {
                for (var i = 0; i < searchResults.length; i++) {
                    productsHTML += searchResults[i]['product_html'];
                }
                
                self.suggestionsShow(productsHTML, searchResults.length, $('#nm-search-suggestions'));
            } else {
                self.suggestionsShow('', 0, $('#nm-search-suggestions'));
            }
        }
		
	});
	
	// Add extension so it can be called from $.nmThemeExtensions
	$.nmThemeExtensions.search = $.nmTheme.search_init;
	
})(jQuery);