javascript - Google Map API BackBoneJS Cannot read property 'offsetWidth' of null - Stack Overflow

I've been through as many StackOverflowgoogle groups as I can imagine trying to figure this guy o

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
Add a ment  | 

1 Answer 1

Reset to default 7

I'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.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742409852a4438594.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信