{"version":3,"sources":["webpack:///o-region-map.js","webpack:///./Sig.Web/src/atomic/organism/o-region-map/o-region-map.chunk.js","webpack:///./Sig.Web/src/atomic/organism/o-region-map/icons/pin.png","webpack:///./Sig.Web/src/atomic/organism/o-region-map/icons/dot.png","webpack:///./Sig.Web/src/atomic/organism/o-region-map/RegionMapCtrl.js","webpack:///./Sig.Web/src/atomic/organism/o-region-map/RegionMapItem.js","webpack:///./Sig.Web/src/atomic/organism/o-region-map/RegionMap.js","webpack:///./node_modules/@google/markerclustererplus/src/markerclusterer.js","webpack:///./Sig.Web/src/atomic/organism/o-region-map/RegionMapStyle.js","webpack:///./Sig.Web/src/atomic/organism/o-region-map/icons/cluster.png","webpack:///./Sig.Web/src/utils/google-map-api/index.js"],"names":["webpackJsonp","169","module","exports","__webpack_require__","require","$","RegionMapCtrl","each","this","170","171","172","173","RegionItem","RegionMap","GoogleMapAPI","moduleHtmlElement","_self","$module","items","map","apiKey","openItem","item","i","length","isOpen","closeItem","open","getMap","close","closeAllItems","getItems","getModuleHtmlElement","onResize","onLayout","onReady","push","attr","window","on","174","ItemMarker","ctrl","gmapMarker","isClosed","googleMap","infoWindow","google","maps","InfoWindow","maxWidth","minWidth","event","addListener","active","inactive","setWindowHtml","html","setContent","visible","hide","setVisible","show","setAnimation","Animation","ln","setTimeout","iconPin","setIcon","url","size","Size","origin","Point","anchor","scaledSize","iconDot","clickable","itemHtmlElement","$item","lat","lng","isArchived","regionCodes","marker","setGmapMarker","getLat","getLng","onVisibilityChange","isVisible","parseFloat","data","split","change","newValue","val","includes","175","MarkerClusterer","CreateMap","Map","get","center","zoom","GetDefaultZoom","mapTypeId","MapTypeId","TERRAIN","styles","backgroundColor","scrollwheel","streetViewControl","maxZoom","mapTypeControl","zoomControlOptions","position","ControlPosition","LEFT_TOP","CreateMarker","markers","cluster","ignoreHidden","imagePath","zoomOnClick","Marker","animation","DROP","repaint","LatLngList","forEach","LatLng","latlngbounds","LatLngBounds","latLng","extend","fitBounds","panToBounds","addMarker","176","ClusterIcon","getMarkerClusterer","OverlayView","cluster_","className_","getClusterClass","styles_","center_","div_","sums_","visible_","setMap","Cluster","mc","markerClusterer_","map_","gridSize_","getGridSize","minClusterSize_","getMinimumClusterSize","averageCenter_","getAverageCenter","markers_","bounds_","clusterIcon_","getStyles","opt_markers","opt_options","clusters_","listeners_","activeMap_","ready_","gridSize","minimumClusterSize","maxZoom_","title_","title","zoomOnClick_","undefined","averageCenter","ignoreHidden_","enableRetinaIcons_","enableRetinaIcons","imagePath_","IMAGE_PATH","imageExtension_","imageExtension","IMAGE_EXTENSION","imageSizes_","imageSizes","IMAGE_SIZES","calculator_","calculator","CALCULATOR","batchSize_","batchSize","BATCH_SIZE","batchSizeIE_","batchSizeIE","BATCH_SIZE_IE","clusterClass_","clusterClass","navigator","userAgent","toLowerCase","indexOf","setupStyles_","addMarkers","prototype","onAdd","cMouseDownInCluster","cDraggingMapByCluster","cClusterIcon","gmVersion","version","parseInt","document","createElement","className","getPanes","overlayMouseTarget","appendChild","boundsChangedListener_","addDomListener","e","stopPropagation","theBounds","mz","trigger","getZoomOnClick","getMaxZoom","getBounds","getZoom","setZoom","cancelBubble","onRemove","parentNode","removeListener","clearInstanceListeners","removeChild","draw","pos","getPosFromLatLng_","style","top","y","left","x","zIndex","MAX_ZINDEX","display","img","bp","backgroundPosition_","spriteH","replace","spriteV","cssText","createCss","url_","width_","height_","innerHTML","anchorText_","textColor_","textSize_","fontFamily_","fontWeight_","fontStyle_","textDecoration_","text","getTitle","useStyle","sums","index","Math","max","min","height","width","anchorText","anchorIcon_","anchorIcon","textColor","textSize","textDecoration","fontWeight","fontStyle","fontFamily","backgroundPosition","setCenter","join","latlng","getProjection","fromLatLngToDivPixel","getSize","getMarkers","getCenter","bounds","getPosition","remove","mCount","isMarkerAlreadyAdded_","l","calculateBounds_","isAdded","updateIcon_","isMarkerInClusterBounds","contains","getExtendedBounds","numStyles","getCalculator","cMarkerClusterer","prevZoom_","minZoom","mapTypes","getMapTypeId","resetViewport_","bind","redraw_","fitMapToMarkers","getVisible","getIgnoreHidden","setGridSize","setMinimumClusterSize","setMaxZoom","setStyles","setTitle","setZoomOnClick","setAverageCenter","setIgnoreHidden","getEnableRetinaIcons","setEnableRetinaIcons","getImageExtension","setImageExtension","getImagePath","setImagePath","getImageSizes","setImageSizes","setCalculator","getBatchSizeIE","setBatchSizeIE","setClusterClass","getTotalMarkers","getClusters","getTotalClusters","opt_nodraw","pushMarkerTo_","key","hasOwnProperty","getDraggable","removeMarker","removed","removeMarker_","removeMarkers","r","splice","clearMarkers","oldClusters","slice","projection","tr","getNorthEast","bl","getSouthWest","trPix","blPix","ne","fromDivPixelToLatLng","sw","createClusters_","opt_hide","distanceBetweenPoints_","p1","p2","dLat","PI","dLon","a","sin","cos","atan2","sqrt","isMarkerInBounds_","addToClosestCluster_","d","distance","clusterToAddTo","iFirst","mapBounds","timerRefStatic","clearTimeout","iLast","obj1","obj2","object","property","apply","count","toString","dv","177","featureType","elementType","stylers","visibility","178","179","loadGoogleMapAPI","opts","apiReady","tag","src","async","defer","firstScriptTag","getElementsByTagName","insertBefore","eventGoogleMapAPIReady","createEvent","initEvent","onGoogleMapAPIReady","dispatchEvent","addEventListener"],"mappings":"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","file":"o-region-map.js","sourcesContent":["webpackJsonp([3],{\n\n/***/ 169:\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\n__webpack_require__(170);\n\n// JavaScript\nvar $ = $ = __webpack_require__(0),\n RegionMapCtrl = __webpack_require__(173);\n\n$('.o-region-map__map').each(function () {\n new RegionMapCtrl(this);\n});\n\n/***/ }),\n\n/***/ 170:\n/***/ (function(module, exports) {\n\n// removed by extract-text-webpack-plugin\n\n/***/ }),\n\n/***/ 171:\n/***/ (function(module, exports, __webpack_require__) {\n\nmodule.exports = __webpack_require__.p + \"atomic/organism/o-region-map/icons/pin.png?v=8dabe1\";\n\n/***/ }),\n\n/***/ 172:\n/***/ (function(module, exports, __webpack_require__) {\n\nmodule.exports = __webpack_require__.p + \"atomic/organism/o-region-map/icons/dot.png?v=db8327\";\n\n/***/ }),\n\n/***/ 173:\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar $ = __webpack_require__(0),\n RegionItem = __webpack_require__(174),\n RegionMap = __webpack_require__(175),\n GoogleMapAPI = __webpack_require__(179);\n\nmodule.exports = function (moduleHtmlElement) {\n\n var _self = this,\n $module = $(moduleHtmlElement),\n items = [],\n map = null,\n apiKey = \"\";\n\n _self.openItem = function (item) {\n for (var i = 0; i < items.length; i++) {\n if (items[i].isOpen() && items[i] !== item) {\n _self.closeItem(items[i]);\n }\n }\n item.open(map.getMap());\n };\n\n _self.closeItem = function (item) {\n item.close();\n };\n\n _self.closeAllItems = function () {\n for (var i = 0; i < items.length; i++) {\n _self.closeItem(items[i]);\n }\n };\n\n _self.getItems = function () {\n return items;\n };\n\n _self.getModuleHtmlElement = function () {\n return moduleHtmlElement;\n };\n\n var onResize = function onResize() {\n onLayout();\n };\n\n var onLayout = function onLayout() {\n if (map === null) {\n GoogleMapAPI({\n apiKey: apiKey,\n onReady: function onReady() {\n map = new RegionMap(_self);\n }\n });\n }\n _self.closeAllItems();\n };\n\n var Constructor = function Constructor() {\n $('.o-region-map__item', $module).each(function () {\n items.push(new RegionItem(_self, this));\n });\n if ($module.attr('data-api-key')) {\n apiKey = $module.attr('data-api-key');\n }\n $(window).on(\"resize.regionmap-ctrl\", onResize);\n onResize();\n };\n\n Constructor();\n};\n\n/***/ }),\n\n/***/ 174:\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar $ = __webpack_require__(0);\n\nvar ItemMarker = function ItemMarker(ctrl, item, gmapMarker, isClosed) {\n\n var _self = this;\n var googleMap;;\n var infoWindow = new google.maps.InfoWindow({\n maxWidth: 270,\n minWidth: 160\n });\n\n google.maps.event.addListener(gmapMarker, \"click\", function () {\n if (googleMap) {\n _self.active();\n }\n });\n\n google.maps.event.addListener(infoWindow, 'closeclick', function () {\n _self.inactive();\n });\n\n _self.setWindowHtml = function (html) {\n infoWindow.setContent(html);\n };\n\n _self.active = function (map) {\n if (map) googleMap = map;\n infoWindow.open(map, gmapMarker);\n };\n\n _self.visible = function () {\n return gmapMarker.visible;\n };\n\n _self.hide = function () {\n gmapMarker.setVisible(false);\n };\n\n _self.show = function () {\n if (!gmapMarker.visible) {\n gmapMarker.setVisible(true);\n gmapMarker.setAnimation(google.maps.Animation.ln);\n setTimeout(function () {\n gmapMarker.setAnimation(null);\n }, 750);\n }\n };\n\n _self.inactive = function () {\n infoWindow.close();\n };\n\n // Icône \"pin\" pour les dossiers en cours\n var iconPin = function iconPin() {\n gmapMarker.setIcon({\n url: __webpack_require__(171),\n size: new google.maps.Size(40, 36),\n origin: new google.maps.Point(0, 0),\n anchor: new google.maps.Point(20, 18),\n scaledSize: new google.maps.Size(40, 36)\n });\n };\n // Icône \"dot\" pour les dossiers terminés depuis 2010 \n var iconDot = function iconDot() {\n var size = 12;\n gmapMarker.setIcon({\n url: __webpack_require__(172),\n size: new google.maps.Size(size, size),\n origin: new google.maps.Point(0, 0),\n anchor: new google.maps.Point(size / 2, size / 2),\n scaledSize: new google.maps.Size(size, size)\n });\n };\n\n (function () {\n gmapMarker.clickable = true;\n google.maps.event.addListener(gmapMarker, 'click', function () {\n ctrl.openItem(item);\n });\n\n if (isClosed) {\n iconDot();\n } else {\n iconPin();\n }\n })();\n};\n\nmodule.exports = function (ctrl, itemHtmlElement) {\n\n var _self = this,\n $item = null,\n lat = 0,\n lng = 0,\n isOpen = false,\n isArchived = true,\n regionCodes = [],\n marker = null;\n\n _self.open = function (map) {\n if (isOpen) return;\n if (marker) {\n marker.setWindowHtml($item.html());\n marker.active(map);\n }\n isOpen = true;\n };\n\n _self.close = function () {\n if (!isOpen) return;\n if (marker) {\n marker.inactive();\n }\n isOpen = false;\n };\n\n _self.setGmapMarker = function (gmapMarker) {\n marker = new ItemMarker(ctrl, _self, gmapMarker, isArchived);\n };\n\n _self.getLat = function () {\n return lat;\n };\n\n _self.getLng = function () {\n return lng;\n };\n\n _self.onVisibilityChange = function () {};\n\n _self.isVisible = function () {\n return marker.visible();\n };\n\n _self.isOpen = function () {\n return isOpen;\n };\n\n (function () {\n $item = $(itemHtmlElement);\n lat = parseFloat($item.data(\"lat\"));\n lng = parseFloat($item.data(\"lng\"));\n isArchived = $item.attr(\"data-is-archived\") === \"1\";\n regionCodes = $item.attr(\"data-region-code\").split(\",\");\n\n var regionSelect = $(\"#regionCode\");\n regionSelect.change(function () {\n var newValue = $(this).val();\n if (newValue === \"-\" || regionCodes.includes(newValue)) {\n marker.show();\n } else {\n marker.hide();\n }\n _self.onVisibilityChange();\n });\n })();\n};\n\n/***/ }),\n\n/***/ 175:\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar $ = __webpack_require__(0);\nvar MarkerClusterer = __webpack_require__(176);\n\nmodule.exports = function (ctrl) {\n\n var _self = this;\n\n var $module = $(ctrl.getModuleHtmlElement()),\n map = null,\n bounds = null;\n\n var CreateMap = function CreateMap() {\n map = new google.maps.Map($(\".o-region-map__gmap-container\", $module).get(0), {\n center: { lat: 46.85, lng: -71.22337 },\n zoom: GetDefaultZoom(),\n mapTypeId: google.maps.MapTypeId.TERRAIN,\n styles: __webpack_require__(177),\n backgroundColor: 'none',\n scrollwheel: false,\n streetViewControl: false,\n maxZoom: 11,\n mapTypeControl: false,\n zoomControlOptions: {\n position: google.maps.ControlPosition.LEFT_TOP\n }\n });\n };\n\n // Cluster\n var CreateMarker = function CreateMarker() {\n var items = ctrl.getItems();\n var markers = [];\n\n var cluster = new MarkerClusterer(map, [], {\n ignoreHidden: true,\n maxZoom: 7, // maxZoom set when clustering will stop,\n imagePath: __webpack_require__(178),\n zoomOnClick: true\n });\n\n for (var i = 0; i < items.length; i++) {\n var gmapMarker = new google.maps.Marker({\n position: { lat: items[i].getLat(), lng: items[i].getLng() },\n map: map,\n animation: google.maps.Animation.DROP\n });\n markers.push(gmapMarker);\n items[i].onVisibilityChange = function () {\n cluster.repaint();\n var LatLngList = [];\n items.forEach(function (item) {\n if (item.isVisible()) {\n LatLngList.push(new google.maps.LatLng(item.getLat(), item.getLng()));\n }\n });\n\n if (LatLngList.length == 0) {\n items.forEach(function (item) {\n LatLngList.push(new google.maps.LatLng(item.getLat(), item.getLng()));\n });\n }\n\n var latlngbounds = new google.maps.LatLngBounds();\n\n LatLngList.forEach(function (latLng) {\n latlngbounds.extend(latLng);\n });\n map.fitBounds(latlngbounds);\n map.panToBounds(latlngbounds);\n };\n\n items[i].setGmapMarker(gmapMarker);\n cluster.addMarker(gmapMarker);\n }\n };\n\n var SetBounds = function SetBounds() {\n bounds = new google.maps.LatLngBounds();\n var items = ctrl.getItems();\n for (var i = 0; i < items.length; i++) {\n bounds.extend({ lat: items[i].getLat(), lng: items[i].getLng() });\n }\n };\n\n var GetDefaultZoom = function GetDefaultZoom() {\n return 6;\n };\n\n _self.getMap = function () {\n return map;\n };\n\n var Constructor = function Constructor() {\n CreateMap();\n CreateMarker();\n };\n\n Constructor();\n};\n\n/***/ }),\n\n/***/ 176:\n/***/ (function(module, exports, __webpack_require__) {\n\n/**\n * @name MarkerClustererPlus for Google Maps V3\n * @version 2.1.11\n * @author Gary Little\n * @fileoverview\n * The library creates and manages per-zoom-level clusters for large amounts of markers.\n *
\n * This is an enhanced V3 implementation of the V2 MarkerClusterer by Xiaoxi Wu. It is\n * based on the V3 MarkerClusterer port by Luke Mahe. MarkerClustererPlus was created\n * by Gary Little.\n *
\n * v2.0 release: MarkerClustererPlus v2.0 is backward compatible with MarkerClusterer v1.0. It\n * adds support for the ignoreHidden
, title
, batchSizeIE
,\n * and calculator
properties as well as support for four more events. It also allows\n * greater control over the styling of the text that appears on the cluster marker. The\n * documentation has been significantly improved and the overall code has been simplified and\n * polished. Very large numbers of markers can now be managed without causing Javascript timeout\n * errors on Internet Explorer. Note that the name of the clusterclick
event has been\n * deprecated. The new name is click
, so please change your application code now.\n */\n\n/**\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n/**\n * @name ClusterIconStyle\n * @class This class represents the object for values in the styles
array passed\n * to the {@link MarkerClusterer} constructor. The element in this array that is used to\n * style the cluster icon is determined by calling the calculator
function.\n *\n * @property {string} url The URL of the cluster icon image file. Required.\n * @property {number} height The display height (in pixels) of the cluster icon. Required.\n * @property {number} width The display width (in pixels) of the cluster icon. Required.\n * @property {Array} [anchorText] The position (in pixels) from the center of the cluster icon to\n * where the text label is to be centered and drawn. The format is [yoffset, xoffset]
\n * where yoffset
increases as you go down from center and xoffset
\n * increases to the right of center. The default is [0, 0]
.\n * @property {Array} [anchorIcon] The anchor position (in pixels) of the cluster icon. This is the\n * spot on the cluster icon that is to be aligned with the cluster position. The format is\n * [yoffset, xoffset]
where yoffset
increases as you go down and\n * xoffset
increases to the right of the top-left corner of the icon. The default\n * anchor position is the center of the cluster icon.\n * @property {string} [textColor=\"black\"] The color of the label text shown on the\n * cluster icon.\n * @property {number} [textSize=11] The size (in pixels) of the label text shown on the\n * cluster icon.\n * @property {string} [textDecoration=\"none\"] The value of the CSS text-decoration
\n * property for the label text shown on the cluster icon.\n * @property {string} [fontWeight=\"bold\"] The value of the CSS font-weight
\n * property for the label text shown on the cluster icon.\n * @property {string} [fontStyle=\"normal\"] The value of the CSS font-style
\n * property for the label text shown on the cluster icon.\n * @property {string} [fontFamily=\"Arial,sans-serif\"] The value of the CSS font-family
\n * property for the label text shown on the cluster icon.\n * @property {string} [backgroundPosition=\"0 0\"] The position of the cluster icon image\n * within the image defined by url
. The format is \"xpos ypos\"
\n * (the same format as for the CSS background-position
property). You must set\n * this property appropriately when the image defined by url
represents a sprite\n * containing multiple images. Note that the position must be specified in px units.\n */\n/**\n * @name ClusterIconInfo\n * @class This class is an object containing general information about a cluster icon. This is\n * the object that a calculator
function returns.\n *\n * @property {string} text The text of the label to be shown on the cluster icon.\n * @property {number} index The index plus 1 of the element in the styles
\n * array to be used to style the cluster icon.\n * @property {string} title The tooltip to display when the mouse moves over the cluster icon.\n * If this value is undefined
or \"\"
, title
is set to the\n * value of the title
property passed to the MarkerClusterer.\n */\n/**\n * A cluster icon.\n *\n * @constructor\n * @extends google.maps.OverlayView\n * @param {Cluster} cluster The cluster with which the icon is to be associated.\n * @param {Array} [styles] An array of {@link ClusterIconStyle} defining the cluster icons\n * to use for various cluster sizes.\n * @private\n */\nfunction ClusterIcon(cluster, styles) {\n cluster.getMarkerClusterer().extend(ClusterIcon, google.maps.OverlayView);\n\n this.cluster_ = cluster;\n this.className_ = cluster.getMarkerClusterer().getClusterClass();\n this.styles_ = styles;\n this.center_ = null;\n this.div_ = null;\n this.sums_ = null;\n this.visible_ = false;\n\n this.setMap(cluster.getMap()); // Note: this causes onAdd to be called\n}\n\n\n/**\n * Adds the icon to the DOM.\n */\nClusterIcon.prototype.onAdd = function () {\n var cClusterIcon = this;\n var cMouseDownInCluster;\n var cDraggingMapByCluster;\n var gmVersion = google.maps.version.split(\".\");\n\n gmVersion = parseInt(gmVersion[0] * 100, 10) + parseInt(gmVersion[1], 10);\n\n this.div_ = document.createElement(\"div\");\n this.div_.className = this.className_;\n if (this.visible_) {\n this.show();\n }\n\n this.getPanes().overlayMouseTarget.appendChild(this.div_);\n\n // Fix for Issue 157\n this.boundsChangedListener_ = google.maps.event.addListener(this.getMap(), \"bounds_changed\", function () {\n cDraggingMapByCluster = cMouseDownInCluster;\n });\n\n google.maps.event.addDomListener(this.div_, \"mousedown\", function () {\n cMouseDownInCluster = true;\n cDraggingMapByCluster = false;\n });\n\n// March 1, 2018: Fix for this 3.32 exp bug, https://issuetracker.google.com/issues/73571522\n// But it doesn't work with earlier releases so do a version check.\n if (gmVersion >= 332) { // Ugly version-dependent code\n google.maps.event.addDomListener(this.div_, \"touchstart\", function (e) {\n e.stopPropagation();\n });\n }\n\n google.maps.event.addDomListener(this.div_, \"click\", function (e) {\n cMouseDownInCluster = false;\n if (!cDraggingMapByCluster) {\n var theBounds;\n var mz;\n var mc = cClusterIcon.cluster_.getMarkerClusterer();\n /**\n * This event is fired when a cluster marker is clicked.\n * @name MarkerClusterer#click\n * @param {Cluster} c The cluster that was clicked.\n * @event\n */\n google.maps.event.trigger(mc, \"click\", cClusterIcon.cluster_);\n google.maps.event.trigger(mc, \"clusterclick\", cClusterIcon.cluster_); // deprecated name\n\n // The default click handler follows. Disable it by setting\n // the zoomOnClick property to false.\n if (mc.getZoomOnClick()) {\n // Zoom into the cluster.\n mz = mc.getMaxZoom();\n theBounds = cClusterIcon.cluster_.getBounds();\n mc.getMap().fitBounds(theBounds);\n // There is a fix for Issue 170 here:\n setTimeout(function () {\n mc.getMap().fitBounds(theBounds);\n // Don't zoom beyond the max zoom level\n if (mz !== null && (mc.getMap().getZoom() > mz)) {\n mc.getMap().setZoom(mz + 1);\n }\n }, 100);\n }\n\n // Prevent event propagation to the map:\n e.cancelBubble = true;\n if (e.stopPropagation) {\n e.stopPropagation();\n }\n }\n });\n\n google.maps.event.addDomListener(this.div_, \"mouseover\", function () {\n var mc = cClusterIcon.cluster_.getMarkerClusterer();\n /**\n * This event is fired when the mouse moves over a cluster marker.\n * @name MarkerClusterer#mouseover\n * @param {Cluster} c The cluster that the mouse moved over.\n * @event\n */\n google.maps.event.trigger(mc, \"mouseover\", cClusterIcon.cluster_);\n });\n\n google.maps.event.addDomListener(this.div_, \"mouseout\", function () {\n var mc = cClusterIcon.cluster_.getMarkerClusterer();\n /**\n * This event is fired when the mouse moves out of a cluster marker.\n * @name MarkerClusterer#mouseout\n * @param {Cluster} c The cluster that the mouse moved out of.\n * @event\n */\n google.maps.event.trigger(mc, \"mouseout\", cClusterIcon.cluster_);\n });\n};\n\n\n/**\n * Removes the icon from the DOM.\n */\nClusterIcon.prototype.onRemove = function () {\n if (this.div_ && this.div_.parentNode) {\n this.hide();\n google.maps.event.removeListener(this.boundsChangedListener_);\n google.maps.event.clearInstanceListeners(this.div_);\n this.div_.parentNode.removeChild(this.div_);\n this.div_ = null;\n }\n};\n\n\n/**\n * Draws the icon.\n */\nClusterIcon.prototype.draw = function () {\n if (this.visible_) {\n var pos = this.getPosFromLatLng_(this.center_);\n this.div_.style.top = pos.y + \"px\";\n this.div_.style.left = pos.x + \"px\";\n this.div_.style.zIndex = google.maps.Marker.MAX_ZINDEX + 1; // Put above all unclustered markers\n }\n};\n\n\n/**\n * Hides the icon.\n */\nClusterIcon.prototype.hide = function () {\n if (this.div_) {\n this.div_.style.display = \"none\";\n }\n this.visible_ = false;\n};\n\n\n/**\n * Positions and shows the icon.\n */\nClusterIcon.prototype.show = function () {\n if (this.div_) {\n var img = \"\";\n // NOTE: values must be specified in px units\n var bp = this.backgroundPosition_.split(\" \");\n var spriteH = parseInt(bp[0].replace(/^\\s+|\\s+$/g, \"\"), 10);\n var spriteV = parseInt(bp[1].replace(/^\\s+|\\s+$/g, \"\"), 10);\n var pos = this.getPosFromLatLng_(this.center_);\n this.div_.style.cssText = this.createCss(pos);\n img = \"\";\n this.div_.innerHTML = img + \"
MarkerClusterer
object with which this\n * cluster is associated.\n */\nfunction Cluster(mc) {\n this.markerClusterer_ = mc;\n this.map_ = mc.getMap();\n this.gridSize_ = mc.getGridSize();\n this.minClusterSize_ = mc.getMinimumClusterSize();\n this.averageCenter_ = mc.getAverageCenter();\n this.markers_ = [];\n this.center_ = null;\n this.bounds_ = null;\n this.clusterIcon_ = new ClusterIcon(this, mc.getStyles());\n}\n\n\n/**\n * Returns the number of markers managed by the cluster. You can call this from\n * a click
, mouseover
, or mouseout
event handler\n * for the MarkerClusterer
object.\n *\n * @return {number} The number of markers in the cluster.\n */\nCluster.prototype.getSize = function () {\n return this.markers_.length;\n};\n\n\n/**\n * Returns the array of markers managed by the cluster. You can call this from\n * a click
, mouseover
, or mouseout
event handler\n * for the MarkerClusterer
object.\n *\n * @return {Array} The array of markers in the cluster.\n */\nCluster.prototype.getMarkers = function () {\n return this.markers_;\n};\n\n\n/**\n * Returns the center of the cluster. You can call this from\n * a click
, mouseover
, or mouseout
event handler\n * for the MarkerClusterer
object.\n *\n * @return {google.maps.LatLng} The center of the cluster.\n */\nCluster.prototype.getCenter = function () {\n return this.center_;\n};\n\n\n/**\n * Returns the map with which the cluster is associated.\n *\n * @return {google.maps.Map} The map.\n * @ignore\n */\nCluster.prototype.getMap = function () {\n return this.map_;\n};\n\n\n/**\n * Returns the MarkerClusterer
object with which the cluster is associated.\n *\n * @return {MarkerClusterer} The associated marker clusterer.\n * @ignore\n */\nCluster.prototype.getMarkerClusterer = function () {\n return this.markerClusterer_;\n};\n\n\n/**\n * Returns the bounds of the cluster.\n *\n * @return {google.maps.LatLngBounds} the cluster bounds.\n * @ignore\n */\nCluster.prototype.getBounds = function () {\n var i;\n var bounds = new google.maps.LatLngBounds(this.center_, this.center_);\n var markers = this.getMarkers();\n for (i = 0; i < markers.length; i++) {\n bounds.extend(markers[i].getPosition());\n }\n return bounds;\n};\n\n\n/**\n * Removes the cluster from the map.\n *\n * @ignore\n */\nCluster.prototype.remove = function () {\n this.clusterIcon_.setMap(null);\n this.markers_ = [];\n delete this.markers_;\n};\n\n\n/**\n * Adds a marker to the cluster.\n *\n * @param {google.maps.Marker} marker The marker to be added.\n * @return {boolean} True if the marker was added.\n * @ignore\n */\nCluster.prototype.addMarker = function (marker) {\n var i;\n var mCount;\n var mz;\n\n if (this.isMarkerAlreadyAdded_(marker)) {\n return false;\n }\n\n if (!this.center_) {\n this.center_ = marker.getPosition();\n this.calculateBounds_();\n } else {\n if (this.averageCenter_) {\n var l = this.markers_.length + 1;\n var lat = (this.center_.lat() * (l - 1) + marker.getPosition().lat()) / l;\n var lng = (this.center_.lng() * (l - 1) + marker.getPosition().lng()) / l;\n this.center_ = new google.maps.LatLng(lat, lng);\n this.calculateBounds_();\n }\n }\n\n marker.isAdded = true;\n this.markers_.push(marker);\n\n mCount = this.markers_.length;\n mz = this.markerClusterer_.getMaxZoom();\n if (mz !== null && this.map_.getZoom() > mz) {\n // Zoomed in past max zoom, so show the marker.\n if (marker.getMap() !== this.map_) {\n marker.setMap(this.map_);\n }\n } else if (mCount < this.minClusterSize_) {\n // Min cluster size not reached so show the marker.\n if (marker.getMap() !== this.map_) {\n marker.setMap(this.map_);\n }\n } else if (mCount === this.minClusterSize_) {\n // Hide the markers that were showing.\n for (i = 0; i < mCount; i++) {\n this.markers_[i].setMap(null);\n }\n } else {\n marker.setMap(null);\n }\n\n this.updateIcon_();\n return true;\n};\n\n\n/**\n * Determines if a marker lies within the cluster's bounds.\n *\n * @param {google.maps.Marker} marker The marker to check.\n * @return {boolean} True if the marker lies in the bounds.\n * @ignore\n */\nCluster.prototype.isMarkerInClusterBounds = function (marker) {\n return this.bounds_.contains(marker.getPosition());\n};\n\n\n/**\n * Calculates the extended bounds of the cluster with the grid.\n */\nCluster.prototype.calculateBounds_ = function () {\n var bounds = new google.maps.LatLngBounds(this.center_, this.center_);\n this.bounds_ = this.markerClusterer_.getExtendedBounds(bounds);\n};\n\n\n/**\n * Updates the cluster icon.\n */\nCluster.prototype.updateIcon_ = function () {\n var mCount = this.markers_.length;\n var mz = this.markerClusterer_.getMaxZoom();\n\n if (mz !== null && this.map_.getZoom() > mz) {\n this.clusterIcon_.hide();\n return;\n }\n\n if (mCount < this.minClusterSize_) {\n // Min cluster size not yet reached.\n this.clusterIcon_.hide();\n return;\n }\n\n var numStyles = this.markerClusterer_.getStyles().length;\n var sums = this.markerClusterer_.getCalculator()(this.markers_, numStyles);\n this.clusterIcon_.setCenter(this.center_);\n this.clusterIcon_.useStyle(sums);\n this.clusterIcon_.show();\n};\n\n\n/**\n * Determines if a marker has already been added to the cluster.\n *\n * @param {google.maps.Marker} marker The marker to check.\n * @return {boolean} True if the marker has already been added.\n */\nCluster.prototype.isMarkerAlreadyAdded_ = function (marker) {\n var i;\n if (this.markers_.indexOf) {\n return this.markers_.indexOf(marker) !== -1;\n } else {\n for (i = 0; i < this.markers_.length; i++) {\n if (marker === this.markers_[i]) {\n return true;\n }\n }\n }\n return false;\n};\n\n\n/**\n * @name MarkerClustererOptions\n * @class This class represents the optional parameter passed to\n * the {@link MarkerClusterer} constructor.\n * @property {number} [gridSize=60] The grid size of a cluster in pixels. The grid is a square.\n * @property {number} [maxZoom=null] The maximum zoom level at which clustering is enabled or\n * null
if clustering is to be enabled at all zoom levels.\n * @property {boolean} [zoomOnClick=true] Whether to zoom the map when a cluster marker is\n * clicked. You may want to set this to false
if you have installed a handler\n * for the click
event and it deals with zooming on its own.\n * @property {boolean} [averageCenter=false] Whether the position of a cluster marker should be\n * the average position of all markers in the cluster. If set to false
, the\n * cluster marker is positioned at the location of the first marker added to the cluster.\n * @property {number} [minimumClusterSize=2] The minimum number of markers needed in a cluster\n * before the markers are hidden and a cluster marker appears.\n * @property {boolean} [ignoreHidden=false] Whether to ignore hidden markers in clusters. You\n * may want to set this to true
to ensure that hidden markers are not included\n * in the marker count that appears on a cluster marker (this count is the value of the\n * text
property of the result returned by the default calculator
).\n * If set to true
and you change the visibility of a marker being clustered, be\n * sure to also call MarkerClusterer.repaint()
.\n * @property {string} [title=\"\"] The tooltip to display when the mouse moves over a cluster\n * marker. (Alternatively, you can use a custom calculator
function to specify a\n * different tooltip for each cluster marker.)\n * @property {function} [calculator=MarkerClusterer.CALCULATOR] The function used to determine\n * the text to be displayed on a cluster marker and the index indicating which style to use\n * for the cluster marker. The input parameters for the function are (1) the array of markers\n * represented by a cluster marker and (2) the number of cluster icon styles. It returns a\n * {@link ClusterIconInfo} object. The default calculator
returns a\n * text
property which is the number of markers in the cluster and an\n * index
property which is one higher than the lowest integer such that\n * 10^i
exceeds the number of markers in the cluster, or the size of the styles\n * array, whichever is less. The styles
array element used has an index of\n * index
minus 1. For example, the default calculator
returns a\n * text
value of \"125\"
and an index
of 3
\n * for a cluster icon representing 125 markers so the element used in the styles
\n * array is 2
. A calculator
may also return a title
\n * property that contains the text of the tooltip to be used for the cluster marker. If\n * title
is not defined, the tooltip is set to the value of the title
\n * property for the MarkerClusterer.\n * @property {string} [clusterClass=\"cluster\"] The name of the CSS class defining general styles\n * for the cluster markers. Use this class to define CSS styles that are not set up by the code\n * that processes the styles
array.\n * @property {Array} [styles] An array of {@link ClusterIconStyle} elements defining the styles\n * of the cluster markers to be used. The element to be used to style a given cluster marker\n * is determined by the function defined by the calculator
property.\n * The default is an array of {@link ClusterIconStyle} elements whose properties are derived\n * from the values for imagePath
, imageExtension
, and\n * imageSizes
.\n * @property {boolean} [enableRetinaIcons=false] Whether to allow the use of cluster icons that\n * have sizes that are some multiple (typically double) of their actual display size. Icons such\n * as these look better when viewed on high-resolution monitors such as Apple's Retina displays.\n * Note: if this property is true
, sprites cannot be used as cluster icons.\n * @property {number} [batchSize=MarkerClusterer.BATCH_SIZE] Set this property to the\n * number of markers to be processed in a single batch when using a browser other than\n * Internet Explorer (for Internet Explorer, use the batchSizeIE property instead).\n * @property {number} [batchSizeIE=MarkerClusterer.BATCH_SIZE_IE] When Internet Explorer is\n * being used, markers are processed in several batches with a small delay inserted between\n * each batch in an attempt to avoid Javascript timeout errors. Set this property to the\n * number of markers to be processed in a single batch; select as high a number as you can\n * without causing a timeout error in the browser. This number might need to be as low as 100\n * if 15,000 markers are being managed, for example.\n * @property {string} [imagePath=MarkerClusterer.IMAGE_PATH]\n * The full URL of the root name of the group of image files to use for cluster icons.\n * The complete file name is of the form imagePath
n.imageExtension
\n * where n is the image file number (1, 2, etc.).\n * @property {string} [imageExtension=MarkerClusterer.IMAGE_EXTENSION]\n * The extension name for the cluster icon image files (e.g., \"png\"
or\n * \"jpg\"
).\n * @property {Array} [imageSizes=MarkerClusterer.IMAGE_SIZES]\n * An array of numbers containing the widths of the group of\n * imagePath
n.imageExtension
image files.\n * (The images are assumed to be square.)\n */\n/**\n * Creates a MarkerClusterer object with the options specified in {@link MarkerClustererOptions}.\n * @constructor\n * @extends google.maps.OverlayView\n * @param {google.maps.Map} map The Google map to attach to.\n * @param {Array.gridSize
property.\n *\n * @return {number} The grid size.\n */\nMarkerClusterer.prototype.getGridSize = function () {\n return this.gridSize_;\n};\n\n\n/**\n * Sets the value of the gridSize
property.\n *\n * @param {number} gridSize The grid size.\n */\nMarkerClusterer.prototype.setGridSize = function (gridSize) {\n this.gridSize_ = gridSize;\n};\n\n\n/**\n * Returns the value of the minimumClusterSize
property.\n *\n * @return {number} The minimum cluster size.\n */\nMarkerClusterer.prototype.getMinimumClusterSize = function () {\n return this.minClusterSize_;\n};\n\n/**\n * Sets the value of the minimumClusterSize
property.\n *\n * @param {number} minimumClusterSize The minimum cluster size.\n */\nMarkerClusterer.prototype.setMinimumClusterSize = function (minimumClusterSize) {\n this.minClusterSize_ = minimumClusterSize;\n};\n\n\n/**\n * Returns the value of the maxZoom
property.\n *\n * @return {number} The maximum zoom level.\n */\nMarkerClusterer.prototype.getMaxZoom = function () {\n return this.maxZoom_;\n};\n\n\n/**\n * Sets the value of the maxZoom
property.\n *\n * @param {number} maxZoom The maximum zoom level.\n */\nMarkerClusterer.prototype.setMaxZoom = function (maxZoom) {\n this.maxZoom_ = maxZoom;\n};\n\n\n/**\n * Returns the value of the styles
property.\n *\n * @return {Array} The array of styles defining the cluster markers to be used.\n */\nMarkerClusterer.prototype.getStyles = function () {\n return this.styles_;\n};\n\n\n/**\n * Sets the value of the styles
property.\n *\n * @param {Array.title
property.\n *\n * @return {string} The content of the title text.\n */\nMarkerClusterer.prototype.getTitle = function () {\n return this.title_;\n};\n\n\n/**\n * Sets the value of the title
property.\n *\n * @param {string} title The value of the title property.\n */\nMarkerClusterer.prototype.setTitle = function (title) {\n this.title_ = title;\n};\n\n\n/**\n * Returns the value of the zoomOnClick
property.\n *\n * @return {boolean} True if zoomOnClick property is set.\n */\nMarkerClusterer.prototype.getZoomOnClick = function () {\n return this.zoomOnClick_;\n};\n\n\n/**\n * Sets the value of the zoomOnClick
property.\n *\n * @param {boolean} zoomOnClick The value of the zoomOnClick property.\n */\nMarkerClusterer.prototype.setZoomOnClick = function (zoomOnClick) {\n this.zoomOnClick_ = zoomOnClick;\n};\n\n\n/**\n * Returns the value of the averageCenter
property.\n *\n * @return {boolean} True if averageCenter property is set.\n */\nMarkerClusterer.prototype.getAverageCenter = function () {\n return this.averageCenter_;\n};\n\n\n/**\n * Sets the value of the averageCenter
property.\n *\n * @param {boolean} averageCenter The value of the averageCenter property.\n */\nMarkerClusterer.prototype.setAverageCenter = function (averageCenter) {\n this.averageCenter_ = averageCenter;\n};\n\n\n/**\n * Returns the value of the ignoreHidden
property.\n *\n * @return {boolean} True if ignoreHidden property is set.\n */\nMarkerClusterer.prototype.getIgnoreHidden = function () {\n return this.ignoreHidden_;\n};\n\n\n/**\n * Sets the value of the ignoreHidden
property.\n *\n * @param {boolean} ignoreHidden The value of the ignoreHidden property.\n */\nMarkerClusterer.prototype.setIgnoreHidden = function (ignoreHidden) {\n this.ignoreHidden_ = ignoreHidden;\n};\n\n\n/**\n * Returns the value of the enableRetinaIcons
property.\n *\n * @return {boolean} True if enableRetinaIcons property is set.\n */\nMarkerClusterer.prototype.getEnableRetinaIcons = function () {\n return this.enableRetinaIcons_;\n};\n\n\n/**\n * Sets the value of the enableRetinaIcons
property.\n *\n * @param {boolean} enableRetinaIcons The value of the enableRetinaIcons property.\n */\nMarkerClusterer.prototype.setEnableRetinaIcons = function (enableRetinaIcons) {\n this.enableRetinaIcons_ = enableRetinaIcons;\n};\n\n\n/**\n * Returns the value of the imageExtension
property.\n *\n * @return {string} The value of the imageExtension property.\n */\nMarkerClusterer.prototype.getImageExtension = function () {\n return this.imageExtension_;\n};\n\n\n/**\n * Sets the value of the imageExtension
property.\n *\n * @param {string} imageExtension The value of the imageExtension property.\n */\nMarkerClusterer.prototype.setImageExtension = function (imageExtension) {\n this.imageExtension_ = imageExtension;\n};\n\n\n/**\n * Returns the value of the imagePath
property.\n *\n * @return {string} The value of the imagePath property.\n */\nMarkerClusterer.prototype.getImagePath = function () {\n return this.imagePath_;\n};\n\n\n/**\n * Sets the value of the imagePath
property.\n *\n * @param {string} imagePath The value of the imagePath property.\n */\nMarkerClusterer.prototype.setImagePath = function (imagePath) {\n this.imagePath_ = imagePath;\n};\n\n\n/**\n * Returns the value of the imageSizes
property.\n *\n * @return {Array} The value of the imageSizes property.\n */\nMarkerClusterer.prototype.getImageSizes = function () {\n return this.imageSizes_;\n};\n\n\n/**\n * Sets the value of the imageSizes
property.\n *\n * @param {Array} imageSizes The value of the imageSizes property.\n */\nMarkerClusterer.prototype.setImageSizes = function (imageSizes) {\n this.imageSizes_ = imageSizes;\n};\n\n\n/**\n * Returns the value of the calculator
property.\n *\n * @return {function} the value of the calculator property.\n */\nMarkerClusterer.prototype.getCalculator = function () {\n return this.calculator_;\n};\n\n\n/**\n * Sets the value of the calculator
property.\n *\n * @param {function(Array.batchSizeIE
property.\n *\n * @return {number} the value of the batchSizeIE property.\n */\nMarkerClusterer.prototype.getBatchSizeIE = function () {\n return this.batchSizeIE_;\n};\n\n\n/**\n * Sets the value of the batchSizeIE
property.\n *\n * @param {number} batchSizeIE The value of the batchSizeIE property.\n */\nMarkerClusterer.prototype.setBatchSizeIE = function (batchSizeIE) {\n this.batchSizeIE_ = batchSizeIE;\n};\n\n\n/**\n * Returns the value of the clusterClass
property.\n *\n * @return {string} the value of the clusterClass property.\n */\nMarkerClusterer.prototype.getClusterClass = function () {\n return this.clusterClass_;\n};\n\n\n/**\n * Sets the value of the clusterClass
property.\n *\n * @param {string} clusterClass The value of the clusterClass property.\n */\nMarkerClusterer.prototype.setClusterClass = function (clusterClass) {\n this.clusterClass_ = clusterClass;\n};\n\n\n/**\n * Returns the array of markers managed by the clusterer.\n *\n * @return {Array} The array of markers managed by the clusterer.\n */\nMarkerClusterer.prototype.getMarkers = function () {\n return this.markers_;\n};\n\n\n/**\n * Returns the number of markers managed by the clusterer.\n *\n * @return {number} The number of markers.\n */\nMarkerClusterer.prototype.getTotalMarkers = function () {\n return this.markers_.length;\n};\n\n\n/**\n * Returns the current array of clusters formed by the clusterer.\n *\n * @return {Array} The array of clusters formed by the clusterer.\n */\nMarkerClusterer.prototype.getClusters = function () {\n return this.clusters_;\n};\n\n\n/**\n * Returns the number of clusters formed by the clusterer.\n *\n * @return {number} The number of clusters formed by the clusterer.\n */\nMarkerClusterer.prototype.getTotalClusters = function () {\n return this.clusters_.length;\n};\n\n\n/**\n * Adds a marker to the clusterer. The clusters are redrawn unless\n * opt_nodraw
is set to true
.\n *\n * @param {google.maps.Marker} marker The marker to add.\n * @param {boolean} [opt_nodraw] Set to true
to prevent redrawing.\n */\nMarkerClusterer.prototype.addMarker = function (marker, opt_nodraw) {\n this.pushMarkerTo_(marker);\n if (!opt_nodraw) {\n this.redraw_();\n }\n};\n\n\n/**\n * Adds an array of markers to the clusterer. The clusters are redrawn unless\n * opt_nodraw
is set to true
.\n *\n * @param {Array.true
to prevent redrawing.\n */\nMarkerClusterer.prototype.addMarkers = function (markers, opt_nodraw) {\n var key;\n for (key in markers) {\n if (markers.hasOwnProperty(key)) {\n this.pushMarkerTo_(markers[key]);\n }\n }\n if (!opt_nodraw) {\n this.redraw_();\n }\n};\n\n\n/**\n * Pushes a marker to the clusterer.\n *\n * @param {google.maps.Marker} marker The marker to add.\n */\nMarkerClusterer.prototype.pushMarkerTo_ = function (marker) {\n // If the marker is draggable add a listener so we can update the clusters on the dragend:\n if (marker.getDraggable()) {\n var cMarkerClusterer = this;\n google.maps.event.addListener(marker, \"dragend\", function () {\n if (cMarkerClusterer.ready_) {\n this.isAdded = false;\n cMarkerClusterer.repaint();\n }\n });\n }\n marker.isAdded = false;\n this.markers_.push(marker);\n};\n\n\n/**\n * Removes a marker from the cluster. The clusters are redrawn unless\n * opt_nodraw
is set to true
. Returns true
if the\n * marker was removed from the clusterer.\n *\n * @param {google.maps.Marker} marker The marker to remove.\n * @param {boolean} [opt_nodraw] Set to true
to prevent redrawing.\n * @return {boolean} True if the marker was removed from the clusterer.\n */\nMarkerClusterer.prototype.removeMarker = function (marker, opt_nodraw) {\n var removed = this.removeMarker_(marker);\n\n if (!opt_nodraw && removed) {\n this.repaint();\n }\n\n return removed;\n};\n\n\n/**\n * Removes an array of markers from the cluster. The clusters are redrawn unless\n * opt_nodraw
is set to true
. Returns true
if markers\n * were removed from the clusterer.\n *\n * @param {Array.true
to prevent redrawing.\n * @return {boolean} True if markers were removed from the clusterer.\n */\nMarkerClusterer.prototype.removeMarkers = function (markers, opt_nodraw) {\n var i, r;\n var removed = false;\n\n for (i = 0; i < markers.length; i++) {\n r = this.removeMarker_(markers[i]);\n removed = removed || r;\n }\n\n if (!opt_nodraw && removed) {\n this.repaint();\n }\n\n return removed;\n};\n\n\n/**\n * Removes a marker and returns true if removed, false if not.\n *\n * @param {google.maps.Marker} marker The marker to remove\n * @return {boolean} Whether the marker was removed or not\n */\nMarkerClusterer.prototype.removeMarker_ = function (marker) {\n var i;\n var index = -1;\n if (this.markers_.indexOf) {\n index = this.markers_.indexOf(marker);\n } else {\n for (i = 0; i < this.markers_.length; i++) {\n if (marker === this.markers_[i]) {\n index = i;\n break;\n }\n }\n }\n\n if (index === -1) {\n // Marker is not in our list of markers, so do nothing:\n return false;\n }\n\n marker.setMap(null);\n this.markers_.splice(index, 1); // Remove the marker from the list of managed markers\n return true;\n};\n\n\n/**\n * Removes all clusters and markers from the map and also removes all markers\n * managed by the clusterer.\n */\nMarkerClusterer.prototype.clearMarkers = function () {\n this.resetViewport_(true);\n this.markers_ = [];\n};\n\n\n/**\n * Recalculates and redraws all the marker clusters from scratch.\n * Call this after changing any properties.\n */\nMarkerClusterer.prototype.repaint = function () {\n var oldClusters = this.clusters_.slice();\n this.clusters_ = [];\n this.resetViewport_(false);\n this.redraw_();\n\n // Remove the old clusters.\n // Do it in a timeout to prevent blinking effect.\n setTimeout(function () {\n var i;\n for (i = 0; i < oldClusters.length; i++) {\n oldClusters[i].remove();\n }\n }, 0);\n};\n\n\n/**\n * Returns the current bounds extended by the grid size.\n *\n * @param {google.maps.LatLngBounds} bounds The bounds to extend.\n * @return {google.maps.LatLngBounds} The extended bounds.\n * @ignore\n */\nMarkerClusterer.prototype.getExtendedBounds = function (bounds) {\n var projection = this.getProjection();\n\n // Turn the bounds into latlng.\n var tr = new google.maps.LatLng(bounds.getNorthEast().lat(),\n bounds.getNorthEast().lng());\n var bl = new google.maps.LatLng(bounds.getSouthWest().lat(),\n bounds.getSouthWest().lng());\n\n // Convert the points to pixels and the extend out by the grid size.\n var trPix = projection.fromLatLngToDivPixel(tr);\n trPix.x += this.gridSize_;\n trPix.y -= this.gridSize_;\n\n var blPix = projection.fromLatLngToDivPixel(bl);\n blPix.x -= this.gridSize_;\n blPix.y += this.gridSize_;\n\n // Convert the pixel points back to LatLng\n var ne = projection.fromDivPixelToLatLng(trPix);\n var sw = projection.fromDivPixelToLatLng(blPix);\n\n // Extend the bounds to contain the new bounds.\n bounds.extend(ne);\n bounds.extend(sw);\n\n return bounds;\n};\n\n\n/**\n * Redraws all the clusters.\n */\nMarkerClusterer.prototype.redraw_ = function () {\n this.createClusters_(0);\n};\n\n\n/**\n * Removes all clusters from the map. The markers are also removed from the map\n * if opt_hide
is set to true
.\n *\n * @param {boolean} [opt_hide] Set to true
to also remove the markers\n * from the map.\n */\nMarkerClusterer.prototype.resetViewport_ = function (opt_hide) {\n var i, marker;\n // Remove all the clusters\n for (i = 0; i < this.clusters_.length; i++) {\n this.clusters_[i].remove();\n }\n this.clusters_ = [];\n\n // Reset the markers to not be added and to be removed from the map.\n for (i = 0; i < this.markers_.length; i++) {\n marker = this.markers_[i];\n marker.isAdded = false;\n if (opt_hide) {\n marker.setMap(null);\n }\n }\n};\n\n\n/**\n * Calculates the distance between two latlng locations in km.\n *\n * @param {google.maps.LatLng} p1 The first lat lng point.\n * @param {google.maps.LatLng} p2 The second lat lng point.\n * @return {number} The distance between the two points in km.\n * @see http://www.movable-type.co.uk/scripts/latlong.html\n*/\nMarkerClusterer.prototype.distanceBetweenPoints_ = function (p1, p2) {\n var R = 6371; // Radius of the Earth in km\n var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;\n var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;\n var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) *\n Math.sin(dLon / 2) * Math.sin(dLon / 2);\n var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n var d = R * c;\n return d;\n};\n\n\n/**\n * Determines if a marker is contained in a bounds.\n *\n * @param {google.maps.Marker} marker The marker to check.\n * @param {google.maps.LatLngBounds} bounds The bounds to check against.\n * @return {boolean} True if the marker is in the bounds.\n */\nMarkerClusterer.prototype.isMarkerInBounds_ = function (marker, bounds) {\n return bounds.contains(marker.getPosition());\n};\n\n\n/**\n * Adds a marker to a cluster, or creates a new cluster.\n *\n * @param {google.maps.Marker} marker The marker to add.\n */\nMarkerClusterer.prototype.addToClosestCluster_ = function (marker) {\n var i, d, cluster, center;\n var distance = 40000; // Some large number\n var clusterToAddTo = null;\n for (i = 0; i < this.clusters_.length; i++) {\n cluster = this.clusters_[i];\n center = cluster.getCenter();\n if (center) {\n d = this.distanceBetweenPoints_(center, marker.getPosition());\n if (d < distance) {\n distance = d;\n clusterToAddTo = cluster;\n }\n }\n }\n\n if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)) {\n clusterToAddTo.addMarker(marker);\n } else {\n cluster = new Cluster(this);\n cluster.addMarker(marker);\n this.clusters_.push(cluster);\n }\n};\n\n\n/**\n * Creates the clusters. This is done in batches to avoid timeout errors\n * in some browsers when there is a huge number of markers.\n *\n * @param {number} iFirst The index of the first marker in the batch of\n * markers to be added to clusters.\n */\nMarkerClusterer.prototype.createClusters_ = function (iFirst) {\n var i, marker;\n var mapBounds;\n var cMarkerClusterer = this;\n if (!this.ready_) {\n return;\n }\n\n // Cancel previous batch processing if we're working on the first batch:\n if (iFirst === 0) {\n /**\n * This event is fired when the MarkerClusterer
begins\n * clustering markers.\n * @name MarkerClusterer#clusteringbegin\n * @param {MarkerClusterer} mc The MarkerClusterer whose markers are being clustered.\n * @event\n */\n google.maps.event.trigger(this, \"clusteringbegin\", this);\n\n if (typeof this.timerRefStatic !== \"undefined\") {\n clearTimeout(this.timerRefStatic);\n delete this.timerRefStatic;\n }\n }\n\n // Get our current map view bounds.\n // Create a new bounds object so we don't affect the map.\n //\n // See Comments 9 & 11 on Issue 3651 relating to this workaround for a Google Maps bug:\n if (this.getMap().getZoom() > 3) {\n mapBounds = new google.maps.LatLngBounds(this.getMap().getBounds().getSouthWest(),\n this.getMap().getBounds().getNorthEast());\n } else {\n mapBounds = new google.maps.LatLngBounds(new google.maps.LatLng(85.02070771743472, -178.48388434375), new google.maps.LatLng(-85.08136444384544, 178.00048865625));\n }\n var bounds = this.getExtendedBounds(mapBounds);\n\n var iLast = Math.min(iFirst + this.batchSize_, this.markers_.length);\n\n for (i = iFirst; i < iLast; i++) {\n marker = this.markers_[i];\n if (!marker.isAdded && this.isMarkerInBounds_(marker, bounds)) {\n if (!this.ignoreHidden_ || (this.ignoreHidden_ && marker.getVisible())) {\n this.addToClosestCluster_(marker);\n }\n }\n }\n\n if (iLast < this.markers_.length) {\n this.timerRefStatic = setTimeout(function () {\n cMarkerClusterer.createClusters_(iLast);\n }, 0);\n } else {\n delete this.timerRefStatic;\n\n /**\n * This event is fired when the MarkerClusterer
stops\n * clustering markers.\n * @name MarkerClusterer#clusteringend\n * @param {MarkerClusterer} mc The MarkerClusterer whose markers are being clustered.\n * @event\n */\n google.maps.event.trigger(this, \"clusteringend\", this);\n }\n};\n\n\n/**\n * Extends an object's prototype by another's.\n *\n * @param {Object} obj1 The object to be extended.\n * @param {Object} obj2 The object to extend with.\n * @return {Object} The new extended object.\n * @ignore\n */\nMarkerClusterer.prototype.extend = function (obj1, obj2) {\n return (function (object) {\n var property;\n for (property in object.prototype) {\n this.prototype[property] = object.prototype[property];\n }\n return this;\n }).apply(obj1, [obj2]);\n};\n\n\n/**\n * The default function for determining the label text and style\n * for a cluster icon.\n *\n * @param {Array.\n * This is an enhanced V3 implementation of the V2 MarkerClusterer by Xiaoxi Wu. It is\n * based on the V3 MarkerClusterer port by Luke Mahe. MarkerClustererPlus was created\n * by Gary Little.\n *
\n * v2.0 release: MarkerClustererPlus v2.0 is backward compatible with MarkerClusterer v1.0. It\n * adds support for the ignoreHidden
, title
, batchSizeIE
,\n * and calculator
properties as well as support for four more events. It also allows\n * greater control over the styling of the text that appears on the cluster marker. The\n * documentation has been significantly improved and the overall code has been simplified and\n * polished. Very large numbers of markers can now be managed without causing Javascript timeout\n * errors on Internet Explorer. Note that the name of the clusterclick
event has been\n * deprecated. The new name is click
, so please change your application code now.\n */\n\n/**\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n/**\n * @name ClusterIconStyle\n * @class This class represents the object for values in the styles
array passed\n * to the {@link MarkerClusterer} constructor. The element in this array that is used to\n * style the cluster icon is determined by calling the calculator
function.\n *\n * @property {string} url The URL of the cluster icon image file. Required.\n * @property {number} height The display height (in pixels) of the cluster icon. Required.\n * @property {number} width The display width (in pixels) of the cluster icon. Required.\n * @property {Array} [anchorText] The position (in pixels) from the center of the cluster icon to\n * where the text label is to be centered and drawn. The format is [yoffset, xoffset]
\n * where yoffset
increases as you go down from center and xoffset
\n * increases to the right of center. The default is [0, 0]
.\n * @property {Array} [anchorIcon] The anchor position (in pixels) of the cluster icon. This is the\n * spot on the cluster icon that is to be aligned with the cluster position. The format is\n * [yoffset, xoffset]
where yoffset
increases as you go down and\n * xoffset
increases to the right of the top-left corner of the icon. The default\n * anchor position is the center of the cluster icon.\n * @property {string} [textColor=\"black\"] The color of the label text shown on the\n * cluster icon.\n * @property {number} [textSize=11] The size (in pixels) of the label text shown on the\n * cluster icon.\n * @property {string} [textDecoration=\"none\"] The value of the CSS text-decoration
\n * property for the label text shown on the cluster icon.\n * @property {string} [fontWeight=\"bold\"] The value of the CSS font-weight
\n * property for the label text shown on the cluster icon.\n * @property {string} [fontStyle=\"normal\"] The value of the CSS font-style
\n * property for the label text shown on the cluster icon.\n * @property {string} [fontFamily=\"Arial,sans-serif\"] The value of the CSS font-family
\n * property for the label text shown on the cluster icon.\n * @property {string} [backgroundPosition=\"0 0\"] The position of the cluster icon image\n * within the image defined by url
. The format is \"xpos ypos\"
\n * (the same format as for the CSS background-position
property). You must set\n * this property appropriately when the image defined by url
represents a sprite\n * containing multiple images. Note that the position must be specified in px units.\n */\n/**\n * @name ClusterIconInfo\n * @class This class is an object containing general information about a cluster icon. This is\n * the object that a calculator
function returns.\n *\n * @property {string} text The text of the label to be shown on the cluster icon.\n * @property {number} index The index plus 1 of the element in the styles
\n * array to be used to style the cluster icon.\n * @property {string} title The tooltip to display when the mouse moves over the cluster icon.\n * If this value is undefined
or \"\"
, title
is set to the\n * value of the title
property passed to the MarkerClusterer.\n */\n/**\n * A cluster icon.\n *\n * @constructor\n * @extends google.maps.OverlayView\n * @param {Cluster} cluster The cluster with which the icon is to be associated.\n * @param {Array} [styles] An array of {@link ClusterIconStyle} defining the cluster icons\n * to use for various cluster sizes.\n * @private\n */\nfunction ClusterIcon(cluster, styles) {\n cluster.getMarkerClusterer().extend(ClusterIcon, google.maps.OverlayView);\n\n this.cluster_ = cluster;\n this.className_ = cluster.getMarkerClusterer().getClusterClass();\n this.styles_ = styles;\n this.center_ = null;\n this.div_ = null;\n this.sums_ = null;\n this.visible_ = false;\n\n this.setMap(cluster.getMap()); // Note: this causes onAdd to be called\n}\n\n\n/**\n * Adds the icon to the DOM.\n */\nClusterIcon.prototype.onAdd = function () {\n var cClusterIcon = this;\n var cMouseDownInCluster;\n var cDraggingMapByCluster;\n var gmVersion = google.maps.version.split(\".\");\n\n gmVersion = parseInt(gmVersion[0] * 100, 10) + parseInt(gmVersion[1], 10);\n\n this.div_ = document.createElement(\"div\");\n this.div_.className = this.className_;\n if (this.visible_) {\n this.show();\n }\n\n this.getPanes().overlayMouseTarget.appendChild(this.div_);\n\n // Fix for Issue 157\n this.boundsChangedListener_ = google.maps.event.addListener(this.getMap(), \"bounds_changed\", function () {\n cDraggingMapByCluster = cMouseDownInCluster;\n });\n\n google.maps.event.addDomListener(this.div_, \"mousedown\", function () {\n cMouseDownInCluster = true;\n cDraggingMapByCluster = false;\n });\n\n// March 1, 2018: Fix for this 3.32 exp bug, https://issuetracker.google.com/issues/73571522\n// But it doesn't work with earlier releases so do a version check.\n if (gmVersion >= 332) { // Ugly version-dependent code\n google.maps.event.addDomListener(this.div_, \"touchstart\", function (e) {\n e.stopPropagation();\n });\n }\n\n google.maps.event.addDomListener(this.div_, \"click\", function (e) {\n cMouseDownInCluster = false;\n if (!cDraggingMapByCluster) {\n var theBounds;\n var mz;\n var mc = cClusterIcon.cluster_.getMarkerClusterer();\n /**\n * This event is fired when a cluster marker is clicked.\n * @name MarkerClusterer#click\n * @param {Cluster} c The cluster that was clicked.\n * @event\n */\n google.maps.event.trigger(mc, \"click\", cClusterIcon.cluster_);\n google.maps.event.trigger(mc, \"clusterclick\", cClusterIcon.cluster_); // deprecated name\n\n // The default click handler follows. Disable it by setting\n // the zoomOnClick property to false.\n if (mc.getZoomOnClick()) {\n // Zoom into the cluster.\n mz = mc.getMaxZoom();\n theBounds = cClusterIcon.cluster_.getBounds();\n mc.getMap().fitBounds(theBounds);\n // There is a fix for Issue 170 here:\n setTimeout(function () {\n mc.getMap().fitBounds(theBounds);\n // Don't zoom beyond the max zoom level\n if (mz !== null && (mc.getMap().getZoom() > mz)) {\n mc.getMap().setZoom(mz + 1);\n }\n }, 100);\n }\n\n // Prevent event propagation to the map:\n e.cancelBubble = true;\n if (e.stopPropagation) {\n e.stopPropagation();\n }\n }\n });\n\n google.maps.event.addDomListener(this.div_, \"mouseover\", function () {\n var mc = cClusterIcon.cluster_.getMarkerClusterer();\n /**\n * This event is fired when the mouse moves over a cluster marker.\n * @name MarkerClusterer#mouseover\n * @param {Cluster} c The cluster that the mouse moved over.\n * @event\n */\n google.maps.event.trigger(mc, \"mouseover\", cClusterIcon.cluster_);\n });\n\n google.maps.event.addDomListener(this.div_, \"mouseout\", function () {\n var mc = cClusterIcon.cluster_.getMarkerClusterer();\n /**\n * This event is fired when the mouse moves out of a cluster marker.\n * @name MarkerClusterer#mouseout\n * @param {Cluster} c The cluster that the mouse moved out of.\n * @event\n */\n google.maps.event.trigger(mc, \"mouseout\", cClusterIcon.cluster_);\n });\n};\n\n\n/**\n * Removes the icon from the DOM.\n */\nClusterIcon.prototype.onRemove = function () {\n if (this.div_ && this.div_.parentNode) {\n this.hide();\n google.maps.event.removeListener(this.boundsChangedListener_);\n google.maps.event.clearInstanceListeners(this.div_);\n this.div_.parentNode.removeChild(this.div_);\n this.div_ = null;\n }\n};\n\n\n/**\n * Draws the icon.\n */\nClusterIcon.prototype.draw = function () {\n if (this.visible_) {\n var pos = this.getPosFromLatLng_(this.center_);\n this.div_.style.top = pos.y + \"px\";\n this.div_.style.left = pos.x + \"px\";\n this.div_.style.zIndex = google.maps.Marker.MAX_ZINDEX + 1; // Put above all unclustered markers\n }\n};\n\n\n/**\n * Hides the icon.\n */\nClusterIcon.prototype.hide = function () {\n if (this.div_) {\n this.div_.style.display = \"none\";\n }\n this.visible_ = false;\n};\n\n\n/**\n * Positions and shows the icon.\n */\nClusterIcon.prototype.show = function () {\n if (this.div_) {\n var img = \"\";\n // NOTE: values must be specified in px units\n var bp = this.backgroundPosition_.split(\" \");\n var spriteH = parseInt(bp[0].replace(/^\\s+|\\s+$/g, \"\"), 10);\n var spriteV = parseInt(bp[1].replace(/^\\s+|\\s+$/g, \"\"), 10);\n var pos = this.getPosFromLatLng_(this.center_);\n this.div_.style.cssText = this.createCss(pos);\n img = \"\";\n this.div_.innerHTML = img + \"
MarkerClusterer
object with which this\n * cluster is associated.\n */\nfunction Cluster(mc) {\n this.markerClusterer_ = mc;\n this.map_ = mc.getMap();\n this.gridSize_ = mc.getGridSize();\n this.minClusterSize_ = mc.getMinimumClusterSize();\n this.averageCenter_ = mc.getAverageCenter();\n this.markers_ = [];\n this.center_ = null;\n this.bounds_ = null;\n this.clusterIcon_ = new ClusterIcon(this, mc.getStyles());\n}\n\n\n/**\n * Returns the number of markers managed by the cluster. You can call this from\n * a click
, mouseover
, or mouseout
event handler\n * for the MarkerClusterer
object.\n *\n * @return {number} The number of markers in the cluster.\n */\nCluster.prototype.getSize = function () {\n return this.markers_.length;\n};\n\n\n/**\n * Returns the array of markers managed by the cluster. You can call this from\n * a click
, mouseover
, or mouseout
event handler\n * for the MarkerClusterer
object.\n *\n * @return {Array} The array of markers in the cluster.\n */\nCluster.prototype.getMarkers = function () {\n return this.markers_;\n};\n\n\n/**\n * Returns the center of the cluster. You can call this from\n * a click
, mouseover
, or mouseout
event handler\n * for the MarkerClusterer
object.\n *\n * @return {google.maps.LatLng} The center of the cluster.\n */\nCluster.prototype.getCenter = function () {\n return this.center_;\n};\n\n\n/**\n * Returns the map with which the cluster is associated.\n *\n * @return {google.maps.Map} The map.\n * @ignore\n */\nCluster.prototype.getMap = function () {\n return this.map_;\n};\n\n\n/**\n * Returns the MarkerClusterer
object with which the cluster is associated.\n *\n * @return {MarkerClusterer} The associated marker clusterer.\n * @ignore\n */\nCluster.prototype.getMarkerClusterer = function () {\n return this.markerClusterer_;\n};\n\n\n/**\n * Returns the bounds of the cluster.\n *\n * @return {google.maps.LatLngBounds} the cluster bounds.\n * @ignore\n */\nCluster.prototype.getBounds = function () {\n var i;\n var bounds = new google.maps.LatLngBounds(this.center_, this.center_);\n var markers = this.getMarkers();\n for (i = 0; i < markers.length; i++) {\n bounds.extend(markers[i].getPosition());\n }\n return bounds;\n};\n\n\n/**\n * Removes the cluster from the map.\n *\n * @ignore\n */\nCluster.prototype.remove = function () {\n this.clusterIcon_.setMap(null);\n this.markers_ = [];\n delete this.markers_;\n};\n\n\n/**\n * Adds a marker to the cluster.\n *\n * @param {google.maps.Marker} marker The marker to be added.\n * @return {boolean} True if the marker was added.\n * @ignore\n */\nCluster.prototype.addMarker = function (marker) {\n var i;\n var mCount;\n var mz;\n\n if (this.isMarkerAlreadyAdded_(marker)) {\n return false;\n }\n\n if (!this.center_) {\n this.center_ = marker.getPosition();\n this.calculateBounds_();\n } else {\n if (this.averageCenter_) {\n var l = this.markers_.length + 1;\n var lat = (this.center_.lat() * (l - 1) + marker.getPosition().lat()) / l;\n var lng = (this.center_.lng() * (l - 1) + marker.getPosition().lng()) / l;\n this.center_ = new google.maps.LatLng(lat, lng);\n this.calculateBounds_();\n }\n }\n\n marker.isAdded = true;\n this.markers_.push(marker);\n\n mCount = this.markers_.length;\n mz = this.markerClusterer_.getMaxZoom();\n if (mz !== null && this.map_.getZoom() > mz) {\n // Zoomed in past max zoom, so show the marker.\n if (marker.getMap() !== this.map_) {\n marker.setMap(this.map_);\n }\n } else if (mCount < this.minClusterSize_) {\n // Min cluster size not reached so show the marker.\n if (marker.getMap() !== this.map_) {\n marker.setMap(this.map_);\n }\n } else if (mCount === this.minClusterSize_) {\n // Hide the markers that were showing.\n for (i = 0; i < mCount; i++) {\n this.markers_[i].setMap(null);\n }\n } else {\n marker.setMap(null);\n }\n\n this.updateIcon_();\n return true;\n};\n\n\n/**\n * Determines if a marker lies within the cluster's bounds.\n *\n * @param {google.maps.Marker} marker The marker to check.\n * @return {boolean} True if the marker lies in the bounds.\n * @ignore\n */\nCluster.prototype.isMarkerInClusterBounds = function (marker) {\n return this.bounds_.contains(marker.getPosition());\n};\n\n\n/**\n * Calculates the extended bounds of the cluster with the grid.\n */\nCluster.prototype.calculateBounds_ = function () {\n var bounds = new google.maps.LatLngBounds(this.center_, this.center_);\n this.bounds_ = this.markerClusterer_.getExtendedBounds(bounds);\n};\n\n\n/**\n * Updates the cluster icon.\n */\nCluster.prototype.updateIcon_ = function () {\n var mCount = this.markers_.length;\n var mz = this.markerClusterer_.getMaxZoom();\n\n if (mz !== null && this.map_.getZoom() > mz) {\n this.clusterIcon_.hide();\n return;\n }\n\n if (mCount < this.minClusterSize_) {\n // Min cluster size not yet reached.\n this.clusterIcon_.hide();\n return;\n }\n\n var numStyles = this.markerClusterer_.getStyles().length;\n var sums = this.markerClusterer_.getCalculator()(this.markers_, numStyles);\n this.clusterIcon_.setCenter(this.center_);\n this.clusterIcon_.useStyle(sums);\n this.clusterIcon_.show();\n};\n\n\n/**\n * Determines if a marker has already been added to the cluster.\n *\n * @param {google.maps.Marker} marker The marker to check.\n * @return {boolean} True if the marker has already been added.\n */\nCluster.prototype.isMarkerAlreadyAdded_ = function (marker) {\n var i;\n if (this.markers_.indexOf) {\n return this.markers_.indexOf(marker) !== -1;\n } else {\n for (i = 0; i < this.markers_.length; i++) {\n if (marker === this.markers_[i]) {\n return true;\n }\n }\n }\n return false;\n};\n\n\n/**\n * @name MarkerClustererOptions\n * @class This class represents the optional parameter passed to\n * the {@link MarkerClusterer} constructor.\n * @property {number} [gridSize=60] The grid size of a cluster in pixels. The grid is a square.\n * @property {number} [maxZoom=null] The maximum zoom level at which clustering is enabled or\n * null
if clustering is to be enabled at all zoom levels.\n * @property {boolean} [zoomOnClick=true] Whether to zoom the map when a cluster marker is\n * clicked. You may want to set this to false
if you have installed a handler\n * for the click
event and it deals with zooming on its own.\n * @property {boolean} [averageCenter=false] Whether the position of a cluster marker should be\n * the average position of all markers in the cluster. If set to false
, the\n * cluster marker is positioned at the location of the first marker added to the cluster.\n * @property {number} [minimumClusterSize=2] The minimum number of markers needed in a cluster\n * before the markers are hidden and a cluster marker appears.\n * @property {boolean} [ignoreHidden=false] Whether to ignore hidden markers in clusters. You\n * may want to set this to true
to ensure that hidden markers are not included\n * in the marker count that appears on a cluster marker (this count is the value of the\n * text
property of the result returned by the default calculator
).\n * If set to true
and you change the visibility of a marker being clustered, be\n * sure to also call MarkerClusterer.repaint()
.\n * @property {string} [title=\"\"] The tooltip to display when the mouse moves over a cluster\n * marker. (Alternatively, you can use a custom calculator
function to specify a\n * different tooltip for each cluster marker.)\n * @property {function} [calculator=MarkerClusterer.CALCULATOR] The function used to determine\n * the text to be displayed on a cluster marker and the index indicating which style to use\n * for the cluster marker. The input parameters for the function are (1) the array of markers\n * represented by a cluster marker and (2) the number of cluster icon styles. It returns a\n * {@link ClusterIconInfo} object. The default calculator
returns a\n * text
property which is the number of markers in the cluster and an\n * index
property which is one higher than the lowest integer such that\n * 10^i
exceeds the number of markers in the cluster, or the size of the styles\n * array, whichever is less. The styles
array element used has an index of\n * index
minus 1. For example, the default calculator
returns a\n * text
value of \"125\"
and an index
of 3
\n * for a cluster icon representing 125 markers so the element used in the styles
\n * array is 2
. A calculator
may also return a title
\n * property that contains the text of the tooltip to be used for the cluster marker. If\n * title
is not defined, the tooltip is set to the value of the title
\n * property for the MarkerClusterer.\n * @property {string} [clusterClass=\"cluster\"] The name of the CSS class defining general styles\n * for the cluster markers. Use this class to define CSS styles that are not set up by the code\n * that processes the styles
array.\n * @property {Array} [styles] An array of {@link ClusterIconStyle} elements defining the styles\n * of the cluster markers to be used. The element to be used to style a given cluster marker\n * is determined by the function defined by the calculator
property.\n * The default is an array of {@link ClusterIconStyle} elements whose properties are derived\n * from the values for imagePath
, imageExtension
, and\n * imageSizes
.\n * @property {boolean} [enableRetinaIcons=false] Whether to allow the use of cluster icons that\n * have sizes that are some multiple (typically double) of their actual display size. Icons such\n * as these look better when viewed on high-resolution monitors such as Apple's Retina displays.\n * Note: if this property is true
, sprites cannot be used as cluster icons.\n * @property {number} [batchSize=MarkerClusterer.BATCH_SIZE] Set this property to the\n * number of markers to be processed in a single batch when using a browser other than\n * Internet Explorer (for Internet Explorer, use the batchSizeIE property instead).\n * @property {number} [batchSizeIE=MarkerClusterer.BATCH_SIZE_IE] When Internet Explorer is\n * being used, markers are processed in several batches with a small delay inserted between\n * each batch in an attempt to avoid Javascript timeout errors. Set this property to the\n * number of markers to be processed in a single batch; select as high a number as you can\n * without causing a timeout error in the browser. This number might need to be as low as 100\n * if 15,000 markers are being managed, for example.\n * @property {string} [imagePath=MarkerClusterer.IMAGE_PATH]\n * The full URL of the root name of the group of image files to use for cluster icons.\n * The complete file name is of the form imagePath
n.imageExtension
\n * where n is the image file number (1, 2, etc.).\n * @property {string} [imageExtension=MarkerClusterer.IMAGE_EXTENSION]\n * The extension name for the cluster icon image files (e.g., \"png\"
or\n * \"jpg\"
).\n * @property {Array} [imageSizes=MarkerClusterer.IMAGE_SIZES]\n * An array of numbers containing the widths of the group of\n * imagePath
n.imageExtension
image files.\n * (The images are assumed to be square.)\n */\n/**\n * Creates a MarkerClusterer object with the options specified in {@link MarkerClustererOptions}.\n * @constructor\n * @extends google.maps.OverlayView\n * @param {google.maps.Map} map The Google map to attach to.\n * @param {Array.gridSize
property.\n *\n * @return {number} The grid size.\n */\nMarkerClusterer.prototype.getGridSize = function () {\n return this.gridSize_;\n};\n\n\n/**\n * Sets the value of the gridSize
property.\n *\n * @param {number} gridSize The grid size.\n */\nMarkerClusterer.prototype.setGridSize = function (gridSize) {\n this.gridSize_ = gridSize;\n};\n\n\n/**\n * Returns the value of the minimumClusterSize
property.\n *\n * @return {number} The minimum cluster size.\n */\nMarkerClusterer.prototype.getMinimumClusterSize = function () {\n return this.minClusterSize_;\n};\n\n/**\n * Sets the value of the minimumClusterSize
property.\n *\n * @param {number} minimumClusterSize The minimum cluster size.\n */\nMarkerClusterer.prototype.setMinimumClusterSize = function (minimumClusterSize) {\n this.minClusterSize_ = minimumClusterSize;\n};\n\n\n/**\n * Returns the value of the maxZoom
property.\n *\n * @return {number} The maximum zoom level.\n */\nMarkerClusterer.prototype.getMaxZoom = function () {\n return this.maxZoom_;\n};\n\n\n/**\n * Sets the value of the maxZoom
property.\n *\n * @param {number} maxZoom The maximum zoom level.\n */\nMarkerClusterer.prototype.setMaxZoom = function (maxZoom) {\n this.maxZoom_ = maxZoom;\n};\n\n\n/**\n * Returns the value of the styles
property.\n *\n * @return {Array} The array of styles defining the cluster markers to be used.\n */\nMarkerClusterer.prototype.getStyles = function () {\n return this.styles_;\n};\n\n\n/**\n * Sets the value of the styles
property.\n *\n * @param {Array.title
property.\n *\n * @return {string} The content of the title text.\n */\nMarkerClusterer.prototype.getTitle = function () {\n return this.title_;\n};\n\n\n/**\n * Sets the value of the title
property.\n *\n * @param {string} title The value of the title property.\n */\nMarkerClusterer.prototype.setTitle = function (title) {\n this.title_ = title;\n};\n\n\n/**\n * Returns the value of the zoomOnClick
property.\n *\n * @return {boolean} True if zoomOnClick property is set.\n */\nMarkerClusterer.prototype.getZoomOnClick = function () {\n return this.zoomOnClick_;\n};\n\n\n/**\n * Sets the value of the zoomOnClick
property.\n *\n * @param {boolean} zoomOnClick The value of the zoomOnClick property.\n */\nMarkerClusterer.prototype.setZoomOnClick = function (zoomOnClick) {\n this.zoomOnClick_ = zoomOnClick;\n};\n\n\n/**\n * Returns the value of the averageCenter
property.\n *\n * @return {boolean} True if averageCenter property is set.\n */\nMarkerClusterer.prototype.getAverageCenter = function () {\n return this.averageCenter_;\n};\n\n\n/**\n * Sets the value of the averageCenter
property.\n *\n * @param {boolean} averageCenter The value of the averageCenter property.\n */\nMarkerClusterer.prototype.setAverageCenter = function (averageCenter) {\n this.averageCenter_ = averageCenter;\n};\n\n\n/**\n * Returns the value of the ignoreHidden
property.\n *\n * @return {boolean} True if ignoreHidden property is set.\n */\nMarkerClusterer.prototype.getIgnoreHidden = function () {\n return this.ignoreHidden_;\n};\n\n\n/**\n * Sets the value of the ignoreHidden
property.\n *\n * @param {boolean} ignoreHidden The value of the ignoreHidden property.\n */\nMarkerClusterer.prototype.setIgnoreHidden = function (ignoreHidden) {\n this.ignoreHidden_ = ignoreHidden;\n};\n\n\n/**\n * Returns the value of the enableRetinaIcons
property.\n *\n * @return {boolean} True if enableRetinaIcons property is set.\n */\nMarkerClusterer.prototype.getEnableRetinaIcons = function () {\n return this.enableRetinaIcons_;\n};\n\n\n/**\n * Sets the value of the enableRetinaIcons
property.\n *\n * @param {boolean} enableRetinaIcons The value of the enableRetinaIcons property.\n */\nMarkerClusterer.prototype.setEnableRetinaIcons = function (enableRetinaIcons) {\n this.enableRetinaIcons_ = enableRetinaIcons;\n};\n\n\n/**\n * Returns the value of the imageExtension
property.\n *\n * @return {string} The value of the imageExtension property.\n */\nMarkerClusterer.prototype.getImageExtension = function () {\n return this.imageExtension_;\n};\n\n\n/**\n * Sets the value of the imageExtension
property.\n *\n * @param {string} imageExtension The value of the imageExtension property.\n */\nMarkerClusterer.prototype.setImageExtension = function (imageExtension) {\n this.imageExtension_ = imageExtension;\n};\n\n\n/**\n * Returns the value of the imagePath
property.\n *\n * @return {string} The value of the imagePath property.\n */\nMarkerClusterer.prototype.getImagePath = function () {\n return this.imagePath_;\n};\n\n\n/**\n * Sets the value of the imagePath
property.\n *\n * @param {string} imagePath The value of the imagePath property.\n */\nMarkerClusterer.prototype.setImagePath = function (imagePath) {\n this.imagePath_ = imagePath;\n};\n\n\n/**\n * Returns the value of the imageSizes
property.\n *\n * @return {Array} The value of the imageSizes property.\n */\nMarkerClusterer.prototype.getImageSizes = function () {\n return this.imageSizes_;\n};\n\n\n/**\n * Sets the value of the imageSizes
property.\n *\n * @param {Array} imageSizes The value of the imageSizes property.\n */\nMarkerClusterer.prototype.setImageSizes = function (imageSizes) {\n this.imageSizes_ = imageSizes;\n};\n\n\n/**\n * Returns the value of the calculator
property.\n *\n * @return {function} the value of the calculator property.\n */\nMarkerClusterer.prototype.getCalculator = function () {\n return this.calculator_;\n};\n\n\n/**\n * Sets the value of the calculator
property.\n *\n * @param {function(Array.batchSizeIE
property.\n *\n * @return {number} the value of the batchSizeIE property.\n */\nMarkerClusterer.prototype.getBatchSizeIE = function () {\n return this.batchSizeIE_;\n};\n\n\n/**\n * Sets the value of the batchSizeIE
property.\n *\n * @param {number} batchSizeIE The value of the batchSizeIE property.\n */\nMarkerClusterer.prototype.setBatchSizeIE = function (batchSizeIE) {\n this.batchSizeIE_ = batchSizeIE;\n};\n\n\n/**\n * Returns the value of the clusterClass
property.\n *\n * @return {string} the value of the clusterClass property.\n */\nMarkerClusterer.prototype.getClusterClass = function () {\n return this.clusterClass_;\n};\n\n\n/**\n * Sets the value of the clusterClass
property.\n *\n * @param {string} clusterClass The value of the clusterClass property.\n */\nMarkerClusterer.prototype.setClusterClass = function (clusterClass) {\n this.clusterClass_ = clusterClass;\n};\n\n\n/**\n * Returns the array of markers managed by the clusterer.\n *\n * @return {Array} The array of markers managed by the clusterer.\n */\nMarkerClusterer.prototype.getMarkers = function () {\n return this.markers_;\n};\n\n\n/**\n * Returns the number of markers managed by the clusterer.\n *\n * @return {number} The number of markers.\n */\nMarkerClusterer.prototype.getTotalMarkers = function () {\n return this.markers_.length;\n};\n\n\n/**\n * Returns the current array of clusters formed by the clusterer.\n *\n * @return {Array} The array of clusters formed by the clusterer.\n */\nMarkerClusterer.prototype.getClusters = function () {\n return this.clusters_;\n};\n\n\n/**\n * Returns the number of clusters formed by the clusterer.\n *\n * @return {number} The number of clusters formed by the clusterer.\n */\nMarkerClusterer.prototype.getTotalClusters = function () {\n return this.clusters_.length;\n};\n\n\n/**\n * Adds a marker to the clusterer. The clusters are redrawn unless\n * opt_nodraw
is set to true
.\n *\n * @param {google.maps.Marker} marker The marker to add.\n * @param {boolean} [opt_nodraw] Set to true
to prevent redrawing.\n */\nMarkerClusterer.prototype.addMarker = function (marker, opt_nodraw) {\n this.pushMarkerTo_(marker);\n if (!opt_nodraw) {\n this.redraw_();\n }\n};\n\n\n/**\n * Adds an array of markers to the clusterer. The clusters are redrawn unless\n * opt_nodraw
is set to true
.\n *\n * @param {Array.true
to prevent redrawing.\n */\nMarkerClusterer.prototype.addMarkers = function (markers, opt_nodraw) {\n var key;\n for (key in markers) {\n if (markers.hasOwnProperty(key)) {\n this.pushMarkerTo_(markers[key]);\n }\n }\n if (!opt_nodraw) {\n this.redraw_();\n }\n};\n\n\n/**\n * Pushes a marker to the clusterer.\n *\n * @param {google.maps.Marker} marker The marker to add.\n */\nMarkerClusterer.prototype.pushMarkerTo_ = function (marker) {\n // If the marker is draggable add a listener so we can update the clusters on the dragend:\n if (marker.getDraggable()) {\n var cMarkerClusterer = this;\n google.maps.event.addListener(marker, \"dragend\", function () {\n if (cMarkerClusterer.ready_) {\n this.isAdded = false;\n cMarkerClusterer.repaint();\n }\n });\n }\n marker.isAdded = false;\n this.markers_.push(marker);\n};\n\n\n/**\n * Removes a marker from the cluster. The clusters are redrawn unless\n * opt_nodraw
is set to true
. Returns true
if the\n * marker was removed from the clusterer.\n *\n * @param {google.maps.Marker} marker The marker to remove.\n * @param {boolean} [opt_nodraw] Set to true
to prevent redrawing.\n * @return {boolean} True if the marker was removed from the clusterer.\n */\nMarkerClusterer.prototype.removeMarker = function (marker, opt_nodraw) {\n var removed = this.removeMarker_(marker);\n\n if (!opt_nodraw && removed) {\n this.repaint();\n }\n\n return removed;\n};\n\n\n/**\n * Removes an array of markers from the cluster. The clusters are redrawn unless\n * opt_nodraw
is set to true
. Returns true
if markers\n * were removed from the clusterer.\n *\n * @param {Array.true
to prevent redrawing.\n * @return {boolean} True if markers were removed from the clusterer.\n */\nMarkerClusterer.prototype.removeMarkers = function (markers, opt_nodraw) {\n var i, r;\n var removed = false;\n\n for (i = 0; i < markers.length; i++) {\n r = this.removeMarker_(markers[i]);\n removed = removed || r;\n }\n\n if (!opt_nodraw && removed) {\n this.repaint();\n }\n\n return removed;\n};\n\n\n/**\n * Removes a marker and returns true if removed, false if not.\n *\n * @param {google.maps.Marker} marker The marker to remove\n * @return {boolean} Whether the marker was removed or not\n */\nMarkerClusterer.prototype.removeMarker_ = function (marker) {\n var i;\n var index = -1;\n if (this.markers_.indexOf) {\n index = this.markers_.indexOf(marker);\n } else {\n for (i = 0; i < this.markers_.length; i++) {\n if (marker === this.markers_[i]) {\n index = i;\n break;\n }\n }\n }\n\n if (index === -1) {\n // Marker is not in our list of markers, so do nothing:\n return false;\n }\n\n marker.setMap(null);\n this.markers_.splice(index, 1); // Remove the marker from the list of managed markers\n return true;\n};\n\n\n/**\n * Removes all clusters and markers from the map and also removes all markers\n * managed by the clusterer.\n */\nMarkerClusterer.prototype.clearMarkers = function () {\n this.resetViewport_(true);\n this.markers_ = [];\n};\n\n\n/**\n * Recalculates and redraws all the marker clusters from scratch.\n * Call this after changing any properties.\n */\nMarkerClusterer.prototype.repaint = function () {\n var oldClusters = this.clusters_.slice();\n this.clusters_ = [];\n this.resetViewport_(false);\n this.redraw_();\n\n // Remove the old clusters.\n // Do it in a timeout to prevent blinking effect.\n setTimeout(function () {\n var i;\n for (i = 0; i < oldClusters.length; i++) {\n oldClusters[i].remove();\n }\n }, 0);\n};\n\n\n/**\n * Returns the current bounds extended by the grid size.\n *\n * @param {google.maps.LatLngBounds} bounds The bounds to extend.\n * @return {google.maps.LatLngBounds} The extended bounds.\n * @ignore\n */\nMarkerClusterer.prototype.getExtendedBounds = function (bounds) {\n var projection = this.getProjection();\n\n // Turn the bounds into latlng.\n var tr = new google.maps.LatLng(bounds.getNorthEast().lat(),\n bounds.getNorthEast().lng());\n var bl = new google.maps.LatLng(bounds.getSouthWest().lat(),\n bounds.getSouthWest().lng());\n\n // Convert the points to pixels and the extend out by the grid size.\n var trPix = projection.fromLatLngToDivPixel(tr);\n trPix.x += this.gridSize_;\n trPix.y -= this.gridSize_;\n\n var blPix = projection.fromLatLngToDivPixel(bl);\n blPix.x -= this.gridSize_;\n blPix.y += this.gridSize_;\n\n // Convert the pixel points back to LatLng\n var ne = projection.fromDivPixelToLatLng(trPix);\n var sw = projection.fromDivPixelToLatLng(blPix);\n\n // Extend the bounds to contain the new bounds.\n bounds.extend(ne);\n bounds.extend(sw);\n\n return bounds;\n};\n\n\n/**\n * Redraws all the clusters.\n */\nMarkerClusterer.prototype.redraw_ = function () {\n this.createClusters_(0);\n};\n\n\n/**\n * Removes all clusters from the map. The markers are also removed from the map\n * if opt_hide
is set to true
.\n *\n * @param {boolean} [opt_hide] Set to true
to also remove the markers\n * from the map.\n */\nMarkerClusterer.prototype.resetViewport_ = function (opt_hide) {\n var i, marker;\n // Remove all the clusters\n for (i = 0; i < this.clusters_.length; i++) {\n this.clusters_[i].remove();\n }\n this.clusters_ = [];\n\n // Reset the markers to not be added and to be removed from the map.\n for (i = 0; i < this.markers_.length; i++) {\n marker = this.markers_[i];\n marker.isAdded = false;\n if (opt_hide) {\n marker.setMap(null);\n }\n }\n};\n\n\n/**\n * Calculates the distance between two latlng locations in km.\n *\n * @param {google.maps.LatLng} p1 The first lat lng point.\n * @param {google.maps.LatLng} p2 The second lat lng point.\n * @return {number} The distance between the two points in km.\n * @see http://www.movable-type.co.uk/scripts/latlong.html\n*/\nMarkerClusterer.prototype.distanceBetweenPoints_ = function (p1, p2) {\n var R = 6371; // Radius of the Earth in km\n var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;\n var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;\n var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) *\n Math.sin(dLon / 2) * Math.sin(dLon / 2);\n var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n var d = R * c;\n return d;\n};\n\n\n/**\n * Determines if a marker is contained in a bounds.\n *\n * @param {google.maps.Marker} marker The marker to check.\n * @param {google.maps.LatLngBounds} bounds The bounds to check against.\n * @return {boolean} True if the marker is in the bounds.\n */\nMarkerClusterer.prototype.isMarkerInBounds_ = function (marker, bounds) {\n return bounds.contains(marker.getPosition());\n};\n\n\n/**\n * Adds a marker to a cluster, or creates a new cluster.\n *\n * @param {google.maps.Marker} marker The marker to add.\n */\nMarkerClusterer.prototype.addToClosestCluster_ = function (marker) {\n var i, d, cluster, center;\n var distance = 40000; // Some large number\n var clusterToAddTo = null;\n for (i = 0; i < this.clusters_.length; i++) {\n cluster = this.clusters_[i];\n center = cluster.getCenter();\n if (center) {\n d = this.distanceBetweenPoints_(center, marker.getPosition());\n if (d < distance) {\n distance = d;\n clusterToAddTo = cluster;\n }\n }\n }\n\n if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)) {\n clusterToAddTo.addMarker(marker);\n } else {\n cluster = new Cluster(this);\n cluster.addMarker(marker);\n this.clusters_.push(cluster);\n }\n};\n\n\n/**\n * Creates the clusters. This is done in batches to avoid timeout errors\n * in some browsers when there is a huge number of markers.\n *\n * @param {number} iFirst The index of the first marker in the batch of\n * markers to be added to clusters.\n */\nMarkerClusterer.prototype.createClusters_ = function (iFirst) {\n var i, marker;\n var mapBounds;\n var cMarkerClusterer = this;\n if (!this.ready_) {\n return;\n }\n\n // Cancel previous batch processing if we're working on the first batch:\n if (iFirst === 0) {\n /**\n * This event is fired when the MarkerClusterer
begins\n * clustering markers.\n * @name MarkerClusterer#clusteringbegin\n * @param {MarkerClusterer} mc The MarkerClusterer whose markers are being clustered.\n * @event\n */\n google.maps.event.trigger(this, \"clusteringbegin\", this);\n\n if (typeof this.timerRefStatic !== \"undefined\") {\n clearTimeout(this.timerRefStatic);\n delete this.timerRefStatic;\n }\n }\n\n // Get our current map view bounds.\n // Create a new bounds object so we don't affect the map.\n //\n // See Comments 9 & 11 on Issue 3651 relating to this workaround for a Google Maps bug:\n if (this.getMap().getZoom() > 3) {\n mapBounds = new google.maps.LatLngBounds(this.getMap().getBounds().getSouthWest(),\n this.getMap().getBounds().getNorthEast());\n } else {\n mapBounds = new google.maps.LatLngBounds(new google.maps.LatLng(85.02070771743472, -178.48388434375), new google.maps.LatLng(-85.08136444384544, 178.00048865625));\n }\n var bounds = this.getExtendedBounds(mapBounds);\n\n var iLast = Math.min(iFirst + this.batchSize_, this.markers_.length);\n\n for (i = iFirst; i < iLast; i++) {\n marker = this.markers_[i];\n if (!marker.isAdded && this.isMarkerInBounds_(marker, bounds)) {\n if (!this.ignoreHidden_ || (this.ignoreHidden_ && marker.getVisible())) {\n this.addToClosestCluster_(marker);\n }\n }\n }\n\n if (iLast < this.markers_.length) {\n this.timerRefStatic = setTimeout(function () {\n cMarkerClusterer.createClusters_(iLast);\n }, 0);\n } else {\n delete this.timerRefStatic;\n\n /**\n * This event is fired when the MarkerClusterer
stops\n * clustering markers.\n * @name MarkerClusterer#clusteringend\n * @param {MarkerClusterer} mc The MarkerClusterer whose markers are being clustered.\n * @event\n */\n google.maps.event.trigger(this, \"clusteringend\", this);\n }\n};\n\n\n/**\n * Extends an object's prototype by another's.\n *\n * @param {Object} obj1 The object to be extended.\n * @param {Object} obj2 The object to extend with.\n * @return {Object} The new extended object.\n * @ignore\n */\nMarkerClusterer.prototype.extend = function (obj1, obj2) {\n return (function (object) {\n var property;\n for (property in object.prototype) {\n this.prototype[property] = object.prototype[property];\n }\n return this;\n }).apply(obj1, [obj2]);\n};\n\n\n/**\n * The default function for determining the label text and style\n * for a cluster icon.\n *\n * @param {Array.