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?