function MarkerClusterer(map, opt_markers, opt_options){
this.extend(MarkerClusterer, google.maps.OverlayView);
this.map_=map;
this.markers_=[];
this.clusters_=[];
this.sizes=[ 53, 56, 66, 78, 90 ];
this.styles_=[];
this.ready_=false;
const options=opt_options||{};
this.gridSize_=options.gridSize||60;
this.minClusterSize_=options.minimumClusterSize||2;
this.maxZoom_=options.maxZoom||null;
this.styles_=options.styles||[];
this.imagePath_=options.imagePath ||
this.MARKER_CLUSTER_IMAGE_PATH_;
this.imageExtension_=options.imageExtension ||
this.MARKER_CLUSTER_IMAGE_EXTENSION_;
this.zoomOnClick_=true;
if(options.zoomOnClick!=undefined){
this.zoomOnClick_=options.zoomOnClick;
}
this.averageCenter_=false;
if(options.averageCenter!=undefined){
this.averageCenter_=options.averageCenter;
}
this.setupStyles_();
this.setMap(map);
this.prevZoom_=this.map_.getZoom();
const that=this;
google.maps.event.addListener(this.map_, 'zoom_changed', function(){
const zoom=that.map_.getZoom();
if(that.prevZoom_!=zoom){
that.prevZoom_=zoom;
that.resetViewport();
}});
google.maps.event.addListener(this.map_, 'idle', function(){
that.redraw();
});
if(opt_markers&&opt_markers.length){
this.addMarkers(opt_markers, false);
}}
MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_PATH_=views_addon_maps_clusterer_i10n.cluster_default_imagePath;
MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_EXTENSION_='png';
MarkerClusterer.prototype.extend=function(obj1, obj2){
return(function(object){
for(const property in object.prototype){
this.prototype[ property ]=object.prototype[ property ];
}
return this;
}).apply(obj1, [ obj2 ]);
};
MarkerClusterer.prototype.onAdd=function(){
this.setReady_(true);
};
MarkerClusterer.prototype.draw=function(){};
MarkerClusterer.prototype.setupStyles_=function(){
if(this.styles_.length){
return;
}
for(var i=0, size; size=this.sizes[ i ]; i++){
this.styles_.push({
url: this.imagePath_ +(i + 1) + '.' + this.imageExtension_,
height: size,
width: size,
});
}};
MarkerClusterer.prototype.fitMapToMarkers=function(){
const markers=this.getMarkers();
const bounds=new google.maps.LatLngBounds();
for(var i=0, marker; marker=markers[ i ]; i++){
bounds.extend(marker.getPosition());
}
this.map_.fitBounds(bounds);
};
MarkerClusterer.prototype.setStyles=function(styles){
this.styles_=styles;
};
MarkerClusterer.prototype.getStyles=function(){
return this.styles_;
};
MarkerClusterer.prototype.isZoomOnClick=function(){
return this.zoomOnClick_;
};
MarkerClusterer.prototype.isAverageCenter=function(){
return this.averageCenter_;
};
MarkerClusterer.prototype.getMarkers=function(){
return this.markers_;
};
MarkerClusterer.prototype.getTotalMarkers=function(){
return this.markers_.length;
};
MarkerClusterer.prototype.setMaxZoom=function(maxZoom){
this.maxZoom_=maxZoom;
};
MarkerClusterer.prototype.getMaxZoom=function(){
return this.maxZoom_;
};
MarkerClusterer.prototype.calculator_=function(markers, numStyles){
let index=0;
const count=markers.length;
let dv=count;
while(dv!==0){
dv=parseInt(dv / 10, 10);
index++;
}
index=Math.min(index, numStyles);
return {
text: count,
index: index,
};};
/**
* Set the calculator function.
*
* @param {function(Array, number)} calculator The function to set as the
*     calculator. The function should return a object properties:
*     'text' (string) and 'index' (number).
*
*/
MarkerClusterer.prototype.setCalculator=function(calculator){
this.calculator_=calculator;
};
/**
* Get the calculator function.
*
* @return {function(Array, number)} the calculator function.
*/
MarkerClusterer.prototype.getCalculator=function(){
return this.calculator_;
};
MarkerClusterer.prototype.addMarkers=function(markers, opt_nodraw){
for(var i=0, marker; marker=markers[ i ]; i++){
this.pushMarkerTo_(marker);
}
if(! opt_nodraw){
this.redraw();
}};
MarkerClusterer.prototype.pushMarkerTo_=function(marker){
marker.isAdded=false;
if(marker.draggable){
const that=this;
google.maps.event.addListener(marker, 'dragend', function(){
marker.isAdded=false;
that.repaint();
});
}
this.markers_.push(marker);
};
MarkerClusterer.prototype.addMarker=function(marker, opt_nodraw){
this.pushMarkerTo_(marker);
if(! opt_nodraw){
this.redraw();
}};
MarkerClusterer.prototype.removeMarker_=function(marker){
let index=-1;
if(this.markers_.indexOf){
index=this.markers_.indexOf(marker);
}else{
for(var i=0, m; m=this.markers_[ i ]; i++){
if(m==marker){
index=i;
break;
}}
}
if(index==-1){
return false;
}
marker.setMap(null);
this.markers_.splice(index, 1);
return true;
};
MarkerClusterer.prototype.removeMarker=function(marker, opt_nodraw){
const removed=this.removeMarker_(marker);
if(! opt_nodraw&&removed){
this.resetViewport();
this.redraw();
return true;
}
return false;
};
MarkerClusterer.prototype.removeMarkers=function(markers, opt_nodraw){
let removed=false;
for(var i=0, marker; marker=markers[ i ]; i++){
const r=this.removeMarker_(marker);
removed=removed||r;
}
if(! opt_nodraw&&removed){
this.resetViewport();
this.redraw();
return true;
}};
MarkerClusterer.prototype.setReady_=function(ready){
if(! this.ready_){
this.ready_=ready;
this.createClusters_();
}};
MarkerClusterer.prototype.getTotalClusters=function(){
return this.clusters_.length;
};
MarkerClusterer.prototype.getMap=function(){
return this.map_;
};
MarkerClusterer.prototype.setMap=function(map){
this.map_=map;
};
MarkerClusterer.prototype.getGridSize=function(){
return this.gridSize_;
};
MarkerClusterer.prototype.setGridSize=function(size){
this.gridSize_=size;
};
MarkerClusterer.prototype.getMinClusterSize=function(){
return this.minClusterSize_;
};
MarkerClusterer.prototype.setMinClusterSize=function(size){
this.minClusterSize_=size;
};
MarkerClusterer.prototype.getExtendedBounds=function(bounds){
const projection=this.getProjection();
const tr=new google.maps.LatLng(bounds.getNorthEast().lat(),
bounds.getNorthEast().lng());
const bl=new google.maps.LatLng(bounds.getSouthWest().lat(),
bounds.getSouthWest().lng());
const trPix=projection.fromLatLngToDivPixel(tr);
trPix.x +=this.gridSize_;
trPix.y -=this.gridSize_;
const blPix=projection.fromLatLngToDivPixel(bl);
blPix.x -=this.gridSize_;
blPix.y +=this.gridSize_;
const ne=projection.fromDivPixelToLatLng(trPix);
const sw=projection.fromDivPixelToLatLng(blPix);
bounds.extend(ne);
bounds.extend(sw);
return bounds;
};
MarkerClusterer.prototype.isMarkerInBounds_=function(marker, bounds){
return bounds.contains(marker.getPosition());
};
MarkerClusterer.prototype.clearMarkers=function(){
this.resetViewport(true);
this.markers_=[];
};
MarkerClusterer.prototype.resetViewport=function(opt_hide){
for(var i=0, cluster; cluster=this.clusters_[ i ]; i++){
cluster.remove();
}
for(var i=0, marker; marker=this.markers_[ i ]; i++){
marker.isAdded=false;
if(opt_hide){
marker.setMap(null);
}}
this.clusters_=[];
};
MarkerClusterer.prototype.repaint=function(){
const oldClusters=this.clusters_.slice();
this.clusters_.length=0;
this.resetViewport();
this.redraw();
window.setTimeout(function(){
for(var i=0, cluster; cluster=oldClusters[ i ]; i++){
cluster.remove();
}}, 0);
};
MarkerClusterer.prototype.redraw=function(){
this.createClusters_();
};
MarkerClusterer.prototype.distanceBetweenPoints_=function(p1, p2){
if(! p1||! p2){
return 0;
}
const R=6371;
const dLat=(p2.lat() - p1.lat()) * Math.PI / 180;
const dLon=(p2.lng() - p1.lng()) * Math.PI / 180;
const a=Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c=2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a) );
const d=R * c;
return d;
};
MarkerClusterer.prototype.addToClosestCluster_=function(marker){
let distance=40000;
let clusterToAddTo=null;
const pos=marker.getPosition();
for(var i=0, cluster; cluster=this.clusters_[ i ]; i++){
const center=cluster.getCenter();
if(center){
const d=this.distanceBetweenPoints_(center, marker.getPosition());
if(d < distance){
distance=d;
clusterToAddTo=cluster;
}}
}
if(clusterToAddTo&&clusterToAddTo.isMarkerInClusterBounds(marker) ){
clusterToAddTo.addMarker(marker);
}else{
var cluster=new Cluster(this);
cluster.addMarker(marker);
this.clusters_.push(cluster);
}};
MarkerClusterer.prototype.createClusters_=function(){
if(! this.ready_){
return;
}
const mapBounds=new google.maps.LatLngBounds(this.map_.getBounds().getSouthWest(),
this.map_.getBounds().getNorthEast());
const bounds=this.getExtendedBounds(mapBounds);
for(var i=0, marker; marker=this.markers_[ i ]; i++){
if(! marker.isAdded&&this.isMarkerInBounds_(marker, bounds) ){
this.addToClosestCluster_(marker);
}}
};
function Cluster(markerClusterer){
this.markerClusterer_=markerClusterer;
this.map_=markerClusterer.getMap();
this.gridSize_=markerClusterer.getGridSize();
this.minClusterSize_=markerClusterer.getMinClusterSize();
this.averageCenter_=markerClusterer.isAverageCenter();
this.center_=null;
this.markers_=[];
this.bounds_=null;
this.clusterIcon_=new ClusterIcon(this, markerClusterer.getStyles(),
markerClusterer.getGridSize());
}
Cluster.prototype.isMarkerAlreadyAdded=function(marker){
if(this.markers_.indexOf){
return this.markers_.indexOf(marker)!=-1;
}
for(var i=0, m; m=this.markers_[ i ]; i++){
if(m==marker){
return true;
}}
return false;
};
Cluster.prototype.addMarker=function(marker){
if(this.isMarkerAlreadyAdded(marker) ){
return false;
}
if(! this.center_){
this.center_=marker.getPosition();
this.calculateBounds_();
}else if(this.averageCenter_){
const l=this.markers_.length + 1;
const lat=(this.center_.lat() *(l - 1) + marker.getPosition().lat()) / l;
const lng=(this.center_.lng() *(l - 1) + marker.getPosition().lng()) / l;
this.center_=new google.maps.LatLng(lat, lng);
this.calculateBounds_();
}
marker.isAdded=true;
this.markers_.push(marker);
const len=this.markers_.length;
if(len < this.minClusterSize_&&marker.getMap()!=this.map_){
marker.setMap(this.map_);
}
if(len==this.minClusterSize_){
for(let i=0; i < len; i++){
this.markers_[ i ].setMap(null);
}}
if(len >=this.minClusterSize_){
marker.setMap(null);
}
this.updateIcon();
return true;
};
Cluster.prototype.getMarkerClusterer=function(){
return this.markerClusterer_;
};
Cluster.prototype.getBounds=function(){
const bounds=new google.maps.LatLngBounds(this.center_, this.center_);
const markers=this.getMarkers();
for(var i=0, marker; marker=markers[ i ]; i++){
bounds.extend(marker.getPosition());
}
return bounds;
};
Cluster.prototype.remove=function(){
this.clusterIcon_.remove();
this.markers_.length=0;
delete this.markers_;
};
Cluster.prototype.getSize=function(){
return this.markers_.length;
};
Cluster.prototype.getMarkers=function(){
return this.markers_;
};
Cluster.prototype.getCenter=function(){
return this.center_;
};
Cluster.prototype.calculateBounds_=function(){
const bounds=new google.maps.LatLngBounds(this.center_, this.center_);
this.bounds_=this.markerClusterer_.getExtendedBounds(bounds);
};
Cluster.prototype.isMarkerInClusterBounds=function(marker){
return this.bounds_.contains(marker.getPosition());
};
Cluster.prototype.getMap=function(){
return this.map_;
};
Cluster.prototype.updateIcon=function(){
const zoom=this.map_.getZoom();
const mz=this.markerClusterer_.getMaxZoom();
if(mz&&zoom > mz){
for(var i=0, marker; marker=this.markers_[ i ]; i++){
marker.setMap(this.map_);
}
return;
}
if(this.markers_.length < this.minClusterSize_){
this.clusterIcon_.hide();
return;
}
const numStyles=this.markerClusterer_.getStyles().length;
const sums=this.markerClusterer_.getCalculator()(this.markers_, numStyles);
this.clusterIcon_.setCenter(this.center_);
this.clusterIcon_.setSums(sums);
this.clusterIcon_.show();
};
function ClusterIcon(cluster, styles, opt_padding){
cluster.getMarkerClusterer().extend(ClusterIcon, google.maps.OverlayView);
this.styles_=styles;
this.padding_=opt_padding||0;
this.cluster_=cluster;
this.center_=null;
this.map_=cluster.getMap();
this.div_=null;
this.sums_=null;
this.visible_=false;
this.setMap(this.map_);
}
ClusterIcon.prototype.triggerClusterClick=function(event){
const markerClusterer=this.cluster_.getMarkerClusterer();
google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_, event);
if(markerClusterer.isZoomOnClick()){
this.map_.fitBounds(this.cluster_.getBounds());
}};
ClusterIcon.prototype.triggerClusterMouseover=function(event){
const markerClusterer=this.cluster_.getMarkerClusterer();
google.maps.event.trigger(markerClusterer, 'clustermouseover', this.cluster_, event);
};
ClusterIcon.prototype.triggerClusterMouseout=function(event){
const markerClusterer=this.cluster_.getMarkerClusterer();
google.maps.event.trigger(markerClusterer, 'clustermouseout', this.cluster_, event);
};
ClusterIcon.prototype.onAdd=function(){
this.div_=document.createElement('DIV');
if(this.visible_){
const pos=this.getPosFromLatLng_(this.center_);
this.div_.style.cssText=this.createCss(pos);
this.div_.innerHTML=this.sums_.text;
}
const panes=this.getPanes();
panes.overlayMouseTarget.appendChild(this.div_);
const that=this;
google.maps.event.addDomListener(this.div_, 'click', function(event){
that.triggerClusterClick(event);
});
google.maps.event.addDomListener(this.div_, 'mouseover', function(event){
that.triggerClusterMouseover(event);
});
google.maps.event.addDomListener(this.div_, 'mouseout', function(event){
that.triggerClusterMouseout(event);
});
};
ClusterIcon.prototype.getPosFromLatLng_=function(latlng){
const pos=this.getProjection().fromLatLngToDivPixel(latlng);
if(typeof this.iconAnchor_==='object'&&this.iconAnchor_.length===2){
pos.x -=this.iconAnchor_[ 0 ];
pos.y -=this.iconAnchor_[ 1 ];
}else{
pos.x -=parseInt(this.width_ / 2, 10);
pos.y -=parseInt(this.height_ / 2, 10);
}
return pos;
};
ClusterIcon.prototype.draw=function(){
if(this.visible_){
const pos=this.getPosFromLatLng_(this.center_);
this.div_.style.top=pos.y + 'px';
this.div_.style.left=pos.x + 'px';
}};
ClusterIcon.prototype.hide=function(){
if(this.div_){
this.div_.style.display='none';
}
this.visible_=false;
};
ClusterIcon.prototype.show=function(){
if(this.div_){
const pos=this.getPosFromLatLng_(this.center_);
this.div_.style.cssText=this.createCss(pos);
this.div_.style.display='';
}
this.visible_=true;
};
ClusterIcon.prototype.remove=function(){
this.setMap(null);
};
ClusterIcon.prototype.onRemove=function(){
if(this.div_&&this.div_.parentNode){
this.hide();
this.div_.parentNode.removeChild(this.div_);
this.div_=null;
}};
ClusterIcon.prototype.setSums=function(sums){
this.sums_=sums;
this.text_=sums.text;
this.index_=sums.index;
if(this.div_){
this.div_.innerHTML=sums.text;
}
this.useStyle();
};
ClusterIcon.prototype.useStyle=function(){
let index=Math.max(0, this.sums_.index - 1);
index=Math.min(this.styles_.length - 1, index);
const style=this.styles_[ index ];
this.url_=style.url;
this.height_=style.height;
this.width_=style.width;
this.textColor_=style.textColor;
this.anchor_=style.anchor;
this.textSize_=style.textSize;
this.backgroundPosition_=style.backgroundPosition;
this.iconAnchor_=style.iconAnchor;
};
ClusterIcon.prototype.setCenter=function(center){
this.center_=center;
};
ClusterIcon.prototype.createCss=function(pos){
const style=[];
style.push('background-image:url(' + this.url_ + ');');
const backgroundPosition=this.backgroundPosition_ ? this.backgroundPosition_:'0 0';
style.push('background-position:' + backgroundPosition + ';');
if(typeof this.anchor_==='object'){
if(typeof this.anchor_[ 0 ]==='number'&&this.anchor_[ 0 ] > 0 &&
this.anchor_[ 0 ] < this.height_){
style.push('height:' +(this.height_ - this.anchor_[ 0 ]) +
'px; padding-top:' + this.anchor_[ 0 ] + 'px;');
}else if(typeof this.anchor_[ 0 ]==='number'&&this.anchor_[ 0 ] < 0 &&
-this.anchor_[ 0 ] < this.height_){
style.push('height:' + this.height_ + 'px; line-height:' +(this.height_ + this.anchor_[ 0 ]) +
'px;');
}else{
style.push('height:' + this.height_ + 'px; line-height:' + this.height_ +
'px;');
}
if(typeof this.anchor_[ 1 ]==='number'&&this.anchor_[ 1 ] > 0 &&
this.anchor_[ 1 ] < this.width_){
style.push('width:' +(this.width_ - this.anchor_[ 1 ]) +
'px; padding-left:' + this.anchor_[ 1 ] + 'px;');
}else{
style.push('width:' + this.width_ + 'px; text-align:center;');
}}else{
style.push('height:' + this.height_ + 'px; line-height:' +
this.height_ + 'px; width:' + this.width_ + 'px; text-align:center;');
}
const txtColor=this.textColor_ ? this.textColor_:'black';
const txtSize=this.textSize_ ? this.textSize_:11;
style.push('cursor:pointer; top:' + pos.y + 'px; left:' +
pos.x + 'px; color:' + txtColor + '; position:absolute; font-size:' +
txtSize + 'px; font-family:Arial,sans-serif; font-weight:bold');
return style.join('');
};
window.MarkerClusterer=MarkerClusterer;
MarkerClusterer.prototype.addMarker=MarkerClusterer.prototype.addMarker;
MarkerClusterer.prototype.addMarkers=MarkerClusterer.prototype.addMarkers;
MarkerClusterer.prototype.clearMarkers =
MarkerClusterer.prototype.clearMarkers;
MarkerClusterer.prototype.fitMapToMarkers =
MarkerClusterer.prototype.fitMapToMarkers;
MarkerClusterer.prototype.getCalculator =
MarkerClusterer.prototype.getCalculator;
MarkerClusterer.prototype.getGridSize =
MarkerClusterer.prototype.getGridSize;
MarkerClusterer.prototype.getExtendedBounds =
MarkerClusterer.prototype.getExtendedBounds;
MarkerClusterer.prototype.getMap=MarkerClusterer.prototype.getMap;
MarkerClusterer.prototype.getMarkers=MarkerClusterer.prototype.getMarkers;
MarkerClusterer.prototype.getMaxZoom=MarkerClusterer.prototype.getMaxZoom;
MarkerClusterer.prototype.getStyles=MarkerClusterer.prototype.getStyles;
MarkerClusterer.prototype.getTotalClusters =
MarkerClusterer.prototype.getTotalClusters;
MarkerClusterer.prototype.getTotalMarkers =
MarkerClusterer.prototype.getTotalMarkers;
MarkerClusterer.prototype.redraw=MarkerClusterer.prototype.redraw;
MarkerClusterer.prototype.removeMarker =
MarkerClusterer.prototype.removeMarker;
MarkerClusterer.prototype.removeMarkers =
MarkerClusterer.prototype.removeMarkers;
MarkerClusterer.prototype.resetViewport =
MarkerClusterer.prototype.resetViewport;
MarkerClusterer.prototype.repaint =
MarkerClusterer.prototype.repaint;
MarkerClusterer.prototype.setCalculator =
MarkerClusterer.prototype.setCalculator;
MarkerClusterer.prototype.setGridSize =
MarkerClusterer.prototype.setGridSize;
MarkerClusterer.prototype.setMaxZoom =
MarkerClusterer.prototype.setMaxZoom;
MarkerClusterer.prototype.onAdd=MarkerClusterer.prototype.onAdd;
MarkerClusterer.prototype.draw=MarkerClusterer.prototype.draw;
Cluster.prototype.getCenter=Cluster.prototype.getCenter;
Cluster.prototype.getSize=Cluster.prototype.getSize;
Cluster.prototype.getMarkers=Cluster.prototype.getMarkers;
ClusterIcon.prototype.onAdd=ClusterIcon.prototype.onAdd;
ClusterIcon.prototype.draw=ClusterIcon.prototype.draw;
ClusterIcon.prototype.onRemove=ClusterIcon.prototype.onRemove;
var WPViews=WPViews||{};
WPViews.view_addon_maps_clusters={};
WPViews.view_addon_maps_osm_clusters={};
jQuery(document).on('js_event_wpv_addon_maps_init_map_completed', function(event, data){
let defaults={
map_id:	false,
map_options:	{},
},
settings=jQuery.extend({}, defaults, data),
cluster_options;
if(views_addon_maps_i10n.api_used=='google' &&
settings.map_id!=false &&
_.has(settings.map_options, 'cluster') &&
settings.map_options.cluster=='on'
){
cluster_options=WPViews.view_addon_maps.get_cluster_options(settings.map_id);
WPViews.view_addon_maps_clusters[ settings.map_id ]=new MarkerClusterer(WPViews.view_addon_maps.maps[ settings.map_id ], _.toArray(WPViews.view_addon_maps.markers[ settings.map_id ]), cluster_options);
if(cluster_options.hasOwnProperty('calculator') ){
WPViews.view_addon_maps_clusters[ settings.map_id ].setCalculator(cluster_options.calculator);
}}else if(views_addon_maps_i10n.api_used=='osm' &&
settings.map_id!=false &&
_.has(settings.map_options, 'cluster') &&
settings.map_options.cluster=='on' &&
typeof L!=='undefined' &&
typeof L.markerClusterGroup==='function'
){
if(WPViews.view_addon_maps.maps[ settings.map_id ]){
let existingClusterGroup=null;
WPViews.view_addon_maps.maps[ settings.map_id ].eachLayer(function(layer){
if(layer instanceof L.MarkerClusterGroup){
existingClusterGroup=layer;
}});
if(existingClusterGroup){
WPViews.view_addon_maps_osm_clusters[ settings.map_id ]=existingClusterGroup;
}}
}});
jQuery(document).on('js_event_wpv_addon_maps_clean_map_completed', function(event, data){
let defaults={
map_id:	false,
},
settings=jQuery.extend({}, defaults, data);
if(settings.map_id!=false){
WPViews.view_addon_maps_clusters=_.omit(WPViews.view_addon_maps_clusters, settings.map_id);
WPViews.view_addon_maps_osm_clusters=_.omit(WPViews.view_addon_maps_osm_clusters, settings.map_id);
}});