Backbone.js with Google Maps - problems with this and listeners

I have a module that I created for Google Maps v3, which I am trying to convert to the Backbone.js view constructor.

Here is my view module: I will explain the problems that I have after the code:

pg.views.CreateMap = Backbone.View.extend({ tagName: "div", className: "map", events: {}, latitude: "-23.56432", longitude: "-46.65183", initialize: function() { _.bindAll(this, 'render', 'dragMarker', 'dragMap'); this.latlng = new google.maps.LatLng(this.latitude, this.longitude); var myOptions = { zoom: 16, center: this.latlng, mapTypeId: google.maps.MapTypeId.ROADMAP }; this.map = new google.maps.Map($(this.el)[0], myOptions); this.marker = new google.maps.Marker({ map: this.map, position: this.latlng, draggable: true }); google.maps.event.addListener(this.marker, "dragend", this.dragMarker()); google.maps.event.addListener(this.map, "dragend", this.dragMap()); }, render: function() { return this; }, dragMarker: function() { this.latlng = this.marker.getPosition(); this.map.panTo(this.latlng); }, dragMap: function() { this.latlng = this.map.getCenter(); this.marker.setPosition(this.latlng); } }); 

The problem I encountered is related to event listeners on Google Maps and how this is handled.

I initially did not have dragMarker and dragMap methods, but instead of these two initialization blocks:

 google.maps.event.addListener(this.marker, "dragend", function() { this.latlng = this.marker.getPosition(); this.map.panTo(this.latlng); }); google.maps.event.addListener(this.map, "dragend", function() { this.latlng = this.map.getCenter(); this.marker.setPosition(this.latlng); }); 

The problem that I encountered in this first approach is that "this" inside these anonymous functions refers to "this.marker" and "this.map" respectively. The problem with this first approach was that in the first listener I had nothing to do with "this.map" and therefore could not execute panTo (). With the second listener, I had nothing to do with "this.marker" and, therefore, could not return the map around this marker with setPosition ().

Then I thought that I could pull out anonymous functions in listeners and declare them as presentation methods, which I would then execute _.bindAll (this, "dragMarker", "dragMap");

The problem with this approach is that I then had to write listeners to the event block like this:

 google.maps.event.addListener(this.marker, "dragend", this.dragMarker()); google.maps.event.addListener(this.map, "dragend", this.dragMap()); 

This meant that when I called the constructor with newmap = new pg.views.CreateMap; that "this.dragMarker ()" and "this.dragMap ()" were immediately evaluated, rather than being evaluated as a callback when the "dragend" event is fired.

No problem, I thought, and then wrapped them in anonymous functions:

 google.maps.event.addListener(this.marker, "dragend", function() { this.dragMarker(); }); google.maps.event.addListener(this.map, "dragend", function() { this.dragMap(); }); 

Unfortunately, this also brings me back to an earlier problem that the “this” in “this.dragMarker” no longer refers to the parent object that I built, but instead refers to “this.marker” again. The same problem occurs with the second listener.

I am completely stuck here. Anyone have any ideas on how I solve this?

+7
javascript this google-maps google-maps-api-3
source share
2 answers

Take the anonymous functions called in dragend and bind explicitly.

 _.bindAll(this, 'dragMarker', 'dragMap'); google.maps.event.addListener(this.marker, "dragend", this.dragMarker); /* etc ... */ 

This this method will always be bound to CreateMap, even if called from the context.

+6
source share

I solved this problem using this / self-hack common in Javascript.

 var self = this; google.maps.event.addListener(this.marker, "dragend", function() { self.latlng = this.getPosition(); self.map.panTo(self.latlng); }); google.maps.event.addListener(this.map, "dragend", function() { self.latlng = this.getCenter(); self.marker.setPosition(self.latlng); }); 

If someone has a solution that does not require this hack, I’m all ears.

+5
source share

All Articles