Skip to content

Instantly share code, notes, and snippets.

@kaz-a
Last active May 12, 2019 17:14
Show Gist options
  • Select an option

  • Save kaz-a/7637986e3953e90aaf47 to your computer and use it in GitHub Desktop.

Select an option

Save kaz-a/7637986e3953e90aaf47 to your computer and use it in GitHub Desktop.
NYC Daycare Finder with Leaflet
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<meta name='viewport' content="width=device-width,initial-scale=1" />
<title>NYC Daycare Facilities</title>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" integrity="sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ==" crossorigin="anonymous">
<link href='https://fonts.googleapis.com/css?family=Slackey' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js" integrity="sha512-K1qjQ+NcF2TYO/eI3M6v8EiNYZfA95pQumfvcVrTHtwQVDG+aHRqLi/ETn2uB+1JqwYqVG3LIvdm9lj6imS/pQ==" crossorigin="anonymous"></script>
<style>
body {
margin: 0;
padding: 0;
font-family: 'Open Sans', sans-serif;
font-size: 13px;
}
#map {
margin: 30px 5px;
width: 100%;
height: 850px;
}
.button {
padding-bottom: 20px;
}
.btn-all {
background-color: #6d594b;
color: white;
margin: 2px 2px;
}
.btn-GFDC {
background-color: #f61900;
color: white;
margin: 2px 2px;
}
.btn-FDC {
background-color: #faa300;
color: white;
margin: 2px 2px;
}
.btn-SACC {
background-color: #74bc00;
color: white;
margin: 2px 2px;
}
.btn-GDC {
background-color: #2b8d4c;
color: white;
margin: 2px 2px;
}
.btn-SBCC {
background-color: #45cae6;
color: white;
margin: 2px 2px;
}
.text {
padding-left: 90px;
}
.header {
/*padding-top: 30px;*/
}
.dateEntry {
color: #6d594b;
}
.dateInput {
/*font-size: 21px;*/
color: #6d594b;
font-weight: bold;
}
.title {
font-family: 'Slackey', cursive;
text-align: center;
color: #6d594b;
}
.title span {
font-family: 'Slackey', cursive;
text-align: center;
font-size: 20px;
}
.subtitle {
font-size: 12px;
color: rgba(0,0,0, 0.5);
text-align: center;
}
.tool {
background: #d1b9a7;
margin: 30px auto;
height: 850px;
padding: 33px;
}
.form-control {
width: 75%;
float: left;
}
#submit {
float: right;
}
#refresh {
background: grey;
color: white;
margin: 5px auto;
position: relative;
left: 35%;
}
.toolheader {
color: #6d594b;
}
.line {
/*height: 1px;
border-top: #6d594b 1px solid;*/
padding: 0;
border: none;
border-top: 1px double #6d594b;
color: #6d594b;
text-align: center;
width: 80%;
padding-bottom: 24px;
}
.line:after {
content: "§";
display: inline-block;
position: relative;
top: -0.7em;
font-size: 1.0em;
padding: 0 0.25em;
background: #d1b9a7;
}
.leaflet-popup-content {
font-family: 'Open Sans', sans-serif;
}
.legend {
line-height: 18px;
color: #555;
background: white;
padding: 10px;
}
.legend i {
width: 18px;
height: 18px;
float: left;
margin-right: 8px;
opacity: 0.7;
}
#poverty {
color: #6d594b;
}
.popup_header {
border-bottom: 1px solid grey;
padding-bottom: -30px;
margin: 4px;
}
.popup_address {
padding-top: 0px;
}
.popup_title {
margin-bottom: -15px;
}
.popup_dsource {
/*color: grey;*/
}
</style>
</head>
<body>
<script src='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/leaflet.markercluster.js'></script>
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/MarkerCluster.css' rel='stylesheet' />
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/MarkerCluster.Default.css' rel='stylesheet' />
<div class="container-fluid">
<div class="col-xs-12 col-md-3 tool">
<div class="header">
<h1 class="title"><span>NYC</span><br />DAYCARE FINDER</h1>
<p class="subtitle">
Welcome to the NYC Daycare Finder! This app lets you visualize the locations of all City and State registered daycare facilities,
and filter them by modality and/or last inspection date. It may take a second or two for the initial data to load, so please be patient!
</p>
<hr class="line" />
<h4 class="toolheader"><i class="fa fa-briefcase"></i>&nbsp;Filter by Modality</h4>
<p class="toolheader">Choose a modality type of the daycare facilities</p>
</div>
<div class="button">
<button type="button" id="all" class="btn btn-all">All</button>
</div>
<div class="header">
<h4 class="toolheader"><i class="fa fa-calendar"></i>&nbsp;Filter by Date</h4>
<p class="toolheader">
Enter date into the box to display all daycares that were inspected on and prior to that date.
Click on the REFRESH button before entering another date.
</p>
</div>
<div class="form-group">
<div class="dateForm col-xs-12 col-md-12">
<input type="text" id="userInput" class="form-control" value="10/5/2011" />
<button id="submit" class="btn btn-default">GO</button>
</div>
</div>
<div class="dateForm col-xs-12 col-md-12">
<span class="dateEntry"></span>
<button id="refresh" class="btn btn-default">REFRESH</button>
</div>
<div class="toolheader">
<input type="checkbox" class="checkbox-primary" value="povertyData" />&nbsp;Show poverty data
</div>
</div>
<div class="col-xs-12 col-md-9">
<div id="map"></div>
</div>
</div>
<script>
// initialize the map
var map = L.map('map').setView([40.71, -74.00], 11);
//specify tile map service
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoiemFrc2Nsb3NldCIsImEiOiJjaWY2dWxkc2gwcXBjczVtM3pnc3hydnI1In0.ABQHwIrVx95WhAVv_2JPeA', {
attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, Imagery © <a href="http://mapbox.com">Mapbox</a>',
maxZoom: 20,
id: 'zakscloset.nj4mj6hk',
accessToken: 'pk.eyJ1IjoiemFrc2Nsb3NldCIsImEiOiJjaWY2dWxkc2gwcXBjczVtM3pnc3hydnI1In0.ABQHwIrVx95WhAVv_2JPeA'
}).addTo(map);
//setting the poverty shades
function getColor(d) {
return d > 30 ? "#0868ac" :
d > 20 ? "#43a2ca" :
d > 10 ? "#7bccc4" :
d > 0 ? "#a8ddb5" :
"grey";
};
//load poverty data
var povertyData = "https://raw.githubusercontent.com/Kaz-A/daycare_finder/master/poverty.geojson";
var legend = L.control({ position: 'bottomright' });
//poverty legend
legend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'info legend'),
povertyLevel = [0, 10, 20, 30],
labels = [];
// loop through intervals and generate a label with a colored square for each interval
for (var i = 0; i < povertyLevel.length; i++) {
div.innerHTML +=
'<i style="background:' + getColor(povertyLevel[i] + 1) + '"></i> ' +
povertyLevel[i] + (povertyLevel[i + 1] ? '&ndash;' + povertyLevel[i + 1] + '%<br>' : '%+');
}
return div;
};
//legend.addTo(map);
$.getJSON(povertyData, function (povertyData) {
//get unique poverty % values
var povertyFeatures = povertyData.features;
var uniquePoverty = [];
povertyFeatures.forEach(function (x) {
if (!povertyFeatures[x.properties.PopInPover]) {
uniquePoverty.push(x.properties.PopInPover);
povertyFeatures[x.properties.Poverty] = true;
}
});
//console.log(povertyData);
console.log(uniquePoverty);
//styling the choropleth
function style(feature) {
return {
fillColor: getColor(feature.properties.PopInPover),
weight: 1,
opacity: 1,
color: "white",
dashArray: '1',
fillOpacity: 0.5
};
};
//add a poverty data
var addPovertyData = L.geoJson(povertyData, { style: style });
//checkbox event to overlay poverty data - needs fix
$(".checkbox-primary").click(function () {
if (this.checked) {
console.log("checked!");
addPovertyData.addTo(map);
legend.addTo(map);
} else {
console.log("unchecked!");
map.removeLayer(addPovertyData);
map.removeControl(legend);
};
});
});
//marker icons
var iconUrl = "https://raw.githubusercontent.com/Kaz-A/daycare_finder/master/images/";
var iconSize = [30, 20];
var daycareIcon = L.icon({ iconUrl: iconUrl + "daycare.png", iconSize: iconSize }),
gfdcIcon = L.icon({ iconUrl: iconUrl + "gfdc.png", iconSize: iconSize }),
fdcIcon = L.icon({ iconUrl: iconUrl + "fdc.png", iconSize: iconSize }),
saccIcon = L.icon({ iconUrl: iconUrl + "sacc.png", iconSize: iconSize }),
gdcIcon = L.icon({ iconUrl: iconUrl + "gdc.png", iconSize: iconSize }),
sbccIcon = L.icon({ iconUrl: iconUrl + "sbcc.png", iconSize: iconSize });
//popup function
function popup(feature, layer) {
var popupContent = "<h4 class='popup_title'>" + feature.properties.CENTER_NAME +
"</h4><br />" + feature.properties.ADDRESS +
"</span><br /><hr class='popup_header' /><p>Permit: " + feature.properties.permit +
"<br />Status: " + feature.properties.STATUS +
"<br />Modality: " + feature.properties.Modality +
"<br />Risk Level = " + feature.properties.risklevel +
"<br />Last Inspection: " + feature.properties.last_inspectiondate +
"<br /><span class='popup_dsource'>Data by " + feature.properties.CityVState + "</span></p>";
if (feature.properties && feature.properties.popupContent) {
popupContent += feature.properties.popupContent;
};
layer.bindPopup(popupContent);
};
//load data
var geojson = "https://raw.githubusercontent.com/Kaz-A/daycare_finder/master/childcare.geojson";
$.getJSON(geojson, function (data) {
//get unique modality values
var modalityFeatures = data.features;
var uniqueModality = [];
modalityFeatures.forEach(function (x) {
if (!modalityFeatures[x.properties.Modality]) {
uniqueModality.push(x.properties.Modality);
modalityFeatures[x.properties.Modality] = true;
}
});
console.log(data);
console.log(uniqueModality);
// //convert modality names to lowercase
// var lowerCaseModalityNames = [];
// for (i = 0; i < uniqueModality.length; i++) {
// lowerCaseModalityNames.push(uniqueModality[i].toLowerCase());
// };
// console.log(lowerCaseModalityNames);
//buttons
var buttonList = $(".button").addClass("button");
var i = 0;
var modalityButtons = "";
$.each(uniqueModality, function () {
modalityButtons += '<button type = "button"' + 'id = "' + this + '" class = "btn btn-' + this + '">' + this + '</button>';
});
$(modalityButtons).appendTo(buttonList);
var daycares = L.geoJson(data, {
pointToLayer: function (feature, latlng) {
var marker = L.marker;
if (feature.properties.Modality == "GFDC") {
marker = L.marker(latlng, { icon: gfdcIcon });
} else if (feature.properties.Modality == "FDC") {
marker = L.marker(latlng, { icon: fdcIcon });
} else if (feature.properties.Modality == "SACC") {
marker = L.marker(latlng, { icon: saccIcon });
} else if (feature.properties.Modality == "GDC") {
marker = L.marker(latlng, { icon: gdcIcon });
} else if (feature.properties.Modality == "SBCC") {
marker = L.marker(latlng, { icon: sbccIcon });
} else {
marker = L.marker(latlng, { icon: daycareIcon });
};
popup(feature, marker);
return marker;
},
});
//marker clustering
var daycareClusters = L.markerClusterGroup({
disableClusteringAtZoom: 15
});
daycareClusters.addLayer(daycares);
map.addLayer(daycareClusters);
//user date input
$("#submit").click(function () {
var input = $("#userInput").val();
$(".dateEntry").html("<br />Showing all daycare facilities inspected on and before <span class = 'dateInput'>" + input + "</span><br />");
var date = L.geoJson(data, {
filter: function (feature, layer) {
var dateFormat = Date.parse(feature.properties.last_inspectiondate);
return dateFormat <= Date.parse(input);
},
pointToLayer: function (feature, latlng) {
var marker = L.marker;
if (feature.properties.Modality == "GFDC") {
marker = L.marker(latlng, { icon: gfdcIcon });
} else if (feature.properties.Modality == "FDC") {
marker = L.marker(latlng, { icon: fdcIcon });
} else if (feature.properties.Modality == "SACC") {
marker = L.marker(latlng, { icon: saccIcon });
} else if (feature.properties.Modality == "GDC") {
marker = L.marker(latlng, { icon: gdcIcon });
} else if (feature.properties.Modality == "SBCC") {
marker = L.marker(latlng, { icon: sbccIcon });
} else {
marker = L.marker(latlng, { icon: daycareIcon });
};
popup(feature, marker);
return marker;
}
});
//console.log(date);
var dateClusters = L.markerClusterGroup({
disableClusteringAtZoom: 15
});
dateClusters.addLayer(date);
map.addLayer(dateClusters);
map.removeLayer(daycareClusters);
//remove all date-input data
$("#refresh").click(function () {
dateClusters.removeLayer(date);
map.removeLayer(date);
$(".dateEntry").html("");
})
});
//show only gfdc data
var gfdc = L.geoJson(data, {
filter: function (feature, layer) {
return feature.properties.Modality == "GFDC";
},
pointToLayer: function (feature, latlng) {
var marker = L.marker(latlng, { icon: gfdcIcon });
popup(feature, marker);
return marker;
}
});
//show only fdc data
var fdc = L.geoJson(data, {
filter: function (feature, layer) {
return feature.properties.Modality == "FDC";
},
pointToLayer: function (feature, latlng) {
var marker = L.marker(latlng, { icon: fdcIcon });
popup(feature, marker);
return marker;
}
});
//show only sacc data
var sacc = L.geoJson(data, {
filter: function (feature, layer) {
return feature.properties.Modality == "SACC";
},
pointToLayer: function (feature, latlng) {
var marker = L.marker(latlng, { icon: saccIcon });
popup(feature, marker);
return marker;
}
});
//show only gdc data
var gdc = L.geoJson(data, {
filter: function (feature, layer) {
return feature.properties.Modality == "GDC";
},
pointToLayer: function (feature, latlng) {
var marker = L.marker(latlng, { icon: gdcIcon });
popup(feature, marker);
return marker;
}
});
//show only sbcc data
var sbcc = L.geoJson(data, {
filter: function (feature, layer) {
return feature.properties.Modality == "SBCC";
},
pointToLayer: function (feature, latlng) {
var marker = L.marker(latlng, { icon: sbccIcon });
popup(feature, marker);
return marker;
}
});
var gfdcClusters = L.markerClusterGroup({
disableClusteringAtZoom: 14
});
var fdcClusters = L.markerClusterGroup({
disableClusteringAtZoom: 14
});
var saccClusters = L.markerClusterGroup({
disableClusteringAtZoom: 14
});
var gdcClusters = L.markerClusterGroup({
disableClusteringAtZoom: 14
});
var sbccClusters = L.markerClusterGroup({
disableClusteringAtZoom: 14
});
$("#GFDC").click(function () {
gfdcClusters.addLayer(gfdc);
map.addLayer(gfdcClusters);
map.removeLayer(fdcClusters);
map.removeLayer(saccClusters);
map.removeLayer(gdcClusters);
map.removeLayer(sbccClusters);
map.removeLayer(daycareClusters);
});
$("#FDC").click(function () {
fdcClusters.addLayer(fdc);
map.addLayer(fdcClusters);
map.removeLayer(gfdcClusters);
map.removeLayer(saccClusters);
map.removeLayer(gdcClusters);
map.removeLayer(sbccClusters);
map.removeLayer(daycareClusters);
});
$("#SACC").click(function () {
saccClusters.addLayer(sacc);
map.addLayer(saccClusters);
map.removeLayer(gfdcClusters);
map.removeLayer(fdcClusters);
map.removeLayer(gdcClusters);
map.removeLayer(sbccClusters);
map.removeLayer(daycareClusters);
});
$("#GDC").click(function () {
gdcClusters.addLayer(gdc);
map.addLayer(gdcClusters);
map.removeLayer(gfdcClusters);
map.removeLayer(fdcClusters);
map.removeLayer(saccClusters);
map.removeLayer(sbccClusters);
map.removeLayer(daycareClusters);
});
$("#SBCC").click(function () {
sbccClusters.addLayer(sbcc);
map.addLayer(sbccClusters);
map.removeLayer(gfdcClusters);
map.removeLayer(fdcClusters);
map.removeLayer(saccClusters);
map.removeLayer(gdcClusters);
map.removeLayer(daycareClusters);
});
$("#all").click(function () {
daycareClusters.addLayer(daycareClusters);
map.addLayer(daycareClusters);
map.removeLayer(gfdcClusters);
map.removeLayer(fdcClusters);
map.removeLayer(saccClusters);
map.removeLayer(gdcClusters);
map.removeLayer(sbccClusters);
});
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment