- create a form in HTML
- using ERB, populate a
select
element withoptions
from a JSON file - understand how to use the
name
andvalue
attributes to populate aparams
hash of user inputted data - create a route to respond to a post from the form
- create instance variables from the
params
hash in your route so you can use it in a view - use embedded ruby to plot points on a map using javascript
- fork and then clone this repo: https://github.com/ashleygwilliams/citibike-sinatra
bundle install
bundle exec shotgun
localhost:9393
This app is using the MultiJSON gem to load in data. If you look in app.rb
you'll see that we are using something called a before
filter to load the JSON into an instance variable called @data
, which will hold our data from the JSON file.
#app.rb
before do
json = File.open("data/citibikenyc.json").read
@data = MultiJson.load(json)
end
The app has a single route, at "/"
that will simple print out the contents of @data
.
#app.rb
get '/' do
erb :home
end
#home.erb
<%= @data.inspect %>
Change the code in home.erb so that it prints a list of every station name, followed by it's longitude and latitude.
- create a route that respond to a get request at
/form
- create a view, and update the route def so that
/form
will render that view - put a heading on the page with the text "Map my route!"
- inside your view, create a
<form>
element with 2<select>
elements, one withname="start"
and the other withname="end"
. also create a submit button. - label each
<select>
element with the words "start:" and "end:" respectively - inside the
<select>
elements, loop through the data hash and create an<option>
element for each station with thevalue
of the station name
you should now have a form that looks like this:
- your form should post to
/form
, so update your<form>
element - create a route in
app.rb
- investigate your form's response by printing
params
to the browser when the form is submitted - once you feel comfortable with your form's response, change the response to a string that read "You chose ______ and _______" where the blanks contain the name of the station that the user chose
the app you cloned also has a view called map.erb
. this map uses leaflet.js. the code in the view looks like this:
<div id="map"></div>
<script type="text/javascript" charset="utf-8">
var map = L.map('map').setView([40.7142, -74.0064], 13);
L.tileLayer('http://tile.stamen.com/toner/{z}/{x}/{y}.png', {attribution: 'Stamen Toner'}, {
attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>',
maxZoom: 18
}).addTo(map);
</script>
basically, this code makes a div
with id=map
. the <script>
contains javascript that makes a map and puts it into that div.
- create a route at
/map
and have it render this view. you should see a map, with no points. it'll look like this:
Let's connect our map to the data we receive from the form now.
- change the action on your form to the
/map
route. - change your map route to respond to a
post
instead of aget
- test your app to ensure that everything still works
- in your map route, create 2 instance variables and store the start and end station names in them
- in
map.erb
create an unordered list and print the name of the start and end station name to the screen
so we're getting name data, but we actually want longitude and latitude data. where is that happening and what should we do to change it?
- take a moment and look at your code. can you change the params that the form is sending to the map view? what are your options? play around for a second.
so, the params are determined by the value
attribute of the <select>
element. originally, we were just putting the station's name in there.. but we can change that.
- change ther
value
of each<select>
element to an array, where the first element is the latitude and the second element is the longitude of any given station. test this by printing the params to the map page. you'll want to see something like this:
ooops. this data doesn't look right. we need to fix it. look at sarah's blog post for advice on how to do this: http://sarahduve.github.io/blog/2013/06/27/dont-forget-to-float/
ok awesome, so now we have an array for the starting location and the ending location. the array contains the latitude and longitude for the selected station. this is rad because this is ALL we need to create markers and draw shapes and lines using the leaflet js mapping library.
you can add a marker to a leaflet map using the following code.
L.marker([longitude, latitude]).addTo(map);
here:
L
is the leaflet library.marker
is a method that creates a marker object. it takes one parameter, an array with 2 elements,longitude
andlatitude
.addTo
is a method that is called on an object and adds it to a map, which is passed as the parametermap
(NOTE: that map was made earlier using this codevar map = L.map('map').setView([40.7142, -74.0064], 13);
)
so now:
- add a marker for the start and end locations
in addition to markers, leaflet also allows you to draw lines and shapes and all sorts of things.
making a line is really similar to making a marker; except you use .polyline
instead of .marker
and you just simply pass it more points as parameters:
L.polyline([
[lat1, lng1],
[lat2, lng2]
]).addTo(map);
using that knowledge 2. create a line from the start location to the end location.
if you want... take a look at the documentation. you can change how the line looks and even make your map zoom to fit your line! http://leafletjs.com/reference.html#polyline
Ashley, what repo do we fork and clone to do this assignment?