Skip to content

Instantly share code, notes, and snippets.

@ArionHardison
Created November 20, 2012 07:16
Show Gist options
  • Save ArionHardison/4116535 to your computer and use it in GitHub Desktop.
Save ArionHardison/4116535 to your computer and use it in GitHub Desktop.
#######################################################################################################
############################################## Google maps ##########################################
#######################################################################################################
class @Gmaps4RailsGoogle extends Gmaps4Rails
constructor: ->
super
#Map settings
@map_options =
zoom: 10,
disableDefaultUI: true
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
map = new google.maps.Map document.getElementById(@map_options.id), mergedOptions
if navigator.geolocation
navigator.geolocation.getCurrentPosition ((position) ->
pos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude)
infowindow = new google.maps.InfoWindow(
map: map
position: pos
)
map.setCenter pos
), ->
handleNoGeolocation true
else
handleNoGeolocation false
return map
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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment