1(function ( $ ) { 2 'use strict'; 3 4 var qodefGoogleMap = { 5 mapHolder: '', 6 mapOptions: [], 7 mapElement: '', 8 map: {}, 9 markers: {}, 10 circleMap: {}, 11 init: function ( $mapHolder, options ) { 12 // Set main map holder. 13 this.mapHolder = $mapHolder; 14 15 if ( typeof google !== 'object' || typeof this.mapHolder === 'undefined' || typeof this.mapHolder === '' ) { 16 return; 17 } 18 19 // Init map. 20 this.initMap( this.mapHolder, options ); 21 }, 22 getMapSettings: function () { 23 return { 24 mapId: "QODE_MAP_ID", 25 mapTypeId: google.maps.MapTypeId.ROADMAP, 26 scrollwheel: qodefMapsVariables.global.mapScrollable, 27 draggable: qodefMapsVariables.global.mapDraggable, 28 streetViewControl: qodefMapsVariables.global.streetViewControl, 29 zoomControl: qodefMapsVariables.global.zoomControl, 30 zoom: parseInt( qodefMapsVariables.global.mapZoom, 10 ), 31 mapTypeControl: qodefMapsVariables.global.mapTypeControl, 32 fullscreenControl: qodefMapsVariables.global.fullscreenControl, 33 }; 34 }, 35 getMapOptions: function ( $mapHolder, forwardOptions ) { 36 var options = { 37 uniqueId: '', 38 holderId: '', 39 mapHeight: 0, 40 addresses: [], 41 addressesLatLng: [], 42 pin: '', 43 selectorIsID: false, 44 multipleTrigger: false, 45 geolocation: false, 46 }; 47 48 options = $.extend( options, forwardOptions ); 49 50 if ( options.selectorIsID ) { 51 options.uniqueId = $mapHolder[0].id; 52 options.holderId = $mapHolder[0].id; 53 } else if ( typeof $mapHolder.data( 'unique-id' ) !== 'undefined' && $mapHolder.data( 'unique-id' ) !== false ) { 54 options.uniqueId = $mapHolder.data( 'unique-id' ); 55 options.holderId = 'qodef-map-id--' + $mapHolder.data( 'unique-id' ); 56 } 57 58 if ( typeof $mapHolder.data( 'height' ) !== 'undefined' && $mapHolder.data( 'height' ) !== false ) { 59 options.mapHeight = parseInt( $mapHolder.data( 'height' ), 10 ); 60 } 61 62 if ( typeof qodefMapsVariables.multiple.addresses !== 'undefined' && qodefMapsVariables.multiple.addresses !== '' ) { 63 options.addresses = qodefMapsVariables.multiple.addresses; 64 } else if ( typeof $mapHolder.data( 'addresses' ) !== 'undefined' && $mapHolder.data( 'addresses' ) !== false ) { 65 options.addresses = $mapHolder.data( 'addresses' ); 66 } 67 68 if ( typeof $mapHolder.data( 'pin' ) !== 'undefined' && $mapHolder.data( 'pin' ) !== false ) { 69 options.pin = $mapHolder.data( 'pin' ); 70 } 71 72 return options; 73 }, 74 initMap: function ( $mapHolder, options ) { 75 this.mapOptions = this.getMapOptions( $mapHolder, options ); 76 this.mapElement = document.getElementById( this.mapOptions.holderId ); 77 this.map = new google.maps.Map( this.mapElement, this.getMapSettings() ); 78 79 var mapStyles = qodefMapsVariables.global.mapStyle; 80 var styledMapType = new google.maps.StyledMapType( mapStyles, {name: "Qode Google Map"} ); 81 82 this.map.mapTypes.set( 'qodef_styled_map', styledMapType ); 83 this.map.setMapTypeId( "qodef_styled_map" ); 84 85 // Trigger geolocation. 86 this.triggerGeolocation(); 87 88 // Set map addresses. 89 this.setAddress(); 90 91 // Set map height. 92 this.setMapHeight(); 93 }, 94 triggerGeolocation: function () { 95 96 // If geolocation enabled set map center to user location. 97 if ( navigator.geolocation && this.mapOptions.geolocation ) { 98 this.centerMapToGeolocationAddress(); 99 } 100 }, 101 setAddress: function () { 102 for ( var index = 0; index < this.mapOptions.addresses.length; index++ ) { 103 var address = this.mapOptions.addresses[index]; 104 105 if ( address === '' ) { 106 return; 107 } 108 109 if ( this.mapOptions.multipleTrigger ) { 110 var addressLocation = address.location; 111 112 if ( typeof addressLocation !== 'undefined' && addressLocation !== null && addressLocation.latitude !== '' && addressLocation.longitude !== '' ) { 113 this.mapOptions.addressesLatLng.push( $.extend( addressLocation, address ) ); 114 } 115 116 } else { 117 this.setSingleAddress( address ); 118 } 119 } 120 121 if ( this.mapOptions.multipleTrigger ) { 122 123 // Center map and set borders of map. 124 this.centerMapMultipleAddresses( this.map, this.mapOptions ); 125 126 // Add markers to the map. 127 this.addMultipleMarkers(); 128 } 129 }, 130 setSingleAddress: function ( address ) { 131 var $infoWindow = new google.maps.InfoWindow( 132 { 133 content: '<div id="content"><div id="siteNotice"></div><div id="bodyContent"><p>' + address + '</p></div></div>', 134 } 135 ); 136 137 var $geocoder = new google.maps.Geocoder(); 138 139 if ( typeof $geocoder === 'object' ) { 140 var $map = this.map, 141 mapOptions = this.mapOptions; 142 143 $geocoder.geocode( 144 { 'address': address }, 145 function ( results, status ) { 146 if ( status === google.maps.GeocoderStatus.OK && typeof results === 'object' ) { 147 148 var pinImg = document.createElement( 'img' ); 149 pinImg.src = mapOptions.pin; 150 151 var $marker = new google.maps.marker.AdvancedMarkerElement( 152 { 153 map: $map, 154 position: results[0].geometry.location, 155 content: pinImg, 156 title: address.store_title, 157 } 158 ); 159 160 google.maps.event.addListener( 161 $marker, 162 'click', 163 function () { 164 $infoWindow.open( $map, $marker ); 165 } 166 ); 167 168 var addressVariables = { 169 address: results[0].formatted_address, 170 latitude: results[0].geometry.location.lat(), 171 longitude: results[0].geometry.location.lng(), 172 }; 173 174 mapOptions.addressesLatLng.push( addressVariables ); 175 176 // Center map address. 177 qodefGoogleMap.centerMapAddress( $map, mapOptions, results ); 178 179 // Re-init markers position on resize. 180 window.addEventListener( 181 'resize', 182 function () { 183 qodefGoogleMap.centerMapAddress( $map, mapOptions, results ); 184 } 185 ); 186 } 187 } 188 ); 189 } 190 }, 191 setMapHeight: function () { 192 var mapOptions = this.mapOptions; 193 194 if ( mapOptions.mapHeight > 0 && this.mapElement !== '' ) { 195 this.mapElement.style.height = mapOptions.mapHeight + 'px'; 196 } 197 }, 198 centerMapAddress: function ( $map, mapOptions, results ) { 199 200 // Different logic for single and multiple addresses. 201 if ( mapOptions.addresses.length === 1 ) { 202 $map.setCenter( results[0].geometry.location ); 203 } else { 204 this.centerMapMultipleAddresses( $map, mapOptions ); 205 } 206 }, 207 centerMapMultipleAddresses: function ( $map, mapOptions ) { 208 var $bounds = new google.maps.LatLngBounds(), 209 addressesLatLng = mapOptions.addressesLatLng; 210 211 if ( mapOptions.multipleTrigger && addressesLatLng.length === 1 ) { 212 $map.setCenter( 213 { 214 lat: parseFloat( addressesLatLng[0].latitude ), 215 lng: parseFloat( addressesLatLng[0].longitude ), 216 } 217 ); 218 } else if ( typeof $bounds === 'object' && addressesLatLng.length ) { 219 for ( var index = 0; index < addressesLatLng.length; index++ ) { 220 $bounds.extend( 221 { 222 lat: parseFloat( addressesLatLng[index].latitude ), 223 lng: parseFloat( addressesLatLng[index].longitude ), 224 } 225 ); 226 } 227 228 $map.fitBounds( $bounds ); 229 } 230 }, 231 centerMapToGeolocationAddress: function ( setInputAddressValue, placesInput, geoLocationLinkIcon, listHolder ) { 232 233 // Try HTML5 geolocation.
234 if ( navigator.geolocation ) { 235 var $map = this.map; 236 237 if ( setInputAddressValue ) { 238 geoLocationLinkIcon.addClass( 'fa-spinner fa-spin' ); 239 } 240 241 navigator.geolocation.getCurrentPosition( 242 function ( position ) { 243 var lat = position.coords.latitude, 244 lng = position.coords.longitude, 245 latlng = { 246 lat: lat, 247 lng: lng, 248 }; 249 250 if ( setInputAddressValue ) { 251 var $geocoder = new google.maps.Geocoder(), 252 cityName = '', 253 cityWithCountryName = ''; 254 255 $geocoder.geocode( 256 { 'latLng': latlng }, 257 function ( results, status ) { 258 if ( status === google.maps.GeocoderStatus.OK && typeof results === 'object' ) { 259 var resultsObject = results; 260 261 for ( var $i = 0; $i <= resultsObject.length; $i++ ) { 262 var result = resultsObject[$i]; 263 264 if ( typeof result === 'object' && result.types[0] === 'locality' ) { 265 var currentAddress = result.address_components; 266 267 cityName = currentAddress[0].long_name; 268 269 for ( var $j = 0; $j <= currentAddress.length; $j++ ) { 270 if ( typeof currentAddress[$j] === 'object' && currentAddress[$j].types[0] === 'country' ) { 271 cityWithCountryName = cityName + ',' + currentAddress[$j].long_name; 272 } 273 } 274 } 275 } 276 277 if ( typeof cityName === 'string' ) { 278 geoLocationLinkIcon.removeClass( 'fa-spinner fa-spin' ); 279 280 if ( typeof cityWithCountryName === 'string' ) { 281 placesInput.val( cityWithCountryName ); 282 } else { 283 placesInput.val( cityName ); 284 } 285 286 window.qodefGeoLocation.showRangeSlider( latlng, true ); 287 qodef.body.trigger( 'mildhill_core_trigger_after_autocomplete_places', [placesInput] ); 288 } 289 } 290 } 291 ); 292 } else { 293 $map.setCenter( latlng ); 294 } 295 } 296 ); 297 } 298 }, 299 centerMapToForwardAddress: function ( addressName ) { 300 301 if ( typeof addressName === 'string' && typeof google === 'object' ) { 302 var $map = this.map, 303 mapSettings = this.getMapSettings(), 304 $geocoder = new google.maps.Geocoder(); 305 306 $geocoder.geocode( 307 { 'address': addressName }, 308 function ( results, status ) { 309 if ( status === google.maps.GeocoderStatus.OK && typeof results[0] === 'object' ) { 310 $map.setZoom( mapSettings.zoom ); 311 $map.setCenter( results[0].geometry.location ); 312 } 313 } 314 ); 315 } 316 }, 317 addMultipleMarkers: function () { 318 var markers = [], 319 addressesLatLng = this.mapOptions.addressesLatLng; 320 321 for ( var i = 0; i < addressesLatLng.length; i++ ) { 322 var latLng = { 323 lat: parseFloat( addressesLatLng[i].latitude ), 324 lng: parseFloat( addressesLatLng[i].longitude ) 325 }; 326 327 // Custom html markers. 328 // Insert marker data into info window template. 329 var templateData = { 330 latLng: latLng, 331 }; 332 333 $.each( 334 addressesLatLng[i], 335 function ( key, value ) { 336 templateData[key] = value; 337 } 338 ); 339 340 var $customMarker = new window.qodefCustomMarker( 341 { 342 position: latLng, 343 map: this.map, 344 templateData: templateData, 345 markerPin: addressesLatLng[i].markerPin, 346 } 347 ); 348 349 markers.push( $customMarker ); 350 } 351 352 this.markers = markers; 353 354 // Init map clusters ( Grouping map markers at small zoom values ). 355 this.initMarkerClusters(); 356 357 // Init marker info. 358 this.initMarkerInfo(); 359 }, 360 initMarkerClusters: function () { 361 var markerOptions = { 362 minimumClusterSize: 2, 363 maxZoom: 12, 364 styles: [{ 365 width: 50, 366 height: 60, 367 url: '', 368 textSize: 12, 369 }], 370 }; 371 372 new MarkerClusterer( 373 this.map, 374 this.markers, 375 markerOptions 376 ); 377 }, 378 initMarkerInfo: function () { 379 var $map = this.map; 380 381 $( document ).off( 382 'click', 383 '.qodef-map-marker' 384 ).on( 385 'click', 386 '.qodef-map-marker', 387 function () { 388 var self = $( this ), 389 $markerHolders = $( '.qodef-map-marker-holder' ), 390 $infoWindows = $( '.qodef-info-window' ), 391 $markerHolder = self.parent( '.qodef-map-marker-holder' ), 392 markerlatlngData = $markerHolder.data( 'latlng' ), 393 $infoWindow = self.siblings( '.qodef-info-window' ); 394 395 if ( $markerHolder.hasClass( 'qodef-active qodef-map-active' ) ) { 396 $markerHolder.removeClass( 'qodef-active qodef-map-active' ); 397 $infoWindow.fadeOut( 0 ); 398 } else { 399 $markerHolders.removeClass( 'qodef-active qodef-map-active' ); 400 $infoWindows.fadeOut( 0 ); 401 $markerHolder.addClass( 'qodef-active qodef-map-active' ); 402 $infoWindow.fadeIn( 300 ); 403 404 if ( markerlatlngData.length && markerlatlngData !== undefined ) { 405 var latlngStr = markerlatlngData.replace( '(', '' ).replace( ')', '' ).split( ',', 2 ); 406 407 $map.panTo( new google.maps.LatLng( parseFloat( latlngStr[0] ), parseFloat( latlngStr[1] ) ) ); 408 } 409 } 410 } 411 ); 412 }, 413 setGeoLocationRadius: function ( $geoLocation, radius, isActive ) { 414 415 if ( typeof $geoLocation === 'object' && typeof google === 'object' ) { 416 var $map = this.map, 417 $markers = this.markers; 418 419 if ( isActive ) { 420 this.circleMap.setMap( null ); 421 } 422 423 this.circleMap = new google.maps.Circle( 424 { 425 map: $map, 426 center: $geoLocation, 427 // 1000 change meters to kilometers.
428 radius: parseInt( radius, 10 ) * 1000, 429 strokeWeight: 0, 430 fillColor: '#fc475f', 431 fillOpacity: 0.15, 432 } 433 ); 434 435 var $currentCircle = this.circleMap; 436 437 var itemsInArea = []; 438 $.each( 439 $markers, 440 function ( i, marker ) { 441 if ( $currentCircle.getBounds().contains( marker.latlng ) ) { 442 itemsInArea.push( marker.templateData.itemId ); 443 } 444 } 445 ); 446 447 window.qodefGeoLocation.disableItemsOutOfRange( itemsInArea ); 448 } 449 }, 450 createAutocompletePlaces: function ( placeInputID ) { 451 452 if ( typeof google === 'object' && typeof google.maps.places === 'object' ) { 453 var autocompleteConfig = { 454 types: ['(cities)'] 455 }; 456 457 var autocomplete = new google.maps.places.Autocomplete( placeInputID, autocompleteConfig ); 458 459 autocomplete.addListener( 460 'place_changed', 461 function () { 462 // Enable reset icon in field. 463 $( placeInputID ).next().show(); 464 window.qodefGeoLocation.reset(); 465 qodef.body.trigger( 'mildhill_core_trigger_after_autocomplete_places', [placeInputID] ); 466 } 467 ); 468 } 469 }, 470 }; 471 472 window.qodefGoogleMap = qodefGoogleMap; 473 474 var qodefGeoLocation = { 475 holder: '', 476 radius: '', 477 slider: '', 478 init: function ( $holder = '' ) { 479 this.holder = $holder; 480 481 if ( this.holder.length ) { 482 this.radius = this.holder.find( '.qodef-places-geo-radius' ); 483 this.slider = document.getElementById( 'qodef-range-slider-id' ); 484 485 if ( this.radius.length && this.slider !== null ) { 486 this.createSlider(); 487 } 488 } 489 }, 490 createSlider: function () { 491 noUiSlider.create( 492 this.slider, 493 { 494 connect: [true, false], 495 start: 0, 496 step: 1, 497 tooltips: true, 498 format: { 499 from: function ( value ) { 500 return parseInt( value ); 501 }, 502 to: function ( value ) { 503 return parseInt( value ); 504 }, 505 }, 506 range: { 507 min: 0, 508 max: 100, 509 } 510 } 511 ); 512 513 this.updateMapRadius(); 514 }, 515 updateMapRadius: function () { 516 var sliderEventCount = 0; 517 518 this.slider.noUiSlider.on( 519 'set', 520 function ( values ) { 521 var $geoLocation = qodefGeoLocation.radius.data( 'geo-location' ); 522 523 if ( typeof $geoLocation === 'object' ) { 524 window.qodefGoogleMap.setGeoLocationRadius( $geoLocation, values, sliderEventCount > 0 ); 525 sliderEventCount++; 526 } 527 } 528 ); 529 }, 530 reset: function () { 531 532 if ( this.slider !== null && this.radius.length && this.radius.is( ':visible' ) ) { 533 this.setRadiusVisibility( '', false ); 534 this.slider.noUiSlider.reset(); 535 } 536 }, 537 showRangeSlider: function ( latlng, visibility ) { 538 539 if ( this.radius.length ) { 540 this.setRadiusVisibility( latlng, visibility ); 541 } 542 }, 543 setRadiusVisibility: function ( latlng, visibility ) { 544 this.radius.data( 'geo-location', latlng ); 545 546 if ( visibility ) { 547 this.radius.show(); 548 } else { 549 this.radius.hide(); 550 } 551 }, 552 disableItemsOutOfRange: function ( $itemsInArea ) { 553 var $holder = this.holder; 554 555 if ( $holder.length && typeof $itemsInArea === 'object' ) { 556 var $items = $holder.find( '.qodef-grid-inner article' ), 557 $outOfRangeHolder, 558 $outOfRangeItems, 559 $inRangeHolder = $holder.find( '.qodef-grid-inner' ); 560 561 if ( ! $holder.children( '.qodef-out-of-range-holder' ).length ) { 562 $holder.append( '<div class="qodef-out-of-range-holder"></div>' ); 563 } 564 565 $outOfRangeHolder = $holder.children( '.qodef-out-of-range-holder' ); 566 $outOfRangeItems = $outOfRangeHolder.children( 'article' ); 567 568 if ( $items.length || $outOfRangeItems.length ) { 569 570 $items.each( 571 function () { 572 var $thisItem = $( this ), 573 itemID = $thisItem.data( 'id' ); 574 575 if ( itemID !== undefined && itemID !== false ) { 576 var itemInRange = false; 577 578 $.each( 579 $itemsInArea, 580 function ( i, id ) { 581 if ( parseInt( itemID, 10 ) === id ) { 582 itemInRange = true; 583 return true; 584 } 585 } 586 ); 587 588 if ( ! itemInRange ) { 589 $thisItem.appendTo( $outOfRangeHolder ); 590 591 if ( $holder.hasClass( 'qodef-layout--masonry' ) ) { 592 $inRangeHolder.isotope( 'layout' ); 593 } 594 } 595 } 596 } 597 ); 598 599 if ( $outOfRangeItems.length ) { 600 $outOfRangeItems.each( 601 function () { 602 var $thisOutItem = $( this ), 603 outItemID = $thisOutItem.data( 'id' ),
604 itemInRange = false; 605 606 $.each( 607 $itemsInArea, 608 function ( i, id ) { 609 if ( parseInt( outItemID, 10 ) === id ) { 610 itemInRange = true; 611 return true; 612 } 613 } 614 ); 615 616 if ( itemInRange ) { 617 $thisOutItem.appendTo( $inRangeHolder ); 618 619 if ( $holder.hasClass( 'qodef-layout--masonry' ) ) { 620 $inRangeHolder.isotope( 'layout' ); 621 } 622 } 623 } 624 ); 625 } 626 } 627 } 628 }, 629 }; 630 631 window.qodefGeoLocation = qodefGeoLocation; 632 633})( 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.