1(function( $ ) { 2 3 'use strict'; 4 5 var JetSearch = { 6 7 initElementor: function() { 8 9 var widgets = { 10 'jet-ajax-search.default': JetSearch.widgetAjaxSearch 11 }; 12 13 $.each( widgets, function( widget, callback ) { 14 window.elementorFrontend.hooks.addAction( 'frontend/element_ready/' + widget, callback ); 15 } ); 16 17 /* 18 // Example of usage AJAX success trigger 19 $( document ).on( 'jet-ajax-search/show-results', function( event, searchResults ) { 20 searchResults.find( '.jet-ajax-search__results-item' ).css( 'border', '2px solid red' ); 21 } ); 22 */ 23 24 }, 25 26 initBlocks() { 27 28 $( '.jet-ajax-search-block' ).each( function() { 29 JetSearch.widgetAjaxSearch( $( this ) ); 30 } ); 31 32 }, 33 34 widgetAjaxSearch: function( $scope ) { 35 36 var settings = { 37 searchClass: '.jet-ajax-search', 38 searchFormClass: '.jet-ajax-search__form', 39 fieldsHolderClass: '.jet-ajax-search__fields-holder', 40 inputClass: '.jet-ajax-search__field', 41 settingsInput: 'input[name="jet_ajax_search_settings"]', 42 submitClass: '.jet-ajax-search__submit', 43 chosenClass: '.jet-ajax-search__categories select[name="jet_ajax_search_categories"]', 44 resultsAreaClass: '.jet-ajax-search__results-area', 45 resultsHeaderClass: '.jet-ajax-search__results-header', 46 resultsFooterClass: '.jet-ajax-search__results-footer', 47 listHolderClass: '.jet-ajax-search__results-holder', 48 listClass: '.jet-ajax-search__results-list', 49 listInnerClass: '.jet-ajax-search__results-list-inner', 50 listSlideClass: '.jet-ajax-search__results-slide', 51 itemClass: '.jet-ajax-search__results-item', 52 countClass: '.jet-ajax-search__results-count', 53 messageHolderClass: '.jet-ajax-search__message', 54 fullResultsClass: '.jet-ajax-search__full-results', 55 navigationClass: '.jet-ajax-search__navigation-holder', 56 navButtonClass: '.jet-ajax-search__navigate-button', 57 bulletClass: '.jet-ajax-search__bullet-button', 58 numberClass: '.jet-ajax-search__number-button', 59 prevClass: '.jet-ajax-search__prev-button', 60 nextClass: '.jet-ajax-search__next-button', 61 activeNavClass: '.jet-ajax-search__active-button', 62 disableNavClass: '.jet-ajax-search__navigate-button-disable', 63 spinnerClass: '.jet-ajax-search__spinner-holder', 64 handlerId: 'jetSearchSettings', 65 isRtl: ( window.elementorFrontend && window.elementorFrontend.config.is_rtl ) ? window.elementorFrontend.config.is_rtl : $( 'body' ).hasClass( 'rtl' ) 66 }; 67 68 if ( $scope.hasClass('jet-ajax-search-block') ) { 69 var resultAreaWidthBy = $scope.find( settings.searchClass ).data('settings')['results_area_width_by'], 70 resultAreaCustomWidth = $scope.find( settings.searchClass ).data('settings')['results_area_custom_width'], 71 resultAreaCustomWidthPosition = $scope.find( settings.searchClass ).data('settings')['results_area_custom_position'], 72 resultAreaContainer = $( '.jet-ajax-search__results-area', $scope ); 73 74 if ( "custom" === resultAreaWidthBy ) { 75 if ( "" !== resultAreaCustomWidth ) { 76 resultAreaContainer.width( resultAreaCustomWidth ); 77 } 78 79 switch( resultAreaCustomWidthPosition ) { 80 case 'left': 81 resultAreaContainer.css( "left", 0 ); 82 resultAreaContainer.css( "right", "auto" ); 83 break; 84 case 'center': 85 resultAreaContainer.css( "left", "50%" ); 86 resultAreaContainer.css( "right", "auto" ); 87 resultAreaContainer.css( "-webkit-transform", "translateX(-55%)" ); 88 resultAreaContainer.css( "transform", "translateX(-50%)" ); 89 break; 90 case 'right': 91 resultAreaContainer.css( "left", "auto" ); 92 resultAreaContainer.css( "right", 0 ); 93 break; 94 } 95 } 96 } 97 98 $scope.find( settings.searchClass ).jetAjaxSearch( settings ); 99 100 var $chosenSelect = $scope.find( settings.chosenClass ); 101 102 if ( $chosenSelect[0] ) { 103 $chosenSelect.chosen( { 104 disable_search: true, 105 placeholder_text: '', 106 placeholder_text_single: '' 107 } ); 108 } 109 } 110 }; 111 112 /** 113 * JetAjaxSearch jQuery Plugin 114 * 115 * @param args 116 */ 117 $.fn.jetAjaxSearch = function( args ) { 118 119 var self = this[0], 120 settings = args, 121 timer = null, 122 itemTemplate = null, 123 resultsArea = $( settings.resultsAreaClass, self ), 124 resultsHolder = $( settings.listHolderClass, resultsArea ), 125 resultsHeader = $( settings.resultsHeaderClass, resultsArea ), 126 resultsFooter = $( settings.resultsFooterClass, resultsArea ),
127 countHolder = $( settings.countClass, resultsArea ), 128 fullResults = $( settings.fullResultsClass, resultsArea ), 129 resultsList = $( settings.listClass, resultsArea ), 130 resultsListInner = $( settings.listInnerClass, resultsArea ), 131 resultsHeaderNav = $( settings.navigationClass, resultsHeader ), 132 resultsFooterNav = $( settings.navigationClass, resultsFooter ), 133 messageHolder = $( settings.messageHolderClass, resultsArea ), 134 spinner = $( settings.spinnerClass, resultsArea ), 135 data = $( self ).data( 'settings' ) || [], 136 formFocusClass = settings.searchFormClass.replace( '.', '' ) + '--focus', 137 currentPosition = 1; 138 139 if ( !self.isInit ) { 140 self.isInit = true; 141 142 /** 143 * Ajax request instance 144 */ 145 self.ajaxRequest = null; 146 147 /** 148 * Ajax settings from localized global variable 149 */ 150 self.ajaxSettings = window[ settings.handlerId ] || {}; 151 152 self.inputChangeHandler = function( event ) { 153 var value = $( event.target ).val(), 154 symbolNumberForStart = 'number' === $.type( data.symbols_for_start_searching ) ? data.symbols_for_start_searching : 2; 155 156 if ( 'number' === $.type( symbolNumberForStart ) && symbolNumberForStart > value.length ) { 157 self.hideList(); 158 return false; 159 } 160 161 resultsHolder.removeClass( 'show' ); 162 self.outputMessage( '', '' ); 163 resultsListInner.css( 'transform', 'translateX(0)' ); 164 resultsList.css( 'height', 'auto' ); 165 166 if ( value ) { 167 self.showList(); 168 spinner.addClass( 'show' ); 169 170 clearTimeout( timer ); 171 timer = setTimeout( function() { 172 data.value = value; 173 data.deviceMode = window.elementorFrontend && window.elementorFrontend.getCurrentDeviceMode() ? window.elementorFrontend.getCurrentDeviceMode() : false; 174 self.ajaxSendData( data ); 175 }, 450 ); 176 } else { 177 self.hideList(); 178 } 179 }; 180 181 self.successCallback = function( response ) { 182 if ( ! response.success ) { 183 spinner.removeClass( 'show' ); 184 self.outputMessage( data.server_error, 'error show' ); 185 return; 186 } 187 188 var responseData = response.data, 189 error = responseData.error, 190 message = responseData.message, 191 posts = responseData.posts, 192 post = null, 193 outputHtml = '', 194 listItemHtml = '', 195 listHtml = '<div class="' + settings.listSlideClass.replace( '.', '' ) + '">%s</div>'; 196 197 resultsHolder.removeClass( 'show' ); 198 spinner.removeClass( 'show' ); 199 currentPosition = 1; 200 201 resultsListInner.html( '' ); 202 203 const allowedHighlightFields = [ 'title', 'after_content', 'after_title', 'before_content', 'before_title', 'content', 'price' ]; 204 205 function highlightMatches( item ) { 206 let searched = responseData.search_value.trim(); 207 208 if ( searched !== "" ) { 209 let re = new RegExp( searched, "gi" ), 210 newText = item.replace( re, str => `<mark>${str}</mark>` ); 211 212 item = newText; 213 } 214 215 return item; 216 } 217 218 function highlightFields( fields, allowHighlightFields ) { 219 220 $.each( fields, function( key, value ) { 221 if ( -1 != $.inArray( key, allowHighlightFields ) && ( null != value && '' != value ) ) { 222 fields[key] = highlightMatches( value ); 223 } 224 } ); 225 226 return fields; 227 } 228 229 if ( 0 !== responseData.post_count && !error ) { 230 231 messageHolder.removeClass( 'show' ); 232 itemTemplate = wp.template( 'jet-ajax-search-results-item' ); 233 234 for ( post in posts ) { 235 if ( responseData.search_highlight && true === responseData.search_highlight ) { 236 highlightFields( posts[post], allowedHighlightFields ); 237 } 238 239 listItemHtml += itemTemplate( posts[post] ); 240 241 if ( (parseInt( post ) + 1) % responseData.limit_query == 0 || parseInt( post ) === posts.length - 1 ) { 242 outputHtml += listHtml.replace( '%s', listItemHtml ); 243 listItemHtml = ''; 244 } 245 } 246 247 $( 'span', countHolder ).html( responseData.post_count ); 248 resultsListInner 249 .html( outputHtml ) 250 .data( 'columns', responseData.columns ); 251 252 resultsHeaderNav.html( responseData.results_navigation.in_header ); 253 resultsFooterNav.html( responseData.results_navigation.in_footer ); 254 255 if ( !countHolder[0] && !responseData.results_navigation.in_header ) { 256 resultsHeader.addClass( 'is-empty' ); 257 } else { 258 resultsHeader.removeClass( 'is-empty' ); 259 } 260 261 if ( !fullResults[0] && !responseData.results_navigation.in_footer ) { 262 resultsFooter.addClass( 'is-empty' ); 263 } else { 264 resultsFooter.removeClass( 'is-empty' ); 265 } 266 267 resultsHolder.addClass( 'show' ); 268 resultsListInner.imagesLoaded( function() { 269 resultsList.css( 'height', $( settings.listSlideClass, resultsListInner ).eq(0).outerHeight() ); 270 } ); 271 272 $( document ).trigger( 'jet-ajax-search/show-results', [ resultsHolder ] ); 273 274 } else { 275 self.outputMessage( message, 'show' ); 276 //self.hideList(); 277 } 278 }; 279 280 self.errorCallback = function( jqXHR ) { 281 if ( 'abort' !== jqXHR.statusText ) { 282 spinner.removeClass( 'show' ); 283 self.outputMessage( data.server_error, 'error show' ); 284 } 285 }; 286 287 self.ajaxSendData = function( sendData ) { 288 var ajaxData = { 289 action: self.ajaxSettings.action, 290 nonce: self.ajaxSettings.nonce, 291 data: sendData || {} 292 }; 293 294 self.ajaxRequest = jQuery.ajax( { 295 type: 'GET', 296 url: self.ajaxSettings.ajaxurl, 297 data: ajaxData, 298 dataType: 'json', 299 cache: false, 300 processData: true, 301 beforeSend: function( jqXHR, ajaxSettings ) { 302 if ( null !== self.ajaxRequest ) { 303 self.ajaxRequest.abort(); 304 } 305 }, 306 error: function( jqXHR, textStatus, errorThrown ) { 307 self.errorCallback( jqXHR ); 308 }, 309 success: function( response, textStatus, jqXHR ) { 310 self.successCallback( response ); 311 } 312 } ); 313 }; 314 315 self.hideList = function() { 316 resultsArea.removeClass( 'show' ); 317 }; 318 319 self.showList = function() { 320 resultsArea.addClass( 'show' ); 321 }; 322 323 self.focusHandler = function( event ) { 324 var value = event.target.value, 325 symbolNumberForStart = 'number' === $.type( data.symbols_for_start_searching ) ? data.symbols_for_start_searching : 2; 326 327 $( settings.searchFormClass, self ).addClass( formFocusClass ); 328 329 if ( 'number' === $.type( symbolNumberForStart ) && symbolNumberForStart > value.length ) { 330 return; 331 } 332 333 self.showList(); 334 }; 335 336 self.blurHandler = function( event ) { 337 $( settings.searchFormClass, self ).removeClass( formFocusClass ); 338 }; 339 340 self.outputMessage = function( message, messageClass ) { 341 message = message.replace( /\\/g, '' ); // remove slashes 342 message = $( "<div/>" ).html( message ).text(); 343 message = message.replace( /\\*"/g, '' ); 344 messageHolder.removeClass( 'error show' ).addClass( messageClass ).html( message ); 345 }; 346 347 self.formClick = function( event ) { 348 event.stopPropagation(); 349 }; 350 351 self.clickFullResults = function( event ) { 352 var searchInput = $( settings.inputClass, self ); 353 354 event.preventDefault(); 355 356 if ( searchInput.val().length != 0) { 357 $( settings.searchFormClass, self ).submit(); 358 } 359 }; 360 361 self.changeSlide = function( number ) { 362 var currentSlide = $( settings.listSlideClass, resultsListInner ).eq( number ), 363 direction = settings.isRtl ? 1 : -1, 364 position = number * 100 * direction; 365 366 currentSlide.scrollTop( 0 ); 367 resultsListInner.css( 'transform', 'translateX(' + position + '%)' ); 368 resultsList.css( 'height', currentSlide.outerHeight() ); 369 }; 370 371 self.clickBulletHandler = function( event ) { 372 var target = $( event.target ); 373 374 currentPosition = target.data( 'number' ); 375 self.syncNavigation(); 376 377 self.changeSlide( currentPosition - 1 ); 378 }; 379 380 self.clickNavigationButtonHandler = function( event ) { 381 var target = $( event.target ), 382 direction = target.data( 'direction' ); 383 384 currentPosition = currentPosition + direction; 385 self.syncNavigation(); 386 387 self.changeSlide( currentPosition - 1 ); 388 }; 389 390 self.syncNavigation = function() { 391 var lastPosition = resultsListInner.data( 'columns' ), 392 disableClass = settings.disableNavClass.replace( '.', '' ), 393 activeClass = settings.activeNavClass.replace( '.', '' ); 394 395 $( settings.activeNavClass, self ).removeClass( activeClass ); 396 $( settings.disableNavClass, self ).removeClass( disableClass ); 397 398 $( settings.navButtonClass + '[data-number="' + currentPosition +'"]', self ).addClass( activeClass ); 399 400 if ( 1 === currentPosition ) { 401 $( settings.prevClass, self ).addClass( disableClass ); 402 } 403 404 if ( lastPosition === currentPosition ) { 405 $( settings.nextClass, self ).addClass( disableClass ); 406 } 407 }; 408 409 self.formSubmit = function( event ) { 410 var value = event.target.value; 411 412 if ( 1 > value.length && ( 13 === event.keyCode || 'click' === event.type ) ) { 413 return false;
414 } else { 415 if ( 13 === event.keyCode && self.ajaxSettings.sumbitOnEnter ) { 416 event.preventDefault(); 417 $( settings.searchFormClass, self ).submit(); 418 } 419 } 420 }; 421 422 self.changeHandler = function( event ) { 423 var target = $( event.target ), 424 settingsInput = $( settings.settingsInput, self ), 425 querySettings = JSON.parse( settingsInput.val() ), 426 globalQuerySettings = $( self ).data( 'settings' ); 427 428 querySettings.category__in = target.val(); 429 globalQuerySettings.category__in = target.val(); 430 431 settingsInput.val( JSON.stringify( querySettings ) ); 432 $( self ).data( 'settings', globalQuerySettings ); 433 434 self.inputChangeHandler( { target: $( settings.inputClass, self ) } ) 435 }; 436 437 self.chosenFocusHandler = function() { 438 self.hideList(); 439 }; 440 441 self.setResultsAreaWidth = function() { 442 443 if ( 'fields_holder' !== data.results_area_width_by ) { 444 return; 445 } 446 447 resultsArea.css( 'width', $( settings.fieldsHolderClass, self ).outerWidth() ); 448 }; 449 450 $( settings.inputClass, self ) 451 .on( 'input' + settings.searchClass, self.inputChangeHandler ) 452 .on( 'focus' + settings.searchClass, self.focusHandler ) 453 .on( 'blur' + settings.searchClass, self.blurHandler ) 454 .on( 'keypress' + settings.searchClass, self.formSubmit ); 455 456 $( settings.submitClass, self ).on( 'click' + settings.searchClass, self.clickFullResults ); 457 458 $( self ) 459 .on( 'click' + settings.searchClass, self.formClick ) 460 .on( 'touchend' + settings.searchClass, self.formClick ) 461 .on( 'click' + settings.searchClass, settings.fullResultsClass, self.clickFullResults ) 462 .on( 'click' + settings.searchClass, settings.countClass, self.clickFullResults ) 463 .on( 'click' + settings.searchClass, settings.bulletClass, self.clickBulletHandler ) 464 .on( 'click' + settings.searchClass, settings.numberClass, self.clickBulletHandler ) 465 .on( 'click' + settings.searchClass, settings.prevClass + ':not( ' + settings.disableNavClass + ' )', self.clickNavigationButtonHandler ) 466 .on( 'click' + settings.searchClass, settings.nextClass + ':not( ' + settings.disableNavClass + ' )', self.clickNavigationButtonHandler ) 467 .on( 'change', settings.chosenClass, self.changeHandler ) 468 .on( 'chosen:showing_dropdown', settings.chosenClass, self.chosenFocusHandler ); 469 470 if ( ! self.ajaxSettings.sumbitOnEnter ){ 471 $( window ).keydown( function( event ) { 472 if ( 13 === event.keyCode && event.target.className.includes( 'jet-ajax-search' ) ) { 473 event.preventDefault(); 474 return false; 475 } 476 }); 477 } 478 479 480 481 // If after reloading the page the value of the select is not '0'. 482 if ( '0' !== $( settings.chosenClass, self ).val() ) { 483 $( settings.chosenClass, self ).trigger( 'change' ); 484 } 485 486 $( 'body' ) 487 .on( 'click' + settings.searchClass, self.hideList ) 488 .on( 'touchend' + settings.searchClass, self.hideList ); 489 490 self.setResultsAreaWidth(); 491 $( window ).on( 'resize' + settings.searchClass, self.setResultsAreaWidth ); 492 493 } else { 494 return 'is init: true'; 495 } 496 }; 497 498 // initialize after all is defined 499 $( window ).on( 'elementor/frontend/init', JetSearch.initElementor ); 500 JetSearch.initBlocks(); 501 502}( 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.