How to Get Multiple Entries from CSV Files in JavaScript

Today, I’m diving into a common challenge: how to plot multiple markers on a Google Map using data from a CSV file in JavaScript. If you’ve ever tried this, you’ve probably encountered quirks like syntax errors, incomplete data handling, or static markers without interactivity. Let’s break down the original approach, its pitfalls, and how to improve it with cleaner code and extra functionality.

The Original Code:

Let’s start with the initial setup. The goal was to read a CSV file (like landmarks.csv) and generate map markers dynamically. Here’s what the original code did:

Hard-Coded Marker

The first JavaScript block created a single marker with fixed values:

var marker = new google.maps.Marker({
    position: myLatlng, 
    map: map,
    title: "Hello World!"
});
  • position: A predefined LatLng object (myLatlng).
  • map: The map instance where the marker is placed.
  • title: A tooltip text shown on hover.

While this works for one marker, it’s not scalable.

PHP Reading CSV & Generating JavaScript

The PHP code looped through landmarks.csv and output JavaScript variables for each row:

<?php 
    $fd = fopen("landmarks.csv", "r");
    echo "var latlngarr = new Array();";
    $i = 0;
    while (!feof($fd)) {
        $buffer = fgetcsv($fd, 4096); 
        echo "latlngarr[$i] = new google.maps.LatLng($buffer[2], $buffer[3]);";
        echo "markerarr[$i] = new google.maps.Marker({ 
            position: latlngarr[$i], 
            map: map,
            title: $buffer[1]
        });";
        $i++;
    }
    fclose($fd);
?>
  • CSV Parsing: It reads latitude ($buffer[2]), longitude ($buffer[3]), and title ($buffer[1]).
  • JavaScript Injection: For each row, it generates code to create a LatLng object and a marker.

Potential Issues in the Original Code

While functional at a glance, this approach has some critical flaws:

  1. Missing Quotes for Strings:
    The title value isn’t wrapped in quotes. If your CSV title is "Central Park", the generated JavaScript becomes title: Central Park, which is invalid. Titles need quotes: title: 'Central Park'.
  2. Unreliable CSV Loop:
    Using while (!feof($fd)) can sometimes process an extra empty line. It’s safer to check fgetcsv’s return value directly.
  3. No Interactivity:
    Markers just sit there! Users might want to click them for details like descriptions or images.

Dynamic Markers with Info Windows

Let’s fix these issues and add interactivity. Here’s a revamped version:

Self-Contained HTML Structure

This example includes the full setup, from the map div to the PHP-JavaScript integration:

<!DOCTYPE html>
<html>
<head>
  <title>Google Maps Multiple Markers Example</title>
  <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
  <script>
    function initMap() {
      var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 12,
        center: { lat: 37.7749, lng: -122.4194 } // Default center
      });

      // Single test marker
      var marker = new google.maps.Marker({
        position: { lat: 37.7749, lng: -122.4194 },
        map: map,
        title: 'Hello World!'
      });

      // Reusable info window
      var infoWindow = new google.maps.InfoWindow();

      <?php
      if (($fd = fopen("landmarks.csv", "r")) !== false) {
          $i = 0;
          while (($buffer = fgetcsv($fd, 4096)) !== false) {
              if (count($buffer) < 4) continue; // Skip incomplete rows
              $title = addslashes($buffer[1]); // Escape quotes
              $lat = $buffer[2];
              $lng = $buffer[3];
              $description = addslashes($buffer[4] ?? 'No additional info.');
              
              // Generate marker code
              echo "var marker = new google.maps.Marker({ 
                position: new google.maps.LatLng($lat, $lng), 
                map: map,
                title: '$title'
              });";
              
              // Add click listener for info window
              echo "marker.addListener('click', () => {
                infoWindow.setContent('<h3>$title</h3><p>$description</p>');
                infoWindow.open(map, marker);
              });";
              $i++;
          }
          fclose($fd);
      }
      ?>
    }
  </script>
</head>
<body onload="initMap()">
  <div id="map" style="height: 600px; width: 100%;"></div>
</body>
</html>

Key Improvements

  1. Proper String Handling:
    • PHP’s addslashes() escapes quotes in titles/descriptions.
    • Titles are wrapped in ' ' to ensure valid JavaScript strings.
  2. Robust CSV Parsing:
    • Checks fgetcsv’s return value directly to avoid empty lines.
    • Skips rows with fewer than 4 columns (avoids runtime errors).
  3. Interactive Info Windows:
    • A single InfoWindow instance is reused for efficiency.
    • Clicking a marker displays its title and description from the CSV.
  4. Cleaner Structure:
    • No redundant arrays (latlngarrmarkerarr) since markers are attached directly to the map.

Final Thoughts

Plotting CSV data on a map doesn’t have to be messy! By addressing syntax pitfalls and adding interactivity, you can create a user-friendly experience.

Next Steps:

  • Try adding custom icons based on CSV data.
  • Implement marker clustering for large datasets.
  • Load the CSV asynchronously using JavaScript’s Fetch API instead of PHP.

Related blog posts