Park Finder Web App
- Apr– May 2022
- Role
- JavaScript Designer
- Duration
- 3 weeks
- Tools
- Vanilla JavaScript
- HTML & CSS
- TomTom Maps & Search Web API
- Leaflet Map
- Features
- JavaScript
- Web APIs & JSON files
- Live Product
Brief
- Final project for DVC's Web and Mobile Design with JavaScript class
- Develop a Web Application by combining at least two Web APIs
- Our group chose to create an app to help dog owners find parks they could take their pets to
Beginning the Project: APIs
To find out what data would work with our chosen topic, we first looked through available Web APIs: different maps and different location data sources.
Connecting Geographic Data
In order to search for parks within a specific area, the API requires four different latitude & longitude points.
I found a JSON file from CountryStateCity that contained the latitude & longitude of (seemingly all) cities in the United States, which I downloaded and then extracted all the California places over into a separate JSON file. We decided that users could type in the city they wish to find parks near, and then scan the area around it.
To find the search area around the city, I wrote a JavaScript query to parse through city names for an exact location, and from there use an equation to find all four corners of the search area. Our search area looks for all parks within about 15 miles north, south, east and west from the location queried.
Calculating Search Area Points
let placeElem = document.getElementById("placeName");
// placeholder city
var placeName = "Alamo";
// placeholder city data
var placeLat = 37.85020000;
var placeLon = -122.03218000;
// creating a new object with the necessary info for querying
var place = {
name: placeName,
nameUniversal: placeName.toUpperCase(),
lat:placeLat,
lon: placeLon,
id: "ca111093",
// equations for finding the new lat & long's
top: function(lat) {
return lat + 0.51;
},
left: function(lon) {
return lon - 0.51;
},
btm: function(lat) {
return lat - 0.51;
},
right: function(lon) {
return lon + 0.51;
}
};
Then, I had to create a function that would connect the search results to a city.
Plugging in the City Data*
async function searchCities() { // compare search input to cities data
try {
let newPlace = await getSearch();
if(errors.innerHTML !== "") {
errors.innerHTML = "";
};
if(newPlace == "") {
throw "Enter a place in California for new results";
};
if(newPlace == place.nameUniversal) {
throw `“${newPlace}” results are already displayed below`;};
let exists = false;
// for loop to scan through cities
for (let i = 0; i < caCitiesData.length; i++) {
// labeling for clarity: as if wrote "forEach((caCity) =>)"
let caCity = caCitiesData[i];
// specifying the city data object
let cityData = caCity.city;
// if search name matches the city name
if(newPlace == cityData.nameUniversal) {
exists = true;
// then replace old map place data with new place's data
place.name = cityData.name;
place.nameUniversal = cityData.nameUniversal;
place.lat = Number(cityData.lat);
place.lon = Number(cityData.lon);
place.id = cityData.id;
return place;
};
};
if (exists == false) {
throw `“${newPlace}” is not in the database`;
};
} catch(err) {
errors.innerHTML = `Search Error: ${err}`;
};
};
Plotting the Results
Next came the hardest bit of code: iterating through the results to plot each of the dog parks on our map.
I went through step-by-step to make sure each new layer worked before I put it together into one function.
Creating plot points on the map*
async function filterParks() {
try {
// get park data from getParks f(x)
let fullList = await getParks();
// clear existing content
list.innerHTML = "";
// iterate through parks
fullList.forEach((park) => {
// filter to parks within limit range
if(park.position.lon < place.right(place.lon)
&& park.position.lon > place.left(place.lon)) {
if(park.position.lat > place.btm(place.lat)
&& park.position.lat < place.top(place.lat)) {
// create a Park object for each park
var parkContent = new Park(
park.id,
park.position.lat,
park.position.lon,
park.poi.name,
park.address.freeformAddress
);
// PLOT POINT for park
var parkMarker = L.marker(
[park.position.lat,
park.position.lon],
{icon: mapIcon, title: park.poi.name, alt: "Marker"}).addTo(parksLayer)
// create pop-up with basic info
.bindPopup(
`${park.poi.name}`,
{maxWidth: 175})
;);
// add id for plot point
parkMarker.getElement().id = `m${park.id}`;
// change marker color
parkMarker.getElement().style.filter = "hue-rotate(160deg)"
};
};
});
} catch(err) {
console.log("Parks Filter Error:", err)
};
};
* For clarity, I have removed all HTML styling for the template literals from each extracted portion of code
Finished Web Application
After the class, I went back and almost entirely redesigned the layout to show myself what I could now do. I added lots of smoothed transitions with JavaScript that I couldn't have done before, and I made a full Web Application that I could feel proud of.