Update: I have discovered a solution to this problem - please see comments at end of this post.
Original Post: I can't get a Google map (API 3) to show in a view page in Ruby on Rails 3. I'm trying to do this directly, rather than using the GM4R gem, so most of the replies on Stack Overflow I've seen don't apply to my situation. I've succeeded in creating a map on a static page, but not on a model's view page. My code is organized as follows:
application.js (in apps/assets/javascripts):
...
//= require jquery
//= require jquery_ujs
//= require_tree .
googlemaps.js (top level of apps/assets/javascripts):
var map, marker, current_pos, initial_pos = new google.maps.LatLng(49.2649, -123.2351);
function updatePositionDisplay( latlng ) // updates the readout under the map with the supplied position
{
document.getElementById('event_latitude').value = latlng.lat();
document.getElementById('event_longitude').value = latlng.lng();
}
function initializemap()
{
var mapOptions = { zoom: 14, center: initial_pos, mapTypeId: google.maps.MapTypeId.ROADMAP };
if (document.getElementById('event_map'))
{ alert( 'There is a map')}
else {alert('There is no map')}
map = new google.maps.Map(document.getElementById('event_map'), mapOptions);
if (map != null) {alert('Map object has been created')}
updatePositionDisplay( initial_pos );
}
google.maps.event.addDomListener(window, 'load', initializemap);
events/new.html.erb:
<h1>Create New Event:</h1>
<!-- Display map-->
<div id="event_map" style="width: 80%; height: 60%;"></div>
<%= render 'form' %>
<%= link_to 'Back', events_path %>
events/_form.html.erb (standard - as generated by scaffold):
<%= form_for(@event) do |f| %>
<% if @event.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@event.errors.count, "error") %> prohibited this event from being saved:</h2>
<ul>
<% @event.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :user_id %><br />
<%= f.number_field :user_id %>
</div>
<div class="field">
<%= f.label :latitude %><br />
<%= f.text_field :latitude %>
</div>
<div class="field">
<%= f.label :longitude %><br />
<%= f.text_field :longitude %>
</div>
<div class="field">
<%= f.label :startdatetime %><br />
<%= f.datetime_select :startdatetime %>
</div>
<div class="field">
<%= f.label :enddatetime %><br />
<%= f.datetime_select :enddatetime %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Summary of behaviour and problem:
What I am hoping will happen when I call events/new is that I will see a map, followed by a form. I have verified (by inserting alert() calls) that the initializemap function gets called and that the map object is not null (ie, it gets created). Furthermore, the latitude and longitude boxes in the form get properly filled out, showing that the updatePositionDisplay code gets called correctly. However, no map appears.
I am very puzzled by this, because I started this project by writing a static page controller that did render the map properly.
The rendered code on the page looks like the following:
<!DOCTYPE html>
<html>
<head>
<title>MapApp Prototype</title>
<!--For alternatives to loading external scripts on all pages, visit: http://railsapps.github.com/rails-javascript-include-external.html-->
<script src="http://maps.googleapis.com/maps/api/js?sensor=false" type="text/javascript"></script>
<link href="/assets/application.css?body=1" media="all" rel="stylesheet" type="text/css" />
<link href="/assets/checkins.css?body=1" media="all" rel="stylesheet" type="text/css" />
<link href="/assets/events.css?body=1" media="all" rel="stylesheet" type="text/css" />
<link href="/assets/scaffolds.css?body=1" media="all" rel="stylesheet" type="text/css" />
<link href="/assets/static_pages.css?body=1" media="all" rel="stylesheet" type="text/css" />
<link href="/assets/users.css?body=1" media="all" rel="stylesheet" type="text/css" />
<script src="/assets/jquery.js?body=1" type="text/javascript"></script>
<script src="/assets/jquery_ujs.js?body=1" type="text/javascript"></script>
<script src="/assets/checkins.js?body=1" type="text/javascript"></script>
<script src="/assets/events.js?body=1" type="text/javascript"></script>
<script src="/assets/googlemaps.js?body=1" type="text/javascript"></script>
<script src="/assets/static_pages.js?body=1" type="text/javascript"></script>
<script src="/assets/users.js?body=1" type="text/javascript"></script>
<script src="/assets/application.js?body=1" type="text/javascript"></script>
<meta content="authenticity_token" name="csrf-param" />
<meta content="SRh+VoCjXu3+LGmiH91+AByrXyNGEzv0nTXuZKbzfS8=" name="csrf-token" />
</head>
<body>
<h1>Create New Event:</h1>
<!-- Display map-->
<div id="event_map" style="width: 80%; height: 60%;"></div>
<form accept-charset="UTF-8" action="/events" class="new_event" id="new_event" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="SRh+VoCjXu3+LGmiH91+AByrXyNGEzv0nTXuZKbzfS8=" /></div>
... (details of form omitted)
</div>
<div class="actions">
<input name="commit" type="submit" value="Create Event" />
</div>
</form>
<a href="/events">Back</a>
</body>
</html>
This all looks correct to me. Any insight or suggestions as to either what I'm doing wrong or what's different between a static page and a model-linked view page would be most welcome.
Update: So it appears that there has to be an explicit styling for the event_map div. I added the following code to app/assets/stylesheets/events.css.scss:
#event_map { height: 300px; }
and that makes it work. However, interestingly, I don't seem to be able to change this to percent notation. If I make it {height: 50%}, I again get a blank map. Any ideas why this is so? I'd prefer to generate a flexible layout with the space allocated to the map being automatically adjusted to the user's browser window size.