(function ($){
'use strict';
var houzez=window.houzez||{};
houzez.Maps=(function (){
let houzezMap;
let mapBounds;
let hideInfoWindows=new Array();
let markerClusterer=null;
let markers=new Array();
let checkOpenedWindows=new Array();
let clusterIcon='';
let map_cluster_enable=1;
let clusterer_zoom=12;
let closeIcon='';
let infoWindowPlac='';
let marker_spiderfier=0;
let current_marker=0;
let markerPricePins='no';
let googlemap_style='';
let mapType='roadmap';
let ajaxurl='';
let userID='';
let not_found='';
let thousands_separator='';
let is_halfmap=0;
let default_lat=0;
let default_lng=0;
let default_zoom=12;
let max_zoom=18;
let houzez_default_radius=0;
let isSearchInProgress=false;
let pagination_only=false;
let viewport_search=false;
let auto_load_map_listings=0;
let map_message_timeout=null;
if(typeof houzez_vars!=='undefined'){
ajaxurl=houzez_vars.admin_url + 'admin-ajax.php';
userID=houzez_vars.user_id;
not_found=houzez_vars.not_found;
thousands_separator=houzez_vars.thousands_separator;
is_halfmap=parseInt(houzez_vars.is_halfmap);
houzez_default_radius=parseInt(houzez_vars.houzez_default_radius);
auto_load_map_listings=parseInt(
houzez_vars.auto_load_map_listings
);
}
const is_mobile=()=> {
if(window.matchMedia('(max-width: 991px)').matches){
return true;
}
if(navigator.userAgentData?.mobile===true){
return true;
}
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent
);
};
const addCommas=function (nStr){
nStr +='';
var x=nStr.split('.');
var x1=x[0];
var x2=x.length > 1 ? '.' + x[1]:'';
var rgx=/(\d+)(\d{3})/;
while (rgx.test(x1)){
x1=x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
};
const thousandSeparator=(n)=> {
if(typeof n==='number'){
n +='';
var x=n.split('.');
var x1=x[0];
var x2=x.length > 1 ? '.' + x[1]:'';
var rgx=/(\d+)(\d{3})/;
while (rgx.test(x1)){
x1=x1.replace(rgx, '$1' + thousands_separator + '$2');
}
return x1 + x2;
}else{
return n;
}};
const processSpecialChars=function (){
return {
'&amp;': '&',
'&quot;': '"',
'&#039;': "'",
'&#8217;': '\u2019',
'&#038;': '&',
'&lt;': '<',
'&gt;': '>',
'&#8216;': '\u2018',
'&#8230;': '\u2026',
'&#8221;': '\u201D',
'&#8211;': 'â€“',
'&#8212;': 'â€”',
};};
const setupMapType=function (mapOptions){
switch (mapType){
case 'hybrid':
mapOptions.mapTypeId=google.maps.MapTypeId.HYBRID;
break;
case 'terrain':
mapOptions.mapTypeId=google.maps.MapTypeId.TERRAIN;
break;
case 'satellite':
mapOptions.mapTypeId=google.maps.MapTypeId.SATELLITE;
break;
default:
mapOptions.mapTypeId=google.maps.MapTypeId.ROADMAP;
}
return mapOptions;
};
const houzez_map_next=function (hMap){
current_marker++;
if(current_marker > markers.length){
current_marker=1;
}
if(markers[current_marker - 1]){
const marker=markers[current_marker - 1];
const propertyId=marker.propertyId;
if(propertyId){
openInfoWindowById(propertyId);
}}
};
const houzez_map_prev=function (hMap){
current_marker--;
if(current_marker < 1){
current_marker=markers.length;
}
if(markers[current_marker - 1]){
const marker=markers[current_marker - 1];
const propertyId=marker.propertyId;
if(propertyId){
openInfoWindowById(propertyId);
}}
};
const houzez_map_zoomin=function (hMap){
const zoomInButton=document.getElementById('listing-mapzoomin');
if(zoomInButton){
zoomInButton.addEventListener('click', function (){
var current=parseInt(hMap.getZoom(), 10);
current++;
if(current > 20){
current=20;
}
hMap.setZoom(current);
console.log(current);
updateViewportCoordinates();
});
}};
const houzez_map_zoomout=function (hMap){
const zoomOutButton=document.getElementById('listing-mapzoomout');
if(zoomOutButton){
zoomOutButton.addEventListener('click', function (){
var current=parseInt(hMap.getZoom(), 10);
current--;
if(current < 0){
current=0;
}
hMap.setZoom(current);
updateViewportCoordinates();
});
}};
const houzez_change_map_type=function (map_type){
if(map_type==='roadmap'){
houzezMap.setMapTypeId(google.maps.MapTypeId.ROADMAP);
}else if(map_type==='satellite'){
houzezMap.setMapTypeId(google.maps.MapTypeId.SATELLITE);
}else if(map_type==='hybrid'){
houzezMap.setMapTypeId(google.maps.MapTypeId.HYBRID);
}else if(map_type==='terrain'){
houzezMap.setMapTypeId(google.maps.MapTypeId.TERRAIN);
}
return false;
};
const removeMapLoader=function (){
google.maps.event.addListener(houzezMap,
'tilesloaded',
function (){
jQuery('.houzez-map-loading').hide();
}
);
};
const clearClusterer=function (){
if(map_cluster_enable!=0&&markerClusterer!=null){
markerClusterer.clearMarkers();
}};
const reloadMarkers=function (){
for (var i=0; i < markers.length; i++){
markers[i].setMap(null);
}
markers=[];
};
const houzez_map_bounds=function (){
const bounds=new google.maps.LatLngBounds();
for (let i=0; i < markers.length; i++){
if(markers[i].position){
bounds.extend(markers[i].position);
}}
houzezMap.fitBounds(bounds);
google.maps.event.addListenerOnce(houzezMap,
'bounds_changed',
function (){
const minZoomLevel=default_zoom;
if(houzezMap.getZoom() > minZoomLevel){
houzezMap.setZoom(minZoomLevel);
}}
);
};
const createMapCircle=(
map,
centerLatLng,
{
strokeColor='#4f5962',
strokeOpacity=0.8,
strokeWeight=2,
fillColor='#4f5962',
fillOpacity=0.35,
radius=0.3 * 1000,
...restOptions
}={}
)=> {
const circleOptions={
strokeColor,
strokeOpacity,
strokeWeight,
fillColor,
fillOpacity,
radius,
...restOptions,
map,
center: centerLatLng,
};
return new google.maps.Circle(circleOptions);
};
const createStandardMarker=async (
map,
propertyData,
position,
{
propertyId=propertyData&&propertyData.property_id
? propertyData.property_id.toString()
: null,
...restOptions
}={}
)=> {
if(!propertyData){
return null;
}
let marker_url=propertyData.marker;
if(window.devicePixelRatio > 1.5){
if(propertyData.retinaMarker){
marker_url=propertyData.retinaMarker;
}}
let title='';
if(propertyData.title){
const specialChars=processSpecialChars();
title=propertyData.title.replace(/\&[\w\d\#]{2,5}\;/g,
(s)=> specialChars[s]
);
}
const markerContent=document.createElement('div');
markerContent.style.position='relative';
const markerImage=document.createElement('img');
markerImage.src=marker_url;
markerImage.style.width='44px';
markerImage.style.height='56px';
markerContent.appendChild(markerImage);
const advancedMarker=new google.maps.marker.AdvancedMarkerElement({
map,
position,
content: markerContent,
title: title,
...restOptions,
}
);
advancedMarker.propertyId=propertyId;
return advancedMarker;
};
const showMapMessage=function (visibleCount, totalCount){
if(auto_load_map_listings!==1){
return;
}
if(map_message_timeout){
clearTimeout(map_message_timeout);
map_message_timeout=null;
}
const $messageContainer=$('#houzez-map-message');
const $messageContent=$messageContainer.find('.map-info-message');
if(visibleCount < totalCount){
const countMessage=houzez_vars.map_show_some
.replace('%s', visibleCount)
.replace('%s', totalCount);
const zoomMessage=houzez_vars.zoom_in_show_more;
$messageContent.html(countMessage + '<br>' + zoomMessage);
$messageContainer.addClass('show');
}else{
const message=houzez_vars.map_show_all.replace('%s',
totalCount
);
$messageContent.html(message);
$messageContainer.addClass('show');
}
map_message_timeout=setTimeout(function (){
$messageContainer.removeClass('show');
}, 3000);
};
const initMapControls=function (){
$('.houzezMapType').on('click', function (e){
e.preventDefault();
var maptype=$(this).data('maptype');
houzez_change_map_type(maptype);
});
if(document.getElementById('listing-mapzoomin')){
houzez_map_zoomin(houzezMap);
}
if(document.getElementById('listing-mapzoomout')){
houzez_map_zoomout(houzezMap);
}
$('#houzez-gmap-next').on('click', function (){
houzez_map_next(houzezMap);
});
$('#houzez-gmap-prev').on('click', function (){
houzez_map_prev(houzezMap);
});
};
const houzezAddMarkers=async function (
map_properties,
houzezMap,
preservePosition=false
){
let currentCenter=null;
let currentZoom=null;
currentCenter=houzezMap.getCenter();
currentZoom=houzezMap.getZoom();
hideInfoWindows=function (){
while (checkOpenedWindows.length > 0){
var closeWindow=checkOpenedWindows.pop();
closeWindow.close();
}};
var houzezMarkerInfoWindow=function (map, marker, infowindow){
marker.addListener('gmp-click', function (){
hideInfoWindows();
infowindow.open({
anchor: marker,
map: map,
});
checkOpenedWindows.push(infowindow);
var infoWindowImages=infowindow
.getContent()
.getElementsByClassName('listing-thumbnail');
for (let i=0; i < infoWindowImages.length; i++){
if(infoWindowImages[i].dataset.src){
infoWindowImages[i].src =
infoWindowImages[i].dataset.src;
}}
});
};
const special_chars=processSpecialChars();
const propertiesByLocation={};
for (var i=0; i < map_properties.length; i++){
const lat=parseFloat(map_properties[i].latitude);
const lng=parseFloat(map_properties[i].longitude);
if(!map_properties[i].latitude ||
!map_properties[i].longitude ||
isNaN(lat) ||
isNaN(lng) ||
lat < -90 ||
lat > 90 ||
lng < -180 ||
lng > 180
){
console.warn('Skipping property with invalid coordinates:',
{
property_id: map_properties[i].property_id,
latitude: map_properties[i].latitude,
longitude: map_properties[i].longitude,
}
);
continue;
}
const locationKey=`${lat.toFixed(6)}_${lng.toFixed(6)}`;
if(!propertiesByLocation[locationKey]){
propertiesByLocation[locationKey]={
lat: lat,
lng: lng,
properties: [],
};}
propertiesByLocation[locationKey].properties.push(map_properties[i]
);
}
for (const locationKey in propertiesByLocation){
const locationData=propertiesByLocation[locationKey];
const position=new google.maps.LatLng(locationData.lat,
locationData.lng
);
const propertiesAtLocation=locationData.properties;
mapBounds.extend(position);
let marker;
let markerTitle='';
const firstProperty=propertiesAtLocation[0];
const propertyId=firstProperty.property_id.toString();
let marker_color=firstProperty.marker_color;
if(propertiesAtLocation.length > 1){
markerTitle=`${propertiesAtLocation.length} properties at this location`;
}else if(firstProperty.title){
markerTitle=firstProperty.title.replace(/\&[\w\d\#]{2,5}\;/g,
function (s){
return special_chars[s];
}
);
}
if(markerPricePins=='yes'){
const pricePin=document.createElement('div');
pricePin.className=`gm-marker map-marker-label`;
pricePin.dataset.id=firstProperty.property_id;
pricePin.style.position='relative';
if(marker_color){
pricePin.style.backgroundColor=marker_color;
pricePin.style.borderColor=marker_color;
pricePin.style.color='#ffffff';
}
const pricePinInner=document.createElement('div');
pricePinInner.className='gm-marker-price';
pricePinInner.innerHTML=firstProperty.pricePin;
pricePin.appendChild(pricePinInner);
if(propertiesAtLocation.length > 1){
const countBadge=document.createElement('div');
countBadge.style.position='absolute';
countBadge.style.top='-8px';
countBadge.style.right='-8px';
countBadge.style.backgroundColor='#333333';
countBadge.style.color='#ffffff';
countBadge.style.borderRadius='50%';
countBadge.style.width='18px';
countBadge.style.height='18px';
countBadge.style.fontSize='10px';
countBadge.style.fontWeight='bold';
countBadge.style.display='flex';
countBadge.style.alignItems='center';
countBadge.style.justifyContent='center';
countBadge.style.border='2px solid #ffffff';
countBadge.style.boxShadow =
'0 2px 4px rgba(0,0,0,0.2)';
countBadge.style.zIndex='1';
countBadge.textContent=propertiesAtLocation.length;
pricePin.appendChild(countBadge);
}
marker=new google.maps.marker.AdvancedMarkerElement({
map: houzezMap,
position: position,
content: pricePin,
title: markerTitle,
});
marker.propertyId=propertyId;
}else{
let marker_url=firstProperty.marker;
if(window.devicePixelRatio > 1.5 &&
firstProperty.retinaMarker
){
marker_url=firstProperty.retinaMarker;
}
const markerContent=document.createElement('div');
markerContent.style.position='relative';
const markerImage=document.createElement('img');
markerImage.src=marker_url;
markerImage.style.width='44px';
markerImage.style.height='56px';
markerContent.appendChild(markerImage);
markerContent.style.outline='none';
markerContent.style.border='none';
markerContent.style.boxShadow='none';
markerContent.addEventListener('focus', (e)=> {
e.target.style.outline='none';
e.target.style.border='none';
e.target.style.boxShadow='none';
});
if(propertiesAtLocation.length > 1){
const countBadge=document.createElement('div');
countBadge.style.position='absolute';
countBadge.style.top='-5px';
countBadge.style.right='-5px';
countBadge.style.backgroundColor='#333333';
countBadge.style.color='#ffffff';
countBadge.style.borderRadius='50%';
countBadge.style.width='20px';
countBadge.style.height='20px';
countBadge.style.fontSize='11px';
countBadge.style.fontWeight='bold';
countBadge.style.display='flex';
countBadge.style.alignItems='center';
countBadge.style.justifyContent='center';
countBadge.style.border='2px solid #ffffff';
countBadge.style.boxShadow =
'0 2px 4px rgba(0,0,0,0.2)';
countBadge.textContent=propertiesAtLocation.length;
markerContent.appendChild(countBadge);
}
marker=new google.maps.marker.AdvancedMarkerElement({
map: houzezMap,
position: position,
content: markerContent,
title: markerTitle,
});
marker.propertyId=propertyId;
}
if(propertiesAtLocation.length > 1){
marker.groupedProperties=propertiesAtLocation;
}
var mainContent=document.createElement('div');
mainContent.className='property-info-window';
var innerHTML='';
if(propertiesAtLocation.length===1){
const property=propertiesAtLocation[0];
if(property.thumbnail){
innerHTML +=
'<div class="info-window-image">' +
property.featured_label +
'<a target="' +
property.link_target +
'" href="' +
property.url +
'">' +
'<img class="img-fluid listing-thumbnail" src="' +
infoWindowPlac +
'" data-src="' +
property.thumbnail +
'" alt="' +
property.title +
'"/>' +
'</a>' +
'</div>';
}else{
innerHTML +=
'<div class="info-window-image">' +
property.featured_label +
'<a target="' +
property.link_target +
'" href="' +
property.url +
'">' +
'<img class="img-fluid listing-thumbnail" src="' +
infoWindowPlac +
'" alt="' +
property.title +
'"/>' +
'</a>' +
'</div>';
}
innerHTML +=
'<div class="info-content" style="padding:10px;">';
if(property.price){
innerHTML +=
'<div class="info-window-price">' +
property.price +
'</div>';
}
innerHTML +=property.meta;
if(property.property_type){
innerHTML +=
'<div class="info-window-property-type">' +
property.property_type +
'</div>';
}
innerHTML +=property.address;
innerHTML +='</div>';
}else{
innerHTML +=
'<div class="info-window-multiple-properties" style="position: relative;">';
innerHTML +=
'<div style="max-height: 240px; overflow-y: auto; padding: 10px; ' +
'scrollbar-width: thin; scrollbar-color: #ccc #f5f5f5;" ' +
'class="info-window-scrollable">';
for (let j=0; j < propertiesAtLocation.length; j++){
const property=propertiesAtLocation[j];
const isLastItem =
j===propertiesAtLocation.length - 1;
innerHTML +=
'<div class="info-window-property-item" data-property-id="' +
property.property_id +
'" style="' +
(isLastItem
? ''
: 'border-bottom: 1px solid #eee; ') +
'padding: 10px 0; display: flex; gap: 10px;">';
innerHTML +='<div style="flex-shrink: 0;">';
if(property.thumbnail){
innerHTML +=
'<a target="' +
property.link_target +
'" href="' +
property.url +
'">' +
'<img class="listing-thumbnail" src="' +
infoWindowPlac +
'" data-src="' +
property.thumbnail +
'" alt="' +
property.title +
'" style="width: 80px; height: 60px; object-fit: cover; border-radius: 4px;"/>' +
'</a>';
}else{
innerHTML +=
'<a target="' +
property.link_target +
'" href="' +
property.url +
'">' +
'<img class="listing-thumbnail" src="' +
infoWindowPlac +
'" alt="' +
property.title +
'" style="width: 80px; height: 60px; object-fit: cover; border-radius: 4px;"/>' +
'</a>';
}
innerHTML +='</div>';
innerHTML +='<div style="flex: 1; min-width: 0;">';
innerHTML +=
'<h5 style="margin: 0 0 5px 0; font-size: 14px; font-weight: 600;">' +
'<a target="' +
property.link_target +
'" href="' +
property.url +
'" style="color: #333; text-decoration: none;">' +
(property.title||'Property ' + (j + 1)) +
'</a></h5>';
if(property.price){
innerHTML +=
'<div style="font-weight: 600; font-size: 14px; margin-bottom: 3px;">' +
property.price +
'</div>';
}
if(property.property_type){
innerHTML +=
'<div style="font-size: 12px; color: #666;">' +
property.property_type +
'</div>';
}
innerHTML +='</div>';
innerHTML +='</div>';
}
innerHTML +='</div>';
innerHTML +='</div>';
}
mainContent.innerHTML=innerHTML;
if(propertiesAtLocation.length > 1){
const styleElement=document.createElement('style');
styleElement.textContent=`
.info-window-scrollable::-webkit-scrollbar {
width: 6px;
}
.info-window-scrollable::-webkit-scrollbar-track {
background: #f5f5f5;
border-radius: 3px;
}
.info-window-scrollable::-webkit-scrollbar-thumb {
background: #ccc;
border-radius: 3px;
}
.info-window-scrollable::-webkit-scrollbar-thumb:hover {
background: #999;
}
`;
mainContent.appendChild(styleElement);
}
if(!document.getElementById('houzez-marker-styles')){
const globalStyleElement=document.createElement('style');
globalStyleElement.id='houzez-marker-styles';
globalStyleElement.textContent=`
.gm-style .gm-style-iw-c,
.gm-style .gm-style-iw-d,
.gm-style-iw,
.gm-style-iw-c,
.gmp-marker-view,
[role="button"]:focus,
[role="button"]:active {
outline: none !important;
border: none !important;
box-shadow: none !important;
}
gmp-advanced-marker,
.gmp-advanced-marker {
outline: none !important;
border: none !important;
box-shadow: none !important;
}
.info-window-property-item.property-highlighted {
background-color: #f0f8ff !important;
}
`;
document.head.appendChild(globalStyleElement);
}
var infowindow=new google.maps.InfoWindow({
content: mainContent,
maxWidth: 350,
});
houzezMarkerInfoWindow(houzezMap, marker, infowindow);
markers.push(marker);
}
if(!preservePosition){
houzez_map_bounds();
}
if(map_cluster_enable!=0){
try {
if(markerClusterer){
if(typeof markerClusterer.clearMarkers==='function'
){
markerClusterer.clearMarkers();
}else if(typeof markerClusterer.clear==='function'
){
markerClusterer.clear();
}}
if(typeof window.markerClusterer!=='undefined'){
markerClusterer =
new window.markerClusterer.MarkerClusterer({
map: houzezMap,
markers: markers,
algorithm:
new window.markerClusterer.GridAlgorithm({
maxZoom: parseInt(clusterer_zoom),
gridSize: 60,
}),
renderer: {
render: ({ count, position })=> {
const clusterDiv =
document.createElement('div');
clusterDiv.className =
'houzez-cluster-marker';
clusterDiv.style.backgroundImage=`url(${clusterIcon})`;
clusterDiv.style.width='48px';
clusterDiv.style.height='48px';
clusterDiv.style.backgroundSize =
'contain';
clusterDiv.style.display='flex';
clusterDiv.style.justifyContent =
'center';
clusterDiv.style.alignItems='center';
clusterDiv.style.color='#ffffff';
clusterDiv.style.fontWeight='bold';
clusterDiv.textContent=count;
return new google.maps.marker.AdvancedMarkerElement({
position,
content: clusterDiv,
}
);
},
},
onClusterClick: (event, cluster, map)=> {
const bounds =
new google.maps.LatLngBounds();
cluster.markers.forEach((marker)=> {
bounds.extend(marker.position);
});
const currentZoom=map.getZoom();
map.fitBounds(bounds);
if(cluster.markers.length > 1){
google.maps.event.addListenerOnce(map,
'bounds_changed',
()=> {
const maxZoom=Math.min(currentZoom + 1,
16
);
if(map.getZoom() > maxZoom){
map.setZoom(maxZoom);
}}
);
}},
});
}else{
console.error('MarkerClusterer library not found. Make sure it is properly loaded.'
);
}} catch (error){
console.error('Error initializing marker clustering:',
error
);
}}
};
const findMarkerByPropertyId=(markers, propertyId)=> {
if(!propertyId||!markers||markers.length===0) return null;
const propIdStr=propertyId.toString();
for (let i=0; i < markers.length; i++){
const marker=markers[i];
if(marker.propertyId===propIdStr){
return { marker: marker, index: i };}
if(marker.groupedProperties){
for (let j=0; j < marker.groupedProperties.length; j++){
if(marker.groupedProperties[
j
].property_id.toString()===propIdStr
){
return {
marker: marker,
index: i,
propertyIndex: j,
};}}
}}
return null;
};
const openInfoWindowById=function (propertyId){
if(!propertyId){
console.log('No property ID provided to openInfoWindowById');
return;
}
let propIdToUse=propertyId;
if(typeof propIdToUse==='string' &&
propIdToUse.indexOf('hz-')===0
){
propIdToUse=propIdToUse.replace('hz-', '');
}
hideInfoWindows();
const markerResult=findMarkerByPropertyId(markers, propIdToUse);
if(markerResult){
const marker=markerResult.marker;
if(marker.content){
marker.content.click();
}else{
marker.click();
}
if(typeof markerResult.propertyIndex!=='undefined'){
setTimeout(()=> {
scrollToPropertyInInfoWindow(propIdToUse);
}, 100);
}
return true;
}else{
console.log('No marker found for property ID:', propIdToUse);
return false;
}};
const scrollToPropertyInInfoWindow=function (propertyId){
const propertyItem=document.querySelector('.info-window-property-item[data-property-id="' +
propertyId +
'"]'
);
if(propertyItem){
clearAllPropertyHighlights();
propertyItem.style.transition='background-color 0.3s ease';
propertyItem.classList.add('property-highlighted');
propertyItem.style.setProperty('background-color',
'#f0f8ff',
'important'
);
const scrollContainer=propertyItem.closest('.info-window-scrollable'
);
if(scrollContainer){
const itemTop=propertyItem.offsetTop;
const containerHeight=scrollContainer.clientHeight;
const itemHeight=propertyItem.offsetHeight;
if(itemTop===0){
scrollContainer.scrollTop=0;
}else{
const targetScrollTop=itemTop - 10;
scrollContainer.scrollTop=Math.max(0,
targetScrollTop
);
}}
}};
const clearAllPropertyHighlights=function (){
const highlightedItems=document.querySelectorAll('.property-highlighted'
);
highlightedItems.forEach((item)=> {
item.style.backgroundColor='';
item.classList.remove('property-highlighted');
});
};
const initInfoboxTrigger=function (){
if(is_mobile()) return;
$('#half-map-listing-area .hz-map-trigger').each(function (){
var propertyID=$(this).data('hz-id');
if(typeof propertyID==='string'){
if(propertyID.indexOf('hz-')===0){
propertyID=propertyID.replace('hz-', '');
}}else{
propertyID=$(this)
.data('hz-id')
.toString()
.replace(/[^\d.]/g, '');
}
const propID=propertyID;
$(this).on('mouseenter', function (){
if(houzezMap){
openInfoWindowById(propID);
}});
$(this).on('mouseleave', function (){
clearAllPropertyHighlights();
hideInfoWindows();
});
});
};
const houzez_half_map_listings=function (current_page, current_form){
var ajax_container=$('#houzez_ajax_container');
var total_results=$('#half-map-listing-area .page-title span');
var sortby=$('#ajax_sort_properties').val();
var item_layout=$('.listing-view').data('layout');
var layout_css=$('.listing-view').data('css');
var layout_view=$('.listing-view').data('view');
const formData=current_form.serialize();
const ajaxData={
action: 'houzez_half_map_listings',
paged: current_page,
sortby: sortby,
item_layout: item_layout,
layout_css: layout_css,
layout_view: layout_view,
};
ajaxData.is_pagination_request=pagination_only;
const serializedData=formData + '&' + $.param(ajaxData);
let finalData=serializedData;
$.ajax({
type: 'GET',
dataType: 'json',
url: ajaxurl,
data: finalData,
beforeSend: function (){
$('.houzez-map-loading').show();
ajax_container
.empty()
.append('' +
'<div id="houzez-map-loading" class="houzez-map-loading">' +
'<div class="mapPlaceholder">' +
'<div class="loader-ripple spinner">' +
'<div class="bounce1"></div>' +
'<div class="bounce2"></div>' +
'<div class="bounce3"></div>' +
'</div>' +
'</div>' +
'</div>'
);
},
success: function (data){
if(data.query!=''){
$('input[name="search_args"]').val(data.query);
}
if(data.search_uri!=''){
$('input[name="search_URI"]').val(data.search_uri);
}
$('.map-notfound').remove();
$('.search-no-results-found').remove();
$('.houzez-map-loading').hide();
if(data.total_results > 0){
if(data.getProperties===true){
let currentCenter=houzezMap.getCenter();
let currentZoom=houzezMap.getZoom();
clearClusterer();
reloadMarkers();
houzezAddMarkers(
data.properties,
houzezMap,
viewport_search
);
if(viewport_search){
if(currentCenter&&currentZoom){
houzezMap.setCenter(currentCenter);
houzezMap.setZoom(currentZoom);
}}
showMapMessage(
data.properties.length,
data.total_results
);
}
ajax_container.empty().html(data.propHtml);
total_results.empty().html(data.total_results);
map_ajax_pagination();
houzez_listing_lightbox();
houzez_grid_image_gallery();
houzez_grid_call_to_action();
compare_for_ajax();
if(!is_mobile()){
initInfoboxTrigger();
}
$('[data-bs-toggle="tooltip"]').tooltip();
}else{
clearClusterer();
reloadMarkers();
let currentCenter=houzezMap.getCenter();
let currentZoom=houzezMap.getZoom();
if(viewport_search){
if(currentCenter&&currentZoom){
houzezMap.setCenter(currentCenter);
houzezMap.setZoom(currentZoom);
}}
houzez_map_zoomin(houzezMap);
houzez_map_zoomout(houzezMap);
$('#houzez-properties-map').append('<div class="map-notfound">' + not_found + '</div>'
);
ajax_container.empty().html(data.propHtml);
total_results.empty().html(data.total_results);
}
return false;
},
complete: function (){
pagination_only=false;
viewport_search=false;
isSearchInProgress=false;
$('.location-trigger')
.find('.icon-location-target')
.removeClass('icon-spin');
},
error: function (xhr, status, error){
console.log(xhr.status);
console.log(xhr.responseText);
console.log(thrownError);
},
});
return false;
};
const triggerDistanceRangeSearch=function (){
if($('#houzez-properties-map').length > 0){
let current_page=0;
let distanceRange=$('#radius-range-slider');
let $form=$('#desktop-search-form');
distanceRange.on('change', (e)=> {
$('input[name="use_radius"]').prop('checked', true);
$('input[name="ne_lat"]').val('');
$('input[name="ne_lng"]').val('');
$('input[name="sw_lat"]').val('');
$('input[name="sw_lng"]').val('');
$('input[name="zoom"]').val('');
houzez_search_on_change(null, $form);
});
}};
const triggerPriceRangeSearch=function (){
if($('#houzez-properties-map').length > 0){
let current_page=0;
let fromPrice=$('#fromSlider_price_range_halfmap');
let toPrice=$('#toSlider_price_range_halfmap');
let $form=$('#desktop-search-form');
fromPrice.on('change', (e)=> {
houzez_search_on_change(null, $form);
});
toPrice.on('change', (e)=> {
houzez_search_on_change(null, $form);
});
}};
const triggerPriceRangeSearchMobile=function (){
if($('#houzez-properties-map').length > 0){
let current_page=0;
let fromPrice=$('#fromSlider_price_range_mobile');
let toPrice=$('#toSlider_price_range_mobile');
let $form=$('#mobile-search-form');
fromPrice.on('change', (e)=> {
houzez_search_on_change(null, $form);
});
toPrice.on('change', (e)=> {
houzez_search_on_change(null, $form);
});
}};
const houzezSetPushState=(pageUrl)=> {
window.history.pushState({ houzezTheme: true }, '', pageUrl);
};
const houzez_set_url=function (currentForm){
var $form =
currentForm||$('form.houzez-search-filters-js').first();
if($form.length){
$form.addClass('loading');
}
var url=$form.attr('action');
if(url==undefined){
return true;
}
var formData=$form
.find(':input')
.filter(function (index, element){
if(!$(element).prop('disabled') &&
$(element).val()!='' &&
$(element).attr('name')!='search_geolocation' &&
$(element).attr('name')!='search_URI' &&
$(element).attr('name')!='search_args' &&
$(element).attr('name')!='houzez_save_search_ajax'
){
return true;
}})
.serialize();
if(url==undefined){
url='';
}else if(url.indexOf('?')!=-1){
url=url + '?' + formData;
}else{
url=url + '?' + formData;
}
houzezSetPushState(url);
};
const initializeFullScreenToggle=function (){
$('#houzez-gmap-full').on('click', function (){
var $this=$(this);
if($this.hasClass('active')){
$this.removeClass('active');
$this
.parents('.map-wrap')
.removeClass('houzez-fullscreen-map');
}else{
$this
.parents('.map-wrap')
.addClass('houzez-fullscreen-map');
$this.addClass('active');
}});
};
const houzez_search_on_change=function (
$this=null,
currentForm=null,
current_page=0
){
if(isSearchInProgress){
return;
}
let $form=currentForm;
if(!$form&&$this){
$form=$this.parents('form');
}
if(!$form||!$form.length){
console.warn('No valid form found for search');
return;
}
isSearchInProgress=true;
$('.hz-halfmap-paged').val(current_page);
houzez_set_url($form);
houzez_half_map_listings(current_page, $form);
};
const updateViewportCoordinates=()=> {
if(!auto_load_map_listings){
return;
}
viewport_search=true;
let $form=$('#desktop-search-form');
let overlayform=$(
'#mobile-search-form.hz-mobile-overlay-search-js'
);
if(overlayform.length > 0){
$form=$('#mobile-search-form');
}
const bounds=houzezMap.getBounds();
if(bounds){
const ne=bounds.getNorthEast();
const sw=bounds.getSouthWest();
const zoom=houzezMap.getZoom();
$('input[name="ne_lat"]').val(ne.lat());
$('input[name="ne_lng"]').val(ne.lng());
$('input[name="sw_lat"]').val(sw.lat());
$('input[name="sw_lng"]').val(sw.lng());
$('input[name="zoom"]').val(zoom);
$('input[name="use_radius"]').prop('checked', false);
houzez_search_on_change(null, $form);
}};
const initPropertiesInViewport=()=> {
let initialLoad=true;
let isDragging=false;
let lastDragTime=0;
google.maps.event.clearListeners(houzezMap, 'idle');
google.maps.event.clearListeners(houzezMap, 'dragend');
google.maps.event.clearListeners(houzezMap, 'dragstart');
google.maps.event.clearListeners(houzezMap, 'zoom_changed');
google.maps.event.addListener(houzezMap, 'dragstart', function (){
isDragging=true;
});
google.maps.event.addListener(houzezMap, 'dragend', function (){
if(!isSearchInProgress&&isDragging){
updateViewportCoordinates();
lastDragTime=Date.now();
isDragging=false;
}else{
isDragging=false;
}});
};
const map_ajax_pagination=function (){
$('.houzez_ajax_pagination a').on('click', function (e){
e.preventDefault();
if(auto_load_map_listings){
pagination_only=true;
}
let current_page=$(this).data('houzepagi');
let $form=$('#desktop-search-form');
if($('#mobile-search-form.apply-mobile-pagination').length > 0
){
$form=$('#mobile-search-form');
}
houzez_search_on_change(null, $form, current_page);
});
return false;
};
const initMapSearchHandlers=function (){
map_ajax_pagination();
$('#ajax_sort_properties').on('change', function (){
let $form=$('#desktop-search-form');
let mobile_sortby=$(this).hasClass('mobile-sortby');
if(mobile_sortby){
$form=$('#mobile-search-form');
}
houzez_search_on_change(null, $form);
});
$('select.houzez_search_ajax, input.houzez_search_ajax').on('change',
function (){
var $form=$(this).closest('form');
houzez_search_on_change(null, $form);
}
);
if($('.half-map-wrap').length > 0){
$(
'.btn-apply, .half-map-search-js-btn, #auto_complete_ajax'
).on('click', function (e){
e.preventDefault();
let $form=$(this).closest('form');
houzez_search_on_change(null, $form);
});
}};
const initMapViewToggle=function (){
$('#houzez-btn-map-view').on('click', function (e){
e.preventDefault();
$('#half-map-listing-area, .listing-wrap').hide();
$('#map-view-wrap').show();
$('#mobile-search-form').addClass('hz-mobile-overlay-search-js'
);
google.maps.event.trigger(houzezMap, 'resize');
houzez_map_bounds();
});
$('#houzez-btn-listing-view').on('click', function (e){
e.preventDefault();
$('#map-view-wrap').hide();
$('#half-map-listing-area, .listing-wrap').show();
$('#mobile-search-form').removeClass('hz-mobile-overlay-search-js'
);
$('.hz-item-gallery-js').removeClass('houzez-gallery-loaded');
window.setTimeout(function (){
if(houzez.Core &&
typeof houzez.Core.reinitializeAjaxFunctions==='function'
){
houzez.Core.reinitializeAjaxFunctions();
}}, 100);
});
};
const initAutocomplete=function (){
if($('.hz-map-field-js').length > 0){
var geo_country_limit=houzez_vars.geo_country_limit;
var geocomplete_country=houzez_vars.geocomplete_country;
var MapField=function ($container){
this.$container=$container;
};
MapField.prototype={
init: function (){
this.initDomElements();
this.autocomplete();
},
initDomElements: function (){
this.addressField =
this.$container.data('address-field');
},
autocomplete: function (){
var that=this,
$address=this.addressField;
if(null===$address){
return;
}
var options={
types: ['geocode', 'establishment'],
};
var inputField=document.getElementById($address);
var autocomplete=new google.maps.places.Autocomplete(inputField,
options
);
if(geo_country_limit!=0 &&
geocomplete_country!=''
){
if(geocomplete_country=='UAE'){
geocomplete_country='AE';
}
autocomplete.setComponentRestrictions({
country: [geocomplete_country],
});
}
google.maps.event.addListener(autocomplete,
'place_changed',
function (){
var place=autocomplete.getPlace();
var latLng=new google.maps.LatLng(place.geometry.location.lat(),
place.geometry.location.lng()
);
that.updateCoordinate(latLng);
if(is_halfmap){
inputField=$(inputField);
houzez_search_on_change(inputField);
}}
);
},
updateCoordinate: function (latLng){
$('input[name="lat"]').val(latLng.lat());
$('input[name="lng"]').val(latLng.lng());
$('input[name="ne_lat"]').val('');
$('input[name="ne_lng"]').val('');
$('input[name="sw_lat"]').val('');
$('input[name="sw_lng"]').val('');
$('input[name="zoom"]').val('');
$('input[name="use_radius"]').prop('checked', true);
},
};
var initMap=function (){
var $this=$(this);
var controller;
controller=new MapField($this);
controller.init();
};
var init=function (e){
$('.hz-map-field-js').each(initMap);
};
init();
$('.location-trigger').on('click', function (e){
e.preventDefault();
let $this=$(this);
let $parent=$this.parents('.location-search');
let $input=$parent.find('input.search_location_js');
$this.find('.icon-location-target').addClass('icon-spin');
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(function (
position
){
let geocoder=new google.maps.Geocoder();
let latLng=new google.maps.LatLng(position.coords.latitude,
position.coords.longitude
);
geocoder.geocode({ location: latLng },
function (results, status){
if(status===google.maps.GeocoderStatus.OK
){
if(results[0]){
$input.val(results[0].formatted_address
);
}else{
$input.val(houzez_vars.current_location
);
}}else{
$input.val(houzez_vars.current_location
);
}
$('input[name="lat"]').val(position.coords.latitude
);
$('input[name="lng"]').val(position.coords.longitude
);
$('input[name="ne_lat"]').val('');
$('input[name="ne_lng"]').val('');
$('input[name="sw_lat"]').val('');
$('input[name="sw_lng"]').val('');
$('input[name="zoom"]').val('');
$('input[name="use_radius"]').prop('checked',
true
);
if(is_halfmap){
houzez_search_on_change($this);
}else{
$this
.find('.icon-location-target')
.removeClass('icon-spin');
}}
);
});
}});
}};
const initializeMap=async function (){
if($('#houzez-properties-map').length > 0){
let mapElement=$('#houzez-properties-map');
let mapDataJSON=mapElement.data('map');
let mapOptionsJSON=mapElement.data('options');
let mapData, mapOptions;
const searchParams=new URLSearchParams(
window.location.search
);
let searchLat=searchParams.get('lat');
let searchLng=searchParams.get('lng');
if(!searchLat||!searchLng){
searchLat=$('input[name="lat"]').val();
searchLng=$('input[name="lng"]').val();
}
if(!mapDataJSON){
return;
}
try {
if(typeof mapDataJSON==='object'){
mapData=mapDataJSON;
}else{
mapData=JSON.parse(mapDataJSON);
}
if(typeof mapOptionsJSON==='object'){
mapOptions=mapOptionsJSON;
}else if(mapOptionsJSON){
mapOptions=JSON.parse(mapOptionsJSON);
}} catch (e){
console.error('Error parsing map data:', e);
return;
}
if(mapOptions){
clusterIcon=mapOptions.clusterIcon;
map_cluster_enable=mapOptions.map_cluster_enable;
clusterer_zoom=mapOptions.clusterer_zoom;
closeIcon=mapOptions.closeIcon;
infoWindowPlac=mapOptions.infoWindowPlac;
markerPricePins=mapOptions.markerPricePins;
mapType=mapOptions.map_type;
googlemap_style=mapOptions.googlemap_style;
default_lat=parseFloat(mapOptions.default_lat);
default_lng=parseFloat(mapOptions.default_lng);
default_zoom=parseFloat(mapOptions.default_zoom);
max_zoom=parseFloat(mapOptions.max_zoom);
if(searchLat &&
searchLng &&
!isNaN(parseFloat(searchLat)) &&
!isNaN(parseFloat(searchLng))
){
default_lat=parseFloat(searchLat);
default_lng=parseFloat(searchLng);
}
if(mapOptions.center_lat&&mapOptions.center_lng){
default_lat=parseFloat(mapOptions.center_lat);
default_lng=parseFloat(mapOptions.center_lng);
}
var mapConfig={
zoom: default_zoom,
maxZoom: max_zoom,
disableDefaultUI: true,
scrollwheel: false,
center: new google.maps.LatLng(default_lat,
default_lng
),
mapId: mapOptions.mapId,
};}
mapConfig=setupMapType(mapConfig);
houzezMap=new google.maps.Map(document.getElementById('houzez-properties-map'),
mapConfig
);
mapBounds=new google.maps.LatLngBounds();
removeMapLoader();
if(mapData.properties&&mapData.properties.length > 0){
await houzezAddMarkers(mapData.properties, houzezMap);
if(!is_mobile()){
initInfoboxTrigger();
}
let total_results =
$('#total-results').data('total-results');
if(total_results > 0){
showMapMessage(
mapData.properties.length,
total_results
);
}}else{
var defaultLocation=new google.maps.LatLng(default_lat,
default_lng
);
var mapConfig={
center: defaultLocation,
zoom: default_zoom,
maxZoom: max_zoom,
disableDefaultUI: true,
scrollwheel: false,
mapId: mapOptions.mapId,
};
houzezMap=new google.maps.Map(document.getElementById('houzez-properties-map'),
mapConfig
);
jQuery('.houzez-map-loading').hide();
}
initMapControls();
if(auto_load_map_listings&&is_halfmap){
initPropertiesInViewport();
}}
};
const init=async function (){
if(typeof google==='object'&&typeof google.maps==='object'){
initializeMap();
initMapSearchHandlers();
initMapViewToggle();
initAutocomplete();
}
triggerPriceRangeSearch();
triggerPriceRangeSearchMobile();
triggerDistanceRangeSearch();
initializeFullScreenToggle();
};
const createPricePin=async (map, propertyData, position)=> {
if(!propertyData){
return null;
}
const pricePin=document.createElement('div');
pricePin.className=`gm-marker map-marker-label`;
pricePin.dataset.id=propertyData.property_id;
const pricePinInner=document.createElement('div');
pricePinInner.className='gm-marker-price';
pricePinInner.innerHTML=propertyData.pricePin;
pricePin.appendChild(pricePinInner);
const advancedMarker=new google.maps.marker.AdvancedMarkerElement({
map,
position,
content: pricePin,
}
);
advancedMarker.propertyId=propertyData.property_id.toString();
return advancedMarker;
};
return {
init: init,
addMarkers: houzezAddMarkers,
clearClusterer: clearClusterer,
reloadMarkers: reloadMarkers,
mapBounds: houzez_map_bounds,
halfMapAjax: houzez_half_map_listings,
setUrl: houzez_set_url,
searchOnChange: houzez_search_on_change,
changeMapType: houzez_change_map_type,
initInfoboxTrigger: initInfoboxTrigger,
removeMapLoader: removeMapLoader,
createMapCircle: createMapCircle,
createStandardMarker: createStandardMarker,
createPricePin: createPricePin,
triggerPriceRangeSearch: triggerPriceRangeSearch,
triggerPriceRangeSearchMobile: triggerPriceRangeSearchMobile,
triggerDistanceRangeSearch: triggerDistanceRangeSearch,
};})();
houzez.SingleAgentMap=(function (){
let agentMap=null;
const init=async ()=> {
if($('#houzez-agent-sidebar-map').length <=0){
return;
}
let mapZoom=15;
const mapType='roadmap';
const mapId='HOUZEZ_MAP_ID';
const agent_lat=$('#houzez-agent-sidebar-map').data('lat');
const agent_lng=$('#houzez-agent-sidebar-map').data('lng');
if(agent_lat!=''&&agent_lng!=''){
const agentLatLng=new google.maps.LatLng(agent_lat,
agent_lng
);
const mapOptions={
center: agentLatLng,
zoom: mapZoom,
disableDefaultUI: true,
scrollwheel: false,
mapId: mapId,
};
agentMap=new google.maps.Map(document.getElementById('houzez-agent-sidebar-map'),
mapOptions
);
const pinElement=new google.maps.marker.PinElement({
background: '#1DABE3',
borderColor: '#FFFFFF',
glyphColor: '#FFFFFF',
});
const marker=new google.maps.marker.AdvancedMarkerElement({
map: agentMap,
position: agentLatLng,
content: pinElement.element,
});
}};
return {
init: init,
};})();
houzez.SinglePropertyOverviewMap=(function (){
let houzezMap;
let marker=null;
const init=async ()=> {
if($('#houzez-overview-listing-map').length <=0){
return;
}
let options;
let infoWindowPlac;
let closeIcon;
const mapElement=$('#houzez-overview-listing-map');
let mapDataJSON=mapElement.data('map');
let mapOptionsJSON=mapElement.data('options');
if(!mapDataJSON){
return;
}
let mapZoom=15;
let google_map_style='';
let showCircle=false;
let map_pin_type='marker';
let markerPricePins='no';
let mapId='HOUZEZ_MAP_ID';
if(mapOptionsJSON){
try {
if(typeof mapOptionsJSON==='object'){
options=mapOptionsJSON;
}else{
options=JSON.parse(mapOptionsJSON);
}} catch (e){
console.error('Error parsing map options:', e);
}}
try {
if(typeof mapDataJSON==='object'){
mapDataJSON=mapDataJSON;
}else{
mapDataJSON=JSON.parse(mapDataJSON);
}} catch (e){
console.error('Error parsing map data:', e);
return;
}
if(!mapDataJSON.latitude||!mapDataJSON.longitude){
console.error('Property coordinates not provided');
return;
}
if(options){
closeIcon=options.closeIcon;
infoWindowPlac=options.infoWindowPlac;
markerPricePins=options.markerPricePins;
map_pin_type=options.map_pin_type;
google_map_style=options.googlemap_style;
mapId=options.mapId||'HOUZEZ_MAP_ID';
if(map_pin_type=='circle'){
showCircle=true;
}
if(options.single_map_zoom > 0){
mapZoom=parseInt(options.single_map_zoom);
}
if(google_map_style){
try {
if(typeof google_map_style==='string'){
google_map_style=JSON.parse(google_map_style);
}} catch (e){
console.error('Error parsing Google Maps style:', e);
google_map_style='';
}}
}
const propertyLatLng=new google.maps.LatLng(mapDataJSON.latitude,
mapDataJSON.longitude
);
const mapOptions={
center: propertyLatLng,
zoom: parseInt(mapZoom),
disableDefaultUI: false,
scrollwheel: false,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapId: mapId,
};
houzezMap=new google.maps.Map(document.getElementById('houzez-overview-listing-map'),
mapOptions
);
if(showCircle){
houzez.Maps.createMapCircle(houzezMap, propertyLatLng);
}else{
const { AdvancedMarkerElement }=google.maps.marker;
if(markerPricePins==='yes'&&mapDataJSON.pricePin){
const pricePin=document.createElement('div');
pricePin.className='gm-marker map-marker-label';
pricePin.dataset.id =
mapDataJSON.property_id||mapDataJSON.post_id;
if(mapDataJSON.marker_color){
pricePin.style.backgroundColor =
mapDataJSON.marker_color;
pricePin.style.borderColor=mapDataJSON.marker_color;
pricePin.style.color='#ffffff';
}
const pricePinInner=document.createElement('div');
pricePinInner.className='gm-marker-price';
pricePinInner.innerHTML=mapDataJSON.pricePin;
pricePin.appendChild(pricePinInner);
marker=new AdvancedMarkerElement({
map: houzezMap,
position: propertyLatLng,
content: pricePin,
title: mapDataJSON.title||'',
});
}else{
let marker_url=mapDataJSON.marker;
if(window.devicePixelRatio > 1.5 &&
mapDataJSON.retinaMarker
){
marker_url=mapDataJSON.retinaMarker;
}
const markerContent=document.createElement('div');
markerContent.style.position='relative';
const markerImage=document.createElement('img');
markerImage.src=marker_url;
markerImage.style.width='44px';
markerImage.style.height='56px';
markerContent.appendChild(markerImage);
marker=new AdvancedMarkerElement({
map: houzezMap,
position: propertyLatLng,
content: markerContent,
title: mapDataJSON.title||'',
});
}}
};
return {
init: init,
};})();
houzez.SinglePropertyMap=(function (){
let propertyMap=null;
let panorama=null;
let streetViewCount=0;
let propertyLatLng=null;
const init=async ({
mapContainerId='houzez-single-listing-map',
streetViewContainerId='pills-street-view',
zoomInBtnId='listing-mapzoomin',
zoomOutBtnId='listing-mapzoomout',
mapTypeSelector='.houzezMapType',
streetViewTabSelector='a[href="#pills-street-view"]',
propertyData=null,
mapOptions={},
}={})=> {
const mapContainer=document.getElementById(mapContainerId);
if(!mapContainer){
console.log('Map container not found:', mapContainerId);
return;
}
if(!propertyData){
try {
const dataAttr=mapContainer.getAttribute('data-map');
if(dataAttr){
propertyData =
typeof dataAttr==='object'
? dataAttr
: JSON.parse(dataAttr);
}} catch (e){
console.error('Error parsing property data:', e);
return;
}}
if(Object.keys(mapOptions).length===0){
try {
const optionsAttr =
mapContainer.getAttribute('data-options');
if(optionsAttr){
mapOptions =
typeof optionsAttr==='object'
? optionsAttr
: JSON.parse(optionsAttr);
}} catch (e){
console.error('Error parsing map options:', e);
}}
if(!propertyData ||
!propertyData.latitude ||
!propertyData.longitude
){
console.error('Property coordinates not provided');
return;
}
propertyLatLng=new google.maps.LatLng(propertyData.latitude,
propertyData.longitude
);
const mapSettings={
center: propertyLatLng,
zoom: parseInt(mapOptions.single_map_zoom)||15,
disableDefaultUI: false,
scrollwheel: false,
mapId: mapOptions.mapId,
};
switch (mapOptions.mapType){
case 'hybrid':
mapSettings.mapTypeId=google.maps.MapTypeId.HYBRID;
break;
case 'terrain':
mapSettings.mapTypeId=google.maps.MapTypeId.TERRAIN;
break;
case 'satellite':
mapSettings.mapTypeId=google.maps.MapTypeId.SATELLITE;
break;
default:
mapSettings.mapTypeId=google.maps.MapTypeId.ROADMAP;
}
propertyMap=new google.maps.Map(mapContainer, mapSettings);
setupMapControls({
map: propertyMap,
zoomInBtnId,
zoomOutBtnId,
mapTypeSelector,
});
await addPropertyMarker({
map: propertyMap,
propertyData,
position: propertyLatLng,
showCircle: mapOptions.map_pin_type==='circle',
markerPricePins: mapOptions.markerPricePins,
});
setupStreetView({
map: propertyMap,
position: propertyLatLng,
streetViewTabSelector,
streetViewContainerId,
});
};
const setupMapControls=({
map,
zoomInBtnId,
zoomOutBtnId,
mapTypeSelector,
})=> {
if(!map) return;
};
const addPropertyMarker=async ({
map,
propertyData,
position,
showCircle=false,
markerPricePins='no',
})=> {
if(!map||!position) return;
if(showCircle){
houzez.Maps.createMapCircle(map, position);
}else{
const { AdvancedMarkerElement }=google.maps.marker;
let marker;
if(markerPricePins==='yes'&&propertyData.pricePin){
const pricePin=document.createElement('div');
pricePin.className='gm-marker map-marker-label';
pricePin.dataset.id=propertyData.property_id;
if(propertyData.marker_color){
pricePin.style.backgroundColor =
propertyData.marker_color;
pricePin.style.borderColor=propertyData.marker_color;
pricePin.style.color='#ffffff';
}
const pricePinInner=document.createElement('div');
pricePinInner.className='gm-marker-price';
pricePinInner.innerHTML=propertyData.pricePin;
pricePin.appendChild(pricePinInner);
marker=new AdvancedMarkerElement({
map,
position,
content: pricePin,
title: propertyData.title,
});
}else{
let marker_url=propertyData.marker;
if(window.devicePixelRatio > 1.5 &&
propertyData.retinaMarker
){
marker_url=propertyData.retinaMarker;
}
const markerContent=document.createElement('div');
markerContent.style.position='relative';
const markerImage=document.createElement('img');
markerImage.src=marker_url;
markerImage.style.width='44px';
markerImage.style.height='56px';
markerContent.appendChild(markerImage);
marker=new AdvancedMarkerElement({
map,
position,
content: markerContent,
title: propertyData.title,
});
}
if(marker){
marker.addListener('gmp-click', ()=> {
});
}}
};
const setupStreetView=({
map,
position,
streetViewTabSelector,
streetViewContainerId,
})=> {
if(!map||!position) return;
const streetViewTab=$(streetViewTabSelector);
if(streetViewTab.length===0) return;
streetViewTab.on('shown.bs.tab', ()=> {
streetViewCount++;
const streetViewContainer=document.getElementById(streetViewContainerId
);
if(!streetViewContainer) return;
const panoramaOptions={
position: position,
pov: {
heading: 34,
pitch: 10,
},
};
if(streetViewCount <=1){
panorama=new google.maps.StreetViewPanorama(streetViewContainer,
panoramaOptions
);
}else if(panorama){
panorama.setPosition(position);
}});
};
const loadMapFromDOM=()=> {
const mapIds=[
'houzez-single-listing-map',
'houzez-single-listing-map-address',
'houzez-single-listing-map-elementor',
];
mapIds.forEach((mapId)=> {
const mapContainer=document.getElementById(mapId);
if(!mapContainer) return;
try {
const mapDataAttr=mapContainer.getAttribute('data-map');
const mapOptionsAttr =
mapContainer.getAttribute('data-options');
if(!mapDataAttr) return;
const propertyData =
typeof mapDataAttr==='object'
? mapDataAttr
: JSON.parse(mapDataAttr);
const mapOptions=mapOptionsAttr
? typeof mapOptionsAttr==='object'
? mapOptionsAttr
: JSON.parse(mapOptionsAttr)
: {};
init({
mapContainerId: mapId,
propertyData,
mapOptions,
}).catch((error)=> {
console.error(`Error initializing single property map (${mapId}):`,
error
);
});
} catch (e){
console.error(`Error initializing property map (${mapId}):`,
e
);
$('.houzez-map-loading').hide();
}});
};
return {
init: loadMapFromDOM,
loadMapFromDOM,
};})();
window.houzez=houzez;
})(jQuery);