Recipe for an interactive map

Ingredients

Google skills
Server access
Smart friends
Ambitious colleagues
A firm deadline
The will to succeed

About the chef

I have this habit of saying “Of course!” and “No problem!” whenever I’m asked if I can do something.

“Can you be there at 7 a.m.?”
“Of course!”

“Can you bake 300 cookies by Wednesday?”
“No problem!”

This agreeability follows me everywhere, even to work.

“Can you have that to me by noon?”
“Of course!”

“Can you make this interactive?”
“No problem!”

This willingness to comply is something I learned young, when my father was preparing me, then a 10-year-old, for the world of business, job interviews and deadlines.

“Just say you can do it, and learn how later,” he would say.

That might sound like lying to some, but to me it sounded like ambition.

So when my colleague Bill Heltzel asked me if I could create a map that would plot 122 points with a variable radius zone around each point, then calculate the population that lay within that radius zone, I said: “Of course! No problem!”

The map was to allow people who read our story, 1.5 million Pennsylvanians live close to large amounts of hazardous ammonia, to see exactly where they are in relation to the chemical.

I would be lying if I said that no small amount of panic entered my mind once I realized the difficulty of this task.

I had created maps before, sure, but the whole radius zone-to-population problem was something I had never tackled. And after 15 minutes of googling, I realized that I would have to venture into depths unknown to get this map completed. And the clock was ticking.

Recipe

Until recently, we had been using ArcGIS (a mapping software program) to both analyze and display our geographical data. ArcGIS has several services, including ArcGIS Desktop, which is a desktop application that is great at geocoding locations, interpreting and displaying shapefile information, joining geostatistical data sets and so much more.

Another of their services is ArcGIS Online, which takes map files and displays them online in an interactive, shareable manner.

What's an API?

An application programming interface, or API, is a way of connecting with and utilizing an applications code base and resources in order to manipulate and display information that is normally accessible only through a graphical user interface (GUI, pronounced gooey).

It's kind of like using a quote from a well known author in your research paper. You might not have the knowledge necessary to make an argument, but by using someone else's knowledge base as a reference, you can build your own case.

While ArcGIS Desktop is amazingly robust, its online counterpart, ArcGIS Online, has its share of problems.

The number of points you can plot on a single map is limited, and settings are complicated to configure if they are configurable at all.  

Once I realized that what I needed to do was not going to be possible using the ArcGIS Online interface with which I was familiar, I turned to plan B, my dear friend and resource that almost never lets me down: Google.

Here’s what I discovered:

  1.  I needed to use an application programming interface (API) to produce the effect I wanted.
  2.  ArcGIS Online has an API, but the documentation on how to use it is either lacking or too difficult to find based on my deadline.
  3.  Google Maps also has an API.
  4.  The documentation on using the Google Maps API is vast and encompassed almost the exact problem I needed to solve.
  5.  I still needed to use ArcGIS to analyze the data.

Armed with that insight, I used ArcGIS Desktop to plot the points for which I needed the radiuszone-to-population statistics. (We already had population estimates for most of the points, but two points — Airgas Specialty Products in Palmerton, Pa.,  and Sysco Philadelphia — did not have population statistics for various reasons).

What's a census tract?

A census tract is a geographic area created by the Census Bureau to make the job of collecting information about populations easier. Multiple census tracts usually exist within a county.

Then, I brought in a Census Bureau tract shapefile. Using an online guide, I was able to create a radius zone around each point, determine what percentage of each census tract fell within that radius zone and divide the total population of each census tract by those percentages to determine how many people live inside the zone. This is an example point on my static ArcGIS map.

Seemingly, my job was done. I had plotted points and created radius zones around them. I had even extracted the populations of the radius zones for the points that were missing data.

But I still was facing a major problem: Users couldn’t zoom in and out on the map. It was static. Just an image. Users would be able to enlarge the image and maybe get a better idea of where they and their family members lived in relation to each site, but they wouldn’t be able to see themselves in the danger zone, wouldn’t be able to feel the closeness of these sites to their homes, their schools, their churches.

ammonia map process screenshot
This is an example point on my static ArcGIS map.

Enter Google Maps API and a wonderful tutorial by Yoh Kawano.

Armed with a spreadsheet of the 122 sites in Pennsylvania that store more than 5 tons of ammonia at any given time, I created an array. An array is a list that allows for each list item to have multiple properties. For example, our sites array looked something like this:

locations = {
[40.208333,-76.083333,2253.08,"Acme Distribution Center",2253.076],
[40.098611,-76.089167,1931.21,"AFP Advanced Food Products",1931.208],
[40.184878,-79.853822,8046.7,"Airgas Specialty Products Inc.",8046.7],
……
}

Each site’s properties are enclosed in brackets and separated with a comma.

