1( function( $ ) { 2 3 "use strict"; 4 5 const initLocationDistanceFilter = function() { 6 7 window.JetSmartFilters.filtersList.JetEngineLocationDistance = 'jet-smart-filters-location-distance'; 8 window.JetSmartFilters.filters.JetEngineLocationDistance = class JetEngineLocationDistance extends window.JetSmartFilters.filters.Search { 9 10 name = 'location-distance'; 11 currentLocationVerbose = 'Your current location'; 12 defaultLocation = null; 13 $locationParent = null; 14 $locationInput = null; 15 $locationDropdown = null; 16 $distanceInput = null; 17 xhr = false; 18 debounced = false; 19 minAutocompleteRequest = 3; 20 21 constructor( $container ) { 22 23 const $filter = $container.find( '.jsf-location-distance' ); 24 25 super( $container, $filter ); 26 27 this.locationData = {}; 28 29 this.$locationParent = $filter.find( '.jsf-location-distance__location' ); 30 this.$locationInput = $filter.find( '.jsf-location-distance__location-input' ); 31 this.$locationDropdown = $filter.find( '.jsf-location-distance__location-dropdown' ); 32 this.$distanceInput = $filter.find( '.jsf-location-distance__distance' ); 33 34 if ( $filter.data( 'geolocation-placeholder' ) ) { 35 this.currentLocationVerbose = $filter.data( 'geolocation-placeholder' ); 36 } 37 38 this.$distanceInput.on( 'change', ( event ) => { 39 this.updateLocationData( { distance: event.target.value } ); 40 } ); 41 42 this.defaultLocation = $filter.data( 'current-location' ); 43 44 if ( this.defaultLocation ) { 45 this.updateLocationData( this.defaultLocation, true ); 46 } 47 48 if ( this.defaultLocation.address ) { 49 this.$locationInput.val( this.defaultLocation.address ); 50 } 51 52 if ( this.defaultLocation.distance ) { 53 this.selectDistance( this.defaultLocation.distance ); 54 } 55 56 this.$locationInput.on( 'keyup', ( event ) => { 57 58 var keyCode = ( event.keyCode ? event.keyCode : event.which ); 59 60 if ( event.target.value.length ) { 61 this.switchClear( true ); 62 this.switchLocate(); 63 } else { 64 this.switchClear(); 65 this.switchLocate( true ); 66 } 67 68 let minAutocompleteRequest = parseInt( this.minAutocompleteRequest ); 69 minAutocompleteRequest = isFinite( minAutocompleteRequest ) ? minAutocompleteRequest : 3; 70 71 if ( minAutocompleteRequest > event.target.value.length ) { 72 this.clearDropdown(); 73 return; 74 } 75 76 this.updateLocationData( { 77 address: event.target.value, 78 }, true ); 79 80 if ( 13 === keyCode ) { 81 this.maybeApplyFilter(); 82 this.clearDropdown(); 83 return; 84 } 85 86 if ( this.debounced ) { 87 clearTimeout( this.debounced ); 88 } 89 90 this.debounced = setTimeout( 91 this.fillAddressDropdown.bind( this ), 92 200, 93 event.target.value 94 ); 95 96 } ); 97 98 this.$locationDropdown.on( 'click', '.jsf-location-distance__location-dropdown-item', ( event ) => { 99 100 const $dropdownItem = $( event.target ); 101 102 this.$locationInput.val( $dropdownItem.data( 'address' ) ); 103 this.clearDropdown(); 104 105 this.updateLocationData( { 106 address: $dropdownItem.data( 'address' ), 107 latitude: 0, 108 longitude: 0, 109 } ); 110 111 } ); 112 113 this.$locationParent.on( 'click', '.jsf-location-distance__location-clear', ( event ) => { 114 //this.clearLocation(); 115 this.reset(); 116 } ); 117 118 this.$locationParent.on( 'click', '.jsf-location-distance__location-locate', ( event ) => { 119 120 this.switchLocate(); 121 this.switchLoading( true ); 122 123 navigator.geolocation.getCurrentPosition( ( position ) => { 124 125 this.switchLoading(); 126 this.$locationInput.val( this.currentLocationVerbose ); 127 this.switchClear( true ); 128 129 this.updateLocationData( { 130 address: 0, 131 latitude: position.coords.latitude, 132 longitude: position.coords.longitude, 133 } ); 134 135 } ); 136 137 } ); 138 139 $( document ).on( 'click', ( event ) => { 140 141 const $parent = $( event.target ).closest( '.jsf-location-distance__location' ); 142 143 if ( ! $parent.length ) { 144 this.clearDropdown(); 145 } 146 147 } ); 148 149 } 150 151 fillAddressDropdown( query ) { 152 if ( this.xhr ) { 153 this.xhr.abort(); 154 } 155 156 this.xhr = $.ajax({ 157 url: window.JetMapListingLocationDistanceFilterData.apiAutocomplete, 158 type: 'GET', 159 dataType: 'json', 160 data: { query: query }, 161 }).done( ( response ) => { 162 163 this.clearDropdown(); 164 165 if ( ! response || ! response.success ) { 166 return; 167 } 168 169 this.$locationDropdown.addClass( 'is-active' ); 170 171 for ( var i = 0; i < response.data.length; i++ ) { 172 this.$locationDropdown.append( 173 '<div class="jsf-location-distance__location-dropdown-item" data-address="' + response.data[ i ].address + '">' 174 + response.data[ i ].address + 175 '</div>' 176 ); 177 } 178 179 }); 180 } 181 182 maybeApplyFilter() { 183 184 const applyOn = [ 'ajax', 'mixed' ]; 185 186 if ( ! applyOn.includes( this.applyType ) ) { 187 return; 188 } 189 190 this.emitFiterApply(); 191 192 } 193 194 reset() { 195 this.resetLocationData( false ); 196 } 197 198 resetLocationData( silent ) { 199 this.updateLocationData( {}, silent, [ 'address', 'longitude', 'latitude', 'distance' ] ); 200 this.clearDistance(); 201 this.clearLocation(); 202 } 203 204 setData( newData ) { 205 206 this.resetLocationData( true ); 207 208 if ( newData ) { 209 this.updateLocationData( { ...newData }, true ); 210 } 211 212 if ( newData && undefined !== newData.address ) { 213 214 if ( 0 == newData.address && newData.latitude && newData.longitude ) { 215 this.$locationInput.val( this.currentLocationVerbose ); 216 } else { 217 this.$locationInput.val( newData.address ); 218 } 219 220 this.switchClear( true ); 221 this.switchLocate(); 222 223 } 224 225 if ( newData && newData.distance ) { 226 this.selectDistance( newData.distance ); 227 } 228 229 } 230 231 selectDistance( distance ) { 232 this.clearDistance(); 233 this.$distanceInput.find( 'option[value="' + distance + '"]' ) 234 .prop( 'selected', true ) 235 .attr( 'selected', true ); 236 } 237 238 clearDistance() { 239 this.$distanceInput.find( 'option[selected]' ) 240 .removeProp( 'selected' ) 241 .removeAttr( 'selected' ); 242 } 243 244 get activeValue() { 245 246 if ( ! this.hasLocation() && ! this.locationData.distance ) { 247 return false;
248 } 249 250 const activeValue = []; 251 252 if ( this.locationData.address && 0 != this.locationData.address ) { 253 activeValue.push( this.locationData.address ); 254 } else if ( this.locationData.latitude && this.locationData.longitude ) { 255 activeValue.push( this.currentLocationVerbose ); 256 } 257 258 activeValue.push( this.locationData.distance + this.locationData.units ); 259 260 return activeValue.join( ', ' ); 261 262 } 263 264 locationDataIsEmpty() { 265 266 if ( ! this.locationData || 0 === Object.keys( this.locationData ).length ) { 267 return true; 268 } 269 270 if ( ! this.hasLocation() && ! this.locationData.distance ) { 271 return true; 272 } 273 274 return false; 275 } 276 277 // Getters 278 get data() { 279 280 if ( this.dataValue && ! this.disabled ) { 281 return { ...this.dataValue }; 282 } else if ( ! this.locationDataIsEmpty() && ! this.disabled ) { 283 return { ...this.locationData }; 284 } else { 285 //console.log( 'Empty' ); 286 return false; 287 } 288 289 } 290 291 processData() { 292 if ( ! this.locationDataIsEmpty ) { 293 this.dataValue = { ...this.locationData }; 294 } else { 295 this.dataValue = false; 296 } 297 } 298 299 clearLocation() { 300 301 this.$locationInput.val( '' ); 302 this.clearDropdown(); 303 304 this.switchClear(); 305 this.switchLocate( true ); 306 307 } 308 309 hasLocation() { 310 if ( 311 ! this.locationData 312 || ( ! this.locationData.address 313 && ! this.locationData.latitude 314 && ! this.locationData.longitude ) 315 ) { 316 return false; 317 } else { 318 return true; 319 } 320 } 321 322 clearDropdown() { 323 this.$locationDropdown.html( '' ).removeClass( 'is-active' ); 324 } 325 326 switchClear( show ) { 327 if ( show && ! this.$locationParent.hasClass( 'jsf-show-clear' ) ) { 328 this.$locationParent.addClass( 'jsf-show-clear' ); 329 } else if ( ! show ) { 330 this.$locationParent.removeClass( 'jsf-show-clear' ); 331 } 332 } 333 334 switchLoading( show ) { 335 if ( show && ! this.$locationParent.hasClass( 'jsf-show-loading' ) ) { 336 this.$locationParent.addClass( 'jsf-show-loading' ); 337 } else if ( ! show ) { 338 this.$locationParent.removeClass( 'jsf-show-loading' ); 339 } 340 } 341 342 switchLocate( show ) { 343 344 if ( ! navigator.geolocation ) { 345 this.$locationParent.removeClass( 'jsf-show-locate' ); 346 return; 347 } 348 349 if ( show && ! this.$locationParent.hasClass( 'jsf-show-locate' ) ) { 350 this.$locationParent.addClass( 'jsf-show-locate' ); 351 } else if ( ! show ) { 352 this.$locationParent.removeClass( 'jsf-show-locate' ); 353 } 354 } 355 356 updateLocationData( newData, silent, deleteData ) { 357 358 if ( 0 !== Object.keys( newData ).length ) { 359 360 // The following condition is commented to prevent conflicts with Reload or Mixed apply types. 361 // if ( 0 !== Object.keys( this.defaultLocation ).length ) { 362 // newData = { ...this.defaultLocation, ...newData }; 363 // } 364 365 for ( const prop in newData ) { 366 this.locationData[ prop ] = newData[ prop ]; 367 } 368 369 if ( ! this.locationData.distance ) { 370 this.locationData.distance = this.$distanceInput.data( 'default' ); 371 } 372 373 if ( ! this.locationData.units ) { 374 this.locationData.units = this.$distanceInput.data( 'units' ); 375 } 376 377 } 378 379 if ( deleteData ) { 380 for ( var i = 0; i < deleteData.length; i++ ) { 381 delete this.locationData[ deleteData[ i ] ]; 382 } 383 } 384 385 if ( ! silent ) { 386 this.emitFiterChange(); 387 this.maybeApplyFilter(); 388 } 389 390 } 391 392 }; 393 } 394 395 // Added the filter name to the `filterNames` property on `DOMContentLoaded` event before `elementor/frontend/init` event 396 // to better compatibility with Elementor Popup. 397 window.addEventListener( 'DOMContentLoaded', () => { 398 if ( window.JetSmartFilters && -1 === window.JetSmartFilters.filterNames.indexOf( 'location-distance' ) ) { 399 window.JetSmartFilters.filterNames.push( 'location-distance' ); 400 } 401 } ); 402 403 if ( window.JetMapListingGeolocationFilterData && 'jet-smart-filters/before-init' === window.JetMapListingGeolocationFilterData.initEvent ) { 404 document.addEventListener( 'jet-smart-filters/before-init', ( e ) => { 405 initLocationDistanceFilter(); 406 }); 407 } else { 408 window.addEventListener( 'DOMContentLoaded', ( e ) => { 409 initLocationDistanceFilter(); 410 }); 411 } 412 413}( 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.