Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added map

  • Loading branch information...
commit c3494e6d12d96b1938c2d6c04a609ab615f2bea5 1 parent 9f45fee
@Sjors authored
Showing with 1,428 additions and 53 deletions.
  1. +1 −0  Gemfile
  2. +3 −0  Gemfile.lock
  3. +1 −0  app/assets/javascripts/companies.js.coffee
  4. +492 −0 app/assets/javascripts/gmaps4rails/gmaps4rails.base.js.coffee
  5. +163 −0 app/assets/javascripts/gmaps4rails/gmaps4rails.bing.js.coffee
  6. +259 −0 app/assets/javascripts/gmaps4rails/gmaps4rails.googlemaps.js.coffee
  7. +134 −0 app/assets/javascripts/gmaps4rails/gmaps4rails.mapquest.js.coffee
  8. +209 −0 app/assets/javascripts/gmaps4rails/gmaps4rails.openlayers.js.coffee
  9. +4 −0 app/assets/stylesheets/companies.css.scss
  10. +24 −0 app/assets/stylesheets/gmaps4rails.css
  11. +1 −1  app/controllers/choices_controller.rb
  12. +17 −1 app/controllers/companies_controller.rb
  13. +1 −0  app/controllers/tasks_controller.rb
  14. +1 −17 app/helpers/choices_helper.rb
  15. +1 −1  app/models/ability.rb
  16. +41 −0 app/models/company.rb
  17. +8 −0 app/views/companies/map.html.haml
  18. +7 −5 app/views/layouts/application.html.haml
  19. +6 −2 config/routes.rb
  20. +6 −0 db/migrate/20120413103507_add_street_to_companies.rb
  21. +7 −0 db/migrate/20120413104405_add_location_fields_to_companies.rb
  22. +6 −0 db/migrate/20120413105350_add_gmaps_to_companies.rb
  23. +4 −22 db/schema.rb
  24. +32 −4 lib/tasks/crunchbase.rake
  25. BIN  public/images/marker.png
