How to Fix the Google Maps JavaScript Error in Ruby

When I first tried integrating Google Maps into my Ruby on Rails app, everything seemed straightforward until I ran the app and got hit with a JavaScript error. The map didn’t load on the first try, and the console screamed:

TypeError: null is not an object (evaluating 'a.offsetWidth')

At first, I thought maybe I’d messed up my API script or marker coordinates. But the issue ran deeper, and I learned a few important lessons about Turbolinks, DOM readiness, and how Rails works with JavaScript. Here’s a breakdown of my process, what went wrong, how I fixed it, and how I added extra functionality for practice.

The First Given Code (with Google Maps Integration)

This was my original .html.erb setup for the Rails layout file:

<!DOCTYPE html>
<html>
<head>
<title>Website</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>

<script src="https://maps.googleapis.com/maps/api/js"></script>

<script type="text/javascript">
function initialize() {
var myLatlng = new google.maps.LatLng(56.794682, 25.224593);

var mapOptions = {
zoom: 15,
center: myLatlng
};

var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);

var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'This is a location'
});
}

google.maps.event.addDomListener(window, 'load', initialize);
</script>

<script type="text/javascript">
ready = function () {
var page_id = $('div.content').attr('id');
var navigation_list = $("nav#navigation a");

navigation_list.each(function (a) {
if ($(this).attr('id') == page_id) {
$(this).css("border-bottom", "3px solid #74c5bd");
}
});
};

$(document).ready(ready);
$(document).on('page:load', ready);
</script>
</head>

<body>
<%= render "layouts/header" %>
<%= yield %>
<%= render "layouts/footer" %>
</body>
</html>

The JavaScript Error

TypeError: null is not an object (evaluating 'a.offsetWidth')

This popped up every time I loaded the page for the first time. But oddly, after a refresh, it went away and the map loaded. So what was going on?

Explanation of the Error and Root Cause

Turbolinks Interference

Rails uses Turbolinks by default, which loads pages via AJAX to make transitions faster. However, Turbolinks doesn’t reload the full DOM or fire standard events like window.onload or even $(document).ready() in the way we expect.

So my initialize() function was firing before the #map_canvas div existed in the DOM.

Missing Map Container

Another reason? I forgot to add the actual map container in the HTML! I was calling:

document.getElementById('map_canvas')

there was no element with that ID, so Google Maps couldn’t attach the map and threw an error when trying to get the container’s width.

The Fix Code

Add the Missing Map Container

I added this directly into my view where I wanted the map:

<div id="map_canvas" style="width: 100%; height: 400px;"></div>

This ensures the JavaScript has something to target when rendering the map.

Replace window.onload with turbolinks:load

To make sure the map initializes only when the DOM is ready, I rewrote the script like this:

initialize() {
var myLatlng = new google.maps.LatLng(56.794682, 25.224593);

var mapOptions = {
zoom: 15,
center: myLatlng
};

var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);

var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'This is a location'
});
}

function loadGoogleMap() {
if (document.getElementById('map_canvas')) {
initialize();
}
}

document.addEventListener("turbolinks:load", loadGoogleMap);

Now it loads properly even with Turbolinks enabled.

Add Practice Functionality Dynamic Marker Input

To test my understanding further, I created a simple interface that allows users to enter new coordinates, and the map updates with a fresh marker.

Here’s the added HTML:

<div style="margin-top: 20px;">
<label>Latitude: <input type="text" id="lat" value="56.794682"></label>
<label>Longitude: <input type="text" id="lng" value="25.224593"></label>
<button onclick="updateMap()">Update Location</button>
</div>

And the updated JS:

updateMap() {
var lat = parseFloat(document.getElementById('lat').value);
var lng = parseFloat(document.getElementById('lng').value);

var myLatlng = new google.maps.LatLng(lat, lng);
var mapOptions = {
zoom: 15,
center: myLatlng
};

var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);

var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Updated Location'
});
}

Final Recommendation

  • Always double check that your HTML elements exist before attaching JavaScript to them.
  • Understand how Turbolinks (or any client-side router) works. They change how DOM events behave.
  • Use turbolinks:load or DOMContentLoaded instead of relying on $(document).ready() or window.onload if you’re using Rails defaults.
  • Test your app in multiple navigation flows: direct load, back button, link clicks, etc.

Final Thought

Integrating Google Maps into Rails wasn’t difficult but understanding the timing of JavaScript execution in a Rails app using Turbolinks was key. This experience reminded me that small details (like a missing <div>) can cause strange, misleading errors. I also learned how to make code resilient, check for elements before acting, and write functionality that’s both dynamic and robust.

Related blog posts