-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f1a1eda
commit d64b71e
Showing
6 changed files
with
309 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>Citi Bike</title> | ||
|
||
<!-- D3 --> | ||
<script src="https://d3js.org/d3.v7.min.js"></script> | ||
|
||
<!-- Leaflet CSS --> | ||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" | ||
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" | ||
crossorigin=""/> | ||
|
||
<!-- polyfill.io is the library for using newer JavaScript features (such as Object.assign) in older browers. --> | ||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script> | ||
|
||
<!-- Google Fonts --> | ||
<link href="https://fonts.googleapis.com/css?family=Sanchez" rel="stylesheet"> | ||
|
||
<!-- Leaflet JavaScript code --> | ||
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" | ||
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" | ||
crossorigin=""></script> | ||
|
||
|
||
<!-- Icons --> | ||
<script src="static/js/leaflet.extra-markers.min.js"></script> | ||
<link rel="stylesheet" type="text/css" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> | ||
<link rel="stylesheet" href="static/css/leaflet.extra-markers.min.css"> | ||
|
||
<!-- Our CSS --> | ||
<link rel="stylesheet" type="text/css" href="static/css/style.css"> | ||
</head> | ||
<body> | ||
|
||
<!-- The div that holds our map --> | ||
<div id="map-id"></div> | ||
|
||
<!-- Our JavaScript file --> | ||
<script type="text/javascript" src="static/js/logic.js"></script> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
html, | ||
body, | ||
#map-id { | ||
height: 100%; | ||
padding: 0; | ||
margin: 0; | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// var newYorkCoords = [40.73, -74.0059]; | ||
// var mapZoomLevel = 12; | ||
|
||
// Create the createMap function. | ||
function createMap(bikeStations) { | ||
|
||
|
||
// Create the tile layer that will be the background of our map. | ||
let streetmap = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | ||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' | ||
}); | ||
|
||
// Create a baseMaps object to hold the lightmap layer. | ||
let baseMaps = { | ||
"Street Map": streetmap | ||
}; | ||
|
||
// Create an overlayMaps object to hold the bikeStations layer. | ||
let overlayMaps = { | ||
"Bike Stations": bikeStations | ||
}; | ||
|
||
// Create the map object with options. | ||
let map = L.map("map-id", { | ||
center: [40.73, -74.0059], | ||
zoom: 12, | ||
layers: [streetmap, bikeStations] | ||
}); | ||
|
||
// Create a layer control, and pass it baseMaps and overlayMaps. Add the layer control to the map. | ||
L.control.layers(baseMaps, overlayMaps, { | ||
collapsed: false | ||
}).addTo(map); | ||
|
||
} | ||
// Create the createMarkers function. | ||
function createMarkers(response) { | ||
|
||
// Pull the "stations" property from response.data. | ||
let stations = response.data.stations; | ||
|
||
// Initialize an array to hold the bike markers. | ||
let bikeMarkers =[]; | ||
|
||
// Loop through the stations array. | ||
// For each station, create a marker, and bind a popup with the station's name. | ||
for (let i = 0; i < stations.length; index++) { | ||
let station = stations[index]; | ||
|
||
let bikeMarker = L.marker([station.lat, station.lon]) | ||
.bindPopup("<h3>" + station.name + "<h3><h3>Capacity: " + station.capacity + "</h3>"); | ||
|
||
|
||
// Add the marker to the bikeMarkers array. | ||
bikeMarkers.push(bikeMarkers); | ||
} | ||
// Create a layer group that's made from the bike markers array, and pass it to the createMap function. | ||
createMap(L.layerGroup(bikeMarkers)); | ||
} | ||
let bikeurl = "https://gbfs.citibikenyc.com/gbfs/en/station_information.json"; | ||
|
||
// Perform an API call to the Citi Bike API to get the station information. Call createMarkers when it completes. | ||
d3.json(bikeurl).then(createMarkers); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
// let newYorkCoords = [40.73, -74.0059]; | ||
// let mapZoomLevel = 12; | ||
|
||
// Create the tile layer that will be the background of our map. | ||
let streetmap = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | ||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' | ||
}); | ||
|
||
// Initialize all the LayerGroups that we'll use. | ||
let layers = { | ||
COMING_SOON: new L.LayerGroup(), | ||
EMPTY: new L.LayerGroup(), | ||
LOW: new L.LayerGroup(), | ||
NORMAL: new L.LayerGroup(), | ||
OUT_OF_ORDER: new L.LayerGroup() | ||
}; | ||
|
||
// Create the map with our layers. | ||
let map = L.map("map-id", { | ||
center: [40.73, -74.0059], | ||
zoom: 12, | ||
layers: [ | ||
layers.COMING_SOON, | ||
layers.EMPTY, | ||
layers.LOW, | ||
layers.NORMAL, | ||
layers.OUT_OF_ORDER | ||
] | ||
}); | ||
|
||
// Add our "streetmap" tile layer to the map. | ||
streetmap.addTo(map); | ||
|
||
// Create an overlays object to add to the layer control. | ||
let overlays = { | ||
"Coming Soon": layers.COMING_SOON, | ||
"Empty Stations": layers.EMPTY, | ||
"Low Stations": layers.LOW, | ||
"Healthy Stations": layers.NORMAL, | ||
"Out of Order": layers.OUT_OF_ORDER | ||
}; | ||
|
||
// Create a control for our layers, and add our overlays to it. | ||
L.control.layers(null, overlays).addTo(map); | ||
|
||
// Create a legend to display information about our map. | ||
let info = L.control({ | ||
position: "bottomright" | ||
}); | ||
|
||
// When the layer control is added, insert a div with the class of "legend". | ||
info.onAdd = function() { | ||
var div = L.DomUtil.create("div", "legend"); | ||
return div; | ||
}; | ||
// Add the info legend to the map. | ||
info.addTo(map); | ||
|
||
// Initialize an object that contains icons for each layer group. | ||
let icons = { | ||
COMING_SOON: L.ExtraMarkers.icon({ | ||
icon: "ion-settings", | ||
iconColor: "white", | ||
markerColor: "yellow", | ||
shape: "star" | ||
}), | ||
EMPTY: L.ExtraMarkers.icon({ | ||
icon: "ion-android-bicycle", | ||
iconColor: "white", | ||
markerColor: "red", | ||
shape: "circle" | ||
}), | ||
OUT_OF_ORDER: L.ExtraMarkers.icon({ | ||
icon: "ion-minus-circled", | ||
iconColor: "white", | ||
markerColor: "blue-dark", | ||
shape: "penta" | ||
}), | ||
LOW: L.ExtraMarkers.icon({ | ||
icon: "ion-android-bicycle", | ||
iconColor: "white", | ||
markerColor: "orange", | ||
shape: "circle" | ||
}), | ||
NORMAL: L.ExtraMarkers.icon({ | ||
icon: "ion-android-bicycle", | ||
iconColor: "white", | ||
markerColor: "green", | ||
shape: "circle" | ||
}) | ||
}; | ||
|
||
// Perform an API call to the Citi Bike station information endpoint. | ||
d3.json("https://gbfs.citibikenyc.com/gbfs/en/station_information.json").then(function(infoRes) { | ||
|
||
// When the first API call completes, perform another call to the Citi Bike station status endpoint. | ||
d3.json("https://gbfs.citibikenyc.com/gbfs/en/station_status.json").then(function(statusRes) { | ||
let updatedAt = infoRes.last_updated; | ||
let stationStatus = statusRes.data.stations; | ||
let stationInfo = infoRes.data.stations; | ||
|
||
// Create an object to keep the number of markers in each layer. | ||
let stationCount = { | ||
COMING_SOON: 0, | ||
EMPTY: 0, | ||
LOW: 0, | ||
NORMAL: 0, | ||
OUT_OF_ORDER: 0 | ||
}; | ||
|
||
// Initialize stationStatusCode, which will be used as a key to access the appropriate layers, icons, and station count for the layer group. | ||
let stationStatusCode; | ||
|
||
// Loop through the stations (they're the same size and have partially matching data). | ||
for (let i = 0; i < stationInfo.length; i++) { | ||
|
||
// Create a new station object with properties of both station objects. | ||
let station = Object.assign({}, stationInfo[i], stationStatus[i]); | ||
// If a station is listed but not installed, it's coming soon. | ||
if (!station.is_installed) { | ||
stationStatusCode = "COMING_SOON"; | ||
} | ||
// If a station has no available bikes, it's empty. | ||
else if (!station.num_bikes_available) { | ||
stationStatusCode = "EMPTY"; | ||
} | ||
// If a station is installed but isn't renting, it's out of order. | ||
else if (station.is_installed && !station.is_renting) { | ||
stationStatusCode = "OUT_OF_ORDER"; | ||
} | ||
// If a station has less than five bikes, it's status is low. | ||
else if (station.num_bikes_available < 5) { | ||
stationStatusCode = "LOW"; | ||
} | ||
// Otherwise, the station is normal. | ||
else { | ||
stationStatusCode = "NORMAL"; | ||
} | ||
|
||
// Update the station count. | ||
stationCount[stationStatusCode]++; | ||
// Create a new marker with the appropriate icon and coordinates. | ||
let newMarker = L.marker([station.lat, station.lon], { | ||
icon: icons[stationStatusCode] | ||
}); | ||
|
||
// Add the new marker to the appropriate layer. | ||
newMarker.addTo(layers[stationStatusCode]); | ||
|
||
// Bind a popup to the marker that will display on being clicked. This will be rendered as HTML. | ||
newMarker.bindPopup(station.name + "<br> Capacity: " + station.capacity + "<br>" + station.num_bikes_available + " Bikes Available"); | ||
} | ||
|
||
// Call the updateLegend function, which will update the legend! | ||
updateLegend(updatedAt, stationCount); | ||
}); | ||
}); | ||
|
||
// Update the legend's innerHTML with the last updated time and station count. | ||
function updateLegend(time, stationCount) { | ||
document.querySelector(".legend").innerHTML = [ | ||
"<p>Updated: " + moment.unix(time).format("h:mm:ss A") + "</p>", | ||
"<p class='out-of-order'>Out of Order Stations: " + stationCount.OUT_OF_ORDER + "</p>", | ||
"<p class='coming-soon'>Stations Coming Soon: " + stationCount.COMING_SOON + "</p>", | ||
"<p class='empty'>Empty Stations: " + stationCount.EMPTY + "</p>", | ||
"<p class='low'>Low Stations: " + stationCount.LOW + "</p>", | ||
"<p class='healthy'>Healthy Stations: " + stationCount.NORMAL + "</p>" | ||
].join(""); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Toggle Animation by Class | ||
|
||
;(function($) { | ||
$(function() { | ||
$('nav ul li > a:not(:only-child)').click(function(e) { | ||
$(this) | ||
.siblings('.nav-dropdown') | ||
.slideToggle() | ||
$('.nav-dropdown') | ||
.not($(this).siblings()) | ||
.hide() | ||
e.stopPropagation() | ||
}) | ||
$('html').click(function() { | ||
$('.nav-dropdown').hide() | ||
}) | ||
// Toggle open and close nav styles on click | ||
$('#nav-toggle').click(function() { | ||
$('nav ul').slideToggle(); | ||
}); | ||
$('#nav-toggle').on('click', function() { | ||
this.classList.toggle('active') | ||
}) | ||
}) | ||
})(jQuery) |