1(function ($) { 2 3 "use strict"; 4 5 $(function(){ 6 var swsL10n = window.swsL10n || {}; 7 8 if ( swsL10n ) { 9 for ( var wId in swsL10n.widgets ) { 10 if ( $( swsL10n.widgets[wId].selector ).length ) { 11 12 const widgets = swsL10n.widgets[wId]; 13 14 let params = { 15 id: wId, 16 serviceUrl: swsL10n.restUrl + 'id=' + encodeURIComponent( wId ), 17 layout: swsL10n.widgets[wId].layout, 18 columns: swsL10n.widgets[wId].columns, 19 productSlug: swsL10n.widgets[wId].productSlug, 20 maxHeight: swsL10n.widgets[wId].popupHeight, 21 maxHeightMobile: swsL10n.widgets[wId].popupHeightMobile, 22 minChars: swsL10n.widgets[wId].charCount, 23 disableAjax: swsL10n.widgets[wId].disableAjax, 24 no_results_text: swsL10n.widgets[wId].noResultsText, 25 loaderIcon: swsL10n.widgets[wId].loaderIcon, 26 loaderImage: swsL10n.widgets[wId].loaderImage, 27 preventBadQueries: swsL10n.widgets[wId].preventBadQueries, 28 fullScreenMode: swsL10n.widgets[wId].fullScreenMode, 29 placeholder: swsL10n.widgets[wId].placeholder, 30 recentSearches: swsL10n.widgets[wId].recentSearches, 31 recentSearchesTitle: swsL10n.widgets[wId].recentSearchesTitle, 32 keywords: swsL10n.widgets[wId].keywords, 33 keywordsLabel: swsL10n.widgets[wId].keywordsLabel, 34 selectedCategories: swsL10n.widgets[wId].selectedCategories, 35 selectedCategoriesLabel: swsL10n.widgets[wId].selectedCategoriesLabel, 36 selectedCategoriesLocation: swsL10n.widgets[wId].selectedCategoriesLocation, 37 selectedCategoriesMobile: swsL10n.widgets[wId].selectedCategoriesMobile, 38 selectedCategoriesCount: swsL10n.widgets[wId].selectedCategoriesCount, 39 selectedCategoriesOnOpen: swsL10n.widgets[wId].selectedCategoriesOnOpen, 40 selectedProducts: swsL10n.widgets[wId].selectedProducts, 41 selectedProductsLabel: swsL10n.widgets[wId].selectedProductsLabel, 42 selectedProductsMobile: swsL10n.widgets[wId].selectedProductsMobile, 43 44 promoBannerLocation: swsL10n.widgets[wId].promoBannerLocation, 45 promoBannerImage: swsL10n.widgets[wId].promoBannerImage, 46 promoBannerLink: swsL10n.widgets[wId].promoBannerLink, 47 promoBannerOnOpen: swsL10n.widgets[wId].promoBannerOnOpen, 48 selectedPromoBannerMobile: swsL10n.widgets[wId].selectedPromoBannerMobile, 49 50 customHtmlContent: swsL10n.widgets[wId].customHtmlContent, 51 customHtmlLabel: swsL10n.widgets[wId].customHtmlLabel, 52 customHtmlLocation: swsL10n.widgets[wId].customHtmlLocation, 53 customHtmlOnOpen: swsL10n.widgets[wId].customHtmlOnOpen, 54 customHtmlMobile: swsL10n.widgets[wId].customHtmlMobile 55 } 56 57 $(widgets.selector).each(function () { 58 const fullscreenMode = widgets.fullScreenMode; 59 const isDesktop = $(window).width() >= 768; 60 const shouldFullscreen = 61 (fullscreenMode == 'desktop_only' && isDesktop) || 62 (fullscreenMode == 'mobile_only' && !isDesktop) || 63 fullscreenMode == 'enable'; 64 65 if (shouldFullscreen) { 66 sws_init_autocomplete_fullscreen(this, params); 67 } else { 68 sws_init_autocomplete(this, params); 69 } 70 }); 71 } 72 } 73 } 74 75 76 /** 77 * Init autocomplete on search widget input 78 * 79 * @param el 80 * @param attr 81 */ 82 function sws_init_autocomplete( el, attr ) { 83 84 let $el = $( el ), 85 $this = $el.find( 'input[type="search"]' ).length ? $el.find( 'input[type="search"]' ) : $el.find( 'input[type="text"]' ), 86 $form = ( el.tagName === 'FORM' || el.tagName === 'form' ) ? $el : $el.find( 'form' ), 87 swsCurrentArray = JSON.parse(localStorage.getItem("swsLatestSearches")) || [], 88 $swsKeywords = []; 89 90 91 if ( ! $this.length ) { 92 return; 93 } 94 95 if ( $el.hasClass('ysm-active') || $form.hasClass('ysm-active') ) { 96 return; 97 } 98 99 $form.addClass( 'ysm-active' ).addClass( 'ysm-hide' ); 100 101 // Body class if widget on page 102 if (!$(document.body).toggleClass('ysm-widget-active', !$(document.body).hasClass('ysm-widget-active'))) { 103 return false; 104 } 105 106 // Divi theme compatibility 107 if ($(document.body).hasClass('ysm-widget-active')) { 108 $el.parents('.et_pb_column').css({ 109 overflow: 'visible', 110 zIndex: '10' 111 }); 112 $el.parents('.et_pb_module').css('overflow', 'visible'); 113 } 114 115 var defaults = { 116 id: '', 117 serviceUrl: swsL10n.restUrl, 118 layout: '', 119 columns: 1, 120 productSlug: 'product', 121 maxHeight: 500, 122 maxHeightMobile: 400, 123 minChars: 3, 124 disableAjax: false, 125 no_results_text: '', 126 loaderIcon: '', 127 preventBadQueries: true, 128 cache: true 129 }; 130 131 var options = $.extend( {}, defaults, attr ); 132 133 $form.on( 'submit', function( e ) { 134 var val = $this.val(); 135 136 if ( val === '' || val.length < options.minChars ) { 137 return false;
138 } else { 139 var action = swsL10n.searchPageUrl; 140 141 val = val.replace( /\+/g, '%2b' ); 142 val = val.replace( /\s/g, '+' ); 143 action += ( -1 !== action.indexOf( '?' ) ) ? '&' : '?'; 144 action += 's=' + val + '&search_id=' + options.id; 145 146 if ( options.layout === 'product' ) { 147 action += '&post_type=' + options.productSlug; 148 } 149 150 e.preventDefault(); 151 location.href = action; 152 } 153 } ); 154 155 if ( options.disableAjax ) { 156 return; 157 } 158 159 $( '<div class="smart-search-popup"><div class="smart-search-results"><div class="smart-search-results-inner"></div></div></div>' ).appendTo( $form ); 160 161 var $popup = $form.find( '.smart-search-popup' ); 162 var popupWidth = 0; 163 164 if ( $this.outerWidth() ) { 165 popupWidth = $this.outerWidth(); 166 $popup.css({ 167 width: popupWidth + 'px' 168 }); 169 } 170 171 var $results_wrapper = $form.find( '.smart-search-results' ); 172 var $resultsWrapperInner = $results_wrapper.find( '.smart-search-results-inner' ); 173 var maxHeightValue = ( Math.min(window.screen.width, window.screen.height) < 768 ) ? options.maxHeightMobile : options.maxHeight; 174 175 $results_wrapper.css({ 176 maxHeight: maxHeightValue + 'px', 177 }); 178 179 if ( navigator.userAgent.indexOf( 'Windows' ) !== -1 && navigator.userAgent.indexOf( 'Firefox' ) !== -1 ) { 180 $results_wrapper.addClass( 'smart-search-firefox' ); 181 } 182 183 let swsUpdateRecentSearches = (removeHiddenClass = false)=> { 184 185 if (removeHiddenClass === true) { 186 $('.sws-search-recent-wrapper').removeClass('sws-search-recent-wrapper--hidden_mod'); 187 } 188 let swsLatestFive = JSON.parse(localStorage.getItem("swsLatestSearches")).slice(-5); 189 $('.sws-search-recent-list').empty(); 190 swsLatestFive.forEach(item => { 191 $('.sws-search-recent-list').append(` 192 <li class="sws-search-recent-list-item"> 193 <span class="sws-search-recent-list-item-trigger">${item}</span> 194 <span class="sws-search-recent-list-item-delete" data-item="${item}" aria-label="close"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="currentColor"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg></span> 195 </li> 196 `); 197 }); 198 } 199 $(document).off('click', '.sws-search-recent-list-item-trigger').on('click', '.sws-search-recent-list-item-trigger', (e) => { 200 e.stopPropagation(); 201 let targetText = $(e.target).text(); 202 $(e.currentTarget).parents('form').find('input[type="search"]').val(targetText).focus(); 203 }); 204 205 $(document).off('click', '.sws-search-recent-list-item-delete').on('click', '.sws-search-recent-list-item-delete', function(e) { 206 e.stopPropagation(); 207 const itemToDelete = $(this).data('item'); 208 let currentStorage = JSON.parse(localStorage.getItem("swsLatestSearches")).filter(item => item !== itemToDelete) 209 localStorage.setItem("swsLatestSearches", JSON.stringify(currentStorage)); 210 211 swsCurrentArray = JSON.parse(localStorage.getItem("swsLatestSearches")); 212 213 swsUpdateRecentSearches(true); 214 215 if (swsCurrentArray.length == 0) { 216 $('.sws-search-recent-wrapper').addClass('sws-search-recent-wrapper--hidden_mod'); 217 } 218 219 }); 220 if (options.recentSearches) { 221 $('<div class="sws-search-recent-wrapper"><h4 class="sws-search-recent-title">'+ options.recentSearchesTitle+'</h4><ul class="sws-search-recent-list"></ul></div>').prependTo($popup); 222 223 if (swsCurrentArray.length) { 224 swsUpdateRecentSearches(true); 225 } 226 } 227 228 229 $( window ).on( 'resize', function () { 230 $popup.css({ 231 width: $this.outerWidth() + 'px' 232 }); 233 }); 234 235 $(document).on('click', '.smart-search-popup-backdrop', ()=>{ 236 $form.addClass( 'ysm-hide' ).removeClass( 'sws-no-results' ); 237 }) 238 239 $( window ).on( 'touchstart' , function( event ) { 240 var $wrapper = $( event.target ).hasClass( 'ysm-active' ) ? $( event.target ) : $( event.target ).parents( '.ysm-active' ); 241 if ( ! $wrapper.length ) { 242 $( '.ysm-active' ).addClass( 'ysm-hide' ); 243 } 244 }); 245 246 if (options.loaderImage.length) { 247 $this.parent().append('<img src='+options.loaderImage+' class="sws-loader-image" alt="Loading...">'); 248 } 249 250 $this.devbridgeAutocomplete({ 251 minChars : options.minChars, 252 appendTo : $resultsWrapperInner, 253 serviceUrl : options.serviceUrl, 254 maxHeight : 100000, 255 dataType : 'json', 256 deferRequestBy : 100, 257 noCache : ! options.cache, 258 containerClass : 'smart-search-suggestions', 259 triggerSelectOnValidInput: false, 260 showNoSuggestionNotice: options.no_results_text.length ? true : false, 261 noSuggestionNotice: options.no_results_text, 262 preventBadQueries: options.preventBadQueries, 263 ajaxSettings: { 264 beforeSend: function(xhr) { 265 if ( swsL10n.nonce ) { 266 xhr.setRequestHeader('X-WP-Nonce', swsL10n.nonce); 267 } 268 }, 269 }, 270 formatResult: function ( suggestion, currentValue ) { 271 return suggestion.data; 272 }, 273 onSearchStart : function ( query ) { 274 275 if ( this.value.indexOf( ' ' ) !== -1 ) { 276 this.value = this.value.replace( /\s+/g, ' ' ); 277 } 278 279 query.query = query.query.replace( /%20/g, ' ' ); 280 281 if (this.value == query.query + ' ') { 282 return; 283 } 284 285 if (!options.loaderImage.length) { 286 $this.css( {'background-image': 'url(' + options.loaderIcon + ')','background-repeat': 'no-repeat', 'background-position': '50% 50%'} ); 287 } 288 $('.sws-loader-image').addClass('sws-loader-image--visible'); 289 290 $form.addClass( 'ysm-hide' ).removeClass( 'sws-no-results' ); 291 }, 292 onSelect : function ( suggestion ) { 293 if ( suggestion.id != -1 && suggestion.url && ! suggestion.addToCart ) { 294 window.location.href = suggestion.url; 295 } 296 }, 297 transformResult: function ( response ) { 298 var res = typeof response === 'string' ? $.parseJSON( response ) : response, 299 val = $this.val(); 300 301 if ( res && res.view_all_link && res.view_all_link != '' ) { 302 if ( ! $popup.find( '.smart-search-view-all-holder' ).length ) { 303 $popup.addClass( 'has-viewall-button' ).append( '<div class="smart-search-view-all-holder"></div>' ); 304 } 305 $popup.find( '.smart-search-view-all-holder' ).html( res.view_all_link ); 306 } 307 308 $this.css( 'background-image', 'none' ); 309 $('.sws-loader-image').removeClass('sws-loader-image--visible'); 310 311 if (res.keywords.length) { 312 $popup.addClass( 'hidden-searches' ) 313 314 } else { 315 $popup.removeClass( 'hidden-searches' ) 316 } 317 318 return res; 319 }, 320 onSearchComplete: function ( query, suggestions ) { 321 if ( $.trim( query ) !== $.trim( $this.val() ) ) { 322 return; 323 } 324 325 if ( ! popupWidth ) { 326 popupWidth = $this.outerWidth(); 327 $popup.css({ 328 width: popupWidth + 'px' 329 }); 330 } 331 332 $this.css( 'background-image', 'none' ); 333 $('.sws-loader-image').removeClass('sws-loader-image--visible'); 334 335 if ( suggestions.length > 0 ) { 336 337 $form.removeClass( 'ysm-hide' ).removeClass( 'sws-no-results' ); 338 339 const $recentWrapper = $('.sws-search-recent-wrapper'); 340 var $viewAllEl = $popup.find( '.smart-search-view-all-holder' ); 341 342 setTimeout( function() {
343 var $wrapperWidth = $results_wrapper.outerWidth(); 344 // var columns = suggestions.length < options.columns ? suggestions.length : options.columns; 345 var columns = options.columns; 346 347 348 if ( $wrapperWidth === 0 ) { 349 $wrapperWidth = $this.outerWidth(); 350 $results_wrapper.width( $wrapperWidth + 'px' ); 351 } 352 353 if ( $wrapperWidth < columns * 200 ) { 354 columns = Math.floor( $wrapperWidth / 200 ); 355 } 356 357 if ( ! $results_wrapper.outerHeight() ) { 358 var suggestionsHeight = $resultsWrapperInner.find('.smart-search-suggestions').outerHeight(); 359 360 if ( suggestionsHeight ) { 361 suggestionsHeight = parseInt( suggestionsHeight, 10 ); 362 $results_wrapper.height( suggestionsHeight > maxHeightValue ? maxHeightValue : suggestionsHeight ); 363 } 364 } 365 366 $results_wrapper 367 .attr( 'data-columns', columns ) 368 .nanoScroller({ 369 contentClass: 'smart-search-results-inner', 370 alwaysVisible: false, 371 iOSNativeScrolling: true 372 }); 373 374 375 376 }, 100); 377 378 if ($viewAllEl.length || options.keywords) { 379 380 const handleVisibility = (element, query, callback) => { 381 if ($this.val().length < options.minChars) { 382 element.hide(); 383 } else { 384 const that = $this.devbridgeAutocomplete(); 385 let serviceUrl = options.serviceUrl; 386 387 if ($.isFunction(serviceUrl)) { 388 serviceUrl = serviceUrl.call(that.element, query); 389 } 390 391 const cacheKey = serviceUrl + '?' + $.param({ query: query }); 392 393 if (that.cachedResponse && that.cachedResponse[cacheKey]) { 394 callback(that.cachedResponse[cacheKey]); 395 } 396 element.show(); 397 } 398 }; 399 400 if ($viewAllEl.length) { 401 handleVisibility($viewAllEl, query, (cachedResponse) => { 402 $viewAllEl.html(cachedResponse.view_all_link); 403 }); 404 } 405 406 if (options.keywords) { 407 const $recentWrapper = $('.sws-search-recent-wrapper'); 408 handleVisibility($('.smart-search-keywords-wrapper'), query, (cachedResponse) => { 409 $swsKeywords = cachedResponse.keywords; 410 411 }); 412 413 if ( ! $popup.find( '.smart-search-keywords-wrapper' ).length ) { 414 $popup.addClass( 'sws-has-keywords' ).prepend( '<div class="smart-search-keywords-wrapper smart-search-keywords-wrapper--hidden_mod"><h3 class="smart-search-keywords-title">'+ options.keywordsLabel+'</h3><ul class="smart-search-keywords-list"></ul></div>' ); 415 } 416 417 if ($swsKeywords.length) { 418 $('.smart-search-keywords-list').empty(); 419 $('.smart-search-keywords-wrapper').removeClass('smart-search-keywords-wrapper--hidden_mod'); 420 $swsKeywords.forEach(item => { 421 $('.smart-search-keywords-list').append(` 422 <li class="sws-search-recent-list-item"> 423 <span class="sws-search-recent-list-item-trigger">${item}</span> 424 </li> 425 `); 426 }); 427 } 428 429 if ($recentWrapper.length) { 430 if ($swsKeywords.length) { 431 $('.smart-search-keywords-wrapper').removeClass('smart-search-keywords-wrapper--hidden_mod'); 432 $('.sws-search-recent-wrapper').addClass('sws-search-recent-wrapper--hidden_by_keywords'); 433 434 } else { 435 $('.smart-search-keywords-wrapper').addClass('smart-search-keywords-wrapper--hidden_mod'); 436 $('.sws-search-recent-wrapper').removeClass('sws-search-recent-wrapper--hidden_by_keywords'); 437 } 438 } 439 } 440 } 441 442 if ( options.recentSearches ) { 443 const currentSearchValue = query; 444 445 446 if (!swsCurrentArray.includes(currentSearchValue)) { 447 swsCurrentArray.push(currentSearchValue); 448 if (swsCurrentArray.length > 10) { 449 swsCurrentArray.shift(); // Remove the oldest item to keep the array size at 10 450 } 451 localStorage.setItem("swsLatestSearches", JSON.stringify(swsCurrentArray)); 452 } 453 if (swsCurrentArray.length) { 454 if ($recentWrapper.length == 0) { 455 456 $('<div class="sws-search-recent-wrapper"><h4 class="sws-search-recent-title">'+ options.recentSearchesTitle+'</h4><ul class="sws-search-recent-list"></ul></div>').prependTo($popup); 457 } 458 swsUpdateRecentSearches(true); 459 } 460 } 461 462 } else if ( options.no_results_text.length ) { 463 $form.removeClass( 'ysm-hide' ).addClass( 'sws-no-results' ); 464 } else { 465 $form.addClass( 'ysm-hide' ).addClass( 'sws-no-results' ); 466 } 467 468 }, 469 onSearchError: function ( query, jqXHR, textStatus, errorThrown ) { 470 if ( textStatus === 'error' ) { 471 var nonceRefresh = jqXHR.getResponseHeader('X-Wp-Nonce'); 472 473 if ( nonceRefresh && swsL10n.nonce !== nonceRefresh ) { 474 window.swsL10n.nonce = nonceRefresh; 475 $this.devbridgeAutocomplete().onValueChange(); 476 return; 477 } else if ( swsL10n.nonce ) { 478 window.swsL10n.nonce = ''; 479 $this.devbridgeAutocomplete().onValueChange(); 480 return; 481 } 482 } 483 484 $form.addClass( 'ysm-hide' ).removeClass( 'sws-no-results' ); 485 }, 486 onInvalidateSelection: function () { 487 488 }, 489 onHide: function (e) { 490 $form.addClass( 'ysm-hide' ).removeClass( 'sws-no-results' ); 491 } 492 }).on( 'focus', function () { 493 $this.devbridgeAutocomplete().onValueChange(); 494 }); 495 } 496 497 498 499 function sws_init_autocomplete_fullscreen( el, attr ) { 500 501 let placeholder = attr.placeholder ? attr.placeholder : ''; 502 503 let $el = $( el ), 504 $form = ( el.tagName === 'FORM' || el.tagName === 'form' ) ? $el : $el.find( 'form' ), 505 $popup = $form.find( '.smart-search-popup' ); 506 507 508 if ( $el.hasClass('ysm-active') || $form.hasClass('ysm-active') ) { 509 return; 510 } 511 512 $form.addClass( 'ysm-active' ).addClass( 'ysm-hide' ); 513 514 // Body class if widget on page 515 if (!$(document.body).toggleClass('ysm-widget-active', !$(document.body).hasClass('ysm-widget-active'))) { 516 return false;
517 } 518 519 // Divi theme compatibility 520 if ($(document.body).hasClass('ysm-widget-active')) { 521 $el.parents('.et_pb_column').css({ 522 overflow: 'visible', 523 zIndex: '10' 524 }); 525 $el.parents('.et_pb_module').css('overflow', 'visible'); 526 } 527 528 529 $( '<div class="smart-search-fullscreen">' + 530 '<div class="smart-search-fullscreen-backdrop"></div>'+ 531 '<div class="smart-search-fullscreen-inner">'+ 532 '<div class="smart-search-input-wrapper">'+ 533 '<input type="search" class="ssf-search-input" placeholder="'+placeholder+'" name="s" id="smart-search-fullscreen-'+attr.id+'">' + 534 '<span class="ssf-search-icon-search"><svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" fill="currentColor"><path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z"/></svg></span>'+ 535 '<span class="ssf-search-icon-close" aria-label="close"><svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24" fill="currentColor"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg></span>'+ 536 '</div>'+ 537 '<div class="smart-search-results-main">'+ 538 '<div class="smart-search-results">' + 539 ' <div class="smart-search-results-inner"></div>' + 540 '</div>' + 541 '</div>' + 542 '</div>' + 543 '</div>' ).appendTo( $form ); 544 545 let $fullscreen_wrapper = $form.find('.smart-search-fullscreen'), 546 $fullscreen_backdrop = $form.find('.smart-search-fullscreen-backdrop'), 547 $search_trigger = $el.find( 'input[type="search"]' ).length ? $el.find( 'input[type="search"]' ) : $el.find( 'input[type="text"]' ), 548 $this = $el.find( '.ssf-search-input' ).length ? $el.find( '.ssf-search-input' ) : $el.find( '.ssf-search-input' ), 549 $results_main = $form.find( '.smart-search-results-main' ), 550 $results_wrapper = $form.find( '.smart-search-results' ), 551 $resultsWrapperInner = $results_wrapper.find( '.smart-search-results-inner' ), 552 $clear_search = $form.find( '.ssf-search-icon-close' ), 553 $btn_trigger = $el.find( '.search-submit' ).length ? $el.find( '.search-submit' ) : '', 554 swsCurrentArray = JSON.parse(localStorage.getItem("swsLatestSearches")) || [], 555 $swsKeywords = []; 556 557 let defaults = { 558 id: '', 559 serviceUrl: swsL10n.restUrl, 560 layout: '', 561 columns: 1, 562 productSlug: 'product', 563 maxHeight: 500, 564 maxHeightMobile: 400, 565 minChars: 3, 566 disableAjax: false, 567 no_results_text: '', 568 loaderIcon: '', 569 preventBadQueries: true, 570 cache: true 571 }; 572 573 let options = $.extend( {}, defaults, attr ); 574 575 let swsUpdateRecentSearches = (removeHiddenClass = false)=> { 576 577 if (removeHiddenClass === true) { 578 $('.sws-search-recent-wrapper').removeClass('sws-search-recent-wrapper--hidden_mod'); 579 } 580 581 let swsLatestFive = JSON.parse(localStorage.getItem("swsLatestSearches")).slice(-5); 582 $('.sws-search-recent-list').empty(); 583 swsLatestFive.forEach(item => { 584 $('.sws-search-recent-list').append(` 585 <li class="sws-search-recent-list-item"> 586 <span class="sws-search-recent-list-item-trigger">${item}</span> 587 <span class="sws-search-recent-list-item-delete" data-item="${item}" aria-label="close"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="currentColor"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg></span> 588 </li> 589 `); 590 }); 591 } 592 593 if (options.selectedCategories || options.promoBannerImage || options.customHtmlContent) { 594 595 $results_main.addClass('smart-search-results-main--column_mod'); 596 597 if(options.selectedCategoriesMobile) { 598 $results_main.addClass('smart-search-results-main--hidden_mobile_mod'); 599 } 600 601 if(options.selectedCategoriesOnOpen) { 602 $results_main.addClass('smart-search-results-main--on_open_mod'); 603 } 604 605 $('<div class="sws-sidebar-holder"></div>').prependTo($results_main); 606 $('<div class="sws-sidebar sws-sidebar--left-mod"><div class="sws-sidebar-widget sws-sidebar--left_slot"></div><div class="sws-sidebar-widget sws-sidebar--left_slot_2"></div></div>').prependTo($results_main); 607 608 $('<div class="sws-sidebar sws-sidebar--right-mod"><div class="sws-sidebar-widget sws-sidebar--right_slot"></div><div class="sws-sidebar-widget sws-sidebar--right_slot_2"></div></div>').appendTo($results_main); 609 610 let selectedCategoriesHtml = $('<div class="sws-selected-categories ">' + 611 '<h4 class="sws-selected-categories-title">'+ options.selectedCategoriesLabel +'</h4>' + 612 '<ul class="sws-selected-categories-list"></ul>' + 613 '</div>'); 614 if (!options.selectedCategories) { 615 selectedCategoriesHtml = ''; 616 } 617 let left_slot = $results_main.find('.sws-sidebar--left-mod .sws-sidebar--left_slot'); 618 let left_slot_2 = $results_main.find('.sws-sidebar--left-mod .sws-sidebar--left_slot_2'); 619 let right_slot = $results_main.find('.sws-sidebar--right-mod .sws-sidebar--right_slot'); 620 let right_slot_2 = $results_main.find('.sws-sidebar--right-mod .sws-sidebar--right_slot_2'); 621 622 623 let promoBanner = ''; 624 if (options.promoBannerLink.length) {
625 promoBanner = $('<div class="sws-promo-banner">' + 626 '<a href="'+ options.promoBannerLink +'" target="_blank"> ' + 627 options.promoBannerImage + 628 '</a>'+ 629 '</div>'); 630 } else { 631 promoBanner = $('<div class="sws-promo-banner">' + 632 options.promoBannerImage + 633 '</div>'); 634 } 635 636 $('.sws-sidebar-holder').hide(); 637 638 if (options.selectedCategories) { 639 selectedCategoriesHtml.prependTo($results_main.find('.sws-sidebar--'+options.selectedCategoriesLocation+'')); 640 } 641 642 // Add custom HTML content 643 if (options.customHtmlContent) { 644 let customHtmlWrapper = $('<div class="sws-custom-html-content"></div>'); 645 646 if (options.customHtmlLabel) { 647 customHtmlWrapper.append('<h4 class="sws-custom-html-title">' + options.customHtmlLabel + '</h4>'); 648 } 649 650 customHtmlWrapper.append('<div class="sws-custom-html-inner">' + options.customHtmlContent + '</div>'); 651 652 if (options.customHtmlLocation) { 653 customHtmlWrapper.prependTo($results_main.find('.sws-sidebar--' + options.customHtmlLocation + '')); 654 } 655 656 if (options.customHtmlOnOpen) { 657 $results_main.addClass('smart-search-results-main--custom_html_on_open_mod'); 658 } 659 660 if (options.customHtmlMobile) { 661 customHtmlWrapper.addClass('sws-custom-html-content--hidden_mobile_mod'); 662 } 663 } 664 665 if (options.promoBannerImage) { 666 667 if(options.promoBannerOnOpen) { 668 $results_main.addClass('smart-search-results-main--banner_on_open_mod'); 669 } 670 671 promoBanner.prependTo($results_main.find('.sws-sidebar--'+options.promoBannerLocation+'')); 672 673 if(options.selectedPromoBannerMobile) { 674 $('.sws-promo-banner').addClass('sws-promo-banner--hidden_mobile_mod'); 675 } 676 } 677 678 if (right_slot.is(':empty') && right_slot_2.is(':empty')) { 679 $results_main.addClass('smart-search-results-main--widgets-on-left--mod'); 680 } 681 682 if (left_slot.is(':empty') && left_slot_2.is(':empty')) { 683 $('.sws-sidebar-holder').show(); 684 $results_main.addClass('smart-search-results-main--widgets-on-right--mod'); 685 } 686 687 688 if (options.selectedCategories) { 689 options.selectedCategories.forEach(item => { 690 691 $results_main.find('.sws-selected-categories-list').append(` 692 <li class="sws-selected-categories-item"> 693 <a class="sws-selected-categories-link" href="${item.url}"> 694 ${item.name} 695 ${(options.selectedCategoriesCount && item.count > 0) ? `(${item.count})` : ''} 696 </a> 697 </li> 698 `); 699 }); 700 } 701 702 } 703 704 if (options.recentSearches) { 705 $('<div class="sws-search-recent-wrapper sws-search-recent-wrapper--hidden_mod"><h4 class="sws-search-recent-title">'+ options.recentSearchesTitle+'</h4><ul class="sws-search-recent-list"></ul></div>').prependTo($results_main); 706 707 if (swsCurrentArray.length) { 708 swsUpdateRecentSearches(true); 709 } 710 } 711 712 if (options.loaderImage.length) { 713 $this.parent().append('<img src='+options.loaderImage+' class="sws-loader-image" alt="Loading...">'); 714 } 715 716 if (options.selectedProducts) { 717 $results_main.addClass('smart-search-results-recent-products--mod'); 718 $results_wrapper.addClass('smart-search-results-hidden'); 719 720 // Insert the Swiper container after the search results 721 $('<div class="sws-recent-products-wrapper"><h3 class="sws-recent-products-heading">'+options.selectedProductsLabel+'</h3><div class="swiper swsProductsSwiper sws-recent-products"><div class="swiper-wrapper"></div></div><div class="swiper-button-next"></div><div class="swiper-button-prev"></div></div>') 722 .insertBefore($results_main.find('.smart-search-results')); 723 724 if(options.selectedProductsMobile) { 725 $('.sws-recent-products-wrapper').addClass('sws-recent-products-wrapper--hidden_mobile_mod'); 726 } 727 728 // Loop through selected products and create swiper slides 729 options.selectedProducts.forEach(item => { 730 const slideHTML = ` 731 <div class="swiper-slide"> 732 <div class="sws-selected-products-item"> 733 <a class="sws-selected-products-picture" href="${item.permalink}"><picture>${item.image}</picture></a> 734 <div class="smart-search-post-category">${item.category}</div> 735 <a class="sws-selected-products-title" href="${item.permalink}">${item.name}</a> 736 <div class="sws-selected-products-meta"> 737 ${item.rating_count > 0 738 ? `<div class="sws-product-rating" style="display: flex; gap: 2px; float: left;"> 739 ${[...Array(5)].map((_, i) => { 740 const index = i + 1; 741 return item.average_rating >= index 742 ? `<span style="color: #ffc107; font-size: 20px;">â </span>` 743 : item.average_rating >= index - 0.5 744 ? `<span style="color: #ffc107; font-size: 20px;">â</span>` 745 : `<span style="color: #ddd; font-size: 20px;">â</span>`;
746 }).join('')} 747 </div>` 748 : ''} 749 ${item.price} 750 ${ item.type === 'variable' 751 ? 752 `<a href="${item.permalink}" class="button product_type_variable" target="_blank" rel="nofollow"> 753 <img src="${item.icon_variable}" alt=""> 754 </a>` 755 : 756 `<a href="?add-to-cart=${item.id}" 757 class="button add_to_cart_button ajax_add_to_cart" 758 data-product_id="${item.id}" 759 aria-label="Add â${item.name}â to your cart" 760 rel="nofollow"> 761 <img src="${item.icon}" alt=""> 762 </a>` 763 } 764 </div> 765 </div> 766 </div> 767 `; 768 $results_main.find('.swiper-wrapper').append(slideHTML); 769 }); 770 const swiperScript = document.createElement('script'); 771 swiperScript.src = 'https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js'; 772 swiperScript.async = true; 773 774 swiperScript.onload = function () { 775 new Swiper('.swsProductsSwiper', { 776 slidesPerView: 'auto', 777 spaceBetween: 0, 778 navigation: { 779 nextEl: '.swiper-button-next', 780 prevEl: '.swiper-button-prev' 781 }, 782 pagination: { 783 el: '.swiper-pagination', 784 clickable: true 785 } 786 }); 787 }; 788 789 document.body.appendChild(swiperScript); 790 791 792 } 793 794 795 $(document).off('click', '.sws-search-recent-list-item-trigger').on('click', '.sws-search-recent-list-item-trigger', (e)=> { 796 e.stopPropagation(); 797 let targetText = $(e.target).text() 798 $(e.currentTarget).parents('form').find( 'input[type="search"]' ).val(targetText).focus(); 799 }); 800 801 $(document).off('click', '.sws-search-recent-list-item-delete').on('click', '.sws-search-recent-list-item-delete', function(e) { 802 e.stopPropagation(); 803 const itemToDelete = $(this).data('item'); 804 let currentStorage = JSON.parse(localStorage.getItem("swsLatestSearches")).filter(item => item !== itemToDelete) 805 localStorage.setItem("swsLatestSearches", JSON.stringify(currentStorage)); 806 807 swsCurrentArray = JSON.parse(localStorage.getItem("swsLatestSearches")); 808 809 swsUpdateRecentSearches(true); 810 811 if (swsCurrentArray.length == 0) { 812 $('.sws-search-recent-wrapper').addClass('sws-search-recent-wrapper--hidden_mod'); 813 } 814 815 }); 816 817 let showPopup = ()=> { 818 $fullscreen_wrapper.addClass('ssf-active'); 819 820 swsCurrentArray = JSON.parse(localStorage.getItem("swsLatestSearches")) || []; 821 822 setTimeout(()=> { 823 824 $fullscreen_wrapper.addClass('ssf-animated'); 825 // Body class if fullscreen widget is opened 826 $(document.body).addClass('ysm-widget-opened') 827 $('.ssf-search-input').focus(); 828 829 }, 100); 830 } 831 832 let closePopup = ()=>{ 833 $fullscreen_wrapper.removeClass('ssf-active ssf-animated'); 834 $(document.body).removeClass('ysm-widget-opened') 835 $('.sws-search-recent-wrapper').removeClass('sws-search-recent-wrapper--hidden_by_keywords'); 836 $('.smart-search-keywords-wrapper').addClass('smart-search-keywords-wrapper--hidden_mod'); 837 setTimeout(()=>{ 838 $('.ssf-search-input').val(''); 839 840 $results_wrapper.css({ 841 maxHeight: 0, 842 }); 843 844 $('.smart-search-view-all-holder').hide(); 845 $('.smart-search-suggestions').empty(); 846 $form.addClass( 'ysm-hide' ) 847 $form.removeClass('sws-no-results'); 848 849 if (options.selectedProducts) { 850 $('.sws-recent-products-wrapper').show(); 851 $results_wrapper.addClass('smart-search-results-hidden'); 852 } 853 854 }, 500) 855 } 856 857 $search_trigger.on('click', ()=> { 858 showPopup(); 859 }); 860 861 if ($btn_trigger.length) { 862 $btn_trigger.on('click', ()=>{ 863 showPopup(); 864 }); 865 } 866 867 $(document).on('keydown', (event) => { 868 if (event.key === 'Tab') { 869 setTimeout(() => { 870 const $focusedElement = $(document.activeElement); 871 if ($focusedElement.is($search_trigger)) { 872 showPopup(); 873 } 874 }, 0); 875 } 876 if (event.key === 'Escape') { 877 closePopup(); 878 879 } 880 }); 881 882 883 $fullscreen_backdrop.on('click', ()=> { 884 closePopup(); 885 }) 886 887 if ($clear_search.length > 0) { 888 $clear_search.on('click', function () { 889 closePopup(); 890 }); 891 } 892 893 894 895 var maxHeightValue = ( Math.min(window.screen.width, window.screen.height) < 768 ) ? options.maxHeightMobile : options.maxHeight; 896 897 $form.on( 'submit', function( e ) { 898 var val = $this.val(); 899 900 if ( val === '' || val.length < options.minChars ) { 901 return false;
902 } else { 903 var action = swsL10n.searchPageUrl; 904 905 val = val.replace( /\+/g, '%2b' ); 906 val = val.replace( /\s/g, '+' ); 907 action += ( -1 !== action.indexOf( '?' ) ) ? '&' : '?'; 908 action += 's=' + val + '&search_id=' + options.id; 909 910 if ( options.layout === 'product' ) { 911 action += '&post_type=' + options.productSlug; 912 } 913 914 e.preventDefault(); 915 location.href = action; 916 } 917 } ); 918 919 if ( options.disableAjax ) { 920 return; 921 } 922 923 var popupWidth = 0; 924 925 if ( $this.outerWidth() ) { 926 popupWidth = $this.outerWidth(); 927 $popup.css({ 928 width: popupWidth + 'px' 929 }); 930 } 931 932 if ( navigator.userAgent.indexOf( 'Windows' ) !== -1 && navigator.userAgent.indexOf( 'Firefox' ) !== -1 ) { 933 $results_wrapper.addClass( 'smart-search-firefox' ); 934 } 935 936 $( window ).on( 'resize', function () { 937 $popup.css({ 938 width: $this.outerWidth() + 'px' 939 }); 940 }); 941 942 $this.devbridgeAutocomplete({ 943 minChars : options.minChars, 944 appendTo : $resultsWrapperInner, 945 serviceUrl : options.serviceUrl, 946 maxHeight : 100000, 947 dataType : 'json', 948 deferRequestBy : 100, 949 noCache : ! options.cache, 950 containerClass : 'smart-search-suggestions', 951 triggerSelectOnValidInput: false, 952 showNoSuggestionNotice: options.no_results_text.length ? true : false, 953 noSuggestionNotice: options.no_results_text, 954 preventBadQueries: options.preventBadQueries, 955 ajaxSettings: { 956 beforeSend: function(xhr) { 957 if ( swsL10n.nonce ) { 958 xhr.setRequestHeader('X-WP-Nonce', swsL10n.nonce); 959 } 960 }, 961 }, 962 formatResult: function ( suggestion, currentValue ) { 963 return suggestion.data; 964 }, 965 onSearchStart : function ( query ) { 966 if ( this.value.indexOf( ' ' ) !== -1 ) { 967 this.value = this.value.replace( /\s+/g, ' ' ); 968 } 969 970 query.query = query.query.replace( /%20/g, ' ' ); 971 972 if (this.value == query.query + ' ') { 973 return; 974 } 975 976 if (!options.loaderImage.length) { 977 $this.css( {'background-image': 'url(' + options.loaderIcon + ')','background-repeat': 'no-repeat', 'background-position': '50% 50%'} ); 978 979 } 980 $('.sws-loader-image').addClass('sws-loader-image--visible'); 981 $form.addClass( 'ysm-hide' ).removeClass( 'sws-no-results' ); 982 983 $results_main.addClass('sws-hiding-results'); 984 $results_wrapper.removeClass('smart-search-results-hidden'); 985 986 }, 987 onSelect : function ( suggestion ) { 988 if ( suggestion.id != -1 && suggestion.url && ! suggestion.addToCart ) { 989 window.location.href = suggestion.url; 990 } 991 }, 992 transformResult: function ( response ) { 993 var res = typeof response === 'string' ? $.parseJSON( response ) : response, 994 val = $this.val(); 995 996 if ( res && res.view_all_link && res.view_all_link != '' ) { 997 if ( ! $results_main.find( '.smart-search-view-all-holder' ).length ) { 998 $results_main.addClass( 'has-viewall-button' ).append( '<div class="smart-search-view-all-holder"></div>' ); 999 } 1000 $results_main.find( '.smart-search-view-all-holder' ).html( res.view_all_link ); 1001 } 1002 1003 $this.css( 'background-image', 'none' ); 1004 1005 $('.sws-loader-image').removeClass('sws-loader-image--visible'); 1006 1007 return res; 1008 }, 1009 onSearchComplete: function ( query, suggestions ) { 1010 if ( $.trim( query ) !== $.trim( $this.val() ) ) { 1011 return; 1012 } 1013 1014 if ( ! popupWidth ) { 1015 popupWidth = $this.outerWidth(); 1016 $popup.css({ 1017 width: popupWidth + 'px' 1018 }); 1019 } 1020 1021 $this.css( 'background-image', 'none' ); 1022 $('.sws-loader-image').removeClass('sws-loader-image--visible'); 1023 1024 1025 const handleVisibility = (element, query, callback) => { 1026 if ($this.val().length < options.minChars) { 1027 element.hide(); 1028 } else { 1029 const that = $this.devbridgeAutocomplete(); 1030 let serviceUrl = options.serviceUrl; 1031 1032 if ($.isFunction(serviceUrl)) { 1033 serviceUrl = serviceUrl.call(that.element, query); 1034 } 1035 1036 const cacheKey = serviceUrl + '?' + $.param({ query: query }); 1037 1038 if (that.cachedResponse && that.cachedResponse[cacheKey]) { 1039 callback(that.cachedResponse[cacheKey]); 1040 } 1041 element.show(); 1042 } 1043 }; 1044 1045 var $viewAllEl = $results_main.find( '.smart-search-view-all-holder' ); 1046 1047 if ($viewAllEl.length || options.keywords) { 1048 1049 if ($viewAllEl.length) { 1050 handleVisibility($viewAllEl, query, (cachedResponse) => { 1051 $viewAllEl.html(cachedResponse.view_all_link); 1052 }); 1053 } 1054 1055 if (options.keywords) { 1056 const $recentWrapper = $('.sws-search-recent-wrapper'); 1057 handleVisibility($('.smart-search-keywords-wrapper'), query, (cachedResponse) => {
1058 $swsKeywords = cachedResponse.keywords; 1059 console.log('triggered keywords'); 1060 }); 1061 1062 if ( ! $results_main.find( '.smart-search-keywords-wrapper' ).length ) { 1063 $results_main.addClass( 'sws-has-keywords' ).prepend( '<div class="smart-search-keywords-wrapper smart-search-keywords-wrapper--hidden_mod"><h3 class="smart-search-keywords-title">'+ options.keywordsLabel+'</h3><ul class="smart-search-keywords-list"></ul></div>' ); 1064 } 1065 1066 if ($swsKeywords.length) { 1067 1068 $('.smart-search-keywords-list').empty(); 1069 $('.smart-search-keywords-wrapper').removeClass('smart-search-keywords-wrapper--hidden_mod'); 1070 $swsKeywords.forEach(item => { 1071 $('.smart-search-keywords-list').append(` 1072 <li class="sws-search-recent-list-item"> 1073 <span class="sws-search-recent-list-item-trigger">${item}</span> 1074 </li> 1075 `); 1076 }); 1077 } 1078 1079 if ($recentWrapper.length) { 1080 1081 if ($swsKeywords.length) { 1082 $('.smart-search-keywords-wrapper').removeClass('smart-search-keywords-wrapper--hidden_mod'); 1083 $recentWrapper.addClass('sws-search-recent-wrapper--hidden_by_keywords'); 1084 1085 } else { 1086 $('.smart-search-keywords-wrapper').addClass('smart-search-keywords-wrapper--hidden_mod'); 1087 $recentWrapper.removeClass('sws-search-recent-wrapper--hidden_by_keywords'); 1088 } 1089 } 1090 } 1091 } 1092 1093 1094 if ( suggestions.length > 0 ) { 1095 1096 $form.removeClass( 'ysm-hide' ).removeClass( 'sws-no-results' ); 1097 1098 $results_main.removeClass('sws-hiding-results'); 1099 $results_wrapper.removeClass('smart-search-results-hidden'); 1100 1101 var $wrapperWidth = $results_wrapper.outerWidth(); 1102 // var columns = suggestions.length < options.columns ? suggestions.length : options.columns; 1103 var columns = options.columns; 1104 1105 1106 if ( $wrapperWidth === 0 ) { 1107 $wrapperWidth = $this.outerWidth(); 1108 $results_wrapper.width( $wrapperWidth + 'px' ); 1109 } 1110 1111 if ( $wrapperWidth < columns * 200 ) { 1112 columns = Math.floor( $wrapperWidth / 200 ); 1113 } 1114 1115 let swsWindowHeight = window.innerHeight 1116 let swsMarginsHeight = 180; 1117 let swsButtonHeight = $viewAllEl.length ? 60 : 0; 1118 let swsRecentSearchesHeight = 0; 1119 if (options.recentSearches || options.keywords) { 1120 swsRecentSearchesHeight = $(window).width() >= 768 ? 45 : 110; 1121 } 1122 let swsMaximumHeight = swsWindowHeight - swsMarginsHeight - swsButtonHeight - swsRecentSearchesHeight; 1123 1124 if (maxHeightValue > swsMaximumHeight) { 1125 $results_wrapper.css({ 1126 maxHeight: swsMaximumHeight + 'px', 1127 }); 1128 } else { 1129 $results_wrapper.css({ 1130 maxHeight: maxHeightValue + 'px', 1131 }); 1132 } 1133 1134 if ( ! $results_wrapper.outerHeight() ) { 1135 var suggestionsHeight = $resultsWrapperInner.find('.smart-search-suggestions').outerHeight(); 1136 1137 if ( suggestionsHeight ) { 1138 suggestionsHeight = parseInt( suggestionsHeight, 10 ); 1139 $results_wrapper.height( suggestionsHeight > maxHeightValue ? maxHeightValue : suggestionsHeight ); 1140 } 1141 } 1142 1143 $results_wrapper 1144 .attr( 'data-columns', columns ) 1145 .nanoScroller({ 1146 contentClass: 'smart-search-results-inner', 1147 alwaysVisible: false, 1148 iOSNativeScrolling: true 1149 }); 1150 1151 1152 1153 if ( options.recentSearches ) { 1154 const currentSearchValue = query; 1155 1156 if (!swsCurrentArray.includes(currentSearchValue)) { 1157 swsCurrentArray.push(currentSearchValue); 1158 if (swsCurrentArray.length > 10) { 1159 swsCurrentArray.shift(); 1160 } 1161 localStorage.setItem("swsLatestSearches", JSON.stringify(swsCurrentArray)); 1162 } 1163 if (swsCurrentArray.length) { 1164 swsUpdateRecentSearches(true); 1165 } 1166 } 1167 1168 if (options.selectedProducts) { 1169 $('.sws-recent-products-wrapper').hide(); 1170 } 1171 1172 } else if ( options.no_results_text.length ) { 1173 $form.removeClass( 'ysm-hide' ).addClass( 'sws-no-results' ); 1174 $results_main.removeClass('sws-hiding-results'); 1175 1176 } else { 1177 $form.addClass( 'ysm-hide' ).addClass( 'sws-no-results' ); 1178 } 1179 1180 }, 1181 onSearchError: function ( query, jqXHR, textStatus, errorThrown ) { 1182 if ( textStatus === 'error' ) { 1183 var nonceRefresh = jqXHR.getResponseHeader('X-Wp-Nonce'); 1184 1185 if ( nonceRefresh && swsL10n.nonce !== nonceRefresh ) { 1186 window.swsL10n.nonce = nonceRefresh; 1187 $this.devbridgeAutocomplete().onValueChange(); 1188 return; 1189 } else if ( swsL10n.nonce ) { 1190 window.swsL10n.nonce = ''; 1191 $this.devbridgeAutocomplete().onValueChange(); 1192 return; 1193 } 1194 } 1195 1196 }, 1197 onInvalidateSelection: function () { 1198 1199 }, 1200 onHide: function () {} 1201 }).on( 'focus', function () { 1202 $this.devbridgeAutocomplete().onValueChange(); 1203 }); 1204 } 1205 1206 }); 1207 1208})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.