mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-29 21:17:17 +00:00
340 lines
13 KiB
CoffeeScript
340 lines
13 KiB
CoffeeScript
#######################################################################################################
|
|
############################################## Google maps ##########################################
|
|
#######################################################################################################
|
|
|
|
class @Gmaps4RailsGoogle extends Gmaps4Rails
|
|
|
|
constructor: ->
|
|
super
|
|
#Map settings
|
|
@map_options =
|
|
disableDefaultUI: false
|
|
disableDoubleClickZoom: false
|
|
type: "ROADMAP" # HYBRID, ROADMAP, SATELLITE, TERRAIN
|
|
|
|
#markers + info styling
|
|
@markers_conf =
|
|
clusterer_gridSize: 50
|
|
clusterer_maxZoom: 5
|
|
custom_cluster_pictures: null
|
|
custom_infowindow_class: null
|
|
|
|
@mergeWithDefault("map_options")
|
|
@mergeWithDefault("markers_conf")
|
|
|
|
@kml_options =
|
|
clickable: true
|
|
preserveViewport: false
|
|
suppressInfoWindows: false
|
|
|
|
#Polygon Styling
|
|
@polygons_conf = # default style for polygons
|
|
strokeColor: "#FFAA00"
|
|
strokeOpacity: 0.8
|
|
strokeWeight: 2
|
|
fillColor: "#000000"
|
|
fillOpacity: 0.35
|
|
clickable: false
|
|
|
|
#Circle Styling
|
|
@circles_conf = #default style for circles
|
|
fillColor: "#00AAFF"
|
|
fillOpacity: 0.35
|
|
strokeColor: "#FFAA00"
|
|
strokeOpacity: 0.8
|
|
strokeWeight: 2
|
|
clickable: false
|
|
zIndex: null
|
|
|
|
#Direction Settings
|
|
@direction_conf =
|
|
panel_id: null
|
|
display_panel: false
|
|
origin: null
|
|
destination: null
|
|
waypoints: [] #[{location: "toulouse,fr", stopover: true}, {location: "Clermont-Ferrand, fr", stopover: true}]
|
|
optimizeWaypoints: false
|
|
unitSystem: "METRIC" #IMPERIAL
|
|
avoidHighways: false
|
|
avoidTolls: false
|
|
region: null
|
|
travelMode: "DRIVING" #WALKING, BICYCLING
|
|
|
|
#////////////////////////////////////////////////////
|
|
#/////////////// Basic Objects //////////////
|
|
#////////////////////////////////////////////////////
|
|
|
|
createPoint : (lat, lng) ->
|
|
return new google.maps.Point(lat, lng)
|
|
|
|
createLatLng : (lat, lng) ->
|
|
return new google.maps.LatLng(lat, lng)
|
|
|
|
createLatLngBounds : ->
|
|
return new google.maps.LatLngBounds()
|
|
|
|
createMap : ->
|
|
defaultOptions =
|
|
maxZoom: @map_options.maxZoom
|
|
minZoom: @map_options.minZoom
|
|
zoom: @map_options.zoom
|
|
center: @createLatLng(@map_options.center_latitude, @map_options.center_longitude)
|
|
mapTypeId: google.maps.MapTypeId[@map_options.type]
|
|
mapTypeControl: @map_options.mapTypeControl
|
|
disableDefaultUI: @map_options.disableDefaultUI
|
|
disableDoubleClickZoom: @map_options.disableDoubleClickZoom
|
|
draggable: @map_options.draggable
|
|
|
|
mergedOptions = @mergeObjectWithDefault @map_options.raw, defaultOptions
|
|
|
|
return new google.maps.Map document.getElementById(@map_options.id), mergedOptions
|
|
|
|
|
|
createMarkerImage : (markerPicture, markerSize, origin, anchor, scaledSize) ->
|
|
return new google.maps.MarkerImage(markerPicture, markerSize, origin, anchor, scaledSize)
|
|
|
|
createSize : (width, height) ->
|
|
return new google.maps.Size(width, height)
|
|
|
|
#////////////////////////////////////////////////////
|
|
#////////////////////// Markers /////////////////////
|
|
#////////////////////////////////////////////////////
|
|
|
|
createMarker : (args) ->
|
|
markerLatLng = @createLatLng(args.Lat, args.Lng)
|
|
#Marker sizes are expressed as a Size of X,Y
|
|
if args.marker_picture == "" and args.rich_marker == null
|
|
defaultOptions = {position: markerLatLng, map: @serviceObject, title: args.marker_title, draggable: args.marker_draggable, zIndex: args.zindex}
|
|
mergedOptions = @mergeObjectWithDefault @markers_conf.raw, defaultOptions
|
|
return new google.maps.Marker mergedOptions
|
|
|
|
if (args.rich_marker != null)
|
|
return new RichMarker({
|
|
position: markerLatLng
|
|
map: @serviceObject
|
|
draggable: args.marker_draggable
|
|
content: args.rich_marker
|
|
flat: if args.marker_anchor == null then false else args.marker_anchor[1]
|
|
anchor: if args.marker_anchor == null then 0 else args.marker_anchor[0]
|
|
zIndex: args.zindex
|
|
})
|
|
|
|
#default behavior
|
|
#calculate MarkerImage anchor location
|
|
imageAnchorPosition = @createImageAnchorPosition args.marker_anchor
|
|
shadowAnchorPosition = @createImageAnchorPosition args.shadow_anchor
|
|
#create or retrieve existing MarkerImages
|
|
markerImage = @createOrRetrieveImage(args.marker_picture, args.marker_width, args.marker_height, imageAnchorPosition)
|
|
shadowImage = @createOrRetrieveImage(args.shadow_picture, args.shadow_width, args.shadow_height, shadowAnchorPosition)
|
|
defaultOptions = {position: markerLatLng, map: @serviceObject, icon: markerImage, title: args.marker_title, draggable: args.marker_draggable, shadow: shadowImage, zIndex: args.zindex}
|
|
mergedOptions = @mergeObjectWithDefault @markers_conf.raw, defaultOptions
|
|
return new google.maps.Marker mergedOptions
|
|
|
|
#checks if obj is included in arr Array and returns the position or false
|
|
includeMarkerImage : (arr, obj) ->
|
|
for object, index in arr
|
|
return index if object.url == obj
|
|
return false
|
|
|
|
#checks if MarkerImage exists before creating a new one
|
|
#returns a MarkerImage or false if ever something wrong is passed as argument
|
|
createOrRetrieveImage : (currentMarkerPicture, markerWidth, markerHeight, imageAnchorPosition) ->
|
|
return null if (currentMarkerPicture == "" or currentMarkerPicture == null )
|
|
|
|
test_image_index = @includeMarkerImage(@markerImages, currentMarkerPicture)
|
|
switch test_image_index
|
|
when false
|
|
markerImage = @createMarkerImage(currentMarkerPicture, @createSize(markerWidth, markerHeight), null, imageAnchorPosition, null )
|
|
@markerImages.push(markerImage)
|
|
return markerImage
|
|
break
|
|
else
|
|
return @markerImages[test_image_index] if typeof test_image_index == 'number'
|
|
return false
|
|
|
|
#clear markers
|
|
clearMarkers : ->
|
|
for marker in @markers
|
|
@clearMarker marker
|
|
|
|
#show and hide markers
|
|
showMarkers : ->
|
|
for marker in @markers
|
|
@showMarker marker
|
|
|
|
hideMarkers : ->
|
|
for marker in @markers
|
|
@hideMarker marker
|
|
|
|
clearMarker : (marker) ->
|
|
marker.serviceObject.setMap(null)
|
|
|
|
showMarker : (marker) ->
|
|
marker.serviceObject.setVisible(true)
|
|
|
|
hideMarker : (marker) ->
|
|
marker.serviceObject.setVisible(false)
|
|
|
|
extendBoundsWithMarkers : ->
|
|
for marker in @markers
|
|
@boundsObject.extend(marker.serviceObject.position)
|
|
|
|
#////////////////////////////////////////////////////
|
|
#/////////////////// Clusterer //////////////////////
|
|
#////////////////////////////////////////////////////
|
|
|
|
createClusterer : (markers_array) ->
|
|
return new MarkerClusterer( @serviceObject, markers_array, { maxZoom: @markers_conf.clusterer_maxZoom, gridSize: @markers_conf.clusterer_gridSize, styles: @customClusterer() })
|
|
|
|
clearClusterer : ->
|
|
@markerClusterer.clearMarkers()
|
|
|
|
#creates clusters
|
|
clusterize : ->
|
|
if @markers_conf.do_clustering == true
|
|
#first clear the existing clusterer if any
|
|
@clearClusterer() if @markerClusterer != null
|
|
|
|
markers_array = new Array
|
|
for marker in @markers
|
|
markers_array.push(marker.serviceObject)
|
|
|
|
@markerClusterer = @createClusterer(markers_array)
|
|
|
|
#////////////////////////////////////////////////////
|
|
#/////////////////// INFO WINDOW ////////////////////
|
|
#////////////////////////////////////////////////////
|
|
|
|
#// creates infowindows
|
|
createInfoWindow : (marker_container) ->
|
|
if typeof(@jsTemplate) == "function" or marker_container.description?
|
|
marker_container.description = @jsTemplate(marker_container) if typeof(@jsTemplate) == "function"
|
|
if @markers_conf.custom_infowindow_class != null
|
|
#creating custom infowindow
|
|
boxText = document.createElement("div")
|
|
boxText.setAttribute("class", @markers_conf.custom_infowindow_class) #to customize
|
|
boxText.innerHTML = marker_container.description
|
|
marker_container.infowindow = new InfoBox(@infobox(boxText))
|
|
currentMap = this
|
|
google.maps.event.addListener(marker_container.serviceObject, 'click', @openInfoWindow(currentMap, marker_container.infowindow, marker_container.serviceObject))
|
|
else
|
|
#create default infowindow
|
|
marker_container.infowindow = new google.maps.InfoWindow({content: marker_container.description })
|
|
#add the listener associated
|
|
currentMap = this
|
|
google.maps.event.addListener(marker_container.serviceObject, 'click', @openInfoWindow(currentMap, marker_container.infowindow, marker_container.serviceObject))
|
|
|
|
openInfoWindow : (currentMap, infoWindow, marker) ->
|
|
return ->
|
|
# Close the latest selected marker before opening the current one.
|
|
currentMap.visibleInfoWindow.close() if currentMap.visibleInfoWindow != null
|
|
infoWindow.open(currentMap.serviceObject, marker)
|
|
currentMap.visibleInfoWindow = infoWindow
|
|
|
|
#////////////////////////////////////////////////////
|
|
#///////////////// KML //////////////////
|
|
#////////////////////////////////////////////////////
|
|
|
|
createKmlLayer : (kml) ->
|
|
kml_options = kml.options || {}
|
|
kml_options = @mergeObjectWithDefault(kml_options, @kml_options)
|
|
kml = new google.maps.KmlLayer( kml.url, kml_options)
|
|
kml.setMap(@serviceObject)
|
|
return kml
|
|
|
|
#////////////////////////////////////////////////////
|
|
#/////////////////// POLYLINES //////////////////////
|
|
#////////////////////////////////////////////////////
|
|
|
|
#creates a single polyline, triggered by create_polylines
|
|
create_polyline : (polyline) ->
|
|
polyline_coordinates = []
|
|
|
|
#2 cases here, either we have a coded array of LatLng or we have an Array of LatLng
|
|
for element in polyline
|
|
#if we have a coded array
|
|
if element.coded_array?
|
|
decoded_array = new google.maps.geometry.encoding.decodePath(element.coded_array)
|
|
#loop through every point in the array
|
|
for point in decoded_array
|
|
polyline_coordinates.push(point)
|
|
|
|
#or we have an array of latlng
|
|
else
|
|
#by convention, a single polyline could be customized in the first array or it uses default values
|
|
if element == polyline[0]
|
|
strokeColor = element.strokeColor || @polylines_conf.strokeColor
|
|
strokeOpacity = element.strokeOpacity || @polylines_conf.strokeOpacity
|
|
strokeWeight = element.strokeWeight || @polylines_conf.strokeWeight
|
|
clickable = element.clickable || @polylines_conf.clickable
|
|
zIndex = element.zIndex || @polylines_conf.zIndex
|
|
|
|
#add latlng if positions provided
|
|
if element.lat? && element.lng?
|
|
latlng = @createLatLng(element.lat, element.lng)
|
|
polyline_coordinates.push(latlng)
|
|
|
|
# Construct the polyline
|
|
new_poly = new google.maps.Polyline
|
|
path: polyline_coordinates
|
|
strokeColor: strokeColor
|
|
strokeOpacity: strokeOpacity
|
|
strokeWeight: strokeWeight
|
|
clickable: clickable
|
|
zIndex: zIndex
|
|
|
|
#save polyline
|
|
polyline.serviceObject = new_poly
|
|
new_poly.setMap(@serviceObject)
|
|
|
|
|
|
updateBoundsWithPolylines: ()->
|
|
for polyline in @polylines
|
|
polyline_points = polyline.serviceObject.latLngs.getArray()[0].getArray()
|
|
for point in polyline_points
|
|
@boundsObject.extend point
|
|
|
|
#////////////////////////////////////////////////////
|
|
#///////////////// KML //////////////////
|
|
#////////////////////////////////////////////////////
|
|
|
|
create_kml : ->
|
|
for kml in @kml
|
|
kml.serviceObject = @createKmlLayer kml
|
|
|
|
#////////////////////////////////////////////////////
|
|
#/////////////////// Other methods //////////////////
|
|
#////////////////////////////////////////////////////
|
|
|
|
fitBounds : ->
|
|
@serviceObject.fitBounds(@boundsObject) unless @boundsObject.isEmpty()
|
|
|
|
centerMapOnUser : ->
|
|
@serviceObject.setCenter(@userLocation)
|
|
|
|
updateBoundsWithPolygons: ()->
|
|
for polygon in @polygons
|
|
polygon_points = polygon.serviceObject.latLngs.getArray()[0].getArray()
|
|
for point in polygon_points
|
|
@boundsObject.extend point
|
|
|
|
updateBoundsWithCircles: ()->
|
|
for circle in @circles
|
|
@boundsObject.extend(circle.serviceObject.getBounds().getNorthEast())
|
|
@boundsObject.extend(circle.serviceObject.getBounds().getSouthWest())
|
|
|
|
extendMapBounds: ()->
|
|
for bound in @map_options.bounds
|
|
#create points from bounds provided
|
|
@boundsObject.extend @createLatLng(bound.lat, bound.lng)
|
|
|
|
adaptMapToBounds:()->
|
|
#if autozoom is false, take user info into account
|
|
if !@map_options.auto_zoom
|
|
map_center = @boundsObject.getCenter()
|
|
@map_options.center_latitude = map_center.lat()
|
|
@map_options.center_longitude = map_center.lng()
|
|
@serviceObject.setCenter(map_center)
|
|
else
|
|
@fitBounds()
|