Google Maps InfoWindow With Knockout


Today I made myself a bit more familiar using the google maps InfoWindow (API V3) in combination with knockout. I wanted to update the info window contents (latlng) by using a knockout data-binding. It seemed to be more natural to find the caveats in jsfiddle before implementing them in a larger project.

The good news is that the knockout usage with google maps is quite straight forward and there was only one thing which irritated me a bit. The InfoWindow is not opened directly when calling InfoWindow.open(…) you have to listen to its domready event if you want to bind knockout.

Jump directly to the jsfiddle example: http://jsfiddle.net/G6MXd/4/

Code in pieces:

HTML

<div id="map_canvas" style="width:50%; height:50%"></div>

<div id="outside">
Latitude: <input type="text" data-bind="value:lat" />
Longitude: <input type="text" data-bind="value:lng" />
<div>​

JavaScript
At first we have a simple knockout view model which stores our marker latitude and longitude value.

$(function() {

//knockout view model
var MarkerPosition = function() {

var self = this;
self.lat = ko.observable(0);
self.lng = ko.observable(0);

};

var model = new MarkerPosition();
ko.applyBindings(model, document.getElementById("outside"));

Then we are initializing our google maps element and a marker which can be dragged around:

// init gmap
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};

var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);

var mapCenter = map.getCenter();
var marker = new google.maps.Marker({
position: mapCenter,
map: map,
draggable: true
});

And finally the more interesting part. At first we attach a function to the markers dragend event to build the contents for the info window object. We do this only once as we do not want to rebind knockout again and again. It’s no problem to close the info window while dragging and show it again in the dragend event. Make sure to use the infow windows’s domready event for binding knockout as its opened asynchronously.

// our info window (reused on every drag)
var infoWindow;

// show info window when marker dragging ends
google.maps.event.addListener(marker, 'dragend', function(e) {

//update knockout view model
var text = "<div id='inside'>Latitude: <input type='text' data-bind='value:lat'/>";
text += "<br />";
text += "Longitude: <input type='text' data-bind='value:lng' / ></div>";

//just create the infoWindow once
if (!infoWindow) {
infoWindow = new google.maps.InfoWindow({
content: text
});

// bind knockout when dom is ready
google.maps.event.addListener(infoWindow, 'domready', function() {
ko.applyBindings(model, document.getElementById("inside"));
});

}
// open info window
infoWindow.open(map, marker);

//update our view model
model.lat(e.latLng.lat());
model.lng(e.latLng.lng());
});

// close info window when marker dragging starts
google.maps.event.addListener(marker, 'dragstart', function(e) {
if (infoWindow) {
infoWindow.close();
}

});
});​ 

That’s all, quite simple and now you can perhaps start to integrate some reverse geocoding to get the correct address in the info window. Have fun!

, , ,

  1. Bisher keine Kommentare.
(wird nicht veröffentlicht)