} The cluster center.\r\n */\r\nCluster.prototype.getMarkers = function () {\r\n return this.markers_;\r\n};\r\n\r\n\r\n/**\r\n * Returns the center of the cluster.\r\n *\r\n * @return {google.maps.LatLng} The cluster center.\r\n */\r\nCluster.prototype.getCenter = function () {\r\n return this.center_;\r\n};\r\n\r\n\r\n/**\r\n * Calculated the extended bounds of the cluster with the grid.\r\n *\r\n * @private\r\n */\r\nCluster.prototype.calculateBounds_ = function () {\r\n var bounds = new google.maps.LatLngBounds(this.center_, this.center_);\r\n this.bounds_ = this.markerClusterer_.getExtendedBounds(bounds);\r\n};\r\n\r\n\r\n/**\r\n * Determines if a marker lies in the clusters bounds.\r\n *\r\n * @param {google.maps.Marker} marker The marker to check.\r\n * @return {boolean} True if the marker lies in the bounds.\r\n */\r\nCluster.prototype.isMarkerInClusterBounds = function (marker) {\r\n return this.bounds_.contains(marker.getPosition());\r\n};\r\n\r\n\r\n/**\r\n * Returns the map that the cluster is associated with.\r\n *\r\n * @return {google.maps.Map} The map.\r\n */\r\nCluster.prototype.getMap = function () {\r\n return this.map_;\r\n};\r\n\r\n\r\n/**\r\n * Updates the cluster icon\r\n */\r\nCluster.prototype.updateIcon = function () {\r\n var zoom = this.map_.getZoom();\r\n var mz = this.markerClusterer_.getMaxZoom();\r\n\r\n if (mz && zoom > mz) {\r\n // The zoom is greater than our max zoom so show all the markers in cluster.\r\n for (var i = 0, marker; marker = this.markers_[i]; i++) {\r\n marker.setMap(this.map_);\r\n }\r\n return;\r\n }\r\n\r\n if (this.markers_.length < this.minClusterSize_) {\r\n // Min cluster size not yet reached.\r\n this.clusterIcon_.hide();\r\n return;\r\n }\r\n\r\n var numStyles = this.markerClusterer_.getStyles().length;\r\n var sums = this.markerClusterer_.getCalculator()(this.markers_, numStyles);\r\n this.clusterIcon_.setCenter(this.center_);\r\n this.clusterIcon_.setSums(sums);\r\n this.clusterIcon_.show();\r\n};\r\n\r\n\r\n/**\r\n * A cluster icon\r\n *\r\n * @param {Cluster} cluster The cluster to be associated with.\r\n * @param {Object} styles An object that has style properties:\r\n * 'url': (string) The image url.\r\n * 'height': (number) The image height.\r\n * 'width': (number) The image width.\r\n * 'anchor': (Array) The anchor position of the label text.\r\n * 'textColor': (string) The text color.\r\n * 'textSize': (number) The text size.\r\n * 'backgroundPosition: (string) The background postition x, y.\r\n * @param {number=} opt_padding Optional padding to apply to the cluster icon.\r\n * @constructor\r\n * @extends google.maps.OverlayView\r\n * @ignore\r\n */\r\nfunction ClusterIcon(cluster, styles, opt_padding) {\r\n cluster.getMarkerClusterer().extend(ClusterIcon, google.maps.OverlayView);\r\n\r\n this.styles_ = styles;\r\n this.padding_ = opt_padding || 0;\r\n this.cluster_ = cluster;\r\n this.center_ = null;\r\n this.map_ = cluster.getMap();\r\n this.div_ = null;\r\n this.sums_ = null;\r\n this.visible_ = false;\r\n\r\n this.setMap(this.map_);\r\n}\r\n\r\n\r\n/**\r\n * Triggers the clusterclick event and zoom's if the option is set.\r\n *\r\n * @param {google.maps.MouseEvent} event The event to propagate\r\n */\r\nClusterIcon.prototype.triggerClusterClick = function (event) {\r\n var markerClusterer = this.cluster_.getMarkerClusterer();\r\n\r\n // Trigger the clusterclick event.\r\n google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_, event);\r\n\r\n if (markerClusterer.isZoomOnClick()) {\r\n // Zoom into the cluster.\r\n this.map_.fitBounds(this.cluster_.getBounds());\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Adding the cluster icon to the dom.\r\n * @ignore\r\n */\r\nClusterIcon.prototype.onAdd = function () {\r\n this.div_ = document.createElement('DIV');\r\n if (this.visible_) {\r\n var pos = this.getPosFromLatLng_(this.center_);\r\n this.div_.style.cssText = this.createCss(pos);\r\n this.div_.innerHTML = this.sums_.text;\r\n }\r\n\r\n var panes = this.getPanes();\r\n panes.overlayMouseTarget.appendChild(this.div_);\r\n\r\n var that = this;\r\n this.div_.addEventListener('click', function (event) {\r\n that.triggerClusterClick(event);\r\n });\r\n\r\n // google.maps.event.addEventListener(this.div_, 'click', function (event) {\r\n // that.triggerClusterClick(event);\r\n // });\r\n};\r\n\r\n\r\n/**\r\n * Returns the position to place the div dending on the latlng.\r\n *\r\n * @param {google.maps.LatLng} latlng The position in latlng.\r\n * @return {google.maps.Point} The position in pixels.\r\n * @private\r\n */\r\nClusterIcon.prototype.getPosFromLatLng_ = function (latlng) {\r\n var pos = this.getProjection().fromLatLngToDivPixel(latlng);\r\n\r\n if (typeof this.iconAnchor_ === 'object' && this.iconAnchor_.length === 2) {\r\n pos.x -= this.iconAnchor_[0];\r\n pos.y -= this.iconAnchor_[1];\r\n } else {\r\n pos.x -= parseInt(this.width_ / 2, 10);\r\n pos.y -= parseInt(this.height_ / 2, 10);\r\n }\r\n return pos;\r\n};\r\n\r\n\r\n/**\r\n * Draw the icon.\r\n * @ignore\r\n */\r\nClusterIcon.prototype.draw = function () {\r\n if (this.visible_) {\r\n var pos = this.getPosFromLatLng_(this.center_);\r\n this.div_.style.top = pos.y + 'px';\r\n this.div_.style.left = pos.x + 'px';\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Hide the icon.\r\n */\r\nClusterIcon.prototype.hide = function () {\r\n if (this.div_) {\r\n this.div_.style.display = 'none';\r\n }\r\n this.visible_ = false;\r\n};\r\n\r\n\r\n/**\r\n * Position and show the icon.\r\n */\r\nClusterIcon.prototype.show = function () {\r\n if (this.div_) {\r\n var pos = this.getPosFromLatLng_(this.center_);\r\n this.div_.style.cssText = this.createCss(pos);\r\n this.div_.style.display = '';\r\n }\r\n this.visible_ = true;\r\n};\r\n\r\n\r\n/**\r\n * Remove the icon from the map\r\n */\r\nClusterIcon.prototype.remove = function () {\r\n this.setMap(null);\r\n};\r\n\r\n\r\n/**\r\n * Implementation of the onRemove interface.\r\n * @ignore\r\n */\r\nClusterIcon.prototype.onRemove = function () {\r\n if (this.div_ && this.div_.parentNode) {\r\n this.hide();\r\n this.div_.parentNode.removeChild(this.div_);\r\n this.div_ = null;\r\n }\r\n};\r\n\r\n\r\n/**\r\n * Set the sums of the icon.\r\n *\r\n * @param {Object} sums The sums containing:\r\n * 'text': (string) The text to display in the icon.\r\n * 'index': (number) The style index of the icon.\r\n */\r\nClusterIcon.prototype.setSums = function (sums) {\r\n this.sums_ = sums;\r\n this.text_ = sums.text;\r\n this.index_ = sums.index;\r\n if (this.div_) {\r\n this.div_.innerHTML = sums.text;\r\n }\r\n\r\n this.useStyle();\r\n};\r\n\r\n\r\n/**\r\n * Sets the icon to the the styles.\r\n */\r\nClusterIcon.prototype.useStyle = function () {\r\n var index = Math.max(0, this.sums_.index - 1);\r\n index = Math.min(this.styles_.length - 1, index);\r\n var style = this.styles_[index];\r\n this.url_ = style['url'];\r\n this.height_ = style['height'];\r\n this.width_ = style['width'];\r\n this.textColor_ = style['textColor'];\r\n this.anchor_ = style['anchor'];\r\n this.textSize_ = style['textSize'];\r\n this.backgroundPosition_ = style['backgroundPosition'];\r\n this.iconAnchor_ = style['iconAnchor'];\r\n};\r\n\r\n\r\n/**\r\n * Sets the center of the icon.\r\n *\r\n * @param {google.maps.LatLng} center The latlng to set as the center.\r\n */\r\nClusterIcon.prototype.setCenter = function (center) {\r\n this.center_ = center;\r\n};\r\n\r\n\r\n/**\r\n * Create the css text based on the position of the icon.\r\n *\r\n * @param {google.maps.Point} pos The position.\r\n * @return {string} The css style text.\r\n */\r\nClusterIcon.prototype.createCss = function (pos) {\r\n var style = [];\r\n style.push('background-image:url(' + this.url_ + ');');\r\n var backgroundPosition = this.backgroundPosition_ ? this.backgroundPosition_ : '0 0';\r\n style.push('background-position:' + backgroundPosition + ';');\r\n\r\n if (typeof this.anchor_ === 'object') {\r\n if (typeof this.anchor_[0] === 'number' && this.anchor_[0] > 0 &&\r\n this.anchor_[0] < this.height_) {\r\n style.push('height:' + (this.height_ - this.anchor_[0]) +\r\n 'px; padding-top:' + this.anchor_[0] + 'px;');\r\n } else if (typeof this.anchor_[0] === 'number' && this.anchor_[0] < 0 &&\r\n -this.anchor_[0] < this.height_) {\r\n style.push('height:' + this.height_ + 'px; line-height:' + (this.height_ + this.anchor_[0]) +\r\n 'px;');\r\n } else {\r\n style.push('height:' + this.height_ + 'px; line-height:' + this.height_ +\r\n 'px;');\r\n }\r\n if (typeof this.anchor_[1] === 'number' && this.anchor_[1] > 0 &&\r\n this.anchor_[1] < this.width_) {\r\n style.push('width:' + (this.width_ - this.anchor_[1]) +\r\n 'px; padding-left:' + this.anchor_[1] + 'px;');\r\n } else {\r\n style.push('width:' + this.width_ + 'px; text-align:center;');\r\n }\r\n } else {\r\n style.push('height:' + this.height_ + 'px; line-height:' +\r\n this.height_ + 'px; width:' + this.width_ + 'px; text-align:center;');\r\n }\r\n\r\n var txtColor = this.textColor_ ? this.textColor_ : 'black';\r\n var txtSize = this.textSize_ ? this.textSize_ : 11;\r\n\r\n style.push('cursor:pointer; top:' + pos.y + 'px; left:' +\r\n pos.x + 'px; color:' + txtColor + '; position:absolute; font-size:' +\r\n txtSize + 'px; font-family:Arial,sans-serif; font-weight:bold');\r\n return style.join('');\r\n};\r\n\r\n\r\n(function ($) {\r\n\r\n 'use strict';\r\n\r\n // Define and expose object\r\n window.App = {\r\n\r\n window: $(window),\r\n body: $('body'),\r\n page: $('#page'),\r\n baseURL: $('base').attr('href')\r\n }\r\n}(jQuery));\r\n(function ($) {\r\n\r\n 'use strict';\r\n\r\n /**\r\n * Map object\r\n */\r\n App.Map = {\r\n\r\n activeMarker: null,\r\n bounds: null,\r\n infoWindow: null,\r\n map: null,\r\n mapNode: null,\r\n markers: [],\r\n markerClusterer: null,\r\n organizations: [],\r\n\r\n options: {\r\n clusterIcons: [\r\n {url: '/images/m1.png', width: 53, height: 52, textColor: '#fff'},\r\n {url: '/images/m2.png', width: 56, height: 55, textColor: '#fff'},\r\n {url: '/images/m3.png', width: 66, height: 65, textColor: '#fff'},\r\n {url: '/images/m4.png', width: 78, height: 77, textColor: '#fff'},\r\n {url: '/images/m5.png', width: 90, height: 98, textColor: '#fff'}\r\n ],\r\n scrollwheel: false,\r\n clusterInfoWindowZoom: 12,\r\n clusterZoomIncrement: 1,\r\n clusterLinkClassName: 'cluster-link',\r\n clusterListInfoWindowHeader: 'Op deze locatie zijn %n organisaties gevestigd',\r\n hideInfoWindowsOnZoom: true,\r\n mapSelector: '#js-partners-map',\r\n markerIcon: '/images/google-map-marker.svg',\r\n markerLinkInfoWindowMore: 'Bekijk organisatie'\r\n },\r\n\r\n /**\r\n * Set up the map\r\n */\r\n init: function () {\r\n this.organizations = window.organizations;\r\n this.mapNode = $(this.options.mapSelector);\r\n\r\n // Make sure both organizations and the map node are set\r\n if (window.organizations && this.mapNode.length) {\r\n this.inititalizeMap();\r\n }\r\n },\r\n\r\n /**\r\n * Set up the Google Map\r\n */\r\n inititalizeMap: function () {\r\n var self = this;\r\n\r\n // Create the map\r\n this.map = new google.maps.Map(this.mapNode[0], {\r\n mapTypeControl: false,\r\n mapTypeId: google.maps.MapTypeId.ROADMAP,\r\n panControl: false,\r\n streetViewControl: false,\r\n center: {lat: 52.1193993, lng: 5.633566},\r\n zoom: 8,\r\n // restriction: {\r\n // latLngBounds: {\r\n // north: -10,\r\n // south: -40,\r\n // east: 160,\r\n // west: 100,\r\n // },\r\n // },\r\n zoomControlOptions: {\r\n scrollwheel: false,\r\n position: google.maps.ControlPosition.RIGHT_BOTTOM\r\n }\r\n });\r\n\r\n // If the option is enabled, hide the active info window when the zoom changes\r\n if (this.options.hideInfoWindowsOnZoom) {\r\n google.maps.event.addListener(this.map, 'zoom_changed', function () {\r\n self.closeActiveInfoWindow();\r\n });\r\n }\r\n\r\n // Set the bounds\r\n this.bounds = new google.maps.LatLngBounds();\r\n\r\n // Add the markers to the map\r\n self.markers = [];\r\n this.addMarkers();\r\n\r\n // Fit to the bounds\r\n this.map.fitBounds(this.bounds);\r\n\r\n // Set up clustering\r\n this.applyClustering();\r\n\r\n this.map.setCenter(new google.maps.LatLng(parseFloat(51.4895218375193), parseFloat(5.493504558944068)));\r\n },\r\n \r\n /**\r\n * Add markers to the map\r\n */\r\n addMarkers: function () {\r\n\r\n var self = this;\r\n self.markerClusterer = new MarkerClusterer(this.map, this.markers, {\r\n styles: this.options.clusterIcons,\r\n zoomOnClick: false\r\n });\r\n\r\n $.each(this.organizations, function (index, organization) {\r\n // Create a new marker\r\n var marker = new google.maps.Marker({\r\n icon: self.options.markerIcon,\r\n index: index,\r\n infoWindowData: organization.infoWindowData,\r\n map: self.map,\r\n position: new google.maps.LatLng(this.lat, this.long)\r\n });\r\n\r\n // Add event handlers to the markers\r\n google.maps.event.addListener(marker, 'click', function () {\r\n self.showMarkerInfoWindow(marker, organization.infoWindowData);\r\n });\r\n\r\n // Add the marker position to the bounds\r\n self.bounds.extend(marker.position);\r\n\r\n // Store the marker clustering\r\n self.markers.push(marker);\r\n });\r\n //letop vierkant hierboven laten staan!!\r\n var bounds = new google.maps.LatLngBounds();\r\n for (var i = 0; i < self.markers.length; i++) {\r\n bounds.extend(self.markers[i].getPosition());\r\n }\r\n\r\n this.map.fitBounds(bounds);\r\n },\r\n\r\n /**\r\n * Show marker info window\r\n * @param {object} marker\r\n * @param {object} data\r\n */\r\n showMarkerInfoWindow: function (marker, data) {\r\n\r\n var content;\r\n\r\n this.closeActiveInfoWindow();\r\n\r\n // Render different content if the data contains a URL\r\n if (data.url) {\r\n content = [\r\n '' + data.title + '
',\r\n '' + data.address + '
',\r\n '' + data.zipCode + '
',\r\n '' + this.options.markerLinkInfoWindowMore + ''\r\n ];\r\n } else {\r\n content = [\r\n '' + data.title + '
',\r\n '' + data.address + '
',\r\n '' + data.zipCode + '
',\r\n '' + data.size + '
',\r\n '' + data.branch + '
'\r\n ];\r\n }\r\n\r\n // Create info window with content\r\n this.infoWindow = new google.maps.InfoWindow({\r\n content: content.join('')\r\n });\r\n\r\n this.infoWindow.open(this.map, marker);\r\n },\r\n\r\n /**\r\n * Show cluster list info window\r\n * @param {object} cluster\r\n * @param {object} center\r\n */\r\n showClusterListInfoWindow: function (cluster, center) {\r\n\r\n var self = this,\r\n markers = cluster.getMarkers(),\r\n content = [];\r\n\r\n this.closeActiveInfoWindow();\r\n\r\n // Loop over marker data and push linked titles to content\r\n var counter = 0;\r\n $.each(markers, function () {\r\n if (counter > 0) {\r\n content.push('
');\r\n }\r\n content.push('' + this.infoWindowData.title + '
');\r\n content.push('' + this.infoWindowData.address + '
');\r\n content.push('' + this.infoWindowData.zipCode + '
');\r\n if (this.infoWindowData.url) {\r\n content.push('' + this.infoWindowData.title + '');\r\n }\r\n counter += 1;\r\n });\r\n\r\n // Create info window from content\r\n this.infoWindow = new google.maps.InfoWindow({\r\n content: content.join('')\r\n });\r\n\r\n this.infoWindow.open(this.map);\r\n this.infoWindow.setPosition(center);\r\n },\r\n\r\n\r\n /**\r\n * Show cluster detail info window\r\n * @param {number} index\r\n * @param {number} lat\r\n * @param {number} lng\r\n */\r\n showClusterDetailInfoWindow: function (index, lat, lng) {\r\n\r\n var data = this.organizations[index].infoWindowData,\r\n position = new google.maps.LatLng(lat, lng);\r\n\r\n this.closeActiveInfoWindow();\r\n\r\n // Create info window with content\r\n this.infoWindow = new google.maps.InfoWindow({\r\n content: [\r\n '' + data.title + '
',\r\n '' + data.street + '
',\r\n '' + data.zipCode + ' ' + data.place + '
',\r\n '' + data.size + '
',\r\n '' + data.branch + '
'\r\n ].join('')\r\n });\r\n\r\n this.infoWindow.open(this.map);\r\n this.infoWindow.setPosition(position);\r\n },\r\n\r\n /**\r\n *\r\n */\r\n closeActiveInfoWindow: function () {\r\n if (this.infoWindow) {\r\n this.infoWindow.close();\r\n }\r\n },\r\n\r\n applyClustering: function () {\r\n\r\n var self = this;\r\n\r\n // Apply clustering\r\n this.markerClusterer = new MarkerClusterer(this.map, this.markers, {\r\n styles: this.options.clusterIcons,\r\n zoomOnClick: false\r\n });\r\n\r\n // When a cluster is clicked, either zoom in (default behaviour)\r\n // When the user is zoomed in past the configured clusterInfoWindowZoom show a cluster list containing the underlying markers\r\n google.maps.event.addListener(this.markerClusterer, 'clusterclick', function (cluster) {\r\n\r\n var zoom = self.map.getZoom(),\r\n center = cluster.getCenter();\r\n\r\n if (zoom > self.options.clusterInfoWindowZoom) {\r\n self.showClusterListInfoWindow(cluster, center);\r\n } else {\r\n self.map.setZoom(zoom + self.options.clusterZoomIncrement);\r\n self.map.panTo(center);\r\n }\r\n });\r\n\r\n // Delegated event handler to handle clicks on the markers in the cluster list\r\n // When a list item is clicked, show a custom info window containing the marker details\r\n App.body.on('click', '.' + this.options.clusterLinkClassName, function (event) {\r\n\r\n var link = $(this),\r\n data = link.data(),\r\n href = link.attr('href');\r\n\r\n if (href === '#') {\r\n self.showClusterDetailInfoWindow(data.index, data.lat, data.lng);\r\n event.preventDefault();\r\n }\r\n });\r\n }\r\n };\r\n\r\n}(jQuery));"],"names":["MarkerClusterer","map","opt_markers","opt_options","this","extend","google","maps","OverlayView","map_","markers_","clusters_","sizes","styles_","ready_","options","gridSize_","minClusterSize_","maxZoom_","imagePath_","MARKER_CLUSTER_IMAGE_PATH_","imageExtension_","MARKER_CLUSTER_IMAGE_EXTENSION_","zoomOnClick_","undefined","averageCenter_","setupStyles_","setMap","prevZoom_","getZoom","that","event","addListener","zoom","resetViewport","redraw","length","addMarkers","Cluster","markerClusterer","markerClusterer_","getMap","getGridSize","getMinClusterSize","isAverageCenter","center_","bounds_","clusterIcon_","ClusterIcon","getStyles","cluster","styles","opt_padding","getMarkerClusterer","padding_","cluster_","div_","sums_","visible_","prototype","obj1","obj2","object","property","apply","onAdd","setReady_","draw","size","i","push","url","height","width","fitMapToMarkers","marker","markers","getMarkers","bounds","LatLngBounds","getPosition","fitBounds","setStyles","isZoomOnClick","getTotalMarkers","setMaxZoom","maxZoom","getMaxZoom","calculator_","numStyles","index","count","dv","parseInt","text","Math","min","setCalculator","calculator","getCalculator","opt_nodraw","pushMarkerTo_","isAdded","repaint","addMarker","removeMarker_","indexOf","m","splice","removeMarker","removed","removeMarkers","r","ready","createClusters_","getTotalClusters","setGridSize","setMinClusterSize","getExtendedBounds","projection","getProjection","tr","LatLng","getNorthEast","lat","lng","bl","getSouthWest","trPix","fromLatLngToDivPixel","x","y","blPix","ne","fromDivPixelToLatLng","sw","isMarkerInBounds_","contains","clearMarkers","opt_hide","remove","oldClusters","slice","window","setTimeout","distanceBetweenPoints_","p1","p2","dLat","PI","dLon","a","sin","cos","atan2","sqrt","addToClosestCluster_","distance","clusterToAddTo","center","getCenter","d","isMarkerInClusterBounds","mapBounds","getBounds","isMarkerAlreadyAdded","l","calculateBounds_","len","updateIcon","getSize","mz","hide","sums","setCenter","setSums","show","triggerClusterClick","trigger","document","createElement","pos","getPosFromLatLng_","style","cssText","createCss","innerHTML","getPanes","overlayMouseTarget","appendChild","addEventListener","latlng","iconAnchor_","width_","height_","top","left","display","onRemove","parentNode","removeChild","text_","index_","useStyle","max","url_","textColor_","anchor_","textSize_","backgroundPosition_","backgroundPosition","txtColor","txtSize","join","$","App","body","page","baseURL","attr","jQuery","Map","activeMarker","infoWindow","mapNode","organizations","clusterIcons","textColor","scrollwheel","clusterInfoWindowZoom","clusterZoomIncrement","clusterLinkClassName","clusterListInfoWindowHeader","hideInfoWindowsOnZoom","mapSelector","markerIcon","markerLinkInfoWindowMore","init","inititalizeMap","self","mapTypeControl","mapTypeId","MapTypeId","ROADMAP","panControl","streetViewControl","zoomControlOptions","position","ControlPosition","RIGHT_BOTTOM","closeActiveInfoWindow","applyClustering","parseFloat","zoomOnClick","each","organization","Marker","icon","infoWindowData","long","showMarkerInfoWindow","data","content","title","address","zipCode","branch","InfoWindow","open","showClusterListInfoWindow","counter","setPosition","showClusterDetailInfoWindow","street","place","close","setZoom","panTo","on","link","preventDefault"],"sourceRoot":""}