I was recently asked to create an HTML page that would access a CSV file containing a list of latitude/longitude values and generate a map with markers for each location. This project was a proof-of-concept challenge for me so I’ve really just made a barebones implementation. That said, it should be very easy to expand using only Google’s API documentation for reference. Google Maps were the clear choice as they’ve become a bit of a de facto standard. Enough – let’s dig into the code!
This block of Javascript converts a local CSV file to a multidimensional array that can be easily accessed and manipulated within memory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
// This will parse a delimited string into an array of // arrays. The default delimiter is the comma, but this // can be overriden in the second argument. function CSVToArray( strData, strDelimiter ){ // Check to see if the delimiter is defined. If not, // then default to comma. strDelimiter = (strDelimiter || ","); // Create a regular expression to parse the CSV values. var objPattern = new RegExp( ( // Delimiters. "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" + // Quoted fields. "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" + // Standard fields. "([^\"\\" + strDelimiter + "\\r\\n]*))" ), "gi"); // Create an array to hold our data. Give the array // a default empty first row. var arrData = [[]]; // Create an array to hold our individual pattern // matching groups. var arrMatches = null; // Keep looping over the regular expression matches // until we can no longer find a match. while (arrMatches = objPattern.exec( strData )) { // Get the delimiter that was found. var strMatchedDelimiter = arrMatches[ 1 ]; // Check to see if the given delimiter has a length // (is not the start of string) and if it matches // field delimiter. If id does not, then we know // that this delimiter is a row delimiter. if (strMatchedDelimiter.length && (strMatchedDelimiter != strDelimiter)) { // Since we have reached a new row of data, // add an empty row to our data array. arrData.push( [] ); } // Now that we have our delimiter out of the way, // let's check to see which kind of value we // captured (quoted or unquoted). if (arrMatches[ 2 ]){ // We found a quoted value. When we capture // this value, unescape any double quotes. var strMatchedValue = arrMatches[ 2 ].replace( new RegExp( "\"\"", "g" ), "\"" ); } else { // We found a non-quoted value. var strMatchedValue = arrMatches[ 3 ]; } // Now that we have our value string, let's add // it to the data array. arrData[ arrData.length - 1 ].push( strMatchedValue ); } // Return the parsed data. return( arrData ); } |
This initialization function is all it takes to generate a Google Map and add all of our markers:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
function initialize() { // Set lat/long to center on the USA var lat = 39.8282; var lng = -98.5795; var zm = 5; // Configure the starting variables for the map var mapOptions = { center: new google.maps.LatLng(lat, lng), zoom: zm, mapTypeId: google.maps.MapTypeId.ROADMAP }; // Generate the actual map var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions); var returnValue = ""; var request = new XMLHttpRequest(); // Read the lat/long info for markers request.open("GET", "zip-lat-long.csv", false); request.send(null); returnValue = request.responseText; // Convert our data from the CVS file to a usable array var data = CSVToArray(returnValue); for (var i = 0; i < data.length; i++) { // Create a lat/long object readable by Google var myLatlng = new google.maps.LatLng(parseFloat(data[i][1]), parseFloat(data[i][2])); // Generate a marker from the lat/long object and add it to the map var marker = new google.maps.Marker({ position: myLatlng, map: map, title:data[i][0] }); } } |
Using these two functions, all it takes to generate the actual map is a single line of code:
1 2 |
// Initialize the Google Map google.maps.event.addDomListener(window, 'load', initialize); |
You can see this code in action right here: http://sideapps.com/smart911/
If you’re interested in the CSV file it can be downloaded here: http://sideapps.com/smart911/zip-lat-long.csv
I must admit, I am a bit prejudiced toward web applications… However, I found Google’s API and the small amount of Javascript I had to learn very pleasant. I anticipated a much longer process and was very happy to be able to complete the task so logically and directly. Hopefully this helps someone out!