Last active
May 12, 2019 17:14
-
-
Save kaz-a/7637986e3953e90aaf47 to your computer and use it in GitHub Desktop.
NYC Daycare Finder with Leaflet
This file contains hidden or 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
| <!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> 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> 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" /> 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 © <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] ? '–' + 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