View
1  Gemfile
@@ -5,6 +5,7 @@ gem 'cancan'
gem 'authlogic' #, :git => 'git://github.com/binarylogic/authlogic.git', :ref => '0297e1c005c626c1e37b'
gem "rest-client"
gem 'mechanize'
+gem 'gmaps4rails'
# Gems used only for assets and not required
# in production environments by default.
View
3  Gemfile.lock
@@ -50,6 +50,8 @@ GEM
erubis (2.7.0)
execjs (1.3.0)
multi_json (~> 1.0)
+ gmaps4rails (1.4.5)
+ json
haml (3.1.4)
hashie (1.2.0)
hike (1.2.1)
@@ -170,6 +172,7 @@ DEPENDENCIES
authlogic
cancan
coffee-rails
+ gmaps4rails
haml
jquery-rails
mechanize
View
1  app/assets/javascripts/companies.js.coffee
@@ -0,0 +1 @@
+//= require gmaps4rails/googlemaps.js
View
492 app/assets/javascripts/gmaps4rails/gmaps4rails.base.js.coffee
@@ -0,0 +1,492 @@
+Gmaps = {}
+
+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 #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
+ @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: true # 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 = []
+
+ #tnitializes the map
+ initialize : ->
+ @map = @createMap()
+ 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()
+ 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(@map)
+ #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(@map)
+
+ # 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(@map)
+
+ #////////////////////////////////////////////////////
+ #///////////////////// 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
+
+ #Construct the polygon
+ new_poly = new google.maps.Polygon
+ paths: polygon_coordinates
+ strokeColor: strokeColor
+ strokeOpacity: strokeOpacity
+ strokeWeight: strokeWeight
+ fillColor: fillColor
+ fillOpacity: fillOpacity
+ clickable: false
+ map: @map
+
+ #save polygon in list
+ polygon.serviceObject = new_poly
+
+ #////////////////////////////////////////////////////
+ #/////////////////// 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
+
+ #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.length
+ polyline_coordinates.push(point)
+ 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
+
+ #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: false
+
+ #save polyline
+ polyline.serviceObject = new_poly
+ new_poly.setMap(@map)
+
+ #////////////////////////////////////////////////////
+ #///////////////////// 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
+ #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
+ "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) ->
+ @clearMarkers()
+ #reset previous markers
+ @markers = new Array
+ #reset current bounds
+ @boundsObject = @createLatLngBounds()
+ #reset sidebar content if exists
+ @resetSidebarContent()
+ #add new markers
+ @markers_conf.offset = 0
+ @addMarkers(new_markers)
+
+ #add new markers to on an existing map
+ addMarkers : (new_markers) ->
+ #update the list of markers to take into account
+ @markers = @markers.concat(new_markers)
+ #put markers on the map
+ @create_markers()
+ @adjustMapToBounds()
+
+ #////////////////////////////////////////////////////
+ #///////////////////// 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:
+ for polyline in @polylines
+ polyline_points = polyline.serviceObject.latLngs.getArray()[0].getArray()
+ for point in polyline_points
+ @boundsObject.extend point
+
+ #from polygons:
+ for polygon in @polygons
+ polygon_points = polygon.serviceObject.latLngs.getArray()[0].getArray()
+ for point in polygon_points
+ @boundsObject.extend point
+
+ #from circles
+ for circle in @circles
+ @boundsObject.extend(circle.serviceObject.getBounds().getNorthEast())
+ @boundsObject.extend(circle.serviceObject.getBounds().getSouthWest())
+
+ #in every case, I've to take into account the bounds set up by the user
+ for bound in @map_options.bounds
+ #create points from bounds provided
+ #TODO:only works with google maps
+ bound = @createLatLng(bound.lat, bound.lng)
+ @boundsObject.extend bound
+
+ #SECOND_STEP: ajust the map to the bounds
+ if @map_options.auto_adjust or @map_options.bounds.length > 0
+
+ #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()
+ @map.setCenter(map_center)
+ else
+ @fitBounds()
+
+ #////////////////////////////////////////////////////
+ #///////////////// KML //////////////////
+ #////////////////////////////////////////////////////
+
+ create_kml : ->
+ for kml in @kml
+ kml.serviceObject = @createKmlLayer kml
+
+ #////////////////////////////////////////////////////
+ #///////////////// 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)
View
163 app/assets/javascripts/gmaps4rails/gmaps4rails.bing.js.coffee
@@ -0,0 +1,163 @@
+######################################################################################################
+############################################## 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: ->
+ @map.setView({bounds: @boundsObject})
+
+ addToMap: (object)->
+ @map.entities.push(object)
+
+ removeFromMap: (object)->
+ @map.entities.remove(object)
+
+ centerMapOnUser: ->
+ @map.setView({ center: @userLocation})
View
259 app/assets/javascripts/gmaps4rails/gmaps4rails.googlemaps.js.coffee
@@ -0,0 +1,259 @@
+#######################################################################################################
+############################################## 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
+
+ #Polyline Styling
+ @polylines_conf = #default style for polylines
+ strokeColor: "#FF0000"
+ strokeOpacity: 1
+ strokeWeight: 2
+
+ #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: @map, title: args.marker_title, draggable: args.marker_draggable}
+ mergedOptions = @mergeObjectWithDefault @markers_conf.raw, defaultOptions
+ return new google.maps.Marker mergedOptions
+
+ if (args.rich_marker != null)
+ return new RichMarker({
+ position: markerLatLng
+ map: @map
+ 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]
+ })
+
+ #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: @map, icon: markerImage, title: args.marker_title, draggable: args.marker_draggable, shadow: shadowImage}
+ 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( @map, 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.map, 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(@map)
+ return kml
+
+
+ #////////////////////////////////////////////////////
+ #/////////////////// Other methods //////////////////
+ #////////////////////////////////////////////////////
+
+ fitBounds : ->
+ @map.fitBounds(@boundsObject) unless @boundsObject.isEmpty()
+
+ centerMapOnUser : ->
+ @map.setCenter(@userLocation)
+
View
134 app/assets/javascripts/gmaps4rails/gmaps4rails.mapquest.js.coffee
@@ -0,0 +1,134 @@
+#######################################################################################################
+############################################## Map Quest #############################################
+#######################################################################################################
+# http://www.mapquestapi.com/sdk/js/v6.0.0/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: ->
+ @map.zoomToRect @boundsObject if @markers.length >=2
+ @map.setCenter @markers[0].serviceObject.latLng if @markers.length == 1
+
+ centerMapOnUser: ->
+ @map.setCenter @userLocation
+
+ addToMap: (object) ->
+ @map.addShape object
+
+ removeFromMap: (object)->
+ @map.removeShape object
View
209 app/assets/javascripts/gmaps4rails/gmaps4rails.openlayers.js.coffee
@@ -0,0 +1,209 @@
+#######################################################################################################
+############################################## 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
+
+ #////////////////////////////////////////////////////
+ #/////////////// 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)
+ @map.addLayer(@markersLayer)
+ #//TODO move?
+ @markersLayer.events.register("featureselected", @markersLayer, @onFeatureSelect)
+ @markersLayer.events.register("featureunselected", @markersLayer, @onFeatureUnselect)
+ @markersControl = new OpenLayers.Control.SelectFeature(@markersLayer)
+ @map.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.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: ->
+ @map.removeLayer(@markersLayer) if @markersLayer != null and @map.getLayer(@markersLayer.id) != null
+
+ extendBoundsWithMarkers: ->
+ 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()
+ @map.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: ->
+ @map.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
+
+ # #////////////////////////////////////////////////////
+ # #/////////////////// Other methods //////////////////
+ # #////////////////////////////////////////////////////
+
+ fitBounds: ->
+ @map.zoomToExtent(@boundsObject, true)
+
+ centerMapOnUser: ->
+ @map.setCenter @userLocation
+
View
4 app/assets/stylesheets/companies.css.scss
@@ -0,0 +1,4 @@
+/*
+ *= require "gmaps4rails"
+*/
+.gmaps4rails_map img { max-width: none; }
View
24 app/assets/stylesheets/gmaps4rails.css
@@ -0,0 +1,24 @@
+.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: 800px;
+}
+
+.gmaps4rails_map {
+ width: 800px;
+ height: 400px;
+}
+
+.bing_map {
+ position: absolute;
+ top: 20;
+ left: 10;
+ width: 400px;
+ height: 400px;
+ border:#555555 2px solid;
+}
View
2  app/controllers/choices_controller.rb
@@ -24,7 +24,7 @@ def show
# GET /choices/new.json
def new
-
+ @top_menu_item = "hot_or_not"
@choice = Choice.new
@company_left = Company.relevant.find(:first, :order => "random()")
View
18 app/controllers/companies_controller.rb
@@ -2,7 +2,7 @@ class CompaniesController < ApplicationController
load_and_authorize_resource
def index
-
+ @top_menu_item = "list"
@companies = Company.relevant.find(:all, :order => "name asc")
@@ -11,4 +11,20 @@ def index
format.html # index.html.erb
end
end
+
+ def map
+ @top_menu_item = "map"
+
+ @scope = "NL"
+ if params[:scope]
+ @scope = params[:scope]
+
+ @json = Company.relevant.find(:all, :conditions => {:city => @scope}).to_gmaps4rails
+ else
+ @json = Company.relevant.to_gmaps4rails
+ end
+
+
+ end
+
end
View
1  app/controllers/tasks_controller.rb
@@ -3,6 +3,7 @@ class TasksController < ApplicationController
# GET /tasks
# GET /tasks.json
def index
+ @top_menu_item = "tasks"
@tasks = Task.all
respond_to do |format|
View
18 app/helpers/choices_helper.rb
@@ -1,21 +1,5 @@
module ChoicesHelper
def blurb(company)
- if company.overview.present?
- res = company.overview[0..450]
- if company.overview.size > 450
- # Remove last partial word
- res = res.split(" ")[0..-2].join(" ")
-
- # add dots
- res = res + " ..."
- end
-
- if res.scan(/<p>/).length > res.scan(/<\/p>/).length
- res << "</p>"
- end
- else
- res = ""
- end
- return res.html_safe
+ return company.blurb
end
end
View
2  app/models/ability.rb
@@ -8,7 +8,7 @@ def initialize(current_user)
else
can :logout, Home
can [:new, :create], Choice
- can [:index], Company
+ can [:index, :map], Company
end
end
end
View
41 app/models/company.rb
@@ -1,4 +1,6 @@
class Company < ActiveRecord::Base
+ acts_as_gmappable
+
FIRST_YEAR = 2008
has_many :choices, :foreign_key => :hot_company_id, :class_name => "Choice", :dependent => :destroy
@@ -9,4 +11,43 @@ class Company < ActiveRecord::Base
def self.FIRST_YEAR
FIRST_YEAR
end
+
+ def gmaps4rails_address
+ "#{self.street}, #{self.city}, Nederland"
+ end
+
+
+ def gmaps4rails_infowindow
+ "<h2>#{self.title}</h2>
+ <p>#{self.description.present? ? self.description : ""}</p>
+ #{ if self.logo_url.present?; "<img src='" + self.logo_url + "' style='max-height:100px;'/>"; end}
+ <p>#{self.blurb}</p>
+ <p><a href='#{self.homepage_url}'>Website</a></p>
+ <p><a href='http://www.crunchbase.com/company/{#{self.name}'>CrunchBase article</a></p>
+ "
+ end
+
+ def gmaps4rails_title
+ self.title
+ end
+
+ def blurb
+ if self.overview.present?
+ res = self.overview[0..450]
+ if self.overview.size > 450
+ # Remove last partial word
+ res = res.split(" ")[0..-2].join(" ")
+
+ # add dots
+ res = res + " ..."
+ end
+
+ if res.scan(/<p>/).length > res.scan(/<\/p>/).length
+ res << "</p>"
+ end
+ else
+ res = ""
+ end
+ return res.html_safe
+ end
end
View
8 app/views/companies/map.html.haml
@@ -0,0 +1,8 @@
+.row
+ .span2
+ %ul.nav.nav-pills.nav-stacked
+ %li{:class => @scope == "NL" ? "active" : ""}=link_to "The Netherlands", "/companies/map"
+ %li{:class => @scope == "Amsterdam" ? "active" : ""}=link_to "Amsterdam", "/companies/map?scope=Amsterdam"
+ %li{:class => @scope == "Utrecht" ? "active" : ""}=link_to "Utrecht", "/companies/map?scope=Utrecht"
+ .span10
+ = gmaps4rails(@json)
View
12 app/views/layouts/application.html.haml
@@ -5,6 +5,7 @@
%meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"}
%title Startup Kaart
= csrf_meta_tags
+ = yield :head
= javascript_include_tag "http://html5shim.googlecode.com/svn/trunk/html5.js"
- if ENV['GOOGLE_ANALYTICS'].present?
:javascript
@@ -32,11 +33,11 @@
%a.brand{:href => "/"} Startup Kaart
.container.nav-collapse
%ul.nav
- //%li= link_to "Map", "/"
- %li= link_to "List", companies_path
- %li= link_to "Hot or Not", new_choice_path
+ %li{:class => @top_menu_item == "map" ? "active" : ""}= link_to "Map", map_companies_path
+ %li{:class => @top_menu_item == "list" ? "active" : ""}= link_to "List", companies_path
+ %li{:class => @top_menu_item == "hot_or_not" ? "active" : ""}= link_to "Hot or Not", new_choice_path
- if can? :index, Task
- %li= link_to("Tasks", tasks_path)
+ %li{:class => @top_menu_item == "tasks" ? "active" : ""}= link_to("Tasks", tasks_path)
- if logged_in?
%li= link_to "Logout", logout_path
- else
@@ -69,4 +70,5 @@
= link_to "sjors@sprovoost.nl", "mailto:sjors@sprovoost.nl"
and Twitter
= link_to("@provoost", "http://sprovoost.nl/") + ""
- = javascript_include_tag "application"
+ = javascript_include_tag "application"
+ = yield :scripts
View
8 config/routes.rb
@@ -2,7 +2,11 @@
resources :tasks
resources :choices
- resources :companies
+ resources :companies do
+ collection do
+ get :map
+ end
+ end
twitter = StartupKaart::Application.config.twitter_login
twitter_endpoint = twitter.login_handler(:return_to => '/')
@@ -62,7 +66,7 @@
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
- root :to => 'choices#new'
+ root :to => 'companies#map'
# See how all your routes lay out with "rake routes"
View
6 db/migrate/20120413103507_add_street_to_companies.rb
@@ -0,0 +1,6 @@
+class AddStreetToCompanies < ActiveRecord::Migration
+ def change
+ add_column :companies, :street, :stitring
+
+ end
+end
View
7 db/migrate/20120413104405_add_location_fields_to_companies.rb
@@ -0,0 +1,7 @@
+class AddLocationFieldsToCompanies < ActiveRecord::Migration
+ def change
+ add_column :companies, :latitude, :float
+
+ add_column :companies, :longitude, :float
+ end
+end
View
6 db/migrate/20120413105350_add_gmaps_to_companies.rb
@@ -0,0 +1,6 @@
+class AddGmapsToCompanies < ActiveRecord::Migration
+ def change
+ add_column :companies, :gmaps, :boolean
+
+ end
+end
View
26 db/schema.rb
@@ -1,3 +1,4 @@
+# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
@@ -10,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20110819220840) do
+ActiveRecord::Schema.define(:version => 20120413105350) do
create_table "choices", :force => true do |t|
t.integer "user_id"
@@ -24,27 +25,8 @@
add_index "choices", ["not_company_id"], :name => "index_choices_on_not_company_id"
add_index "choices", ["user_id"], :name => "index_choices_on_user_id"
- create_table "companies", :force => true do |t|
- t.string "name"
- t.string "title"
- t.string "homepage_url"
- t.string "category_code"
- t.integer "number_of_employees"
- t.integer "founded_year"
- t.string "description"
- t.string "total_money_raised"
- t.integer "total_dollars_raised"
- t.string "latest_round_code"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.boolean "crawled", :default => false
- t.string "city"
- t.string "country"
- t.boolean "parse_error", :default => false
- t.text "overview"
- t.string "logo_url"
- t.boolean "needs_update", :default => false
- end
+# Could not dump table "companies" because of following StandardError
+# Unknown type 'stitring' for column 'street'
create_table "tasks", :force => true do |t|
t.integer "mw_task_id"
View
36 lib/tasks/crunchbase.rake
@@ -68,10 +68,13 @@ namespace :crunchbase do
# Location
unless result["offices"].empty?
- # Pick the first one
- hq = result["offices"][0]
- company.country = hq["country_code"]
- company.city = hq["city"]
+ # Pick the first one in The Netherlands
+ hq = result["offices"].keep_if{|office| office["country_code"] == "NLD"}.first
+ if hq.present?
+ company.street = hq["address1"]
+ company.country = hq["country_code"]
+ company.city = hq["city"]
+ end
end
# Logo
@@ -107,6 +110,31 @@ namespace :crunchbase do
end
end
+
+ desc "Fetch coordinates from Google"
+ task :fetch_coordinates => :environment do
+ Company.find(:all, :conditions => {:latitude => nil}, :order => "name asc").each do |c|
+ begin
+ res = Gmaps4rails.geocode(c.gmaps4rails_address)
+ # Only coordinates in The Netherlands
+ res.keep_if{|c| c[:full_data]["address_components"].keep_if{|c| c["types"].include? "country"}.first["short_name"] == "NL" }
+
+ if res.count > 0
+ c.latitude = res[0][:lat]
+ c.longitude = res[0][:lng]
+ c.save
+ else
+ puts "No acceptable coordinates returned by Google"
+ end
+ rescue Gmaps4rails::GeocodeStatus
+ puts "Google could not find coordinate for " + c.name
+ # rescue Gmaps4rails::GeocodeNetStatus
+ # puts "Network issue"
+ end
+
+ sleep 0.2
+ end
+ end
# desc "Process funding"
# task :process_funding => :environment do
View
BIN  public/images/marker.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Please sign in to comment.
Something went wrong with that request. Please try again.