After creating my array, I created a function to go through the array and pull out each property when I needed it. The function would pull out the latitude and longitude to create the point, and the radius to create the radius zone. Then, it would pull the rest of the properties and add them to a box that would pop up when the point was clicked.

I ran into some snags, but with the help of Google, smart friends and the browser console, I was able to sort them all out and voilà: A lovely map that plots 122 points with a variable radius zone around each point.

To top the whole thing off, I added some HTML explainer text above the map and an address locator bar so the reader can type in his or her home address — or any address, for that matter — and see if they fall within a hazard zone.

And I realized that without online sources and people who share their own mistakes and successes, I would accomplish very little.

And the best thing was, I met my deadline.

---------

Here is the code I used to produce the map. I have included annotation so that the logic behind each process is explained.

<!DOCTYPE html>  <!-- Reference: http://stackoverflow.com/questions/3059044/google-maps-js-api-v3-simple-multiple-marker-example-->  <html>   <head>     <meta name="viewport" content="initial-scale=1.0, user-scalable=no">    <meta charset="utf-8">        <!--A little bit of CSS to make things look right. This can also be placed in its own stylesheet and linked to here.-->    <style type="text/css">      html { height: 100% }      body { height: 100%; margin: 0px; padding: 0px }      #map { height: 100%;}      #sidebar-overlay { position:absolute; width:100%; top:55px; left:0; background: #f7f8f8; font-family: helvetica, arial, sans-serif; color:#000000; padding:0px; margin:0; font-size: .875em; border-bottom:1px solid #cccccc;}      #sidebar-overlay .block{ width:28%; padding:10px 0 10px 20px; display:inline-block; vertical-align: top; }      #sidebar-overlay h1{ font-size:2em; font-weight: 100;}      #sidebar-overlay h3{ margin-bottom:0;}      #sidebar-overlay p{ font-family: Georgia, "Times New Roman", serif; line-height: 1.5em; margin-top:10px; margin-bottom:20px;}      #sidebar-overlay p a {color:#489ec1; text-decoration: none;}      #sidebar-overlay p a:hover{ color:#489ec1; text-decoration: underline;}      #sidebar-overlay .notes p{ font-size: .875em; font-style: italic;}      .controls {          margin-top: 16px;          border: 1px solid transparent;          border-radius: 2px 0 0 2px;          box-sizing: border-box;          -moz-box-sizing: border-box;          height: 32px;          outline: none;          box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);        }          #pac-input {          background-color: #fff;          padding: 0 11px 0 13px;          width: 400px;          font-family: Roboto;          font-size: 15px;          font-weight: 300;          text-overflow: ellipsis;        }          #pac-input:focus {          border-color: #4d90fe;          margin-left: -1px;          padding-left: 14px;  /* Regular padding-left + 1. */          width: 401px;        }          .pac-container {          font-family: Roboto;        }          #type-selector {          color: #fff;          background-color: #4d90fe;          padding: 5px 11px 0px 11px;        }          #type-selector label {          font-family: Roboto;          font-size: 13px;          font-weight: 300;        }                #target {          width: 345px;}  	</style>    <title>PublicSource:Sites in PA that have at least five tons of ammonia</title>         <!--Pull in the Google Maps API and load the Places library which will allow users to search for buildings, businesses, companies, etc in the map.-->      <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places"></script>          <script type="text/javascript">          //Now we create our array of sites. Each site includes latitude, longitude, site name, site address, site county, business type, radius zone in meters (required for google maps processing), radius zone in miles, population effected      var locations = {};      locations = [        [40.208333,-76.083333,2253.08,"Acme Distribution Center","500 South Muddy Creek Rd.","Denver","Lancaster ","Warehousing","10,700",1.4,"2,554"],  			[40.098611,-76.089167,1931.21,"AFP Advanced Food Products","158 West Jackson St.","New Holland","Lancaster ","Food & Beverage","3,750",1.2,"1,830"],  			[40.184878,-79.853822,8046.7,"Airgas Specialty Products Inc.","611 Scott St.","Donora","Washington ","Wholesale trade","205,000",5,"57,000"],  			[40.808866,-75.5854,8046.7,"Airgas Specialty Products Inc.","900 Delaware Ave","Palmerton","Carbon ","Wholesale trade","*",5,"30000*","PublicSource was unable to obtain the worst case scenario quanitity released and population data for this location. The population was estimated based on 2010 census data."],  			[40.413547,-78.135338,5149.89,"Albemarle Corp.","2858 Back  Vail Rd.","Tyrone","Blair ","Chemical manufacturing, Agriculture","77,262",3.2,"8,077"],  			  			[40.554067,-75.399883,1448.41,"ALDI Inc.","2700 Saucon Valley Rd.","Center Valley","Lehigh ","Warehousing","11,000",0.9,654],  			[40.345466,-76.4644,2092.14,"Always Bagels","3010 Hanford Dr.","Lebanon","Lebanon ","Food & Beverage","16,000",1.3,"5,854"],  			[41.262222,-75.501984,4184.28,"Americold","91 First Ave.","Covington Township","Lackawanna ","Warehousing","20,000",2.6,840],  			[40.591451,-75.620282,1931.21,"Americold","7150 Ambassador Dr.","Fogelsville","Lehigh ","Warehousing","8,800",1.2,"2,252"],  			[40.588792,-75.613646,1931.21,"Americold","651 Mill Rd.","Fogelsville","Lehigh ","Warehousing","8,800",1.2,"2,252"],  			  			[40.291389,-75.300556,3057.75,"Americold","2525 Bergey Rd.","Hatfield","Montgomery ","Warehousing","23,000",1.9,"21,193"],  			[40.443274,-75.958984,2414.01,"Americold","412 Orchard Lane","Leesport","Berks ","Warehousing","11,000",1.5,"2,586"],  			[40.066473,-75.557905,1609.34,"Americold","8 Lee Blvd.","Malvern","Chester ","Warehousing","7,050",1,808],  			[40.037823,-76.721618,2735.88,"Americold","60 Steamboat Blvd.","Manchester","York ","Warehousing","21,000",1.7,"3,944"],  			[40.042676,-76.418601,2414.01,"Americold","3800 Hempland Rd.","Mountville","Lancaster ","Warehousing","12,803",1.5,"2,371"],  			  			[40.042222,-76.740278,1287.47,"Americold","380 Willow Springs Lane","York","York ","Warehousing","4,349",0.8,326],  			[39.845269,-75.424934,1287.47,"Arctic Glacier Inc.","410 Bethel Ave.","Twin Oaks","Delaware ","Food & Beverage","3,800",0.8,"3,327"],  			[40.927083,-76.063972,1931.21,"Aryzta LLC","2 Chestnut Hill Dr.","Hazleton","Luzerne ","Food & Beverage","8,500",1.2,76],  			[40.99,-76.46056,1931.21,"Bernardi Italian Foods","595 West 11th St.","Bloomsburg","Columbia ","Food & Beverage","9,000",1.2,"8,426"],  			[40.619167,-75.313333,4184.28,"Bethlehem Energy Center","2254 Applebutter Rd.","Bethlehem","Northampton ","Utility","52,500",2.6,"25,019"],  			  			[42.211111,-79.829167,1303.57,"Better Baked Foods Inc.","56 Smedley St.","North East","Erie ","Food & Beverage","2,703",0.8,"5,235"],  			[42.012056,-80.020556,3218.68,"Better Baked Foods LLC","2200 East 38th St.","Erie","Erie ","Food & Beverage","27,084",2,"38,465"],  			[41.02828,-78.42462,5471.76,"Bionol Clearfield LLC","250 Technology Dr.","Clearfield","Clearfield ","Chemical manufacturing","86,900",3.4,"13,000"],  			[40.068058,-76.765327,2735.88,"C&S Wholesale Grocers Inc.","4875 Susquehanna Trail","York","York ","Warehousing","17,000",1.7,"2,263"],  			[40.9131,-76.1017,1931.21,"Cargill Meat Solutions","65 Green Mountain Rd.","Hazleton","Schuylkill ","Food & Beverage","17,000",1.2,185],  			  			[41.683889,-76.240833,3057.75,"Cargill Meat Solutions","1252 Route 706","Wyalusing","Bradford ","Food & Beverage","38,300",1.9,943],  			[40.440278,-75.424444,965.6,"CFC Logistics LLC","4000 AM Dr.","Quakertown","Bucks ","Warehousing","8,100",0.6,600],  			[39.9125,-77.656667,1287.47,"Chambersburg Cold Storage","1480 Nitterhouse Dr.","Chambersburg","Franklin ","Warehousing","8,143",0.8,93],  			[40.32037,-79.3901,1770.27,"City Brewing Co. LLC","100 33rd St.","Latrobe","Westmoreland ","Food & Beverage","8,894",1.1,"8,309"],  			[40.549956,-78.798623,6437.36,"Colver Power Project","141 Interpower Dr.","Colver","Cambria ","Utility","51,200",4,"3,296"],  			  			[41.289167,-80.485278,2735.88,"Dean Dairy Products Co. ","1858 Oneida Lane","Sharpsville","Mercer ","Food & Beverage","18,648",1.7,"1,901"],  			[40.01667,-75.05,1448.41,"Dietz & Watson","5701 Tacony St.","Philadelphia","Philadelphia ","Food & Beverage","6,500",0.9,"22,767"],  			[40.403889,-79.614722,3701.48,"Dormont Manufacturing Co.","6015 Enterprise Dr.","Export","Westmoreland ","Metal manufacturing","42,000",2.3,"6,000"],  			[40.847744,-76.801651,965.6,"Dutch Valley Food Co.","1000 S. Second St.","Sunbury","Northumberland ","Food & Beverage","2,000",0.6,462],  			[40.188611,-79.856389,9816.97,"Dyno Nobel Inc.","1320 Galiffa Dr.","Donora","Washington ","Chemical manufacturing","284,988",6.1,"67,927"],  			  			[40.470556,-75.766667,11104.45,"East Penn Manufacturing Co. Inc.","Deka Rd.","Lyon Station","Berks ","Metal manufacturing","130,000",6.9,"36,700"],  			[40.265833,-79.901111,2253.08,"Eastman Chemical Co.","State Highway 837","Jefferson Borough","Allegheny ","Chemical manufacturing","45,000",1.4,"2,700"],  			[41.889444,-77.808611,3218.68,"Edko Farms","911 Pushersiding Rd.","Ulysses","Potter ","Agriculture","16,000",2,0],  			[41.8425,-79.271944,4184.28,"Ellwood National Crankshaft Co.","One Front St.","Irvine","Warren ","Metal manufacturing","83,754",2.6,"2,136"],  			[40.5102,-79.1929,8046.7,"EME Homer City Generation L.P.","1750 Power Plant Rd.","Homer City","Indiana ","Utility","221,000",5,"9,700"],  			  			[40.559167,-77.397778,1287.47,"Empire Kosher Poultry Inc.","RR 5","Mifflintown","Juniata ","Food & Beverage","3,500",0.8,"1,095"],  			[40.445014,-76.43442,2414.01,"Farmer's Pride Inc.","154 West Main St.","Fredericksburg","Lebanon ","Food & Beverage","14,000",1.5,"3,500"],  			[39.766139,-77.738361,0,"Food Lion","16 Commerce Ave","Greencastle","Franklin ","Warehousing","*","*","*","PublicSource was unable to obtain information about this location. It's radius, population affected and worst case scenario quanitity relased are not available at this time."],  			[40.200556,-77.231944,1448.41,"Giant Distribution Center","1621 Industrial Dr.","Carlisle","Cumberland ","Warehousing","8,968",0.9,813],  			[40.679806,-80.153222,965.6,"Giant Eagle","2500 Lovi Rd.","Freedom","Beaver ","Warehousing","6,200",0.6,463],  			  			[40.445366,-75.898766,933.42,"Giorgio Fresh Co.","347 June Ave","Blandon","Berks ","Agriculture","14,000",0.6,"1,152"],  			[41.786389,-76.445278,7081.1,"Global Tungsten and Powders","1 Hawes St.","Towanda","Bradford ","Chemical manufacturing","160,000",4.4,"5,000"],  			[40.944217,-76.052902,885.14,"Gonnella Frozen Products","301 Parkview Rd.","Hazle Township","Luzerne ","Food & Beverage","5,000",0.6,0],  			[40.713333,-80.117778,3057.75,"Great Lakes Cold Storage","263 West Kensinger Dr.","Cranberry Township","Butler ","Warehousing","25,000",1.9,"13,297"],  			[39.977778,-75.587778,2414.01,"Hain Celestial Group","700 Old Fern Hill Rd.","West Chester","Chester ","Food & Beverage","30,000",1.5,"39,000"],  			  			[40.843576,-77.639182,4023.35,"Hanover Foods Corp.","3008 Penns Valley Pike","Centre Hall","Centre ","Food & Beverage","42,200",2.5,500],  			[40.2675,-75.321667,2414.01,"Hatfield Quality Meats Inc.","2700 Clemens Rd.","Hatfield","Montgomery ","Food & Beverage","14,000",1.5,"13,000"],  			[40.124139,-76.648444,3218.68,"Heisey Farm Service Co.","4305 Bossler Rd.","Bainbridge","Lancaster ","Agriculture","16,000",2,500],  			[40.260556,-76.871972,2414.01,"Hershey Creamery Co.","301 South Cameron St.","Harrisburg","Dauphin ","Food & Beverage","15,000",1.5,"58,000"],  			[40.231944,-76.740278,3057.75,"Hershey Creamery Co.","1200 AIP Dr.","Middletown","Dauphin ","Food & Beverage","11,000",1.9,"7,600"],  			  			[39.917683,-75.134609,1931.21,"Horizon Stevedoring Inc","2201 S. Columbus Blvd.","Philadelphia","Philadelphia ","Warehousing","8,600",1.2,"20,094"],  			[41.860556,-78.445,2253.08,"International Waxes Inc.","45 Route 446","Smethport","McKean ","Petroleum and coal products","6,018",1.4,223],  			[40.294444,-75.341667,2414.01,"JBS - Souderton Beef Processing","249 Allentown Rd.","Souderton","Montgomery ","Food & Beverage","22,800",1.5,"7,150"],  			[40.614262,-79.906685,2414.01,"Keane Refrigerated Logistics LLC","24 Frontier Dr.","Gibsonia","Allegheny ","Warehousing","10,500",1.5,"4,000"],  			[39.848056,-77.349167,1931.21,"Knouse Foods","1505 Orrtanna Rd.","Orrtanna","Adams ","Food & Beverage","15,911",1.2,868],  			  			[40.019417,-77.232722,1609.34,"Knouse Foods","800 Peach Glen - Idaville Rd.","Peach Glen","Adams ","Food & Beverage","12,000",1,356],  			[40.573611,-75.605556,1673.71,"Kraft Foods Global Inc.","7352 Industrial Blvd.","Allentown","Lehigh ","Food & Beverage","18,542",1,"1,406"],  			[40.312417,-76.888972,1287.47,"KTR Capital Partners","3900 Industrial Rd.","Harrisburg","Dauphin ","Warehousing","7,305",0.8,"2,633"],  			[40.033481,-76.317459,1126.54,"Kunzler & Co. Inc.","652 Manor St.","Lancaster","Lancaster ","Food & Beverage","3,500",0.7,"20,771"],  			[40.348056,-76.381389,2896.81,"Lebanon Chemical Corp.","1600 E. Cumberland St.","Lebanon","Lebanon ","Chemical manufacturing","160,000",1.8,"9,610"],  			  			[40.382987,-79.449021,2623.22,"Lone Maple Agricultural Services","259 Lone Maple Dr.","New Alexandria","Westmoreland ","Chemical manufacturing","78,000",1.6,250],  			[40.241804,-79.36199,2735.88,"Metalor Technologies Americas Corp.","1003 Corporate Lane","Export","Westmoreland ","Metal manufacturing","21,000",1.7,"4,000"],  			[41.361667,-75.706667,2896.81,"MIA Products","Rocky Glen Industrial Park","Moosic","Lackawanna ","Food & Beverage","22,000",1.8,"3,500"],  			[40.569779,-75.601511,5471.76,"Millard Refrigerated Services","7132 Ruppsville Rd.","Allentown","Lehigh ","Warehousing","34,810",3.4,"30,710"],  			[41.069722,-76.665833,14323.13,"Montour Steam Electric Station","18 McMichael Rd.","Washingtonville","Montour ","Utility","272,320",8.9,"27,819"],  			  			[39.978583,-77.229667,1931.21,"Mott's LLP","45 Aspers-North Rd.","Aspers","Adams ","Food & Beverage","10,000",1.2,"1,395"],  			[40.820806,-76.194306,1448.41,"Mrs. T's Pierogies","600 E Center St.","Shenandoah","Schuylkill ","Food & Beverage","5,400",0.9,"6,094"],  			[40.340834,-76.436971,1448.41,"Murry's Inc.","1501 Willow St.","Lebanon","Lebanon ","Food & Beverage","7,500",0.9,"14,308"],  			[41.207292,-75.923226,3701.48,"Nardone Bros. Baking Co.","420 New Commerce Blvd","Hanover Twp","Luzerne ","Food & Beverage","1,659",2.3,"23,754"],  			[40.830111,-76.838389,1770.27,"National Beef Packing Co. LLC","1811 N. Old Trail","Selinsgrove","Snyder ","Food & Beverage","8,300",1.1,"2,100"],  			  			[40.092611,-75.013333,2735.88,"NEP Cold Storage","2701 Red Lion Rd.","Philadelphia","Philadelphia ","Warehousing","22,000",1.7,"41,875"],  			[39.858889,-77.056667,1448.41,"New Oxford Foods LLC","304 South Water St.","New Oxford","Adams ","Food & Beverage","10,500",0.9,"3,900"],  			[40.468889,-80.087222,2092.14,"OK Grocery Perishables Warehouse","735 Beechnut St.","Pittsburgh","Allegheny ","Warehousing","11,267",1.3,"16,008"],  			[40.4226,-75.9349,6437.36,"Ontelaunee Energy Center","5115 Pottsville Pike","Reading","Berks ","Utility","52,530",4,"40,000"],  			[40.663023,-75.604584,1287.47,"Orefield Cold Storage","3824 Route 309","Orefield","Lehigh ","Warehousing","4,082",0.8,"1,067"],  			  			[40.855556,-75.877222,4345.22,"Panther Creek Energy Facility","4 Dennison Rd.","Nesquehoning","Carbon ","Utility","100,000",2.7,"4,800"],  			[40.660278,-76.696667,0,"Papetti's Hygrade Egg Products Inc.","68 Spain Rd.","Klingerstown","Schuylkill ","Food & Beverage","*","*","*","PublicSource was unable to obtain information about this location. It's radius, population affected and worst case scenario quanitity relased are not available at this time."],  			[40.003611,-75.685833,1287.47,"Pepperidge Farm Inc.","421 Boot Rd.","Downingtown","Chester ","Food & Beverage","13,000",0.8,"3,100"],  			[41.123056,-78.736667,2574.94,"Riverside BiLo Perishables Distribution Center","851 Beaver Rd.","Dubois","Clearfield ","Wholesale trade","18,000",1.6,"6,350"],  			[41.307222,-75.771944,2735.88,"RLS Logistics","1075 Oak St.","Pittston","Luzerne ","Warehousing","15,000",1.7,"1,200"],  			  			[40.938611,-76.031944,1287.47,"Romark Logistics","100 Route 924 Cando Expressway","Hazleton","Luzerne ","Warehousing","4,000",0.8,76],  			[40.736111,-76.304167,2414.01,"Ryder / Hillshire Brands North East Mixing Center","110 Keystone Blvd East","Pottsville","Schuylkill ","Warehousing","12,000",1.5,2],  			[40.679126,-75.363894,1931.21,"Schenker Logistics","4000 Miller Circle N","Bethlehem","Lehigh ","Warehousing","12,000",1.2,"1,451"],  			[40.045914,-77.510233,2735.88,"SFI - Shippensburg Plant","208 Dykeman Rd.","Shippensburg","Cumberland ","Warehousing, Food & Beverage","17,500",1.7,"12,000"],  			[41.066667,-78.366667,4184.28,"Shawville Station","Route 970","Shawville","Clearfield ","Utility","46,582",2.6,788],  			  			[40.277222,-78.466111,2735.88,"Sheetz Inc.","242 Sheetz Way","Claysburg","Blair ","Warehousing, Food & Beverage","8,500",1.7,"1,974"],  			[40.210163,-79.613084,2574.94,"Supervalu","400 Paintersville Rd.","New Stanton","Westmoreland ","Wholesale trade, Warehousing","14,695",1.6,"2,861"],  			[40.36406,-75.922333,1931.21,"Sweet St. Desserts","722 Hiesters Lane","Reading","Berks ","Food & Beverage","10,400",1.2,"23,457"],  			[40.331389,-76.459722,1931.21,"Swiss Premium","2401 Walnut St.","Lebanon","Lebanon ","Food & Beverage","9,000",1.2,"7,538"],  			[40.271694,-76.822917,1931.21,"Sysco Central Pennsylvania LLC.","3905 Corey Rd.","Harrisburg","Dauphin ","Wholesale trade","9,158",1.2,"14,168"],  			  			[39.907,-75.159417,1931.21,"Sysco Philadelphia LLC","600 Packer Ave.","Philadelphia","Philadelphia ","Wholesale trade","20,672",1.2,"48,000*","PublicSource was unable to obtain the population data for this location. The population was estimated based on 2010 census data."],  			[40.800056,-80.12025,2092.14,"Sysco Pittsburgh","One Whitney Dr.","Harmony","Butler ","Wholesale trade","8,236",1.3,"4,049"],  			[40.973306,-80.367,5954.56,"Tanner Industries Inc.","501 Industrial St.","New Castle","Lawrence ","Wholesale trade","160,000",3.7,"37,675"],  			[40.010278,-75.055556,5954.56,"Tanner Industries Inc.","5811 Tacony St.","Philadelphia","Philadelphia ","Wholesale trade","133,000",3.7,"350,733"],  			[40.807778,-75.9425,5954.56,"Tanner Industries Inc.","Rt 209 & Lehigh Coal Navigation Rd.","Tamaqua","Schuylkill ","Wholesale trade","160,000",3.7,"15,890"],  			  			[39.79212,-75.969973,2414.01,"Tasty Baking Oxford Inc.","700 Lincoln St.","Oxford","Chester ","Food & Beverage","15,000",1.5,"5,618"],  			[40.278333,-76.675833,1931.21,"The Hershey Co.","1033 Old West Chocolate Ave.","Hershey","Dauphin ","Food & Beverage","10,000",1.2,"6,285"],  			[39.961111,-76.446917,4988.95,"Turkey Hill Dairy","2601 River Rd.","Conestoga","Lancaster ","Food & Beverage","30,405",3.1,"3,785"],  			[40.230944,-75.299667,2414.01,"Tuscan / Lehigh Dairies Inc.","880 Allentown Rd.","Lansdale","Montgomery ","Food & Beverage","13,500",1.5,"24,496"],  			[40.094444,-76.085556,4184.28,"Tyson Foods Inc.","403 South Custer Ave.","New Holland","Lancaster ","Food & Beverage","51,761",2.6,"11,111"],  			  			[39.890556,-79.730278,1448.41,"United Dairy, Fike's Division","47 West Craig St.","Uniontown","Fayette ","Food & Beverage","6,725",0.9,"9,386"],  			[40.193056,-76.721111,321.87,"Univar USA Inc.","532 East Emaus St.","Middletown PA","Dauphin ","Wholesale trade",150,0.2,176],  			[40.634389,-75.4325,1448.41,"US Food Service Inc.","1200 Hover Ave.","Allentown","Lehigh ","Warehousing","5,200",0.9,"1,800"],  			[40.294722,-79.874444,9656.04,"US Steel Clairton Works","400 State St.","Clairton","Allegheny ","Metal manufacturing","150,000",6,"70,500"],  			[40.262435,-76.769592,160.93,"Verdelli Farms","7505 Grayson Rd.","Harrisburg","Dauphin ","Food & Beverage","13,000",0.1,0],  			  			[40.983333,-75.15,4184.28,"Vertellus Health & Specialty Products LLC","Route 611","Delaware Water Gap","Monroe ","Chemical manufacturing","51,852",2.6,"16,792"],  			[40.094444,-78.522778,2414.01,"Wal-Mart Distribution Center","181 Wal-Mart Rd.","Bedford","Bedford ","Warehousing","10,515",1.5,680],  			[40.731667,-76.322222,3701.48,"Wal-Mart Distribution Center","390 Highridge Park Rd.","Pottsville","Schuylkill ","Warehousing","35,162",2.3,"2,680"],  			[39.906387,-75.453888,3057.75,"Wawa Dairy Warehouse & Distribution Center","1393 W. Baltimore Pike","Wawa","Delaware ","Food & Beverage","26,000",1.9,"13,789"],  			[41.107556,-77.484472,1899.02,"Webb's Super-Gro Products Inc.","30 Pennsylvania Ave.","Mill Hall","Clinton ","Nursery and garden center","160,000",1.2,"3,000"],  			  			[40.849167,-76.800556,965.6,"Weis Markets - Ice Cream","1000 S. Second St.","Sunbury","Northumberland ","Food & Beverage","7,000",0.6,954],  			[40.854167,-76.798056,1287.47,"Weis Markets - Meat","618 S. Second St.","Sunbury","Northumberland ","Warehousing","4,000",0.8,"4,537"],  			[40.984693,-76.851532,1367.94,"Weis Markets Distribution Center","16 S. Industrial Park Rd.","Milton","Northumberland ","Warehousing","12,905",0.9,426],  			[42.208333,-79.843333,4506.15,"Welch's","139 South Lake St.","North East","Erie ","Food & Beverage","24,000",2.8,"8,500"],  			[39.73916,-76.30777,4506.15,"York Energy Center","1055 Pikes Peak","Delta","York ","Utility","56,000",2.8,"4,475"],  			  			[40.699722,-76.175278,2092.14,"Yuengling Brewery","310 Mill Creek","Pottsville","Schuylkill ","Food & Beverage","12,000",1.3,"8,106"],  			[40.682833,-76.198222,1931.21,"Yuengling Brewery","Fifth and Mahantongo St.","Pottsville","Schuylkill ","Food & Beverage","10,000",1.2,"14,890"]      ];        // [START initialize function]  function initialize() {  	//[START create map]  	//create our map, call it map and set its proporties; https://developers.google.com/maps/documentation/javascript/controls    var map = new google.maps.Map(document.getElementById('map'), {      zoom: 7,      center: new google.maps.LatLng(41.889444,-77.808611),      mapTypeId: google.maps.MapTypeId.ROADMAP,       mapTypeControl: true,      mapTypeControlOptions: {          style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,          position: google.maps.ControlPosition.BOTTOM_CENTER      },      panControl: true,      panControlOptions: {          position: google.maps.ControlPosition.LEFT_CENTER      },      zoomControl: true,      zoomControlOptions: {          style: google.maps.ZoomControlStyle.LARGE,          position: google.maps.ControlPosition.LEFT_CENTER      },      scaleControl: false,      scaleControlOptions: {          position: google.maps.ControlPosition.TOP_LEFT      },      streetViewControl: false,      streetViewControlOptions: {          position: google.maps.ControlPosition.BOTTOM_CENTER      }    });    // [END create map]          	// [START infoWindows]    var infowindow = new google.maps.InfoWindow(); // establish the popup box variable        var marker, i; // establish the marker variable and set its value to i        for (i = 0; i < locations.length; i++) { // iterate throught the below code until i equals the number of items in our locations array                     // create a new marker for each location     // set that markers position using the latitude and longitude properties of each location     // put the markers on our already established map, named map     marker = new google.maps.Marker({        position: new google.maps.LatLng(locations[i][0], locations[i][1]),         map: map      });        		// the code below creates the popup box for each marker when it's clicked  		// use html and pull from our locations array to display more info about each location  		// this lovely piece of code courtesy http://stackoverflow.com/questions/3059044/google-maps-js-api-v3-simple-multiple-marker-example      google.maps.event.addListener(marker, 'click', (function(marker, i) {         return function() {          infowindow.setContent('<h2>' + locations[i][3] + '</h2><p>' + locations[i][4] + '<br>' + locations[i][5] + '<br>' + locations[i][6] + ' County</p><p><strong>Hazard zone (miles):</strong> ' + locations[i][9] + '</p><p><strong>Population affected:</strong> ' + locations[i][10] + '</p><p><strong>Industry:</strong> ' + locations[i][7] + '</p><p><strong>Max. possible pounds released:</strong> ' + locations[i][8] + '</p>');          infowindow.open(map, marker);        }      })(marker, i));    	}   	// [END infoWindows]             // [START add radius zone]   	var cityCircle, n; // create a variable for our radius zones, set its value to n   	for (n = 0; n < locations.length; n++) { // iterate through the code below until n is greater than the number of locations in our array          // create radius zones with properties established in the circleOptions variable below     // https://developers.google.com/maps/documentation/javascript/examples/circle-simple     cityCircle = new google.maps.Circle(circleOptions);               var circleOptions = {        strokeColor: '#FF0000',        strokeOpacity: 0.8,        strokeWeight: 2,        fillColor: '#FF0000',        fillOpacity: 0.35,        map: map,        center: new google.maps.LatLng(locations[n][0],	locations[n][1]),        radius: locations[n][2]      };     }     // [END add radius zone]              // [START region_getplaces]    // this is why we added the Places library to our API call script above    // the comments below are from https://developers.google.com/maps/documentation/javascript/examples/places-searchbox    var user_markers = [];	    var defaultBounds = new google.maps.LatLngBounds(        new google.maps.LatLng(42.316884, -80.516791),        new google.maps.LatLng(39.716924, -74.200025));    map.fitBounds(defaultBounds);      // Create the search box and link it to the UI element.    var input = /** @type {HTMLInputElement} */(        document.getElementById('pac-input'));    map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);      var searchBox = new google.maps.places.SearchBox(      /** @type {HTMLInputElement} */(input));          // Listen for the event fired when the user selects an item from the    // pick list. Retrieve the matching places for that item.    google.maps.event.addListener(searchBox, 'places_changed', function() {      var places = searchBox.getPlaces();        for (var m = 0, user_marker; user_marker = user_markers[m]; m++) {        user_marker.setMap(null);      }        // For each place, get the icon, place name, and location.      user_markers = [];      var bounds = new google.maps.LatLngBounds();      for (var m = 0, place; place = places[m]; m++) {        var image = {          url: place.icon,          size: new google.maps.Size(71, 71),          origin: new google.maps.Point(0, 0),          anchor: new google.maps.Point(17, 34),          scaledSize: new google.maps.Size(25, 25)        };          // Create a marker for each place.        var user_marker = new google.maps.Marker({          map: map,          icon: image,          title: place.name,          position: place.geometry.location        });          user_markers.push(marker);          bounds.extend(place.geometry.location);      }        map.fitBounds(bounds);    });    // [END region_getplaces]  	    // Bias the SearchBox results towards places that are within the bounds of the    // current map's viewport.    google.maps.event.addListener(map, 'bounds_changed', function() {      var bounds = map.getBounds();      searchBox.setBounds(bounds);    });      }  // [END initialize function]    // once the window loads, run the initialize function  google.maps.event.addDomListener(window, 'load', initialize);    </script>      </head>   <body>  <div id="map"></div>    <div id="sidebar-overlay">    	<div class="block">    		<h1>Sites in PA that use at least five tons of ammonia</h1>    		<p><em>Are you located in a hazard zone? Type your address in the search bar above.</em></p>    	</div>    	<div class="block">    		<h3>About this project:</h3>    		<p>Reporters examined Environmental Protection Agency filings for 122 Pennsylvania facilities that use large amounts of ammonia, a chemical that the EPA classifies as extremely hazardous. Each report shows how many people could be affected in a worst-case ammonia leak.   <br>    		<a href="http://publicsource.org/investigations/15-million-pennsylvanians-live-close-large-amounts-of-hazardous-ammonia">Read the story here.</a>    		</p>    	</div>    	<div class="block">    		<div class="notes">  	  		<p><strong>Note:</strong>  	  	*The populations of the areas around Airgas Palmerton and Sysco Philadelphia were estimated by PublicSource using 2010 U.S. Census data.</p>  	  		<p><strong>Sources:</strong> EPA data from the RTK Network, PublicSource reporting, 2010 U.S Census data</p>  	  	</div>  	  </div>    </div>    <input id="pac-input" class="controls" type="text" placeholder="Search Box">  </body>  </html>