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