1(function( $ ) { 2 3 'use strict'; 4 5 var JetSearch = { 6 7 addedScripts: [], 8 addedStyles: [], 9 addedPostCSS: [], 10 assetsPromises: [], 11 12 initElementor: function() { 13 14 var widgets = { 15 'jet-ajax-search.default': JetSearch.widgetAjaxSearch, 16 'jet-search-suggestions.default': JetSearch.widgetSearchSuggestions 17 }; 18 19 $.each( widgets, function( widget, callback ) { 20 window.elementorFrontend.hooks.addAction( 'frontend/element_ready/' + widget, callback ); 21 } ); 22 23 // Re-init widgets in nested tabs 24 window.elementorFrontend.elements.$window.on( 25 'elementor/nested-tabs/activate', 26 ( event, content ) => { 27 28 const $content = $( content ); 29 JetSearch.reinitSlickSlider( $content ); 30 JetSearch.initElementsHandlers( $content ); 31 } 32 ); 33 34 window.addEventListener( 'elementor/popup/show', ( event ) => { 35 const instance = event.detail.instance; 36 37 const interval = setInterval( () => { 38 39 if ( ! instance.keyboardHandler ) return; 40 41 const handler = instance.keyboardHandler; 42 const config = handler.config; 43 44 if ( ! config || ! config.$modalElements ) return; 45 46 if ( handler.changeFocusAfterAnimation !== true ) { 47 clearInterval( interval ); 48 return; 49 } 50 51 const $input = instance.$element.find('.jet-ajax-search__field'); 52 53 if ( $input.length ) { 54 handler.firstFocusableElement = $input[0]; 55 } 56 57 clearInterval( interval ); 58 59 }, 50) ; 60 61 setTimeout( () => clearInterval( interval ), 1000 ); 62 63 }); 64 65 /* 66 // Example of usage AJAX success trigger 67 $( document ).on( 'jet-ajax-search/show-results', function( event, searchResults ) { 68 searchResults.find( '.jet-ajax-search__results-item' ).css( 'border', '2px solid red' ); 69 } ); 70 */ 71 72 /* 73 * Example of usage `jet-ajax-search/results-area/listing-add-suggestion` trigger 74 * 75 * Parameters: 76 * - itemWrapper: A CSS selector that points to the element containing the wrapper of the search result item. 77 * - itemLink: Represents the element that contains the link of the search result item. 78 * - itemTitle: A CSS selector that points to the element containing the title of the search result item. 79 * - itemUrlAttr: Specifies the attribute used to extract the URL from the itemLink. 80 $( document ).on( "jet-ajax-search/results-area/listing-add-suggestion", function( event, itemWrapper, itemLink, itemTitle, itemUrlAttr ) { 81 itemWrapper = '.jet-ajax-search__results-item', 82 itemLink = $( '.jet-listing-dynamic-image__link', itemWrapper ); 83 itemTitle = '.jet-ajax-search-item-title .jet-listing-dynamic-field__content'; 84 itemUrlAttr = 'href'; 85 86 window.JetSearch.addSuggestionFromResultAreaItem( itemWrapper, itemLink, itemTitle, itemUrlAttr ); 87 } ); 88 */ 89 }, 90 91 initBricks: function( $scope ) { 92 93 if ( window.bricksIsFrontend ) { 94 return; 95 } 96 97 $scope = $scope || $( 'body' ); 98 99 JetSearch.initBlocks( $scope ); 100 101 }, 102 103 initBlocks: function( $scope ) { 104 105 $scope = $scope || $( 'body' ); 106 107 window.JetPlugins.init( $scope, [ 108 { 109 block: 'jet-search/ajax-search', 110 callback: JetSearch.widgetAjaxSearch 111 }, 112 { 113 block: 'jet-search/search-suggestions', 114 callback: JetSearch.widgetSearchSuggestions 115 } 116 ] ); 117 }, 118 119 widgetAjaxSearch: function( $scope ) { 120 121 var settings = { 122 searchClass: '.jet-ajax-search', 123 searchFormClass: '.jet-ajax-search__form', 124 fieldsHolderClass: '.jet-ajax-search__fields-holder', 125 inputClass: '.jet-ajax-search__field', 126 settingsInput: 'input[name="jet_ajax_search_settings"]', 127 submitClass: '.jet-ajax-search__submit', 128 chosenClass: '.jet-ajax-search__categories select[name="jet_ajax_search_categories"]', 129 resultsAreaClass: '.jet-ajax-search__results-area', 130 resultsHeaderClass: '.jet-ajax-search__results-header', 131 resultsFooterClass: '.jet-ajax-search__results-footer', 132 listHolderClass: '.jet-ajax-search__results-holder', 133 listClass: '.jet-ajax-search__results-list', 134 listInnerClass: '.jet-ajax-search__results-list-inner', 135 listSlideClass: '.jet-ajax-search__results-slide', 136 itemClass: '.jet-ajax-search__results-item', 137 inlineSuggestionsAreaClass: '.jet-ajax-search__suggestions-inline-area', 138 inlineSuggestionsItemClass: '.jet-ajax-search__suggestions-inline-area-item', 139 resultsSuggestionsAreaClass: '.jet-ajax-search__results-suggestions-area', 140 resultsSuggestionItemClass: '.jet-ajax-search__results-suggestions-area-item', 141 countClass: '.jet-ajax-search__results-count', 142 messageHolderClass: '.jet-ajax-search__message', 143 fullResultsClass: '.jet-ajax-search__full-results', 144 navigationClass: '.jet-ajax-search__navigation-holder', 145 navButtonClass: '.jet-ajax-search__navigate-button', 146 bulletClass: '.jet-ajax-search__bullet-button', 147 numberClass: '.jet-ajax-search__number-button', 148 prevClass: '.jet-ajax-search__prev-button', 149 nextClass: '.jet-ajax-search__next-button', 150 activeNavClass: '.jet-ajax-search__active-button', 151 disableNavClass: '.jet-ajax-search__navigate-button-disable', 152 spinnerClass: '.jet-ajax-search__spinner-holder', 153 handlerId: 'jetSearchSettings', 154 isRtl: ( window.elementorFrontend && window.elementorFrontend.config.is_rtl ) ? window.elementorFrontend.config.is_rtl : $( 'body' ).hasClass( 'rtl' ) 155 }; 156 157 if ( $scope.hasClass('jet-ajax-search-block') ) { 158 var resultAreaWidthBy = $scope.find( settings.searchClass ).data('settings')['results_area_width_by'], 159 resultAreaCustomWidth = $scope.find( settings.searchClass ).data('settings')['results_area_custom_width'], 160 resultAreaCustomWidthPosition = $scope.find( settings.searchClass ).data('settings')['results_area_custom_position'], 161 resultAreaContainer = $( '.jet-ajax-search__results-area', $scope ); 162 163 if ( "custom" === resultAreaWidthBy ) { 164 if ( "" !== resultAreaCustomWidth ) { 165 resultAreaContainer.width( resultAreaCustomWidth ); 166 } 167 168 switch( resultAreaCustomWidthPosition ) { 169 case 'left': 170 resultAreaContainer.css( "left", 0 ); 171 resultAreaContainer.css( "right", "auto" ); 172 break; 173 case 'center': 174 resultAreaContainer.css( "left", "50%" ); 175 resultAreaContainer.css( "right", "auto" ); 176 resultAreaContainer.css( "-webkit-transform", "translateX(-55%)" ); 177 resultAreaContainer.css( "transform", "translateX(-50%)" ); 178 break; 179 case 'right': 180 resultAreaContainer.css( "left", "auto" ); 181 resultAreaContainer.css( "right", 0 ); 182 break; 183 } 184 } 185 } 186 187 $scope.find( settings.searchClass ).jetAjaxSearch( settings ); 188 189 $scope.find( settings.inputClass ) 190 .on( 'focus.jetSearchSlick input.jetSearchSlick', function() { 191 window.JetSearch.pauseAllSlick( $( document ) ); 192 }) 193 .on( 'blur.jetSearchSlick', function() { 194 window.JetSearch.playAllSlick( $( document ) ); 195 }); 196 197 var $chosenSelect = $scope.find( settings.chosenClass ); 198 199 if ( $chosenSelect[0] ) { 200 $chosenSelect.chosen( { 201 disable_search: true, 202 placeholder_text: '', 203 placeholder_text_single: '' 204 } ); 205 } 206 }, 207 208 widgetSearchSuggestions: function( $scope ) { 209 210 let $target = $scope.find( '.jet-search-suggestions' ), 211 settings = { 212 searchClass: '.jet-search-suggestions', 213 searchFormClass: '.jet-search-suggestions__form', 214 fieldsHolderClass: '.jet-search-suggestions__fields-holder', 215 inputClass: '.jet-search-suggestions__field', 216 spinnerClass: '.jet-search-suggestions__spinner-holder', 217 messageHolderClass: '.jet-search-suggestions__message', 218 settingsInput: 'input[name="jet_search_suggestions_settings"]', 219 submitClass: '.jet-search-suggestions__submit', 220 chosenClass: '.jet-search-suggestions__categories select[name="jet_search_suggestions_categories"]', 221 inlineClass: '.jet-search-suggestions__inline-area', 222 inlineItemClass: '.jet-search-suggestions__inline-area-item', 223 focusClass: '.jet-search-suggestions__focus-area', 224 focusHolderClass: '.jet-search-suggestions__focus-results-holder', 225 focusItemClass: '.jet-search-suggestions__focus-area-item', 226 handlerId: 'jetSearchSettings', 227 isRtl: ( window.elementorFrontend && window.elementorFrontend.config.is_rtl ) ? window.elementorFrontend.config.is_rtl : $( 'body' ).hasClass( 'rtl' ) 228 }, 229 $chosenSelect = $scope.find( settings.chosenClass ); 230 231 $target.jetAjaxSearchSuggestions( settings ); 232 233 if ( $chosenSelect[0] ) { 234 $chosenSelect.chosen( { 235 disable_search: true, 236 placeholder_text: '', 237 placeholder_text_single: '' 238 } ); 239 } 240 }, 241 242 setFormSuggestion: function( name, form, url = '' ) { 243 const ajaxSettings = window['jetSearchSettings']['searchSuggestions'] || {}, 244 sendData = { 245 name: name 246 }, 247 nonce = ajaxSettings.nonce_rest; 248 249 const ajaxData = { 250 action: ajaxSettings.add_action, 251 data: sendData || {}, 252 nonce: ajaxSettings.nonce 253 }; 254 255 $.ajax( { 256 type: 'POST', 257 url: ajaxSettings.add_suggestions_rest_api_url, 258 data: ajaxData, 259 dataType: 'json', 260 beforeSend: function( jqXHR ) { 261 jqXHR.setRequestHeader( 'X-WP-Nonce', nonce ); 262 }, 263 complete: function() { 264 if ( false != form ) {
265 if ( '' != url ) { 266 url = JetSearch.getResultsUrl( form, url ); 267 268 window.location.href = url; 269 } else { 270 form.submit(); 271 } 272 } else { 273 window.location.href = url; 274 } 275 } 276 } ); 277 }, 278 getResultsUrl: function( form, url = '' ) { 279 let redirectUrl = ''; 280 281 if ( '' != url ) { 282 redirectUrl = url; 283 } else { 284 redirectUrl = form.attr( 'action' ); 285 } 286 287 if ( redirectUrl && ! redirectUrl.startsWith( 'http' ) && ! redirectUrl.startsWith( '/' ) ) { 288 const actionBase = ( form.attr( 'action' ) || '/' ).replace( /\/+$/, '' ); 289 290 redirectUrl = actionBase + '/' + redirectUrl.replace( /^\/+/, '' ); 291 } 292 293 let formData = {}, 294 result = ''; 295 296 formData = form.serializeArray().reduce( function( obj, item ) { 297 if ( item.name === 's' ) { 298 item.value = item.value.replace(/\u3000/g, ' '); 299 } 300 301 obj[item.name] = item.value; 302 303 return obj; 304 }, {} ); 305 306 if ( Object.keys( formData ).length > 0 ) { 307 const queryString = $.param( formData ).replace(/=&/g, '&').replace(/=$/, '' ); 308 const separator = redirectUrl.indexOf( '?' ) === -1 ? '?' : '&'; 309 310 result = redirectUrl + separator + queryString; 311 } else { 312 result = redirectUrl; 313 } 314 315 return result; 316 }, 317 suggestionsPreloader: function( is_active, state, preloader ) { 318 if ( ! is_active ) { 319 return; 320 } 321 322 if ( '' != preloader ) { 323 if ( 'show' === state ) { 324 preloader.addClass( 'show' ); 325 } else if ( 'hide' === state ) { 326 preloader.removeClass( 'show' ); 327 } 328 } 329 }, 330 getUrlParams: function() { 331 let params = {}, 332 queryString = window.location.search.slice(1); 333 334 if ( queryString ) { 335 let pairs = queryString.split( '&' ); 336 337 for ( let i = 0; i < pairs.length; i++ ) { 338 let pair = pairs[i].split( '=' ); 339 340 params[pair[0]] = decodeURIComponent( pair[1] || '' ); 341 } 342 } 343 344 return params; 345 }, 346 md5: function(str) { 347 let hash = ''; 348 349 for (let i = 0; i < str.length; i++) { 350 let char = str.charCodeAt(i); 351 hash += char; 352 } 353 return hash; 354 }, 355 generateHash: function( string, length = 6 ) { 356 let md5Hash = JetSearch.md5( string ), 357 hash = ''; 358 359 for ( let i = 0; i < length; i++ ) { 360 hash += md5Hash.charAt( Math.floor( Math.random() * md5Hash.length ) ); 361 } 362 363 hash = hash.toLowerCase(); 364 365 return hash; 366 }, 367 generateRandomId: function() { 368 let hash = JetSearch.generateHash( Math.random().toString() ); 369 370 return hash; 371 }, 372 initElementsHandlers: function( $selector ) { 373 // Actual init 374 window.JetPlugins.init( $selector ); 375 376 // Legacy Elementor-only init 377 $selector.find( '[data-element_type]' ).each( function() { 378 var excludeWidgets = [ 379 'jet-form-builder-form.default', 380 'nav-menu.default', 381 'jet-woo-product-gallery-slider.default', 382 'accordion.default' 383 ]; 384 385 var $this = $( this ), 386 elementType = $this.data( 'element_type' ); 387 388 if ( !elementType ) { 389 return; 390 } 391 392 if ( 'widget' === elementType ) { 393 elementType = $this.data( 'widget_type' ); 394 395 if ( excludeWidgets.includes( elementType ) ) { 396 return; 397 } 398 399 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/widget', $this, $ ); 400 } 401 402 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/global', $this, $ ); 403 window.elementorFrontend.hooks.doAction( 'frontend/element_ready/' + elementType, $this, $ ); 404 } ); 405 406 if ( window.elementorFrontend ) { 407 const elementorLazyLoad = new Event( "elementor/lazyload/observe" ); 408 document.dispatchEvent( elementorLazyLoad ); 409 } 410 411 if ( window.JetPopupFrontend && window.JetPopupFrontend.initAttachedPopups ) { 412 window.JetPopupFrontend.initAttachedPopups( $selector ); 413 } 414 }, 415 reinitSlickSlider: function( $scope ) { 416 var $slider = $scope.find('.slick-initialized'); 417 418 if ( $slider.length ) { 419 420 $slider.each( function() { 421 $( this ).slick('unslick'); 422 } ); 423 } 424 }, 425 426 toggleSlickAutoplay: function( $root, shouldPlay ) { 427 const $slicks = $root ? $root.find( '.slick-initialized' ) : $( '.slick-initialized' ); 428 429 $slicks.each( function(){
430 try { 431 $( this ).slick( shouldPlay ? 'slickPlay' : 'slickPause' ); 432 } catch(e) {} 433 }); 434 }, 435 436 pauseAllSlick: function( $root ) { 437 this.toggleSlickAutoplay( $root || $( document ), false ); 438 }, 439 440 playAllSlick: function( $root ) { 441 setTimeout( () => this.toggleSlickAutoplay( $root || $( document ), true ), 60 ); 442 }, 443 444 enqueueAssetsFromResponse: function( response ) { 445 if ( response.data.scripts ) { 446 JetSearch.enqueueScripts( response.data.scripts ); 447 } 448 449 if ( response.data.styles ) { 450 JetSearch.enqueueStyles( response.data.styles ); 451 } 452 }, 453 454 enqueueScripts: function( scripts ) { 455 $.each( scripts, function( handle, scriptHtml ) { 456 JetSearch.enqueueScript( handle, scriptHtml ) 457 } ); 458 }, 459 460 enqueueStyles: function( styles ) { 461 $.each( styles, function( handle, styleHtml ) { 462 JetSearch.enqueueStyle( handle, styleHtml ) 463 } ); 464 }, 465 466 enqueueScript: function( handle, scriptHtml ) { 467 468 if ( -1 !== JetSearch.addedScripts.indexOf( handle ) ) { 469 return; 470 } 471 472 if ( ! scriptHtml ) { 473 return; 474 } 475 476 var selector = 'script[id="' + handle + '-js"]'; 477 478 if ( $( selector ).length ) { 479 return; 480 } 481 482 var scriptsTags = scriptHtml.match( /<script[\s\S]*?<\/script>/gm ); 483 484 if ( scriptsTags.length ) { 485 486 for ( var i = 0; i < scriptsTags.length; i++ ) { 487 488 JetSearch.assetsPromises.push( 489 new Promise( function( resolve, reject ) { 490 491 var $tag = $( scriptsTags[i] ); 492 493 if ( $tag[0].src ) { 494 495 var tag = document.createElement( 'script' ); 496 497 tag.type = $tag[0].type; 498 tag.src = $tag[0].src; 499 tag.id = $tag[0].id; 500 tag.async = false; 501 tag.onload = function() { 502 resolve(); 503 }; 504 505 document.body.append( tag ); 506 } else { 507 $( 'body' ).append( scriptsTags[i] ); 508 resolve(); 509 } 510 } ) 511 ); 512 } 513 } 514 515 JetSearch.addedScripts.push( handle ); 516 }, 517 518 enqueueStyle: function( handle, styleHtml ) { 519 520 if ( -1 !== handle.indexOf( 'google-fonts' ) ) { 521 JetSearch.enqueueGoogleFonts( handle, styleHtml ); 522 return; 523 } 524 525 if ( -1 !== JetSearch.addedStyles.indexOf( handle ) ) { 526 return; 527 } 528 529 var selector = 'link[id="' + handle + '-css"],style[id="' + handle + '"]'; 530 531 if ( $( selector ).length ) { 532 return; 533 } 534 535 $( 'head' ).append( styleHtml ); 536 537 JetSearch.addedStyles.push( handle ); 538 539 if ( -1 !== handle.indexOf( 'elementor-post' ) ) { 540 var postID = handle.replace( 'elementor-post-', '' ); 541 JetSearch.addedPostCSS.push( postID ); 542 } 543 }, 544 545 enqueueGoogleFonts: function( handle, styleHtml ) { 546 547 var selector = 'link[id="' + handle + '-css"]'; 548 549 if ( $( selector ).length ) {} 550 551 $( 'head' ).append( styleHtml ); 552 }, 553 554 reinitBricksScripts: function( _this ) { 555 556 if ( !$( 'body' ).hasClass( 'theme-bricks' ) && !$( 'body' ).hasClass( 'bricks-is-frontend') ) { 557 return; 558 } 559 560 const resultsArea = $( '.jet-ajax-search__results-list', _this ); 561 const sourcesHolder = $( '.jet-ajax-search__source-results-holder', _this ); 562 563 //Results Area 564 resultsArea.find( '[data-script-id]' ).each( function() { 565 const newId = JetSearch.generateRandomId(); 566 567 $( this ).attr( 'data-script-id', newId ); 568 } ); 569 570 resultsArea.find( '[id^="brxe-"]' ).each( function() { 571 var id = $( this ).attr( 'id' ); 572 573 $( this ).addClass( id ); 574 } ); 575 576 const bricksScripts = { 577 ".bricks-lightbox": 'bricksPhotoswipe', 578 ".brxe-accordion, .brxe-accordion-nested": 'bricksAccordion', 579 ".brxe-animated-typing": 'bricksAnimatedTyping', 580 ".brxe-audio": 'bricksAudio', 581 ".brxe-countdown": 'bricksCountdown', 582 ".brxe-counter": 'bricksCounter', 583 ".brxe-video": 'bricksVideo', 584 ".bricks-lazy-hidden": 'bricksLazyLoad', 585 ".brx-animated": 'bricksAnimation', 586 ".brxe-pie-chart": 'bricksPieChart', 587 ".brxe-progress-bar .bar span": 'bricksProgressBar', 588 ".brxe-form": 'bricksForm', 589 ".brx-query-trail": 'bricksInitQueryLoopInstances', 590 "[data-interactions]": 'bricksInteractions', 591 ".brxe-alert svg": 'bricksAlertDismiss', 592 ".brxe-tabs, .brxe-tabs-nested": 'bricksTabs', 593 ".bricks-video-overlay, .bricks-video-overlay-icon, .bricks-video-preview-image": 'bricksVideoOverlayClickDetector',
594 ".bricks-background-video-wrapper": 'bricksBackgroundVideoInit', 595 ".brxe-toggle": 'bricksToggle', 596 ".brxe-offcanvas": 'bricksOffcanvas', 597 '.brxe-slider': 'bricksSwiper', 598 '.brxe-slider-nested': 'bricksSplide', 599 '.brxe-image': 'bricksSwiper' 600 }; 601 602 const contentWrapper = resultsArea[0]; 603 604 //Result Area 605 for ( const key in bricksScripts ) { 606 const widget = contentWrapper.querySelector(key); 607 608 if ( widget && typeof window[bricksScripts[key]] === "function" && bricksScripts[key] ) { 609 window[bricksScripts[key]](); 610 } 611 } 612 613 //Sources Holder 614 if ( sourcesHolder.length ) { 615 sourcesHolder.find( '[data-script-id]' ).each( function() { 616 const newId = JetSearch.generateRandomId(); 617 618 $( this ).attr( 'data-script-id', newId ); 619 } ); 620 621 sourcesHolder.find( '[id^="brxe-"]' ).each( function() { 622 var id = $( this ).attr( 'id' ); 623 624 $( this ).addClass( id ); 625 } ); 626 627 const sourcesWrapper = sourcesHolder[0]; 628 629 for ( const key in bricksScripts ) { 630 const widget = sourcesWrapper.querySelector( key ); 631 632 if ( widget && typeof window[bricksScripts[key]] === "function" && bricksScripts[key] ) { 633 window[bricksScripts[key]](); 634 } 635 } 636 } 637 }, 638 639 getCurrentDeviceMode: function() { 640 const width = window.innerWidth; 641 642 if ( width > 1024 ) { 643 return 'desktop'; 644 } else if ( width <= 1024 && width > 767 ) { 645 return 'tablet'; 646 } else { 647 return 'mobile'; 648 } 649 }, 650 651 trimString: function( str, numWords ) { 652 if ( typeof str !== 'string' ) { 653 return str; 654 } 655 656 let wordsArray = str.split( ' ' ); 657 658 if ( wordsArray.length <= numWords ) { 659 return str; 660 } 661 662 let truncatedString = wordsArray.slice( 0, numWords ).join( ' ' ); 663 664 return truncatedString + '...'; 665 }, 666 667 escapeHTML: function( str ) { 668 return str.replace(/[&<>"']/g, function ( match ) { 669 const escapeMap = { 670 '&': '&', 671 '<': '<', 672 '>': '>', 673 '"': '"', 674 "'": ''' 675 }; 676 677 return escapeMap[match]; 678 } ); 679 }, 680 681 addSuggestionFromResultAreaItem: function( itemWrapper, itemLink, itemTitle, itemUrlAttr ) { 682 itemLink.on( 'click', function( e ) { 683 e.stopImmediatePropagation(); 684 e.preventDefault(); 685 686 let item = $( this ).closest( itemWrapper ), 687 value = $( itemTitle, item ).text(), 688 url = $( this ).attr( itemUrlAttr ); 689 690 JetSearch.setFormSuggestion( value, false, url ); 691 } ); 692 } 693 }; 694 695 $.fn.getSuggestionsList = function( options, settings, showSpinner, hightlightText = false, callback = () => {} ) { 696 let self = this[0], 697 outputHtml = '', 698 listPosition = options.list_position, 699 inlineItemTemplate = wp.template( 'jet-search-inline-suggestion-item' ), 700 focusItemTemplate = wp.template( 'jet-search-focus-suggestion-item' ), 701 spinner = $( settings.spinnerClass, self ), 702 manualList = []; 703 704 const ajaxSettings = window['jetSearchSettings']['searchSuggestions'] || {}; 705 706 function highlightMatches( item ) { 707 let searched = options.value.trim(); 708 709 if ( searched !== "" ) { 710 let reg = new RegExp("[\>][^\<]*"+searched+"[^\<]*[\<]","gi"), 711 reg2 = new RegExp( searched, "gi" ), 712 regHtml = new RegExp("<\/?[a-z](.*?)[\s\S]*>", "gi"); 713 714 if ( reg.test( item ) ) { 715 item = item.replace( reg, function( item ) { 716 let subRegex = new RegExp( searched, "gi" ); 717 return item.replace( subRegex,`<mark>${searched}</mark>` ); 718 } ); 719 } 720 721 if ( regHtml.test( item ) ) { 722 return item; 723 } else { 724 item = item.replace( reg2, str => `<mark>${str}</mark>` ); 725 } 726 } 727 728 return item; 729 } 730 731 if ( 'manual' === options.list_type ) { 732 733 if ( options['manual_list'].length ) { 734 let list = options['manual_list'].split( "," ); 735 736 list.map( function( suggestion, i ) { 737 manualList[i] = { name: suggestion }; 738 } ); 739 740 if ( 'inline' === listPosition ) { 741 manualList.map( function( suggestion ) { 742 outputHtml += inlineItemTemplate( suggestion ); 743 } ); 744 745 $( self ).html( outputHtml ); 746 } else if ( 'focus' === listPosition ) { 747 manualList.map( function( suggestion ) { 748 outputHtml += focusItemTemplate( suggestion ); 749 } ); 750 751 $( settings.focusHolderClass ,self ).html( outputHtml ); 752 753 if ( typeof callback === 'function' ) { 754 callback(); 755 } 756 757 JetSearch.suggestionsPreloader( showSpinner, 'hide', spinner ); 758 } 759 } 760 761 return; 762 } 763 764 let sendData = { 765 list_type: options.list_type || '', 766 value: options.value || '', 767 limit: options.limit 768 }, 769 ajaxData = { 770 action: ajaxSettings.get_action, 771 data: sendData || {}, 772 }; 773 774 jQuery.ajax( { 775 type: 'GET', 776 url: ajaxSettings.get_suggestions_rest_api_url, 777 data: ajaxData, 778 dataType: 'json', 779 cache: false, 780 processData: true, 781 error: function( jqXHR, textStatus, errorThrown ) { 782 errorCallback( jqXHR ); 783 }, 784 success: function( response, textStatus, jqXHR ) { 785 successCallback( response ); 786 if ( typeof callback === 'function' ) { 787 callback(); 788 } 789 } 790 } ); 791 792 const successCallback = function( response ) { 793 794 if ( response ) { 795 JetSearch.suggestionsPreloader( showSpinner, 'hide', spinner ); 796 797 if ( 'inline' === listPosition ) { 798 response.map( function( suggestion ) { 799 suggestion['name'] = JetSearch.escapeHTML( suggestion['name'] ); 800 suggestion['fullName'] = JetSearch.escapeHTML( suggestion['name'] ); 801 802 if ( 0 < options.maxLength ) { 803 suggestion['name'] = JetSearch.trimString( suggestion['name'], options.maxLength ); 804 } 805 806 outputHtml += inlineItemTemplate( suggestion ); 807 } ); 808 809 $( self ).html( outputHtml ); 810 } else if ( 'focus' === listPosition ) { 811 812 response.map( function( suggestion ) { 813 suggestion['name'] = JetSearch.escapeHTML( suggestion['name'] ); 814 suggestion['fullName'] = JetSearch.escapeHTML( suggestion['name'] ); 815 816 if ( 0 < options.maxLength ) { 817 suggestion['name'] = JetSearch.trimString( suggestion['name'], options.maxLength ); 818 } 819 820 if ( options.value && ( "yes" === hightlightText || true === hightlightText ) ) {
821 suggestion['name'] = highlightMatches( suggestion['name'] ); 822 } 823 824 outputHtml += focusItemTemplate( suggestion ); 825 } ); 826 827 $( settings.focusHolderClass, self ).html( outputHtml ); 828 } 829 } 830 } 831 832 const errorCallback = function( jqXHR ) { 833 if ( 'abort' !== jqXHR.statusText ) { 834 JetSearch.suggestionsPreloader( showSpinner, 'hide', spinner ); 835 } 836 }; 837 }; 838 839 /** 840 * jetAjaxSearchSuggestions jQuery Plugin 841 * 842 * @param args 843 */ 844 $.fn.jetAjaxSearchSuggestions = function( args ) { 845 let self = this[0], 846 settings = args, 847 options = $( self ).data( 'settings' ) || {}, 848 timer = null, 849 showformList = options['show_search_suggestions_list_inline'] || false, 850 showfocusList = options['show_search_suggestions_list_on_focus'] || false, 851 formListType = options['search_suggestions_list_inline'] || false, 852 focusListType = options['search_suggestions_list_on_focus'] || false, 853 searchSuggestionsLimit = options['search_suggestions_quantity_limit'] || 10, 854 inlineLimit = options['search_suggestions_list_inline_quantity'] || 5, 855 focusLimit = options['search_suggestions_list_on_focus_quantity'] || 5, 856 showSpinner = options['show_search_suggestions_list_on_focus_preloader'] || '', 857 hightlightText = options['highlight_searched_text'] || '', 858 spinner = $( settings.spinnerClass, self ), 859 formFocusClass = settings.searchFormClass.replace( '.', '' ) + '--focus', 860 form = $( settings.searchFormClass, self ), 861 focusTarget = $( settings.focusHolderClass, self ), 862 disableInputs = false, 863 customResultUrl = options['search_results_url'] || '', 864 useSession = 'false', 865 focusItem; 866 867 if ( window.elementorFrontend ) { 868 var editMode = Boolean( window.elementorFrontend.isEditMode() ) 869 } else { 870 var editMode = false; 871 } 872 873 if ( !self.isInit ) { 874 self.isInit = true; 875 876 /** 877 * Ajax settings from localized global variable 878 */ 879 self.ajaxSettings = window[ settings.handlerId ]['searchSuggestions'] || {}; 880 881 customResultUrl = $.trim( customResultUrl ); 882 useSession = self.ajaxSettings.use_session; 883 884 self.selectSuggestion = function( event ) { 885 const keyCode = event.keyCode || event.which; 886 const $target = $( event.currentTarget ); 887 888 let value = $target.attr( 'aria-label' ); 889 890 if ( ! value ) { 891 return; 892 } 893 894 value = value.trim(); 895 896 if ( false === disableInputs && !editMode ) { 897 898 if ( 'keydown' === event.type ) { 899 if ( 13 === keyCode ) { 900 disableInputs = true; 901 902 $( settings.inputClass, self )[0].value = value; 903 904 JetSearch.setFormSuggestion( value, form, customResultUrl ); 905 } 906 } else if ( 'click' === event.type ) { 907 disableInputs = true; 908 909 $( settings.inputClass, self )[0].value = value; 910 JetSearch.setFormSuggestion( value, form, customResultUrl ); 911 } 912 } 913 } 914 915 self.focusItemsNav = function() { 916 focusItem = $( '.jet-search-suggestions__focus-area-item', self ); 917 918 if ( 0 < focusItem.length ) { 919 focusItem.on( 'keydown', function( e ) { 920 const keyCode = e.keyCode || e.which; 921 922 switch ( keyCode ) { 923 case 40: // Down arrow 924 e.preventDefault(); 925 926 var next = $( this ).next(); 927 928 if ( next.length > 0 ) { 929 focusItem.removeClass( 'focused' ); 930 next.addClass( 'focused' ); 931 next.focus(); 932 } 933 break; 934 935 case 38: // Up arrow 936 e.preventDefault(); 937 938 var prev = $( this ).prev(); 939 940 if ( prev.length > 0 ) { 941 focusItem.removeClass( 'focused' ); 942 prev.addClass( 'focused' ); 943 prev.focus(); 944 } else { 945 focusItem.removeClass( 'focused' ); 946 $( settings.inputClass, self ).focus(); 947 } 948 break; 949 case 13: 950 e.preventDefault(); 951 let value = e.target.innerText.trim(); 952 $( settings.inputClass, self )[0].value = value; 953 954 JetSearch.setFormSuggestion( value, form, customResultUrl ); 955 break; 956 } 957 958 if ( $( this ).is( ':focus-visible' ) ) { 959 focusItem.removeClass( 'focused' ); 960 } 961 } ); 962 } 963 } 964 965 if ( formListType || focusListType ) { 966
967 if ( '' != formListType && ( "yes" === showformList || true === showformList ) ) { 968 let listOptions = { 969 list_position: 'inline', 970 list_type: formListType, 971 limit: inlineLimit, 972 maxLength: options.search_suggestions_list_inline_item_title_length, 973 }; 974 975 if ( 'manual' === formListType ) { 976 listOptions.manual_list = options['search_suggestions_list_inline_manual']; 977 } 978 979 $( settings.inlineClass, self ).getSuggestionsList( listOptions, settings, showSpinner, false, () => { 980 let inlineItem = $( '.jet-search-suggestions__inline-area-item', self ); 981 982 if ( 0 < inlineItem.length ) { 983 inlineItem.on( 'focus', function () { 984 if ( $( this ).is( ':focus-visible' ) ) { 985 self.hideList(); 986 } 987 } ); 988 } 989 990 inlineItem.on( 'keydown', function( e ) { 991 const keyCode = e.keyCode || e.which; 992 993 let value = $( this ).attr( 'aria-label' ); 994 995 if ( ! value ) { 996 return; 997 } 998 999 value = value.trim(); 1000 1001 if ( 13 === keyCode ) { 1002 $( settings.inputClass, self )[0].value = value; 1003 1004 JetSearch.setFormSuggestion( value, form, customResultUrl ); 1005 } 1006 } ); 1007 } ); 1008 } 1009 1010 if ( '' != focusListType && ( "yes" === showfocusList || true === showfocusList ) ) { 1011 let listOptions = { 1012 list_position: 'focus', 1013 list_type: focusListType, 1014 limit: focusLimit, 1015 maxLength: options.search_suggestions_list_on_focus_item_title_length || 0, 1016 }; 1017 1018 if ( 'manual' === focusListType ) { 1019 listOptions.manual_list = options['search_suggestions_list_on_focus_manual']; 1020 } 1021 1022 $( settings.focusClass, self ).getSuggestionsList( listOptions, settings, showSpinner, false, () => { 1023 self.focusItemsNav(); 1024 } ); 1025 } 1026 } 1027 1028 self.inputChangeHandler = function( event ) { 1029 1030 let value = $( event.target ).val(), 1031 listOptions = { 1032 list_position: 'focus', 1033 value: value, 1034 limit: searchSuggestionsLimit, 1035 maxLength: options.search_suggestions_list_on_focus_item_title_length || 0, 1036 }; 1037 1038 if ( '' != value ) { 1039 focusTarget.empty(); 1040 self.showList(); 1041 JetSearch.suggestionsPreloader( showSpinner, 'show', spinner ); 1042 1043 clearTimeout( timer ); 1044 timer = setTimeout( function() { 1045 $( settings.focusClass, self ).getSuggestionsList( listOptions, settings, showSpinner, hightlightText, () => { 1046 self.focusItemsNav(); 1047 } ); 1048 }, 450 ); 1049 } else { 1050 clearTimeout( timer ); 1051 focusTarget.empty(); 1052 JetSearch.suggestionsPreloader( showSpinner, 'hide', spinner ); 1053 1054 if ( false != focusListType && ( "yes" === showfocusList || true === showfocusList ) ) { 1055 JetSearch.suggestionsPreloader( showSpinner, 'show', spinner ); 1056 1057 listOptions.limit = focusLimit; 1058 1059 if ( 'manual' === focusListType ) { 1060 listOptions.list_type = focusListType; 1061 listOptions.manual_list = options['search_suggestions_list_on_focus_manual']; 1062 } 1063 1064 $( settings.focusClass, self ).getSuggestionsList( listOptions, settings, showSpinner, false, () => { 1065 self.focusItemsNav(); 1066 } ); 1067 } 1068 } 1069 }; 1070 1071 self.hideList = function(event) { 1072 $( settings.focusClass, self ).removeClass( 'show' ); 1073 $( '.chosen-single', self ).removeClass( 'focused' ); 1074 1075 if ( focusItem && 0 < focusItem.length ) { 1076 focusItem.removeClass( 'focused' ); 1077 } 1078 }; 1079 1080 self.showList = function() { 1081 $( settings.focusClass, self ).addClass( 'show' ); 1082 }; 1083 1084 self.focusHandler = function( event ) { 1085 $( settings.searchFormClass, self ).addClass( formFocusClass ); 1086 self.showList(); 1087 }; 1088 1089 self.chosenFocusHandler = function() { 1090 self.hideList(); 1091 }; 1092 1093 self.formClick = function( event ) { 1094 event.stopPropagation(); 1095 }; 1096 1097 self.changeHandler = function( event ) { 1098 let target = $( event.target ), 1099 settingsInput = $( settings.settingsInput, self ), 1100 querySettings = JSON.parse( settingsInput.val() ), 1101 globalQuerySettings = $( self ).data( 'settings' ); 1102 1103 querySettings.category__in = target.val(); 1104 globalQuerySettings.category__in = target.val(); 1105 1106 settingsInput.val( JSON.stringify( querySettings ) ); 1107 $( self ).data( 'settings', globalQuerySettings ); 1108 1109 self.inputChangeHandler( { target: $( settings.inputClass, self ) } ) 1110 }; 1111 1112 self.formSubmit = function( event ) { 1113 let keyCode = event.keyCode || event.which; 1114 1115 if ( false === disableInputs ) { 1116 let value = event.target.value; 1117 1118 if ( 13 === keyCode && value.length != 0 ) { 1119 disableInputs = true; 1120 event.preventDefault(); 1121 1122 JetSearch.setFormSuggestion( value, form, customResultUrl ); 1123 } 1124 } 1125 1126 if ( 40 === keyCode ) {
1127 if ( focusItem && 0 < focusItem.length ) { 1128 event.preventDefault(); 1129 focusItem.removeClass( 'focused' ); 1130 focusItem.first().addClass( 'focused' ); 1131 focusItem.first().focus(); 1132 } 1133 } 1134 } 1135 1136 self.blurHandler = function( event ) { 1137 $( settings.searchFormClass, self ).removeClass( formFocusClass ); 1138 }; 1139 1140 self.clickFullResults = function( event ) { 1141 if ( false === disableInputs ) { 1142 disableInputs = true; 1143 1144 var searchInput = $( settings.inputClass, self ), 1145 value = searchInput.val(); 1146 1147 event.preventDefault(); 1148 1149 JetSearch.setFormSuggestion( value, form, customResultUrl ); 1150 } 1151 }; 1152 1153 $( settings.inputClass, self ) 1154 .on( 'input' + settings.searchClass, self.inputChangeHandler ) 1155 .on( 'focus' + settings.searchClass, self.focusHandler ) 1156 .on( 'blur' + settings.searchClass, self.blurHandler ) 1157 .on( 'keydown' + settings.searchClass, self.formSubmit ); 1158 1159 $( settings.submitClass, self ).on( 'click' + settings.searchClass, self.clickFullResults ); 1160 1161 $( self ) 1162 .on( 'click' + settings.searchClass, settings.focusItemClass, self.selectSuggestion ) 1163 .on( 'click keydown' + settings.searchClass, settings.inlineItemClass, self.selectSuggestion ) 1164 .on( 'click' + settings.searchClass, self.formClick ) 1165 .on( 'change', settings.chosenClass, self.changeHandler ) 1166 .on( 'touchend' + settings.searchClass, self.formClick ) 1167 .on( 'chosen:showing_dropdown', settings.chosenClass, self.chosenFocusHandler ); 1168 1169 $( self ).on( 'keydown', function( e ) { 1170 const keyCode = e.keyCode || e.which; 1171 1172 if ( 9 === keyCode ) { 1173 setTimeout( () => { 1174 const focusedElement = document.activeElement; 1175 1176 if ( $( focusedElement ).is( '.chosen-search-input' ) ) { 1177 $( '.chosen-single', self ).addClass( 'focused' ); 1178 } else { 1179 $( '.chosen-single', self ).removeClass( 'focused' ); 1180 } 1181 1182 if ( $( focusedElement ).is( '.jet-search-suggestions__inline-area-item' ) ) { 1183 self.hideList(); 1184 } 1185 }, 50 ); 1186 } 1187 } ); 1188 1189 $( settings.inputClass, self ).on( 'click' + settings.searchClass, () => { 1190 $( '.chosen-single', self ).removeClass( 'focused' ); 1191 } ); 1192 1193 $( 'body' ) 1194 .on( 'click' + settings.searchClass, self.hideList ) 1195 .on( 'touchend' + settings.searchClass, self.hideList ); 1196 1197 // If after reloading the page the value of the select is not '0'. 1198 if ( '0' !== $( settings.chosenClass, self ).val() ) { 1199 $( settings.chosenClass, self ).trigger( 'change' ); 1200 } 1201 } 1202 }; 1203 1204 /** 1205 * JetAjaxSearch jQuery Plugin 1206 * 1207 * @param args 1208 */ 1209 $.fn.jetAjaxSearch = function( args ) { 1210 1211 var self = this[0], 1212 settings = args, 1213 timer = null, 1214 itemTemplate = null, 1215 resultsArea = $( settings.resultsAreaClass, self ), 1216 resultsHolder = $( settings.listHolderClass, resultsArea ), 1217 resultsHeader = $( settings.resultsHeaderClass, resultsArea ), 1218 resultsFooter = $( settings.resultsFooterClass, resultsArea ), 1219 countHolder = $( settings.countClass, resultsArea ), 1220 fullResults = $( settings.fullResultsClass, resultsArea ), 1221 resultsList = $( settings.listClass, resultsArea ), 1222 resultsListInner = $( settings.listInnerClass, resultsArea ), 1223 resultsHeaderNav = $( settings.navigationClass, resultsHeader ), 1224 resultsFooterNav = $( settings.navigationClass, resultsFooter ), 1225 messageHolder = $( settings.messageHolderClass, resultsArea ), 1226 spinner = $( settings.spinnerClass, resultsArea ), 1227 form = $( settings.searchFormClass, self ), 1228 resultsSuggestions = $( settings.resultsSuggestionsAreaClass, self ), 1229 inlineSuggestions = $( settings.inlineSuggestionsAreaClass, self ), 1230 data = $( self ).data( 'settings' ) || [], 1231 customResultUrl = data['search_results_url'] || '', 1232 hightlightText = data['highlight_searched_text'] || '', 1233 formFocusClass = settings.searchFormClass.replace( '.', '' ) + '--focus', 1234 searchLogging = data['search_logging'] || '', 1235 currentPosition = 1, 1236 lang = '', 1237 disableInputs = false, 1238 allowEmptyString = false, 1239 allowSubmitOnEnter = 1,
1240 urlParams = JetSearch.getUrlParams(), 1241 listingID = data['listing_id'] || '', 1242 categoryIndex = urlParams.jet_ajax_search_categories || '', 1243 getResultsOnFocus = true, 1244 maxUserSearches = 20, 1245 showSearchSuggestions = data['show_search_suggestions'] || false, 1246 suggestionsTitle = '', 1247 suggestionsType = data['search_suggestions_source'] || false, 1248 suggestionsPosition = data['search_suggestions_position'] || false, 1249 searchSuggestionsLimits = data['search_suggestions_limits'] || 20, 1250 storedUserSearches = JSON.parse( localStorage.getItem('jetUserSearches') ) || [], 1251 suggestionsList = []; 1252 1253 if ( 'yes' === data.search_by_empty_value || true === data.search_by_empty_value ) { 1254 allowEmptyString = true; 1255 } 1256 1257 if ( !self.isInit ) { 1258 self.isInit = true; 1259 1260 /** 1261 * Ajax request instance 1262 */ 1263 self.ajaxRequest = null; 1264 1265 self.suggestionsListLoaded = false; 1266 1267 if ( data.hasOwnProperty('lang') ) { 1268 lang = data.lang; 1269 delete data.lang; 1270 } 1271 1272 /** 1273 * Ajax settings from localized global variable 1274 */ 1275 self.ajaxSettings = window[ settings.handlerId ] || {}; 1276 self.suggestionsSettings = window['jetSearchSettings']['searchSuggestions'] || {}; 1277 1278 if ( self.ajaxSettings['ajaxSearchSuggestionsLimits'] ) { 1279 maxUserSearches = self.ajaxSettings['ajaxSearchSuggestionsLimits']; 1280 } 1281 1282 if ( 'yes' === data.submit_on_enter || true === data.submit_on_enter ) { 1283 allowSubmitOnEnter = false; 1284 } else { 1285 allowSubmitOnEnter = true; 1286 } 1287 1288 if ( '' === self.ajaxSettings.sumbitOnEnter ) { 1289 allowSubmitOnEnter = false; 1290 } 1291 1292 if ( window.elementorFrontend ) { 1293 var editMode = Boolean( window.elementorFrontend.isEditMode() ) 1294 } else { 1295 var editMode = false; 1296 } 1297 1298 self.suggestionsListHTML = function( suggestionsList ) { 1299 1300 let resultsSuggestionsTemplate = wp.template('jet-ajax-search-results-suggestion-item'), 1301 inlineSuggestionsTemplate = wp.template('jet-ajax-search-inline-suggestion-item'), 1302 inlineOutputHtml = '', 1303 resultsOutputHtml = ''; 1304 1305 1306 suggestionsList.forEach( item => { 1307 let inlineListItemHtml = '', 1308 resultsListItemHtml = '', 1309 maxLength = data.search_suggestions_item_title_length || 0, 1310 suggestionItem = {}; 1311 1312 suggestionItem['fullName'] = JetSearch.escapeHTML( item ); 1313 suggestionItem['name'] = JetSearch.escapeHTML( item ); 1314 1315 if ( 0 < maxLength ) { 1316 suggestionItem['name'] = JetSearch.trimString( suggestionItem['name'], maxLength ); 1317 } 1318 1319 if ( 'under_form' === suggestionsPosition ) { 1320 inlineListItemHtml = inlineSuggestionsTemplate( suggestionItem ); 1321 } else if ( 'inside_results_area' === suggestionsPosition ) { 1322 resultsListItemHtml = resultsSuggestionsTemplate( suggestionItem ); 1323 } 1324 1325 inlineOutputHtml += inlineListItemHtml; 1326 resultsOutputHtml += resultsListItemHtml; 1327 } ); 1328 1329 if ( 'under_form' === suggestionsPosition ) { 1330 suggestionsTitle = inlineSuggestions.html(); 1331 1332 inlineSuggestions.html( inlineOutputHtml ).prepend( suggestionsTitle ); 1333 } else if ( 'inside_results_area' === suggestionsPosition ) { 1334 suggestionsTitle = resultsSuggestions.html(); 1335 1336 resultsSuggestions.html( resultsOutputHtml ).prepend( suggestionsTitle ); 1337 } 1338 }; 1339 1340 self.showSuggestions = function() { 1341 1342 if ( suggestionsType ) { 1343 if ( 'popular' === suggestionsType ) { 1344 1345 if ( false === window.bricksIsFrontend ) { 1346 1347 let sendData = { 1348 list_type: 'popular', 1349 value: '', 1350 limit: searchSuggestionsLimits 1351 }, 1352 ajaxData = { 1353 action: self.ajaxSettings['searchSuggestions'].get_action, 1354 data: sendData || {}, 1355 }; 1356 1357 $.ajax( { 1358 type: 'GET', 1359 url: self.ajaxSettings['searchSuggestions'].get_suggestions_rest_api_url, 1360 data: ajaxData, 1361 dataType: 'json', 1362 cache: false, 1363 processData: true, 1364 error: function( jqXHR, textStatus, errorThrown ) { 1365 errorCallback( jqXHR ); 1366 }, 1367 success: function( response, textStatus, jqXHR ) { 1368 if ( response.length ) { 1369 suggestionsList = $.map( response, function( obj ) { 1370 return obj.name; 1371 } ); 1372 1373 self.suggestionsListLoaded = true; 1374 1375 if ( suggestionsList.length ) { 1376 suggestionsList = suggestionsList.slice( 0, searchSuggestionsLimits ); 1377 1378 self.suggestionsListHTML( suggestionsList ); 1379 } else { 1380 resultsSuggestions.hide(); 1381 inlineSuggestions.hide(); 1382 } 1383 } 1384 } 1385 } ); 1386 } else { 1387 suggestionsList = self.ajaxSettings['ajaxSearchPopularSuggestions'] || []; 1388 1389 if ( suggestionsList.length ) { 1390 suggestionsList = suggestionsList.slice( 0, searchSuggestionsLimits ); 1391 1392 self.suggestionsListHTML( suggestionsList ); 1393 } else { 1394 resultsSuggestions.hide(); 1395 inlineSuggestions.hide(); 1396 } 1397 } 1398 } else if ( 'user' === suggestionsType ) { 1399 let userSearches = localStorage.getItem('jetUserSearches'); 1400 1401 if ( userSearches ) { 1402 suggestionsList = JSON.parse( userSearches ) || []; 1403 1404 suggestionsList.reverse(); 1405 1406 suggestionsList = suggestionsList.slice( 0, searchSuggestionsLimits ); 1407 1408 self.suggestionsListHTML( suggestionsList ); 1409 } else { 1410 resultsSuggestions.hide(); 1411 inlineSuggestions.hide(); 1412 } 1413 } 1414 } 1415 }; 1416 1417 if ( 'yes' === showSearchSuggestions || true === showSearchSuggestions ) { 1418 self.showSuggestions(); 1419 } 1420 1421 self.inputChangeHandler = function( event ) { 1422 var value = $( event.target ).val(), 1423 symbolNumberForStart = 'number' === $.type( data.symbols_for_start_searching ) ? data.symbols_for_start_searching : 2; 1424 1425 value = value.replace(/\u3000/g, ' '); 1426 1427 if ( 'number' === $.type( symbolNumberForStart ) && symbolNumberForStart > value.length ) { 1428 if ( 'inside_results_area' === suggestionsPosition && suggestionsList.length ) { 1429 resultsHeader.hide(); 1430 resultsFooter.hide(); 1431 resultsList.hide(); 1432 resultsSuggestions.show(); 1433 resultsSuggestions.addClass( 'active' ); 1434 resultsHolder.addClass( 'show' ); 1435 self.showList(); 1436 } else { 1437 self.hideList(); 1438 } 1439 1440 return false;
1441 } 1442 1443 if ( 'inside_results_area' === suggestionsPosition && suggestionsList.length ) { 1444 resultsSuggestions.removeClass( 'active' ); 1445 resultsHeader.show(); 1446 resultsFooter.show(); 1447 resultsList.show(); 1448 } 1449 1450 resultsHolder.removeClass( 'show' ); 1451 self.outputMessage( '', '' ); 1452 resultsListInner.css( 'transform', 'translateX(0)' ); 1453 resultsList.css( 'height', 'auto' ); 1454 1455 if ( value ) { 1456 self.showList(); 1457 spinner.addClass( 'show' ); 1458 1459 clearTimeout( timer ); 1460 timer = setTimeout( function() { 1461 data.value = value; 1462 data.deviceMode = window.elementorFrontend && window.elementorFrontend.getCurrentDeviceMode() ? window.elementorFrontend.getCurrentDeviceMode() : JetSearch.getCurrentDeviceMode(); 1463 self.ajaxSendData( data, lang ); 1464 }, 450 ); 1465 } else { 1466 self.hideList(); 1467 } 1468 }; 1469 1470 self.successCallback = function( response ) { 1471 1472 if ( response.error ) { 1473 spinner.removeClass( 'show' ); 1474 self.outputMessage( data.server_error, 'error show' ); 1475 return; 1476 } 1477 1478 JetSearch.enqueueAssetsFromResponse( response ); 1479 1480 var responseData = response.data, 1481 error = responseData.error, 1482 message = responseData.message, 1483 posts = responseData.posts, 1484 listingItems = responseData.listing_items, 1485 post = null, 1486 outputHtml = '', 1487 listItemHtml = '', 1488 listHtml = '<div class="' + settings.listSlideClass.replace( '.', '' ) + '">%s</div>', 1489 searchSources = responseData.sources, 1490 searchSourcesBeforePosts = null, 1491 searchSourcesAfterPosts = null, 1492 countAllResults = null, 1493 searchSourcesHolder = $( '.jet-ajax-search__source-results-holder', self ); 1494 1495 resultsHolder.removeClass( 'show' ); 1496 spinner.removeClass( 'show' ); 1497 currentPosition = 1; 1498 1499 searchSourcesHolder.remove(); 1500 1501 resultsListInner.html( '' ); 1502 resultsHeaderNav.html( '' ); 1503 resultsFooterNav.html( '' ); 1504 1505 searchSourcesBeforePosts = searchSources 1506 .filter( item => item.priority < 0 && '' != item.content ) 1507 .sort( ( a, b ) => a.priority - b.priority ); 1508 1509 searchSourcesAfterPosts = searchSources 1510 .filter( item => item.priority > 0 && '' != item.content ) 1511 .sort( ( a, b ) => a.priority - b.priority ); 1512 1513 if ( '' != listingID && 0 !== responseData.post_count && !error ) { 1514 var outputHtml = '', 1515 listItemHtml = '', 1516 listHtml = '<div class="jet-listing-grid__items jet-listing-base ' + settings.listSlideClass.replace( '.', '' ) + '">%s</div>'; 1517 1518 if ( listingItems.length ) { 1519 $.each( listingItems, ( i, item ) => { 1520 listItemHtml += item; 1521 1522 if ( ( parseInt( i ) + 1 ) % responseData.limit_query == 0 || parseInt( i ) === listingItems.length - 1 ) { 1523 outputHtml += listHtml.replace( '%s', listItemHtml ); 1524 listItemHtml = ''; 1525 } 1526 } ); 1527 } 1528 1529 messageHolder.removeClass( 'show' ); 1530 1531 countAllResults = responseData.post_count; 1532 1533 if ( responseData.sources_results_count && 0 < responseData.sources_results_count ) { 1534 countAllResults += responseData.sources_results_count; 1535 } 1536 1537 $( 'span', countHolder ).html( countAllResults ); 1538 resultsListInner 1539 .html( outputHtml ) 1540 .data( 'columns', responseData.columns ); 1541 1542 Promise.all( JetSearch.assetsPromises ).then( function() { 1543 JetSearch.initElementsHandlers( resultsListInner ); 1544 JetSearch.reinitBricksScripts( self ); 1545 JetSearch.assetsPromises = []; 1546 } ); 1547 1548 resultsHeaderNav.html( responseData.results_navigation.in_header ); 1549 resultsFooterNav.html( responseData.results_navigation.in_footer ); 1550 1551 if ( !countHolder[0] && !responseData.results_navigation.in_header ) { 1552 resultsHeader.addClass( 'is-empty' ); 1553 } else { 1554 resultsHeader.removeClass( 'is-empty' ); 1555 } 1556 1557 if ( !fullResults[0] && !responseData.results_navigation.in_footer ) { 1558 resultsFooter.addClass( 'is-empty' ); 1559 } else { 1560 resultsFooter.removeClass( 'is-empty' ); 1561 } 1562 1563 resultsList.css( 'height', 'auto' ); 1564 1565 $( document ).trigger( 'jet-ajax-search/show-results/listing', [ resultsListInner ] ); 1566 1567 resultsHolder.addClass( 'show' ); 1568 1569 if ( 'yes' === searchLogging || true === searchLogging ) { 1570 let itemWrapper = settings.itemClass, 1571 itemLink = $( '.jet-engine-listing-overlay-wrap', itemWrapper ), 1572 itemTitle = '.jet-ajax-search-item-title .jet-listing-dynamic-field__content', 1573 itemUrlAttr = 'data-url'; 1574 1575 $( document ).trigger( 'jet-ajax-search/results-area/listing-ad
1575d-suggestion', [ self, itemWrapper, itemLink, itemTitle, itemUrlAttr ] ); 1576 1577 JetSearch.addSuggestionFromResultAreaItem( itemWrapper, itemLink, itemTitle, itemUrlAttr ); 1578 } 1579 } 1580 1581 const allowedHighlightFields = [ 'title', 'after_content', 'after_title', 'before_content', 'before_title', 'content', 'price' ]; 1582 1583 function highlightMatches( item ) { 1584 let searched = responseData.search_value.trim(); 1585 1586 if ( searched !== "" ) { 1587 let reg = new RegExp("[\>][^\<]*"+searched+"[^\<]*[\<]","gi"), 1588 reg2 = new RegExp( searched, "gi" ), 1589 regHtml = new RegExp("<\/?[a-z](.*?)[\s\S]*>", "gi"); 1590 1591 if ( reg.test( item ) ) { 1592 item = item.replace( reg, function( item ) { 1593 let subRegex = new RegExp( searched, "gi" ); 1594 return item.replace( subRegex,`<mark>${searched}</mark>` ); 1595 } ); 1596 } 1597 1598 if ( regHtml.test( item ) ) { 1599 return item; 1600 } else { 1601 item = item.replace( reg2, str => `<mark>${str}</mark>` ); 1602 } 1603 } 1604 1605 return item; 1606 } 1607 1608 function highlightFields( fields, allowHighlightFields ) { 1609 1610 $.each( fields, function( key, value ) { 1611 if ( -1 != $.inArray( key, allowHighlightFields ) && ( null != value && '' != value ) ) { 1612 fields[key] = highlightMatches( value ); 1613 } 1614 } ); 1615 1616 return fields; 1617 } 1618 1619 if ( 0 !== responseData.post_count && !error && '' === listingID) { 1620 1621 messageHolder.removeClass( 'show' ); 1622 itemTemplate = wp.template( 'jet-ajax-search-results-item' ); 1623 1624 for ( post in posts ) { 1625 if ( responseData.search_highlight && true === responseData.search_highlight ) { 1626 if ( '' != hightlightText && ( "yes" === hightlightText || true === hightlightText ) ) { 1627 highlightFields( posts[post], allowedHighlightFields ); 1628 } 1629 } 1630 1631 if ( posts[post].is_product ) { 1632 let productType = posts[post].product_type, 1633 productTypeClass = 'add-to-cart-button'; 1634 1635 if ( 'product_type_variable' === productType ) { 1636 productTypeClass = 'select-options-button'; 1637 } 1638 1639 posts[post].add_to_cart = '<div class="jet-ajax-search__item-add-to-cart"><button data-quantity="1" class="jet-ajax-search__results-item-cart-button ' + productTypeClass + '" data-product_id="' + posts[post].product_id + '" data-product_sku="' + posts[post].product_sku + '" aria-label="' + posts[post].product_label + '" data-product_url="' + posts[post].product_url + '" rel="nofollow" target="_blank">' + posts[post].product_add_text + '</button></div>'; 1640 } 1641 1642 let templateResult = itemTemplate( posts[post] ); 1643 1644 listItemHtml += templateResult; 1645 1646 if ( (parseInt( post ) + 1) % responseData.limit_query == 0 || parseInt( post ) === posts.length - 1 ) { 1647 outputHtml += listHtml.replace( '%s', listItemHtml ); 1648 listItemHtml = ''; 1649 } 1650 } 1651 1652 countAllResults = responseData.post_count; 1653 1654 if ( responseData.sources_results_count && 0 < responseData.sources_results_count ) { 1655 countAllResults += responseData.sources_results_count; 1656 } 1657 1658 $( 'span', countHolder ).html( countAllResults ); 1659 resultsListInner 1660 .html( outputHtml ) 1661 .data( 'columns', responseData.columns ); 1662 1663 $( '.jet-ajax-search__results-item-cart-button.add-to-cart-button', self ).on( 'click', function( e ) { 1664 e.preventDefault(); 1665 1666 let _this = $( this); 1667 1668 if ( _this.attr( 'data-product_id' ) ) { 1669 let addToCartData = {}; 1670 1671 $.each( _this[0].dataset, function( key, value ) { 1672 addToCartData[ key ] = value; 1673 } ); 1674 1675 _this.prop( 'disabled', true ); 1676 1677 $.ajax( { 1678 type: 'POST', 1679 url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'add_to_cart' ), 1680 dataType: 'json', 1681 data: addToCartData, 1682 success: function( response ) { 1683 $( document.body ).trigger( 'wc_fragment_refresh' ); 1684 $( document.body ).trigger( 'added_to_cart' ); 1685 1686 _this.prop( 'disabled', false ); 1687 }, 1688 error: function(xhr, status, error) { 1689 _this.prop( 'disabled', false ); 1690 } 1691 } ); 1692 } 1693 } ); 1694 1695 $( '.jet-ajax-search__results-item-cart-button.select-options-button', self ).on( 'click', function( e ) { 1696 e.preventDefault(); 1697 1698 const productUrl = $( this ).data( 'product_url' ); 1699 1700 window.open( productUrl, '_blank' ); 1701 } ); 1702 1703 resultsHeaderNav.html( responseData.results_navigation.in_header ); 1704 resultsFooterNav.html( responseData.results_navigation.in_footer ); 1705 1706 if ( !countHolder[0] && !responseData.results_navigation.in_header ) { 1707 resultsHeader.addClass( 'is-empty' ); 1708 } else { 1709 resultsHeader.removeClass( 'is-empty' ); 1710 } 1711 1712 if ( !fullResults[0] && !responseData.results_navigation.in_footer ) { 1713 resultsFooter.addClass( 'is-empty' ); 1714 } else { 1715 resultsFooter.removeClass( 'is-empty' ); 1716 } 1717 1718 resultsHolder.addClass( 'show' ); 1719 1720 $( document ).trigger( 'jet-ajax-search/show-results', [ resultsHolder ] ); 1721 1722 var inputField = $( '.jet-ajax-search__field', self ), 1723 resultsItem = $( '.jet-ajax-search__item-link', self ), 1724 focusedItem = resultsItem.filter( ':focus' ); 1725 1726 inputField.on( 'keydown', function( e ) {
1727 const keyCode = e.keyCode || e.which; 1728 1729 if ( 40 === keyCode ) { // Down arrow 1730 e.preventDefault(); 1731 1732 var position = currentPosition - 1, 1733 activeSlide = $( settings.listSlideClass, resultsListInner ).eq( position ), 1734 next = activeSlide.find( '.jet-ajax-search__item-link' ).first(); 1735 1736 if ( focusedItem.length === 0 ) { 1737 setTimeout( () => { 1738 resultsItem.removeClass( 'focused' ); 1739 next.addClass( 'focused' ); 1740 next.focus(); 1741 }, 0 ); 1742 } 1743 } 1744 } ); 1745 1746 resultsItem.on( 'keydown', function( e ) { 1747 const keyCode = e.keyCode || e.which; 1748 1749 switch ( keyCode ) { 1750 case 40: // Down arrow 1751 e.preventDefault(); 1752 1753 var next = $( this ).parent().next().find( '.jet-ajax-search__item-link' ).first(); 1754 1755 if ( 0 < next.length ) { 1756 resultsItem.removeClass( 'focused' ); 1757 next.addClass( 'focused' ); 1758 next.focus(); 1759 } 1760 break; 1761 1762 case 38: // Up arrow 1763 e.preventDefault(); 1764 1765 var prev = $( this ).parent().prev().find( '.jet-ajax-search__item-link' ).first(); 1766 1767 if ( 0 < prev.length ) { 1768 resultsItem.removeClass( 'focused' ); 1769 prev.addClass( 'focused' ); 1770 prev.focus(); 1771 } else { 1772 resultsItem.removeClass( 'focused' ); 1773 inputField.focus(); 1774 } 1775 break; 1776 1777 case 37: // Left arrow 1778 var prevSlide = $( this ).closest( '.jet-ajax-search__results-slide' ).prev(); 1779 1780 if ( 0 < prevSlide.length ) { 1781 1782 $( settings.prevClass + ':not( ' + settings.disableNavClass + ' )' ).click(); 1783 1784 resultsItem.removeClass( 'focused' ); 1785 1786 setTimeout( () => { 1787 $( settings.listSlideClass, resultsListInner ).eq( currentPosition - 1 ).find( '.jet-ajax-search__item-link' ).first().focus().addClass( 'focused' ); 1788 }, 350 ); 1789 } 1790 break; 1791 1792 case 39: // Right arrow 1793 var nextSlide = $( this ).closest( '.jet-ajax-search__results-slide' ).next(); 1794 1795 if ( 0 < nextSlide.length ) { 1796 1797 $( settings.nextClass + ':not( ' + settings.disableNavClass + ' )' ).click(); 1798 1799 resultsItem.removeClass( 'focused' ); 1800 1801 setTimeout( () => { 1802 $( settings.listSlideClass, resultsListInner ).eq( currentPosition - 1 ).find( '.jet-ajax-search__item-link' ).first().focus().addClass( 'focused' ); 1803 }, 350 ); 1804 } 1805 break; 1806 case 9: 1807 resultsItem.removeClass( 'focused' ); 1808 break; 1809 } 1810 } ); 1811 1812 if ( 'yes' === searchLogging || true === searchLogging ) { 1813 let itemWrapper = settings.itemClass, 1814 resultAreaItemLink = $( '.jet-ajax-search__item-link', itemWrapper ), 1815 resultAreaItemTitle = '.jet-ajax-search__item-title', 1816 resultAreaItemUrlAttr = 'href'; 1817 1818 JetSearch.addSuggestionFromResultAreaItem( itemWrapper, resultAreaItemLink, resultAreaItemTitle, resultAreaItemUrlAttr ); 1819 } 1820 1821 searchSourcesBeforePosts.forEach( function( item ) { 1822 self.maybeHasListing( item ); 1823 1824 resultsListInner.before( item.content ); 1825 resultsHolder.addClass( 'show' ); 1826 } ); 1827 1828 searchSourcesAfterPosts.forEach( function( item ) { 1829 self.maybeHasListing( item ); 1830 1831 resultsListInner.after( item.content ); 1832 resultsHolder.addClass( 'show' ); 1833 } ); 1834 } else { 1835 1836 if ( searchSourcesBeforePosts.length || searchSourcesAfterPosts.length ) { 1837 searchSourcesBeforePosts.forEach( function( item ) { 1838 self.maybeHasListing( item ); 1839 1840 resultsListInner.before( item.content ); 1841 resultsHolder.addClass( 'show' ); 1842 } ); 1843 1844 searchSourcesAfterPosts.forEach( function( item ) { 1845 self.maybeHasListing( item ); 1846 1847 resultsListInner.after( item.content ); 1848 resultsHolder.addClass( 'show' ); 1849 } ); 1850 1851 countAllResults = responseData.post_count; 1852 1853 if ( responseData.sources_results_count && 0 < responseData.sources_results_count ) { 1854 countAllResults += responseData.sources_results_count; 1855 } 1856 1857 $( 'span', countHolder ).html( countAllResults ); 1858 1859 } else { 1860 self.outputMessage( message, 'show' ); 1861 } 1862 } 1863 }; 1864 1865 self.maybeHasListing = function( item ) { 1866 if ( typeof item.listing_template !== 'undefined' && true === item.listing_template ) { 1867 Promise.all( JetSearch.assetsPromises ).then( function() { 1868 JetSearch.initElementsHandlers( resultsListInner ); 1869 JetSearch.reinitBricksScripts( self ); 1870 JetSearch.assetsPromises = []; 1871 } ); 1872 } 1873 } 1874 1875 self.errorCallback = function( jqXHR ) { 1876 if ( 'abort' !== jqXHR.statusText ) { 1877 spinner.removeClass( 'show' ); 1878 self.outputMessage( data.server_error, 'error show' ); 1879 } 1880 }; 1881 1882 self.ajaxSendData = function( sendData, lang = '' ) { 1883 let filteredData = {}; 1884 1885 Object.keys( sendData ).forEach( key => { 1886 if ( 1887 sendData[key] !== '' && 1888 sendData[key] !== null && 1889 sendData[key] !== undefined && 1890 !( Array.isArray( sendData[key] ) && sendData[key].length === 0 ) 1891 ) { 1892 filteredData[key] = sendData[key]; 1893 } 1894 } ); 1895 1896 var ajaxData = { 1897 action: self.ajaxSettings.action, 1898 nonce: self.ajaxSettings.nonce, 1899 data: filteredData || {} 1900 }; 1901
1902 if ( '' != lang ) { 1903 ajaxData.lang = lang; 1904 } 1905 1906 const isRestAPI = self.ajaxSettings.rest_api_url && self.ajaxSettings.rest_api_url.includes( '/wp-json/' ); 1907 1908 self.ajaxRequest = jQuery.ajax( { 1909 type: 'GET', 1910 url: self.ajaxSettings.rest_api_url, 1911 data: ajaxData, 1912 dataType: 'json', 1913 cache: false, 1914 processData: true, 1915 beforeSend: function( jqXHR, ajaxSettings ) { 1916 1917 if ( null !== self.ajaxRequest ) { 1918 self.ajaxRequest.abort(); 1919 } 1920 1921 if ( isRestAPI ) { 1922 jqXHR.setRequestHeader( 'X-WP-Nonce', self.ajaxSettings.nonce ); 1923 } 1924 1925 }, 1926 error: function( jqXHR, textStatus, errorThrown ) { 1927 self.errorCallback( jqXHR ); 1928 }, 1929 success: function( response, textStatus, jqXHR ) { 1930 self.successCallback( response ); 1931 } 1932 } ); 1933 }; 1934 1935 self.hideList = function() { 1936 resultsArea.removeClass( 'show' ); 1937 $( '.chosen-single', self ).removeClass( 'focused' ); 1938 }; 1939 1940 self.showList = function() { 1941 resultsArea.addClass( 'show' ); 1942 }; 1943 1944 self.focusHandler = function( event ) { 1945 var value = event.target.value, 1946 symbolNumberForStart = 'number' === $.type( data.symbols_for_start_searching ) ? data.symbols_for_start_searching : 2; 1947 1948 $( settings.searchFormClass, self ).addClass( formFocusClass ); 1949 1950 if ( 'inside_results_area' === suggestionsPosition && suggestionsList.length ) { 1951 if ( value && getResultsOnFocus ) { 1952 spinner.addClass( 'show' ); 1953 1954 data.value = value; 1955 data.deviceMode = window.elementorFrontend && window.elementorFrontend.getCurrentDeviceMode() ? window.elementorFrontend.getCurrentDeviceMode() : JetSearch.getCurrentDeviceMode(); 1956 1957 self.ajaxSendData( data, lang ); 1958 1959 getResultsOnFocus = false; 1960 } 1961 1962 if ( '' === value ) { 1963 resultsHeader.hide(); 1964 resultsFooter.hide(); 1965 resultsList.hide(); 1966 resultsSuggestions.addClass( 'active' ); 1967 resultsHolder.addClass( 'show' ); 1968 self.showList(); 1969 } 1970 } 1971 1972 if ( 'number' === $.type( symbolNumberForStart ) && symbolNumberForStart > value.length ) { 1973 return; 1974 } 1975 1976 self.showList(); 1977 }; 1978 1979 self.blurHandler = function( event ) { 1980 $( settings.searchFormClass, self ).removeClass( formFocusClass ); 1981 }; 1982 1983 self.outputMessage = function( message, messageClass ) { 1984 message = message.replace( /\\/g, '' ); // remove slashes 1985 //message = $( "<div/>" ).html( message ).text(); 1986 message = message.replace( /\\*"/g, '' ); 1987 messageHolder.removeClass( 'error show' ).addClass( messageClass ).html( message ); 1988 }; 1989 1990 self.formClick = function( event ) { 1991 event.stopPropagation(); 1992 }; 1993 1994 self.clickFullResults = function( event ) { 1995 1996 var searchInput = $( settings.inputClass, self ), 1997 value = searchInput.val(), 1998 url = JetSearch.getResultsUrl( form ); 1999 2000 event.preventDefault(); 2001 2002 if ( value.length != 0 || true === allowEmptyString ) { 2003 if ( false === disableInputs ) { 2004 disableInputs = true; 2005 2006 value = value.replace(/\u3000/g, ' '); 2007 2008 searchInput.val( value ); 2009 2010 if ( '' != customResultUrl ) { 2011 customResultUrl = $.trim( customResultUrl ); 2012 2013 url = JetSearch.getResultsUrl( form, customResultUrl ); 2014 } 2015 2016 if ( 'yes' === showSearchSuggestions || true === showSearchSuggestions ) { 2017 self.addUserSearch( value ); 2018 } 2019 2020 if ( 'yes' === searchLogging || true === searchLogging ) { 2021 JetSearch.setFormSuggestion( value, form, url ); 2022 } else { 2023 window.location.href = url; 2024 } 2025 } 2026 } 2027 }; 2028 2029 self.changeSlide = function( number ) { 2030 var currentSlide = $( settings.listSlideClass, resultsListInner ).eq( number ), 2031 direction = settings.isRtl ? 1 : -1, 2032 position = number * 100 * direction; 2033 2034 currentSlide.scrollTop( 0 ); 2035 resultsListInner.css( 'transform', 'translateX(' + position + '%)' ); 2036 resultsList.css( 'height', 'auto' ); 2037 }; 2038 2039 self.clickBulletHandler = function( event ) { 2040 var target = $( event.target ); 2041 2042 currentPosition = target.data( 'number' ); 2043 self.syncNavigation(); 2044 2045 self.changeSlide( currentPosition - 1 ); 2046 }; 2047 2048 self.clickNavigationButtonHandler = function( event ) { 2049 var target = $( event.target ), 2050 direction = target.data( 'direction' ); 2051 2052 currentPosition = currentPosition + direction; 2053 self.syncNavigation(); 2054 2055 self.changeSlide( currentPosition - 1 ); 2056 }; 2057 2058 self.syncNavigation = function() { 2059 var lastPosition = resultsListInner.data( 'columns' ), 2060 disableClass = settings.disableNavClass.replace( '.', '' ), 2061 activeClass = settings.activeNavClass.replace( '.', '' ); 2062 2063 $( settings.activeNavClass, self ).removeClass( activeClass ); 2064 $( settings.disableNavClass, self ).removeClass( disableClass ); 2065 2066 $( settings.navButtonClass + '[data-number="' + currentPosition +'"]', self ).addClass( activeClass ); 2067 2068 if ( 1 === currentPosition ) { 2069 $( settings.prevClass, self ).addClass( disableClass ); 2070 } 2071 2072 if ( lastPosition === currentPosition ) { 2073 $( settings.nextClass, self ).addClass( disableClass ); 2074 } 2075 }; 2076 2077 self.formSubmit = function( event ) { 2078 var value = event.target.value, 2079 url = JetSearch.getResultsUrl( form ); 2080 2081 if ( ( 1 > value.length && false === allowEmptyString ) && ( 13 === event.keyCode || 'click' === event.type ) ) { 2082 return false;
2083 } else { 2084 if ( 13 === event.keyCode && allowSubmitOnEnter ) { 2085 if ( false === disableInputs ) { 2086 disableInputs = true; 2087 2088 event.preventDefault(); 2089 2090 if ( '' != customResultUrl ) { 2091 customResultUrl = $.trim( customResultUrl ); 2092 2093 url = JetSearch.getResultsUrl( form, customResultUrl ); 2094 } 2095 2096 self.addUserSearch( value ); 2097 2098 if ( 'yes' === searchLogging || true === searchLogging ) { 2099 JetSearch.setFormSuggestion( value, form, url ); 2100 } else { 2101 window.location.href = url; 2102 } 2103 } 2104 } 2105 } 2106 }; 2107 2108 self.changeHandler = function( event ) { 2109 var target = $( event.target ), 2110 globalQuerySettings = $( self ).data( 'settings' ); 2111 2112 globalQuerySettings.category__in = target.val(); 2113 data.category__in = target.val(); 2114 2115 $( self ).data( 'settings', globalQuerySettings ); 2116 2117 self.inputChangeHandler( { target: $( settings.inputClass, self ) } ) 2118 }; 2119 2120 self.chosenFocusHandler = function() { 2121 self.hideList(); 2122 }; 2123 2124 self.setResultsAreaWidth = function() { 2125 2126 if ( 'fields_holder' !== data.results_area_width_by ) { 2127 return; 2128 } 2129 2130 resultsArea.css( 'width', $( settings.fieldsHolderClass, self ).outerWidth() ); 2131 }; 2132 2133 self.addUserSearch = function( newSearchRequest ) { 2134 if ( 'user' === suggestionsType ) { 2135 newSearchRequest = newSearchRequest.trim(); 2136 2137 if ( ! storedUserSearches.some( search => search === newSearchRequest ) ) { 2138 if ( storedUserSearches.length >= maxUserSearches ) { 2139 storedUserSearches.shift(); 2140 } 2141 2142 storedUserSearches.push( newSearchRequest ); 2143 2144 localStorage.setItem( 'jetUserSearches', JSON.stringify( storedUserSearches ) ); 2145 } 2146 } 2147 } 2148 2149 self.selectSuggestion = function( event ) { 2150 const keyCode = event.keyCode || event.which; 2151 const $target = $( event.currentTarget ); 2152 2153 let value = $target.attr( 'aria-label' ); 2154 2155 if ( ! value ) { 2156 return; 2157 } 2158 2159 value = value.trim(); 2160 2161 let url = null; 2162 2163 if ( false === disableInputs && !editMode ) { 2164 2165 if ( 'keydown' === event.type ) { 2166 if ( 13 === keyCode ) { 2167 disableInputs = true; 2168 2169 $( settings.inputClass, self )[0].value = value; 2170 2171 self.addUserSearch( value ); 2172 2173 url = JetSearch.getResultsUrl( form ); 2174 2175 if ( '' != customResultUrl ) { 2176 customResultUrl = $.trim( customResultUrl ); 2177 2178 url = JetSearch.getResultsUrl( form, customResultUrl ); 2179 } 2180 2181 if ( 'yes' === searchLogging || true === searchLogging ) { 2182 JetSearch.setFormSuggestion( value, false, url ); 2183 } else { 2184 window.location.href = url; 2185 } 2186 } 2187 } else if ( 'click' === event.type ) { 2188 disableInputs = true; 2189 2190 $( settings.inputClass, self )[0].value = value; 2191 2192 self.addUserSearch( value ); 2193 2194 url = JetSearch.getResultsUrl( form ); 2195 2196 if ( '' != customResultUrl ) { 2197 customResultUrl = $.trim( customResultUrl ); 2198 2199 url = JetSearch.getResultsUrl( form, customResultUrl ); 2200 } 2201 2202 if ( 'yes' === searchLogging || true === searchLogging ) { 2203 JetSearch.setFormSuggestion( value, false, url ); 2204 } else { 2205 window.location.href = url; 2206 } 2207 } 2208 } 2209 } 2210 2211 self.customUrlActions = { 2212 selectorOnClick: 'a[href^="#jet-engine-action"][href*="event=click"]', 2213 selectorOnHover: 'a[href^="#jet-engine-action"][href*="event=hover"], [data-url^="#jet-engine-action"][data-url*="event=hover"]', 2214 2215 init: function() { 2216 var timeout = null; 2217 2218 $( document ).on( 'click.JetSearch', this.selectorOnClick, function( event ) { 2219 event.preventDefault(); 2220 self.customUrlActions.actionHandler( event ) 2221 } ); 2222 2223 $( document ).on( 'click.JetSearch', this.selectorOnHover, function( event ) { 2224 if ( 'A' === event.currentTarget.nodeName ) { 2225 event.preventDefault(); 2226 } 2227 } ); 2228 2229 $( document ).on( { 2230 'mouseenter.JetSearch': function( event ) { 2231 2232 if ( timeout ) { 2233 clearTimeout( timeout ); 2234 } 2235 2236 timeout = setTimeout( function() { 2237 self.customUrlActions.actionHandler( event ) 2238 }, window.JetEngineSettings.hoverActionTimeout ); 2239 }, 2240 'mouseleave.JetSearch': function() { 2241 if ( timeout ) { 2242 clearTimeout( timeout ); 2243 timeout = null; 2244 } 2245 }, 2246 }, this.selectorOnHover ); 2247 }, 2248 2249 actions: {}, 2250 2251 addAction: function( name, callback ) { 2252 this.actions[ name ] = callback; 2253 }, 2254 2255 actionHandler: function( event ) { 2256 var url = $( event.currentTarget ).attr( 'href' ) || $( event.currentTarget ).attr( 'data-url' ); 2257 2258 this.runAction( url ); 2259 }, 2260 2261 runAction: function( url ) { 2262 var queryParts = url.split( '&' ), 2263 settings = {}; 2264
2265 queryParts.forEach( function( item ) { 2266 if ( -1 !== item.indexOf( '=' ) ) { 2267 var pair = item.split( '=' ); 2268 2269 settings[ pair[0] ] = decodeURIComponent( pair[1] ); 2270 } 2271 } ); 2272 2273 if ( ! settings.action ) { 2274 return; 2275 } 2276 2277 var actionCb = this.actions[ settings.action ]; 2278 2279 if ( ! actionCb ) { 2280 return; 2281 } 2282 2283 actionCb( settings ); 2284 } 2285 }; 2286 2287 self.handleListingItemClick = function( event ) { 2288 var url = $( this ).data( 'url' ), 2289 target = $( this ).data( 'target' ) || false; 2290 2291 if ( url ) { 2292 2293 event.preventDefault(); 2294 2295 if ( window.elementorFrontend && window.elementorFrontend.isEditMode() ) { 2296 return; 2297 } 2298 2299 if ( -1 !== url.indexOf( '#jet-engine-action' ) ) { 2300 2301 self.customUrlActions.runAction( url ); 2302 2303 } else { 2304 2305 if ( '_blank' === target ) { 2306 window.open( url ); 2307 return; 2308 } 2309 2310 window.location = url; 2311 } 2312 } 2313 }; 2314 2315 self.isWooAddToCartTrigger = function( $target ) { 2316 2317 if ( $target.data( 'product_id' ) || $target.attr( 'data-product_id' ) ) { 2318 return true; 2319 } 2320 2321 const href = $target.attr( 'href' ) || ''; 2322 2323 if ( href && href.includes( 'add-to-cart=' ) ) { 2324 return true; 2325 } 2326 2327 if ( $target.closest( 'form.cart' ).length ) { 2328 return true; 2329 } 2330 2331 if ( $target.is( '.add_to_cart_button, .ajax_add_to_cart, .single_add_to_cart_button' ) ) { 2332 return true; 2333 } 2334 2335 return false; 2336 }; 2337 2338 self.getWooAddToCartData = function( $trigger ) { 2339 let addToCartData = {}, 2340 href = $trigger.attr( 'href' ) || '', 2341 form = $trigger.closest( 'form.cart' ), 2342 productId = $trigger.attr( 'data-product_id' ) || $trigger.data( 'product_id' ) || '', 2343 quantity = $trigger.attr( 'data-quantity' ) || $trigger.data( 'quantity' ) || 1; 2344 2345 $.each( $trigger[0].dataset || {}, function( key, value ) { 2346 addToCartData[ key ] = value; 2347 } ); 2348 2349 if ( form.length ) { 2350 $.each( form.serializeArray(), function( index, field ) { 2351 if ( '' !== field.value ) { 2352 addToCartData[ field.name ] = field.value; 2353 } 2354 } ); 2355 } 2356 2357 if ( href && -1 !== href.indexOf( 'add-to-cart=' ) && ! productId ) { 2358 try { 2359 let parsedUrl = new URL( href, window.location.origin ), 2360 hrefProduct = parsedUrl.searchParams.get( 'add-to-cart' ); 2361 2362 if ( hrefProduct ) { 2363 productId = hrefProduct; 2364 } 2365 } catch ( e ) {} 2366 } 2367 2368 if ( ! productId && addToCartData.product_id ) { 2369 productId = addToCartData.product_id; 2370 } 2371 2372 if ( ! productId && addToCartData['add-to-cart'] ) { 2373 productId = addToCartData['add-to-cart']; 2374 } 2375 2376 if ( productId ) { 2377 addToCartData.product_id = productId; 2378 } 2379 2380 if ( quantity && ! addToCartData.quantity ) { 2381 addToCartData.quantity = quantity; 2382 } 2383 2384 $( document ).trigger( 'jet-ajax-search/resolve-add-to-cart-data', [ addToCartData, $trigger, self ] ); 2385 2386 return addToCartData; 2387 }; 2388 2389 self.normalizeWooAddToCartData = function( addToCartData ) { 2390 let normalizedData = {}; 2391 2392 if ( addToCartData.product_id ) { 2393 normalizedData.product_id = addToCartData.product_id; 2394 } 2395 2396 if ( addToCartData.quantity ) { 2397 normalizedData.quantity = addToCartData.quantity; 2398 } else { 2399 normalizedData.quantity = 1; 2400 } 2401 2402 if ( addToCartData.variation_id ) { 2403 normalizedData.variation_id = addToCartData.variation_id; 2404 } 2405 2406 $.each( addToCartData, function( key, value ) { 2407 if ( 0 === key.indexOf( 'attribute_' ) ) { 2408 normalizedData[ key ] = value; 2409 } 2410 } ); 2411 2412 return normalizedData; 2413 }; 2414 2415 self.handleWooAddToCartInResults = function( event ) { 2416 const $trigger = $( event.target ).closest( 2417 '.add_to_cart_button, .ajax_add_to_cart, .single_add_to_cart_button, [data-product_id], a[href*="add-to-cart="], form.cart button' 2418 ); 2419 2420 if ( ! $trigger.length || ! self.isWooAddToCartTrigger( $trigger ) ) { 2421 return; 2422 } 2423 2424 if ( 'undefined' === typeof wc_add_to_cart_params || ! wc_add_to_cart_params.wc_ajax_url ) { 2425 return; 2426 } 2427 2428 event.preventDefault(); 2429 event.stopImmediatePropagation(); 2430 2431 if ( $trigger.prop( 'disabled' ) || $trigger.hasClass( 'loading' ) ) { 2432 return; 2433 } 2434 2435 let addToCartData = self.getWooAddToCartData( $trigger ); 2436 2437 addToCartData = self.normalizeWooAddToCartData( addToCartData ); 2438 2439 if ( ! addToCartData.product_id ) { 2440 return; 2441 } 2442 2443 $trigger.addClass( 'loading' ).prop( 'disabled', true ); 2444 2445 $( document.body ).trigger( 'adding_to_cart', [ $trigger, addToCartData ] ); 2446 2447 $.ajax( { 2448 type: 'POST', 2449 url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'add_to_cart' ), 2450 dataType: 'json', 2451 data: addToCartData, 2452 success: function( response ) { 2453 if ( response && response.error && response.product_url ) { 2454 window.location = response.product_url; 2455 return; 2456 } 2457 2458 if ( response && response.fragments ) { 2459 $.each( response.fragments, function( key, value ) { 2460 $( key ).replaceWith( value ); 2461 } ); 2462 } 2463 2464 $( document.body ).trigger( 'added_to_cart', [ response.fragments || {}, response.cart_hash || '', $trigger ] ); 2465 }, 2466 complete: function() { 2467 $trigger.removeClass( 'loading' ).prop( 'disabled', false ); 2468 } 2469 } ); 2470 }; 2471 2472 $( settings.inputClass, self ) 2473 .on( 'input' + settings.searchClass, self.inputChangeHandler ) 2474 .on( 'focus' + settings.searchClass, self.focusHandler ) 2475 .on( 'blur' + settings.searchClass, self.blurHandler ) 2476 .on( 'keydown' + settings.searchClass, self.formSubmit ); 2477 2478 $( settings.submitClass, self ).on( 'click' + settings.searchClass, self.clickFullResults ); 2479 2480 $( self ) 2481 .on( 'click' + settings.searchClass, self.formClick ) 2482 .on( 'touchend' + settings.searchClass, self.formClick ) 2483 .on( 'click' + settings.searchClass, settings.fullResultsClass, self.clickFullResults ) 2484 .on( 'click' + settings.searchClass, settings.countClass, self.clickFullResults ) 2485 .on( 'click' + settings.searchClass, settings.bulletClass, self.clickBulletHandler ) 2486 .on( 'click' + settings.searchClass, settings.numberClass, self.clickBulletHandler ) 2487 .on( 'click' + settings.searchClass, settings.prevClass + ':not( ' + settings.disableNavClass + ' )', self.clickNavigationButtonHandler ) 2488 .on( 'click' + settings.searchClass, settings.nextClass + ':not( ' + settings.disableNavClass + ' )', self.clickNavigationButtonHandler ) 2489 .on( 'click keydown' + settings.searchClass, settings.inlineSuggestionsItemClass, self.selectSuggestion ) 2490 .on( 'click keydown' + settings.searchClass, settings.resultsSuggestionItemClass, self.selectSuggestion ) 2491 .on( 'change', settings.chosenClass, self.changeHandler ) 2492 .on( 'chosen:showing_dropdown', settings.chosenClass, self.chosenFocusHandler ) 2493 .on( 'click' + settings.searchClass, '.jet-engine-listing-overlay-wrap:not([data-url*="event=hover"])', self.handleListingItemClick ) 2494 .on( 'click' + settings.searchClass, 2495 settings.resultsAreaClass + ' .add_to_cart_button, ' + 2496 settings.resultsAreaClass + ' .ajax_add_to_cart, ' + 2497 settings.resultsAreaClass + ' form.cart .single_add_to_cart_button', 2498 self.handleWooAddToCartInResults 2499 ); 2500 2501 if ( ! allowSubmitOnEnter ){ 2502 $( window ).keydown( function( event ) { 2503 if ( 13 === event.keyCode && event.target.className.includes( 'jet-ajax-search' ) ) { 2504 event.preventDefault(); 2505 return false;
2506 } 2507 }); 2508 } 2509 2510 $( self ).on( 'keydown', function( e ) { 2511 const keyCode = e.keyCode || e.which; 2512 2513 if ( 9 === keyCode ) { 2514 setTimeout( () => { 2515 const focusedElement = document.activeElement; 2516 2517 if ( $( focusedElement ).is( '.chosen-search-input' ) ) { 2518 $( '.chosen-single', self ).addClass( 'focused' ); 2519 } else { 2520 $( '.chosen-single', self ).removeClass( 'focused' ); 2521 } 2522 }, 50 ); 2523 } 2524 } ); 2525 2526 $( settings.inputClass, self ).on( 'click' + settings.searchClass, () => { 2527 $( '.chosen-single', self ).removeClass( 'focused' ); 2528 } ); 2529 2530 if ( '' != categoryIndex ) { 2531 let target = $( settings.chosenClass, self ), 2532 globalQuerySettings = $( self ).data( 'settings' ), 2533 categorySelect = $( '.jet-ajax-search__categories-select', self ), 2534 currentCategory = ''; 2535 2536 categorySelect.find( 'option' ).each( function() { 2537 var value = $( this ).val(); 2538 2539 if ( value === categoryIndex ) { 2540 currentCategory = $( this ).text(); 2541 } 2542 } ); 2543 2544 categorySelect.find( 'option:contains("' + currentCategory + '")' ).attr( 'selected', 'selected' ); 2545 2546 globalQuerySettings.category__in = target.val(); 2547 data.category__in = target.val(); 2548 2549 $( self ).data( 'settings', globalQuerySettings ); 2550 } else { 2551 // If after reloading the page the value of the select is not '0'. 2552 2553 if ( '0' !== $( settings.chosenClass, self ).val() ) { 2554 $( settings.chosenClass, self ).trigger( 'change' ); 2555 } 2556 } 2557 2558 $( 'body' ) 2559 .on( 'click' + settings.searchClass, self.hideList ) 2560 .on( 'touchend' + settings.searchClass, self.hideList ); 2561 2562 self.setResultsAreaWidth(); 2563 $( window ).on( 'resize' + settings.searchClass, self.setResultsAreaWidth ); 2564 2565 $( window ).on( 'orientationchange resize', function () { 2566 resultsListInner.imagesLoaded( function() { 2567 const $firstSlide = $( settings.listSlideClass, resultsListInner ).eq(0); 2568 const firstSlideHeight = $firstSlide.length ? $firstSlide.outerHeight() : 0; 2569 2570 resultsList.css( 'height', firstSlideHeight > 0 ? firstSlideHeight : 'auto' ); 2571 } ); 2572 } ); 2573 2574 } else { 2575 return 'is init: true'; 2576 } 2577 }; 2578 2579 // initialize after all is defined 2580 $( window ).on( 'elementor/frontend/init', JetSearch.initElementor ); 2581 JetSearch.initBlocks(); 2582 2583 window.jetSearchBricks = function() { 2584 JetSearch.initBricks(); 2585 } 2586 2587 window.JetSearch = JetSearch; 2588 2589}( 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.