Ohio Ballot Drop Box Locator

Spurred on by Mapbox Election Mapping Challenge

Image for post
Image for post
Drive-through drop box in Hamilton County, Ohio. Image: Cincinnati Enquirer.

Around Halloween 2020, there was a growing sentiment around the US that it was too late to put mail-in ballots in your mailbox, and rather, the safest bet was to deliver them directly. Fortunately in Ohio, ballots postmarked by Election Day would still be counted even by November 13th. Still, the guarantee of a hand-delivered ballot is a valuable feeling, and every person in Ohio had the option to deliver theirs to their board of election site.

Ohio voters could find where to drop off their ballots on each Ohio county’s board of election website, usually an easy Google search away. Some sites even have pictures and helpful directions! However, each site is pretty different, and sometimes a voter is left with just an address. They may wonder how far a drive the drop box is, or what does the drop box look like when they reach the address. Providing these answers in a consolidated and consistent format can save a voter a couple minutes of searches and perhaps give them confidence because they’ve seen the area ahead of time. Answering voter questions about drop boxes with maps and additional context is right up the alley of a web app built with Mapbox GL JS.

The Project

https://bennkeel.github.io/OhioElections/index.html#

My Ohio Ballot Drop box Locator displays a data set of each Board of Elections location (source) through a Mapbox-styled and GL JS-coded interactive. If you’re familiar with Mapbox’s tutorials, you’ll recognize the basis for this code came from their Store Locator example. As such, the left side has listings for each county Board of Elections (BoE), links, and details, while the right side contains the map and BoE location markers.

Image for post
Image for post
Base Screen

Clicking on a listing or marker does a couple things: the map zooms closer to the marker, a pop-up appears over the marker to display the address and a link to directions (provided by the SoS site), and in most cases the listing expands to reveal a picture of the drop box if it’s available.

Image for post
Image for post
Zooming in on the drop box for Hamilton County, Ohio

The Data

The data was compiled in a spreadsheet manually. I used a Beautiful Soup python function in a Jupyter notebook to get the BoE links and navigation directions off the SoS’s site quickly. Getting the lat-long items and the addresses was a manual copy-paste operation, to my spreadsheet chagrin. The drop box images were the hardest to find, as they are either on a Board of Elections’ site, Facebook page, or photographed for a local newspaper — all over the place. Once that was done, the Mapbox studio dataset editor made it very easy to convert to a geojson. Find that geojson here.

Image for post
Image for post
View of the data and fields in Mapbox Studio

The Process

Though I’m a professional designer, I am still very much a student of web apps. Using that store locator as a base, here were a number of elements that weren’t in the tutorial that I worked to include:

First was learning how to extract a geojson from an online site using an HTTPRequest function. I’m just extracting from the same link I’ve provided above. The store locator code needed to be nested within this HTTPRequest because the markers and listings need data to be created, and won’t function if it isn’t called already.

var boxesconst url = “https://bennkeel.github.io/OhioElections/BoE-Locations-OH.geojson";const updateUISuccess = function(data) {             
const parsedData = JSON.parse(data);
console.log(parsedData);boxes = parsedDataboxes.features.forEach(function(box, i){box.properties.id = i;});/*Rest of Store Locator code here*/}
const updateUIError = function(error) {console.log(error);};
const responseMethod = function(httpRequest) {if (httpRequest.readyState === 4) {if (httpRequest.status === 200) {updateUISuccess(httpRequest.responseText);} else {updateUIError(httpRequest.status + ': ' + httpRequest.responseText);
}}};
const createRequest = function(url){const httpRequest = new XMLHttpRequest(url);httpRequest.addEventListener('readystatechange', (url) => responseMethod(httpRequest));httpRequest.open('GET', url);httpRequest.send();};createRequest(url);

Next was changing the listing the entries alphabetically by county, which I do in the code here:

data.features.sort( function( a, b ) {a = a.properties.county;b = b.properties.county;return a < b ? -1 : a > b ? 1 : 0;});

Third, I changed many of the .setHTML and other lines to use template literals to simplify the code. This doesn’t work with some older browsers unfortunately, but for the quickness of this exercise, the simpler formatting helped me understand what I was writing and changing.

The final addition was adding drop box images under the listings when either the marker or listing is clicked. I built a separate function to add to the Event Listeners inside the listing and marker-building functions. This code also includes an additional if statement to display a disclaimer if I couldn’t confirm a drop box location available outside the BoE 24/7.

Image for post
Image for post
Disclaimer (left) under the listing notes that a voter should be prepared to visit during the office hours of the Board of Election and before the Election Day deadline. Most probably do and just didn’t note it as such online, and a call to the BoE could have clarified this question for me.
function addDropbox(element, confirm, img, source){var dropboxImage = document.getElementById(“db”);var dropboxSource = document.getElementById(“dbSource”);var NoImage = document.getElementById(“imgna”);if (dropboxImage){dropboxImage.remove();}if (dropboxSource){dropboxSource.remove();}if (NoImage){NoImage.remove();}if (img) {element.appendChild(img_create(img, “Dropbox Location Image”, “Dropbox”, “db”));if (source) {var s = document.createElement(‘a’);s.href = `${source}`;s.id = “dbSource”;s.innerHTML = “Image Source”;s.target = “blank”;element.appendChild(s);}} else {var d = document.createElement(‘div’);d.id = “imgna”;d.innerHTML = “Image Not Available”;element.appendChild(d);}if (confirm == 0){var c = document.getElementById(‘Confirm’);if (c){c.remove();}c = document.createElement(‘div’);c.id = ‘Confirm’;c.innerHTML = “Could not confirm if a 24-hour dropbox is available. Please be prepared to deliver ballot to Board of Election office during open hours (see link) or by 7:30pm on November 3rd.”;element.appendChild(c);} else {var c = document.getElementById(‘Confirm’);if ©{c.remove();}c = document.createElement(‘div’);c.id = ‘Confirm’;c.innerHTML = “You can drop your absentee ballot off at a drop box at the Board of Elections.”;element.appendChild(c);}}

Note: This solution of “naming a div or img as a specific ID and removing it by calling that ID later when another entry is clicked” works but doesn’t seem elegant, so if you have suggestions, I’m open to feedback.

The Future

The eventual aim was to make an easy database in case more drop boxes were added through the last month, but the Ohio Secretary of State did not permit more drop boxes off of BoE sites. Features I’d love to add in similar projects are an automatic county locator button, in-app directions, and perhaps a drive time estimate. I’m looking forward to learning more about Mapbox GL JS with future projects.

Graphic Communication Designer in DC/OH

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store