mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Assets for gmap4rails gem.
This commit is contained in:
@@ -0,0 +1,444 @@
|
||||
Gmaps = {}
|
||||
|
||||
Gmaps.triggerOldOnload = ->
|
||||
Gmaps.oldOnload() if typeof(Gmaps.oldOnload) == 'function'
|
||||
|
||||
Gmaps.loadMaps = ->
|
||||
#loop through all variable names.
|
||||
#there should only be maps inside so it trigger their load function
|
||||
for key, value of Gmaps
|
||||
searchLoadIncluded = key.search(/load/)
|
||||
if searchLoadIncluded == -1
|
||||
load_function_name = "load_" + key
|
||||
Gmaps[load_function_name]()
|
||||
|
||||
window.Gmaps = Gmaps
|
||||
|
||||
class @Gmaps4Rails
|
||||
|
||||
constructor: ->
|
||||
#map config
|
||||
@map = null #DEPRECATED: will still contain a copy of serviceObject below as transition
|
||||
@serviceObject = null #contains the map we're working on
|
||||
@visibleInfoWindow = null #contains the current opened infowindow
|
||||
@userLocation = null #contains user's location if geolocalization was performed and successful
|
||||
|
||||
#empty slots
|
||||
@geolocationSuccess = -> false #triggered when geolocation succeeds. Can be customized.
|
||||
@geolocationFailure = -> false #triggered when geolocation fails. If customized, must be like= function(navigator_handles_geolocation){} where 'navigator_handles_geolocation' is a boolean
|
||||
@callback = -> false #to let user set a custom callback function
|
||||
@customClusterer = -> false #to let user set custom clusterer pictures
|
||||
@infobox = -> false #to let user use custom infoboxes
|
||||
@jsTemplate = false #to let user create infowindows client side
|
||||
|
||||
@default_map_options =
|
||||
id: 'map'
|
||||
draggable: true
|
||||
detect_location: false # should the browser attempt to use geolocation detection features of HTML5?
|
||||
center_on_user: false # centers map on the location detected through the browser
|
||||
center_latitude: 0
|
||||
center_longitude: 0
|
||||
zoom: 7
|
||||
maxZoom: null
|
||||
minZoom: null
|
||||
auto_adjust : true # adjust the map to the markers if set to true
|
||||
auto_zoom: true # zoom given by auto-adjust
|
||||
bounds: [] # adjust map to these limits. Should be [{"lat": , "lng": }]
|
||||
raw: {} # raw json to pass additional options
|
||||
|
||||
@default_markers_conf =
|
||||
#Marker config
|
||||
title: ""
|
||||
#MarkerImage config
|
||||
picture : ""
|
||||
width: 22
|
||||
length: 32
|
||||
draggable: false # how to modify: <%= gmaps( "markers" => { "data" => @object.to_gmaps4rails, "options" => { "draggable" => true }}) %>
|
||||
#clustering config
|
||||
do_clustering: false # do clustering if set to true
|
||||
randomize: false # Google maps can't display two markers which have the same coordinates. This randomizer enables to prevent this situation from happening.
|
||||
max_random_distance: 100 # in meters. Each marker coordinate could be altered by this distance in a random direction
|
||||
list_container: null # id of the ul that will host links to all markers
|
||||
offset: 0 # used when adding_markers to an existing map. Because new markers are concated with previous one, offset is here to prevent the existing from being re-created.
|
||||
raw: {} # raw json to pass additional options
|
||||
|
||||
#Stored variables
|
||||
@markers = [] # contains all markers. A marker contains the following: {"description": , "longitude": , "title":, "latitude":, "picture": "", "width": "", "length": "", "sidebar": "", "serviceObject": google_marker}
|
||||
@boundsObject = null # contains current bounds from markers, polylines etc...
|
||||
@polygons = [] # contains raw data, array of arrays (first element could be a hash containing options)
|
||||
@polylines = [] # contains raw data, array of arrays (first element could be a hash containing options)
|
||||
@circles = [] # contains raw data, array of hash
|
||||
@markerClusterer = null # contains all marker clusterers
|
||||
@markerImages = []
|
||||
|
||||
#Polyline Styling
|
||||
@polylines_conf = #default style for polylines
|
||||
strokeColor: "#FF0000"
|
||||
strokeOpacity: 1
|
||||
strokeWeight: 2
|
||||
clickable: false
|
||||
zIndex: null
|
||||
|
||||
#tnitializes the map
|
||||
initialize : ->
|
||||
@serviceObject = @createMap()
|
||||
@map = @serviceObject #beware, soon deprecated
|
||||
if (@map_options.detect_location == true or @map_options.center_on_user == true)
|
||||
@findUserLocation(this)
|
||||
#resets sidebar if needed
|
||||
@resetSidebarContent()
|
||||
|
||||
findUserLocation : (map_object) ->
|
||||
if (navigator.geolocation)
|
||||
#try to retrieve user's position
|
||||
positionSuccessful = (position) ->
|
||||
map_object.userLocation = map_object.createLatLng(position.coords.latitude, position.coords.longitude)
|
||||
#change map's center to focus on user's geoloc if asked
|
||||
if(map_object.map_options.center_on_user == true)
|
||||
map_object.centerMapOnUser()
|
||||
map_object.geolocationSuccess()
|
||||
positionFailure = ->
|
||||
map_object.geolocationFailure(true)
|
||||
|
||||
navigator.geolocation.getCurrentPosition( positionSuccessful, positionFailure)
|
||||
else
|
||||
#failure but the navigator doesn't handle geolocation
|
||||
map_object.geolocationFailure(false)
|
||||
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#//////////////////// DIRECTIONS ////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
create_direction : ->
|
||||
directionsDisplay = new google.maps.DirectionsRenderer()
|
||||
directionsService = new google.maps.DirectionsService()
|
||||
|
||||
directionsDisplay.setMap(@serviceObject)
|
||||
#display panel only if required
|
||||
if @direction_conf.display_panel
|
||||
directionsDisplay.setPanel(document.getElementById(@direction_conf.panel_id))
|
||||
|
||||
directionsDisplay.setOptions
|
||||
suppressMarkers: false
|
||||
suppressInfoWindows: false
|
||||
suppressPolylines: false
|
||||
|
||||
request =
|
||||
origin: @direction_conf.origin
|
||||
destination: @direction_conf.destination
|
||||
waypoints: @direction_conf.waypoints
|
||||
optimizeWaypoints: @direction_conf.optimizeWaypoints
|
||||
unitSystem: google.maps.DirectionsUnitSystem[@direction_conf.unitSystem]
|
||||
avoidHighways: @direction_conf.avoidHighways
|
||||
avoidTolls: @direction_conf.avoidTolls
|
||||
region: @direction_conf.region
|
||||
travelMode: google.maps.DirectionsTravelMode[@direction_conf.travelMode]
|
||||
language: "en"
|
||||
|
||||
directionsService.route request, (response, status) ->
|
||||
if (status == google.maps.DirectionsStatus.OK)
|
||||
directionsDisplay.setDirections(response)
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#///////////////////// CIRCLES //////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
#Loops through all circles
|
||||
#Loops through all circles and draws them
|
||||
create_circles : ->
|
||||
for circle in @circles
|
||||
@create_circle circle
|
||||
|
||||
create_circle : (circle) ->
|
||||
#by convention, default style configuration could be integrated in the first element
|
||||
if circle == @circles[0]
|
||||
@circles_conf.strokeColor = circle.strokeColor if circle.strokeColor?
|
||||
@circles_conf.strokeOpacity = circle.strokeOpacity if circle.strokeOpacity?
|
||||
@circles_conf.strokeWeight = circle.strokeWeight if circle.strokeWeight?
|
||||
@circles_conf.fillColor = circle.fillColor if circle.fillColor?
|
||||
@circles_conf.fillOpacity = circle.fillOpacity if circle.fillOpacity?
|
||||
|
||||
if circle.lat? and circle.lng?
|
||||
# always check if a config is given, if not, use defaults
|
||||
# NOTE: is there a cleaner way to do this? Maybe a hash merge of some sort?
|
||||
newCircle = new google.maps.Circle
|
||||
center: @createLatLng(circle.lat, circle.lng)
|
||||
strokeColor: circle.strokeColor || @circles_conf.strokeColor
|
||||
strokeOpacity: circle.strokeOpacity || @circles_conf.strokeOpacity
|
||||
strokeWeight: circle.strokeWeight || @circles_conf.strokeWeight
|
||||
fillOpacity: circle.fillOpacity || @circles_conf.fillOpacity
|
||||
fillColor: circle.fillColor || @circles_conf.fillColor
|
||||
clickable: circle.clickable || @circles_conf.clickable
|
||||
zIndex: circle.zIndex || @circles_conf.zIndex
|
||||
radius: circle.radius
|
||||
|
||||
circle.serviceObject = newCircle
|
||||
newCircle.setMap(@serviceObject)
|
||||
|
||||
# clear circles
|
||||
clear_circles : ->
|
||||
for circle in @circles
|
||||
@clear_circle circle
|
||||
|
||||
clear_circle : (circle) ->
|
||||
circle.serviceObject.setMap(null)
|
||||
|
||||
hide_circles : ->
|
||||
for circle in @circles
|
||||
@hide_circle circle
|
||||
|
||||
hide_circle : (circle) ->
|
||||
circle.serviceObject.setMap(null)
|
||||
|
||||
show_circles : ->
|
||||
for circle in @circles
|
||||
@show_circle @circle
|
||||
|
||||
show_circle : (circle) ->
|
||||
circle.serviceObject.setMap(@serviceObject)
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#///////////////////// POLYGONS /////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
#polygons is an array of arrays. It loops.
|
||||
create_polygons : ->
|
||||
for polygon in @polygons
|
||||
@create_polygon(polygon)
|
||||
|
||||
#creates a single polygon, triggered by create_polygons
|
||||
create_polygon : (polygon) ->
|
||||
polygon_coordinates = []
|
||||
|
||||
#Polygon points are in an Array, that's why looping is necessary
|
||||
for point in polygon
|
||||
latlng = @createLatLng(point.lat, point.lng)
|
||||
polygon_coordinates.push(latlng)
|
||||
#first element of an Array could contain specific configuration for this particular polygon. If no config given, use default
|
||||
if point == polygon[0]
|
||||
strokeColor = point.strokeColor || @polygons_conf.strokeColor
|
||||
strokeOpacity = point.strokeOpacity || @polygons_conf.strokeOpacity
|
||||
strokeWeight = point.strokeWeight || @polygons_conf.strokeWeight
|
||||
fillColor = point.fillColor || @polygons_conf.fillColor
|
||||
fillOpacity = point.fillOpacity || @polygons_conf.fillOpacity
|
||||
clickable = point.clickable || @polygons_conf.clickable
|
||||
|
||||
#Construct the polygon
|
||||
new_poly = new google.maps.Polygon
|
||||
paths: polygon_coordinates
|
||||
strokeColor: strokeColor
|
||||
strokeOpacity: strokeOpacity
|
||||
strokeWeight: strokeWeight
|
||||
fillColor: fillColor
|
||||
fillOpacity: fillOpacity
|
||||
clickable: clickable
|
||||
map: @serviceObject
|
||||
|
||||
#save polygon in list
|
||||
polygon.serviceObject = new_poly
|
||||
|
||||
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#///////////////////// MARKERS //////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
#creates, clusterizes and adjusts map
|
||||
create_markers : ->
|
||||
@createServiceMarkersFromMarkers()
|
||||
@clusterize()
|
||||
|
||||
#create google.maps Markers from data provided by user
|
||||
createServiceMarkersFromMarkers : ->
|
||||
for marker, index in @markers
|
||||
if not @markers[index].serviceObject?
|
||||
#extract options, test if value passed or use default
|
||||
Lat = @markers[index].lat
|
||||
Lng = @markers[index].lng
|
||||
|
||||
#alter coordinates if randomize is true
|
||||
if @markers_conf.randomize
|
||||
LatLng = @randomize(Lat, Lng)
|
||||
#retrieve coordinates from the array
|
||||
Lat = LatLng[0]
|
||||
Lng = LatLng[1]
|
||||
|
||||
#save object
|
||||
@markers[index].serviceObject = @createMarker
|
||||
"marker_picture": if @markers[index].picture then @markers[index].picture else @markers_conf.picture
|
||||
"marker_width": if @markers[index].width then @markers[index].width else @markers_conf.width
|
||||
"marker_height": if @markers[index].height then @markers[index].height else @markers_conf.length
|
||||
"marker_title": if @markers[index].title then @markers[index].title else null
|
||||
"marker_anchor": if @markers[index].marker_anchor then @markers[index].marker_anchor else null
|
||||
"shadow_anchor": if @markers[index].shadow_anchor then @markers[index].shadow_anchor else null
|
||||
"shadow_picture": if @markers[index].shadow_picture then @markers[index].shadow_picture else null
|
||||
"shadow_width": if @markers[index].shadow_width then @markers[index].shadow_width else null
|
||||
"shadow_height": if @markers[index].shadow_height then @markers[index].shadow_height else null
|
||||
"marker_draggable": if @markers[index].draggable then @markers[index].draggable else @markers_conf.draggable
|
||||
"rich_marker": if @markers[index].rich_marker then @markers[index].rich_marker else null
|
||||
"zindex": if @markers[index].zindex then @markers[index].zindex else null
|
||||
"Lat": Lat
|
||||
"Lng": Lng
|
||||
"index": index
|
||||
|
||||
#add infowindowstuff if enabled
|
||||
@createInfoWindow(@markers[index])
|
||||
#create sidebar if enabled
|
||||
@createSidebar(@markers[index])
|
||||
|
||||
@markers_conf.offset = @markers.length
|
||||
|
||||
#creates Image Anchor Position or return null if nothing passed
|
||||
createImageAnchorPosition : (anchorLocation) ->
|
||||
if (anchorLocation == null)
|
||||
return null
|
||||
else
|
||||
return @createPoint(anchorLocation[0], anchorLocation[1])
|
||||
|
||||
|
||||
#replace old markers with new markers on an existing map
|
||||
replaceMarkers : (new_markers, adjustBounds = true) ->
|
||||
@clearMarkers()
|
||||
#reset previous markers
|
||||
@markers = new Array
|
||||
#reset current bounds
|
||||
@boundsObject = @createLatLngBounds() if adjustBounds
|
||||
#reset sidebar content if exists
|
||||
@resetSidebarContent()
|
||||
#add new markers
|
||||
@markers_conf.offset = 0
|
||||
@addMarkers(new_markers, adjustBounds)
|
||||
|
||||
#add new markers to on an existing map
|
||||
addMarkers : (new_markers, adjustBounds = true) ->
|
||||
#update the list of markers to take into account
|
||||
@markers = @markers.concat(new_markers)
|
||||
#put markers on the map
|
||||
@create_markers()
|
||||
@adjustMapToBounds() if adjustBounds
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#///////////////////// SIDEBAR //////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
#//creates sidebar
|
||||
createSidebar : (marker_container) ->
|
||||
if (@markers_conf.list_container)
|
||||
ul = document.getElementById(@markers_conf.list_container)
|
||||
li = document.createElement('li')
|
||||
aSel = document.createElement('a')
|
||||
aSel.href = 'javascript:void(0);'
|
||||
html = if marker_container.sidebar? then marker_container.sidebar else "Marker"
|
||||
aSel.innerHTML = html
|
||||
currentMap = this
|
||||
aSel.onclick = @sidebar_element_handler(currentMap, marker_container.serviceObject, 'click')
|
||||
li.appendChild(aSel)
|
||||
ul.appendChild(li)
|
||||
|
||||
#moves map to marker clicked + open infowindow
|
||||
sidebar_element_handler : (currentMap, marker, eventType) ->
|
||||
return () ->
|
||||
currentMap.map.panTo(marker.position)
|
||||
google.maps.event.trigger(marker, eventType)
|
||||
|
||||
|
||||
resetSidebarContent : ->
|
||||
if @markers_conf.list_container isnt null
|
||||
ul = document.getElementById(@markers_conf.list_container)
|
||||
ul.innerHTML = ""
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#////////////////// MISCELLANEOUS ///////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
#to make the map fit the different LatLng points
|
||||
adjustMapToBounds : ->
|
||||
#FIRST_STEP: retrieve all bounds
|
||||
#create the bounds object only if necessary
|
||||
if @map_options.auto_adjust or @map_options.bounds isnt null
|
||||
@boundsObject = @createLatLngBounds()
|
||||
|
||||
#if autodjust is true, must get bounds from markers polylines etc...
|
||||
if @map_options.auto_adjust
|
||||
#from markers
|
||||
@extendBoundsWithMarkers()
|
||||
|
||||
#from polylines:
|
||||
@updateBoundsWithPolylines()
|
||||
|
||||
#from polygons:
|
||||
@updateBoundsWithPolygons()
|
||||
|
||||
#from circles
|
||||
@updateBoundsWithCircles()
|
||||
|
||||
#in every case, I've to take into account the bounds set up by the user
|
||||
@extendMapBounds()
|
||||
|
||||
#SECOND_STEP: ajust the map to the bounds
|
||||
@adaptMapToBounds()
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////////// POLYLINES //////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
#replace old markers with new markers on an existing map
|
||||
replacePolylines : (new_polylines) ->
|
||||
#reset previous polylines and kill them from map
|
||||
@destroy_polylines()
|
||||
#set new polylines
|
||||
@polylines = new_polylines
|
||||
#create
|
||||
@create_polylines()
|
||||
#.... and adjust map boundaries
|
||||
@adjustMapToBounds()
|
||||
|
||||
destroy_polylines : ->
|
||||
for polyline in @polylines
|
||||
#delete polylines from map
|
||||
polyline.serviceObject.setMap(null)
|
||||
#empty array
|
||||
@polylines = []
|
||||
|
||||
#polylines is an array of arrays. It loops.
|
||||
create_polylines : ->
|
||||
for polyline in @polylines
|
||||
@create_polyline polyline
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#///////////////// Basic functions //////////////////
|
||||
#///////////////////tests coded//////////////////////
|
||||
|
||||
#//basic function to check existence of a variable
|
||||
exists : (var_name) ->
|
||||
return (var_name != "" and typeof var_name != "undefined")
|
||||
|
||||
|
||||
#randomize
|
||||
randomize : (Lat0, Lng0) ->
|
||||
#distance in meters between 0 and max_random_distance (positive or negative)
|
||||
dx = @markers_conf.max_random_distance * @random()
|
||||
dy = @markers_conf.max_random_distance * @random()
|
||||
Lat = parseFloat(Lat0) + (180/Math.PI)*(dy/6378137)
|
||||
Lng = parseFloat(Lng0) + ( 90/Math.PI)*(dx/6378137)/Math.cos(Lat0)
|
||||
return [Lat, Lng]
|
||||
|
||||
mergeObjectWithDefault : (object1, object2) ->
|
||||
copy_object1 = {}
|
||||
for key, value of object1
|
||||
copy_object1[key] = value
|
||||
|
||||
for key, value of object2
|
||||
unless copy_object1[key]?
|
||||
copy_object1[key] = value
|
||||
return copy_object1
|
||||
|
||||
mergeWithDefault : (objectName) ->
|
||||
default_object = @["default_" + objectName]
|
||||
object = @[objectName]
|
||||
@[objectName] = @mergeObjectWithDefault(object, default_object)
|
||||
return true
|
||||
|
||||
#gives a value between -1 and 1
|
||||
random : -> return(Math.random() * 2 -1)
|
||||
@@ -0,0 +1,174 @@
|
||||
######################################################################################################
|
||||
############################################## Bing Maps ##########################################
|
||||
######################################################################################################
|
||||
|
||||
#// http://wiki.openstreetmap.org/wiki/OpenLayers
|
||||
#// http://openlayers.org/dev/examples
|
||||
#//http://docs.openlayers.org/contents.html
|
||||
|
||||
class @Gmaps4RailsBing extends Gmaps4Rails
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@map_options =
|
||||
type: "road" # aerial, auto, birdseye, collinsBart, mercator, ordnanceSurvey, road
|
||||
@markers_conf =
|
||||
infobox: "description" #description or htmlContent
|
||||
|
||||
@mergeWithDefault("map_options")
|
||||
@mergeWithDefault("markers_conf")
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////// Basic Objects //////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
getMapType: ->
|
||||
switch @map_options.type
|
||||
when "road" then return Microsoft.Maps.MapTypeId.road
|
||||
when "aerial" then return Microsoft.Maps.MapTypeId.aerial
|
||||
when "auto" then return Microsoft.Maps.MapTypeId.auto
|
||||
when "birdseye" then return Microsoft.Maps.MapTypeId.birdseye
|
||||
when "collinsBart" then return Microsoft.Maps.MapTypeId.collinsBart
|
||||
when "mercator" then return Microsoft.Maps.MapTypeId.mercator
|
||||
when "ordnanceSurvey" then return Microsoft.Maps.MapTypeId.ordnanceSurvey
|
||||
else return Microsoft.Maps.MapTypeId.auto
|
||||
|
||||
createPoint: (lat, lng) ->
|
||||
return new Microsoft.Maps.Point(lat, lng)
|
||||
|
||||
createLatLng:(lat, lng) ->
|
||||
return new Microsoft.Maps.Location(lat, lng)
|
||||
|
||||
createLatLngBounds: ->
|
||||
|
||||
createMap: ->
|
||||
return new Microsoft.Maps.Map(document.getElementById(@map_options.id), {
|
||||
credentials: @map_options.provider_key,
|
||||
mapTypeId: @getMapType(),
|
||||
center: @createLatLng(@map_options.center_latitude, @map_options.center_longitude),
|
||||
zoom: @map_options.zoom
|
||||
})
|
||||
|
||||
createSize: (width, height) ->
|
||||
return new google.maps.Size(width, height)
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#////////////////////// Markers /////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
createMarker: (args) ->
|
||||
markerLatLng = @createLatLng(args.Lat, args.Lng)
|
||||
marker
|
||||
#// Marker sizes are expressed as a Size of X,Y
|
||||
if args.marker_picture == ""
|
||||
marker = new Microsoft.Maps.Pushpin(@createLatLng(args.Lat, args.Lng), {
|
||||
draggable: args.marker_draggable,
|
||||
anchor: @createImageAnchorPosition(args.Lat, args.Lng),
|
||||
text: args.marker_title
|
||||
}
|
||||
);
|
||||
else
|
||||
marker = new Microsoft.Maps.Pushpin(@createLatLng(args.Lat, args.Lng), {
|
||||
draggable: args.marker_draggable,
|
||||
anchor: @createImageAnchorPosition(args.Lat, args.Lng),
|
||||
icon: args.marker_picture,
|
||||
height: args.marker_height,
|
||||
text: args.marker_title,
|
||||
width: args.marker_width
|
||||
}
|
||||
);
|
||||
@addToMap(marker)
|
||||
return marker
|
||||
|
||||
#// clear markers
|
||||
clearMarkers: ->
|
||||
for marker in @markers
|
||||
@clearMarker marker
|
||||
|
||||
clearMarker: (marker) ->
|
||||
@removeFromMap(marker.serviceObject)
|
||||
|
||||
#//show and hide markers
|
||||
showMarkers: ->
|
||||
for marker in @markers
|
||||
@showMarker marker
|
||||
|
||||
showMarker: (marker) ->
|
||||
marker.serviceObject.setOptions({ visible: true })
|
||||
|
||||
hideMarkers: ->
|
||||
for marker in @markers
|
||||
@hideMarker marker
|
||||
|
||||
hideMarker: (marker) ->
|
||||
marker.serviceObject.setOptions({ visible: false })
|
||||
|
||||
extendBoundsWithMarkers: ->
|
||||
locationsArray = []
|
||||
for marker in @markers
|
||||
locationsArray.push(marker.serviceObject.getLocation())
|
||||
@boundsObject = Microsoft.Maps.LocationRect.fromLocations(locationsArray)
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////////// Clusterer //////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
createClusterer: (markers_array) ->
|
||||
|
||||
clearClusterer: ->
|
||||
|
||||
#//creates clusters
|
||||
clusterize: ->
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////////// INFO WINDOW ////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
#// creates infowindows
|
||||
createInfoWindow: (marker_container) ->
|
||||
if marker_container.description?
|
||||
#//create the infowindow
|
||||
if @markers_conf.infobox == "description"
|
||||
marker_container.info_window = new Microsoft.Maps.Infobox(marker_container.serviceObject.getLocation(), { description: marker_container.description, visible: false, showCloseButton: true})
|
||||
else
|
||||
marker_container.info_window = new Microsoft.Maps.Infobox(marker_container.serviceObject.getLocation(), { htmlContent: marker_container.description, visible: false})
|
||||
|
||||
#//add the listener associated
|
||||
currentMap = this
|
||||
Microsoft.Maps.Events.addHandler(marker_container.serviceObject, 'click', @openInfoWindow(currentMap, marker_container.info_window))
|
||||
@addToMap(marker_container.info_window)
|
||||
|
||||
openInfoWindow: (currentMap, infoWindow) ->
|
||||
return ->
|
||||
# Close the latest selected marker before opening the current one.
|
||||
if currentMap.visibleInfoWindow
|
||||
currentMap.visibleInfoWindow.setOptions({ visible: false })
|
||||
infoWindow.setOptions({ visible:true })
|
||||
currentMap.visibleInfoWindow = infoWindow
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////////// Other methods //////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
fitBounds: ->
|
||||
@serviceObject.setView({bounds: @boundsObject})
|
||||
|
||||
addToMap: (object)->
|
||||
@serviceObject.entities.push(object)
|
||||
|
||||
removeFromMap: (object)->
|
||||
@serviceObject.entities.remove(object)
|
||||
|
||||
centerMapOnUser: ->
|
||||
@serviceObject.setView({ center: @userLocation})
|
||||
|
||||
updateBoundsWithPolylines: ()->
|
||||
|
||||
updateBoundsWithPolygons: ()->
|
||||
|
||||
updateBoundsWithCircles: ()->
|
||||
|
||||
extendMapBounds :->
|
||||
|
||||
adaptMapToBounds: ->
|
||||
@fitBounds()
|
||||
@@ -0,0 +1,339 @@
|
||||
#######################################################################################################
|
||||
############################################## 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()
|
||||
@@ -0,0 +1,145 @@
|
||||
#######################################################################################################
|
||||
############################################## Map Quest #############################################
|
||||
#######################################################################################################
|
||||
# http://developer.mapquest.com/web/documentation/sdk/javascript/v7.0/api/MQA.Poi.html
|
||||
|
||||
class @Gmaps4RailsMapquest extends Gmaps4Rails
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
#Map settings
|
||||
@map_options = {type: "map"} #map type (map, sat, hyb)
|
||||
@markers_conf = {}
|
||||
@mergeWithDefault "markers_conf"
|
||||
@mergeWithDefault "map_options"
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////// Basic Objects //////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
createPoint: (lat, lng) ->
|
||||
return new MQA.Poi({lat: lat, lng: lng})
|
||||
|
||||
createLatLng: (lat, lng) ->
|
||||
return {lat: lat, lng: lng}
|
||||
|
||||
createLatLngBounds: ->
|
||||
|
||||
createMap: ->
|
||||
map = new MQA.TileMap( #// Constructs an instance of MQA.TileMap
|
||||
document.getElementById(@map_options.id), #//the id of the element on the page you want the map to be added into
|
||||
@map_options.zoom, #//intial zoom level of the map
|
||||
{lat: @map_options.center_latitude, lng: @map_options.center_longitude},
|
||||
@map_options.type) #//map type (map, sat, hyb)
|
||||
|
||||
MQA.withModule('zoomcontrol3', (->
|
||||
map.addControl(
|
||||
new MQA.LargeZoomControl3(),
|
||||
new MQA.MapCornerPlacement(MQA.MapCorner.TOP_LEFT)
|
||||
)
|
||||
))
|
||||
return map
|
||||
|
||||
createMarkerImage: (markerPicture, markerSize, origin, anchor, scaledSize) ->
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#////////////////////// Markers /////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
createMarker: (args)->
|
||||
marker = new MQA.Poi( {lat: args.Lat, lng: args.Lng} )
|
||||
|
||||
if args.marker_picture != ""
|
||||
icon = new MQA.Icon(args.marker_picture, args.marker_height, args.marker_width)
|
||||
marker.setIcon(icon)
|
||||
if args.marker_anchor != null
|
||||
marker.setBias({x: args.marker_anchor[0], y: args.marker_anchor[1]})
|
||||
|
||||
if args.shadow_picture != ""
|
||||
icon = new MQA.Icon(args.shadow_picture, args.shadow_height, args.shadow_width)
|
||||
marker.setShadow(icon)
|
||||
|
||||
if args.shadow_anchor != null
|
||||
marker.setShadowOffset({x: args.shadow_anchor[0], y: args.shadow_anchor[1]})
|
||||
|
||||
@addToMap marker
|
||||
return marker
|
||||
|
||||
|
||||
#// 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) ->
|
||||
@removeFromMap(marker.serviceObject)
|
||||
|
||||
showMarker: (marker) ->
|
||||
#// marker.serviceObject
|
||||
|
||||
hideMarker: (marker) ->
|
||||
#// marker.serviceObject
|
||||
|
||||
extendBoundsWithMarkers: ->
|
||||
if @markers.length >=2
|
||||
@boundsObject = new MQA.RectLL(@markers[0].serviceObject.latLng, @markers[1].serviceObject.latLng)
|
||||
for marker in @markers
|
||||
@boundsObject.extend marker.serviceObject.latLng
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////////// Clusterer //////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
createClusterer: (markers_array) ->
|
||||
|
||||
clearClusterer: ->
|
||||
|
||||
#//creates clusters
|
||||
clusterize: ->
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////////// INFO WINDOW ////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
#// creates infowindows
|
||||
createInfoWindow: (marker_container) ->
|
||||
marker_container.serviceObject.setInfoTitleHTML(marker_container.description)
|
||||
#//TODO: how to disable the mouseover display when using setInfoContentHTML?
|
||||
#//marker_container.serviceObject.setInfoContentHTML(marker_container.description);
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////////// Other methods //////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
fitBounds: ->
|
||||
@serviceObject.zoomToRect @boundsObject if @markers.length >=2
|
||||
@serviceObject.setCenter @markers[0].serviceObject.latLng if @markers.length == 1
|
||||
|
||||
centerMapOnUser: ->
|
||||
@serviceObject.setCenter @userLocation
|
||||
|
||||
addToMap: (object) ->
|
||||
@serviceObject.addShape object
|
||||
|
||||
removeFromMap: (object)->
|
||||
@serviceObject.removeShape object
|
||||
|
||||
updateBoundsWithPolylines: ()->
|
||||
|
||||
updateBoundsWithPolygons: ()->
|
||||
|
||||
updateBoundsWithCircles: ()->
|
||||
|
||||
extendMapBounds :->
|
||||
|
||||
adaptMapToBounds: ->
|
||||
@fitBounds()
|
||||
@@ -0,0 +1,261 @@
|
||||
#######################################################################################################
|
||||
############################################## Open Layers ##########################################
|
||||
#######################################################################################################
|
||||
|
||||
#// http://wiki.openstreetmap.org/wiki/OpenLayers
|
||||
#// http://openlayers.org/dev/examples
|
||||
#//http://docs.openlayers.org/contents.html
|
||||
|
||||
class @Gmaps4RailsOpenlayers extends Gmaps4Rails
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@map_options = {}
|
||||
@mergeWithDefault "map_options"
|
||||
@markers_conf = {}
|
||||
@mergeWithDefault "markers_conf"
|
||||
|
||||
@openMarkers = null
|
||||
@markersLayer = null
|
||||
@markersControl = null
|
||||
@polylinesLayer = null
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////// Basic Objects ////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
createPoint: (lat, lng)->
|
||||
|
||||
createLatLng: (lat, lng)->
|
||||
return new OpenLayers.LonLat(lng, lat).transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) # transform from WGS 1984 to Spherical Mercator Projection
|
||||
|
||||
createAnchor: (offset)->
|
||||
return null if offset == null
|
||||
return new OpenLayers.Pixel(offset[0], offset[1])
|
||||
|
||||
createSize: (width, height)->
|
||||
return new OpenLayers.Size(width, height)
|
||||
|
||||
createLatLngBounds: ->
|
||||
return new OpenLayers.Bounds()
|
||||
|
||||
createMap: ->
|
||||
#//todo add customization: kind of map and other map options
|
||||
map = new OpenLayers.Map(@map_options.id)
|
||||
map.addLayer(new OpenLayers.Layer.OSM())
|
||||
map.setCenter(@createLatLng(@map_options.center_latitude, @map_options.center_longitude), #// Center of the map
|
||||
@map_options.zoom) #// Zoom level
|
||||
return map
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#////////////////////// Markers /////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
#//http://openlayers.org/dev/examples/marker-shadow.html
|
||||
createMarker: (args) ->
|
||||
style_mark = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default'])
|
||||
style_mark.fillOpacity = 1
|
||||
|
||||
#//creating markers' dedicated layer
|
||||
if (@markersLayer == null)
|
||||
@markersLayer = new OpenLayers.Layer.Vector("Markers", null)
|
||||
@serviceObject.addLayer(@markersLayer)
|
||||
#//TODO move?
|
||||
@markersLayer.events.register("featureselected", @markersLayer, @onFeatureSelect)
|
||||
@markersLayer.events.register("featureunselected", @markersLayer, @onFeatureUnselect)
|
||||
@markersControl = new OpenLayers.Control.SelectFeature(@markersLayer)
|
||||
@serviceObject.addControl(@markersControl)
|
||||
@markersControl.activate()
|
||||
#//showing default pic if none available
|
||||
if args.marker_picture == ""
|
||||
#style_mark.graphicWidth = 24
|
||||
style_mark.graphicHeight = 30
|
||||
style_mark.externalGraphic = "http://openlayers.org/dev/img/marker-blue.png"
|
||||
#//creating custom pic
|
||||
else
|
||||
style_mark.graphicWidth = args.marker_width
|
||||
style_mark.graphicHeight = args.marker_height
|
||||
style_mark.externalGraphic = args.marker_picture
|
||||
#//adding anchor if any
|
||||
if args.marker_anchor != null
|
||||
style_mark.graphicXOffset = args.marker_anchor[0]
|
||||
style_mark.graphicYOffset = args.marker_anchor[1]
|
||||
#//adding shadow if any
|
||||
if args.shadow_picture != ""
|
||||
style_mark.backgroundGraphic = args.shadow_picture
|
||||
style_mark.backgroundWidth = args.shadow_width
|
||||
style_mark.backgroundHeight = args.shadow_height
|
||||
#//adding shadow's anchor if any
|
||||
if args.shadow_anchor != null
|
||||
style_mark.backgroundXOffset = args.shadow_anchor[0]
|
||||
style_mark.backgroundYOffset = args.shadow_anchor[1]
|
||||
|
||||
style_mark.graphicTitle = args.marker_title
|
||||
marker = new OpenLayers.Feature.Vector(
|
||||
new OpenLayers.Geometry.Point(args.Lng, args.Lat),
|
||||
null,
|
||||
style_mark)
|
||||
#//changing coordinates so that it actually appears on the map!
|
||||
marker.geometry.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"))
|
||||
#//adding layer to the map
|
||||
@markersLayer.addFeatures([marker])
|
||||
|
||||
return marker
|
||||
|
||||
#//clear markers
|
||||
clearMarkers: ->
|
||||
@clearMarkersLayerIfExists()
|
||||
@markersLayer = null
|
||||
@boundsObject = new OpenLayers.Bounds()
|
||||
|
||||
clearMarkersLayerIfExists: ->
|
||||
@serviceObject.removeLayer(@markersLayer) if @markersLayer != null and @serviceObject.getLayer(@markersLayer.id) != null
|
||||
|
||||
extendBoundsWithMarkers: ->
|
||||
console.log "here"
|
||||
for marker in @markers
|
||||
@boundsObject.extend(@createLatLng(marker.lat,marker.lng))
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////////// Clusterer //////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
#//too ugly to be considered valid :(
|
||||
|
||||
createClusterer: (markers_array)->
|
||||
options =
|
||||
pointRadius: "${radius}"
|
||||
fillColor: "#ffcc66"
|
||||
fillOpacity: 0.8
|
||||
strokeColor: "#cc6633"
|
||||
strokeWidth: "${width}"
|
||||
strokeOpacity: 0.8
|
||||
funcs =
|
||||
context:
|
||||
width: (feature) ->
|
||||
return (feature.cluster) ? 2 : 1
|
||||
radius: (feature) ->
|
||||
pix = 2
|
||||
pix = Math.min(feature.attributes.count, 7) + 2 if feature.cluster
|
||||
return pix
|
||||
|
||||
style = new OpenLayers.Style options, funcs
|
||||
|
||||
strategy = new OpenLayers.Strategy.Cluster()
|
||||
|
||||
clusters = new OpenLayers.Layer.Vector "Clusters",
|
||||
strategies: [strategy]
|
||||
styleMap: new OpenLayers.StyleMap
|
||||
"default": style
|
||||
"select":
|
||||
fillColor: "#8aeeef"
|
||||
strokeColor: "#32a8a9"
|
||||
|
||||
@clearMarkersLayerIfExists()
|
||||
@serviceObject.addLayer(clusters)
|
||||
clusters.addFeatures(markers_array)
|
||||
return clusters
|
||||
|
||||
clusterize: ->
|
||||
|
||||
if @markers_conf.do_clustering == true
|
||||
#//first clear the existing clusterer if any
|
||||
if @markerClusterer != null
|
||||
@clearClusterer()
|
||||
markers_array = new Array
|
||||
for marker in @markers
|
||||
markers_array.push(marker.serviceObject)
|
||||
@markerClusterer = @createClusterer markers_array
|
||||
|
||||
clearClusterer: ->
|
||||
@serviceObject.removeLayer @markerClusterer
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////////// INFO WINDOW ////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
#// creates infowindows
|
||||
createInfoWindow: (marker_container) ->
|
||||
marker_container.serviceObject.infoWindow = marker_container.description if marker_container.description?
|
||||
|
||||
onPopupClose: (evt) ->
|
||||
#// 'this' is the popup.
|
||||
@markersControl.unselect @feature
|
||||
|
||||
onFeatureSelect: (evt) ->
|
||||
feature = evt.feature
|
||||
popup = new OpenLayers.Popup.FramedCloud("featurePopup",
|
||||
feature.geometry.getBounds().getCenterLonLat(),
|
||||
new OpenLayers.Size(300,200),
|
||||
feature.infoWindow,
|
||||
null, true, @onPopupClose)
|
||||
feature.popup = popup
|
||||
popup.feature = feature
|
||||
@map.addPopup popup
|
||||
|
||||
onFeatureUnselect: (evt) ->
|
||||
feature = evt.feature
|
||||
if feature.popup
|
||||
#//popup.feature = null;
|
||||
@map.removePopup feature.popup
|
||||
feature.popup.destroy()
|
||||
feature.popup = null
|
||||
|
||||
#////////////////////////////////////////////////////
|
||||
#/////////////////// POLYLINES //////////////////////
|
||||
#////////////////////////////////////////////////////
|
||||
|
||||
create_polyline : (polyline) ->
|
||||
|
||||
if(@polylinesLayer == null)
|
||||
@polylinesLayer = new OpenLayers.Layer.Vector("Polylines", null)
|
||||
@serviceObject.addLayer(@polylinesLayer)
|
||||
@polylinesLayer.events.register("featureselected", @polylinesLayer, @onFeatureSelect)
|
||||
@polylinesLayer.events.register("featureunselected", @polylinesLayer, @onFeatureUnselect)
|
||||
@polylinesControl = new OpenLayers.Control.DrawFeature(@polylinesLayer, OpenLayers.Handler.Path)
|
||||
@serviceObject.addControl(@polylinesControl)
|
||||
|
||||
polyline_coordinates = []
|
||||
|
||||
for element in polyline
|
||||
#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 = new OpenLayers.Geometry.Point(element.lng, element.lat)
|
||||
polyline_coordinates.push(latlng)
|
||||
|
||||
line_points = new OpenLayers.Geometry.LineString(polyline_coordinates);
|
||||
line_style = { strokeColor: strokeColor, strokeOpacity: strokeOpacity, strokeWidth: strokeWeight };
|
||||
|
||||
polyline = new OpenLayers.Feature.Vector(line_points, null, line_style);
|
||||
polyline.geometry.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"))
|
||||
|
||||
@polylinesLayer.addFeatures([polyline])
|
||||
|
||||
return polyline
|
||||
|
||||
updateBoundsWithPolylines: ()->
|
||||
|
||||
updateBoundsWithPolygons: ()->
|
||||
|
||||
updateBoundsWithCircles: ()->
|
||||
|
||||
# #////////////////////////////////////////////////////
|
||||
# #/////////////////// Other methods //////////////////
|
||||
# #////////////////////////////////////////////////////
|
||||
|
||||
fitBounds: ->
|
||||
@serviceObject.zoomToExtent(@boundsObject, true)
|
||||
|
||||
centerMapOnUser: ->
|
||||
@serviceObject.setCenter @userLocation
|
||||
|
||||
extendMapBounds :->
|
||||
|
||||
adaptMapToBounds: ->
|
||||
@fitBounds()
|
||||
19
app/assets/stylesheets/search/gmaps4rails.css
Normal file
19
app/assets/stylesheets/search/gmaps4rails.css
Normal file
@@ -0,0 +1,19 @@
|
||||
.map_container {
|
||||
padding: 6px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #ccc #ccc #999 #ccc;
|
||||
-webkit-box-shadow: rgba(64, 64, 64, 0.5) 0 2px 5px;
|
||||
-moz-box-shadow: rgba(64, 64, 64, 0.5) 0 2px 5px;
|
||||
box-shadow: rgba(64, 64, 64, 0.1) 0 2px 5px;
|
||||
width: 645px;
|
||||
}
|
||||
|
||||
.gmaps4rails_map {
|
||||
width: 630px;
|
||||
height: 530px;
|
||||
}
|
||||
|
||||
.map_container img {
|
||||
max-width: none;
|
||||
}
|
||||
Reference in New Issue
Block a user