I've been through as many StackOverflow/google groups as I can imagine trying to figure this guy out.
I'm using BackboneJS to render a map that has a start location and an end location. On a fresh page/page refresh, I don't get this error, and the map and stuff work fine, for I am using jQuery's $(window).load(.....) function; however, when I dynamically render my View, I get this error-I believe-because the DOM hasn't loaded the DIV yet (failing with document.getElementById). I have tried all manner of different methods other than the $(window).load(), but I can't get anything which works for both use cases (fresh page load -- BackboneJS view loading). Trying to call the function right after the template doesn't work, either.
Any help would be appreciated.
Robert
View:
App.Views.MapShow = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render');
var self = this;
$(window).load(function() {
self.renderMap();
});
},
render: function() {
this.renderTemplate();
},
renderTemplate: function() {
this.$el.html(JST['path/to/show/file']());
},
renderMap: function() {
var from = this.model.get('location_from');
var to = this.model.get('location_to');
var geocoder = new google.maps.Geocoder();
var map = new google.maps.Map(document.getElementById('mapCanvas'), {
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(map);
var request = {
origin: from,
destination: to,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
});
HTML:
<div class="map" id="mapCanvas"></div>
I've been through as many StackOverflow/google groups as I can imagine trying to figure this guy out.
I'm using BackboneJS to render a map that has a start location and an end location. On a fresh page/page refresh, I don't get this error, and the map and stuff work fine, for I am using jQuery's $(window).load(.....) function; however, when I dynamically render my View, I get this error-I believe-because the DOM hasn't loaded the DIV yet (failing with document.getElementById). I have tried all manner of different methods other than the $(window).load(), but I can't get anything which works for both use cases (fresh page load -- BackboneJS view loading). Trying to call the function right after the template doesn't work, either.
Any help would be appreciated.
Robert
View:
App.Views.MapShow = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render');
var self = this;
$(window).load(function() {
self.renderMap();
});
},
render: function() {
this.renderTemplate();
},
renderTemplate: function() {
this.$el.html(JST['path/to/show/file']());
},
renderMap: function() {
var from = this.model.get('location_from');
var to = this.model.get('location_to');
var geocoder = new google.maps.Geocoder();
var map = new google.maps.Map(document.getElementById('mapCanvas'), {
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(map);
var request = {
origin: from,
destination: to,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
});
HTML:
<div class="map" id="mapCanvas"></div>
Share
Improve this question
edited Aug 12, 2012 at 20:37
rpearce
asked Aug 12, 2012 at 20:29
rpearcerpearce
1,7711 gold badge21 silver badges30 bronze badges
3
-
Have you tried putting the map stuff inside a
setTimeout(function() { ...}, 0)
call? stackoverflow./a/9145790/479863 – mu is too short Commented Aug 12, 2012 at 21:19 - If you don't mind putting this as an answer that'd be great. Fixed it – rpearce Commented Aug 12, 2012 at 22:21
- Refactored to Underscore's _.defer function based off a friend's remendation. – rpearce Commented Aug 12, 2012 at 22:30
1 Answer
Reset to default 7I'd guess that your problem is that #mapCanvas
isn't in the DOM until after you try to access it so this:
document.getElementById('mapCanvas')
will give you a useless null
. You need to wait until #mapCanvas
is in the DOM before using it; you can't do something like this either:
map_canvas = this.$el.find('#mapCanvas')[0];
That will give you a valid ID but you'll confuse the Google Maps functions because it won't have a size so the map will be rendered oddly. This puts you back to waiting for everything to be in the DOM before binding your Google Maps stuff.
One way around this is to use setTimeout
with a delay of zero:
var _this = this;
setTimeout(function() { _this.renderMap() }, 0);
This looks strange bit it does work, this trick basically dumps your renderMap
call into the browser's work queue and it'll get around to running it once you've returned control to the browser.
You can also use _.defer
:
defer
_.defer(function, [*arguments])
Defers invoking the function until the current call stack has cleared, similar to using setTimeout with a delay of 0. Useful for performing expensive putations or HTML rendering in chunks without blocking the UI thread from updating.
This might be a better choice as it makes your intent explicit.