- Overview
- Handling Events
- Accessing Arguments in UI Events
- Using Closures in Event Listeners
- Getting and Setting Properties within Event Handlers
- Listening to DOM Events
- Removing Event Listeners
Overview
JavaScript within the browser is event driven, meaning that JavaScript responds to interactions by generating events, and expects a program to listen to interesting events. There are two types of events:
- User events (such as "click" mouse events) are propagated from the DOM to the Google Maps API. These events are separate and distinct from standard DOM events.
- MVC state change notifications reflect changes in Maps API objects and
are named using a
property_changedconvention.
Each Maps API object exports a number of named events. Programs interested
in certain events will register JavaScript event listeners
for those events and execute code when those events are received by
registering addListener() event handlers on the
google.maps.event namespace.
The below sample will show you what events are triggered by the
google.maps.Map as you interact with the map.
For a complete list of events, consult the Maps API Reference. Events are listed in a separate section for each object which contains events.
UI Events
Some objects within the Maps API are designed to respond to user events
such as mouse or keyboard events. For example, these are some of the user
events that a google.maps.Marker object can listen to:
'click''dblclick''mouseup''mousedown''mouseover''mouseout'
For the full list, see the Marker class. These events may look like standard DOM events, but they are actually part of the Maps API. Because different browsers implement different DOM event models, the Maps API provides these mechanisms to listen for and respond to DOM events without needing to handle the various cross-browser peculiarities. These events also typically pass arguments within the event noting some UI state (such as the mouse position).
MVC State Changes
MVC objects typically contain state. Whenever an object's property changes,
the API will fire an event that the property has changed. For example, the
API will fire a zoom_changed event on a map when the map's zoom
level changes. You can intercept these state changes by registering
addListener() event handlers on the event namespace
method as well.
User events and MVC state changes may look similar, but you generally wish
to treat them differently in your code. MVC events, for example, do not pass
arguments within their event. You will want to inspect the property that
changed on an MVC state change by calling the appropriate
getProperty method on that object.
Handling Events
To register for event notifications, use the addListener()
event handler. That method takes an object, an event to listen for, and a
function to call when the specified event occurs.
Example: Map and Marker Events
The following code mixes user events with state change events. We attach an
event handler to a marker that zooms the map when clicked. We also add an
event handler to the map for changes to the center property and
pan the map back to the marker after 3 seconds on receipt of the
center_changed event:
function initialize() {
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(-25.363882, 131.044922)
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var marker = new google.maps.Marker({
position: map.getCenter(),
map: map,
title: 'Click to zoom'
});
google.maps.event.addListener(map, 'center_changed', function() {
// 3 seconds after the center of the map has changed, pan back to the
// marker.
window.setTimeout(function() {
map.panTo(marker.getPosition());
}, 3000);
});
google.maps.event.addListener(marker, 'click', function() {
map.setZoom(8);
map.setCenter(marker.getPosition());
});
}
google.maps.event.addDomListener(window, 'load', initialize);
View example (event-simple.html)
Tip: If you're trying to detect a change in
the viewport, be sure to use the specific bounds_changed event
rather than constituent zoom_changed and
center_changed events. Because the Maps API fires these latter
events independently, getBounds() may not report useful results
until after the viewport has authoritatively changed. If you wish to
getBounds() after such an event, be sure to listen to the
bounds_changed event instead.
Example: Shape Editing and Dragging Events
When a shape is edited or dragged, an event is fired upon completion of the action. For a list of the events and some code snippets, see Shapes.
View example (rectangle-event.html)
Accessing Arguments in UI Events
UI events within the Google Maps API V3 typically pass an event argument,
which can be accessed by the event listener, noting the UI state when the
event occurred. For example, a UI 'click' event typically passes
a MouseEvent containing a latLng property denoting
the clicked location on the map. Note that this behavior is unique to UI
events; MVC state changes do not pass arguments in their events.
You can access the event's arguments within an event listener the same way you would access an object's properties. The following example adds an event listener for the map, and creates a marker when the user clicks on the map at the clicked location.
var map;
function initialize() {
var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
var mapOptions = {
zoom: 4,
center: myLatlng
}
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
google.maps.event.addListener(map, 'click', function(event) {
placeMarker(event.latLng);
});
}
function placeMarker(location) {
var marker = new google.maps.Marker({
position: location,
map: map
});
map.setCenter(location);
}
View example (event-arguments.html)
Using Closures in Event Listeners
When executing an event listener, it is often advantageous to have both private and persistent data attached to an object. JavaScript does not support "private" instance data, but it does support closures which allows inner functions to access outer variables. Closures are useful within event listeners to access variables not normally attached to the objects on which events occur.
The following example uses a function closure in the event listener to assign a secret message to a set of markers. Clicking on each marker will review a portion of the secret message, which is not contained within the marker itself.
var map;
function initialize() {
var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
var mapOptions = {
zoom: 4,
center: myLatlng
}
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
// Add 5 markers to the map at random locations.
var southWest = new google.maps.LatLng(-31.203405,125.244141);
var northEast = new google.maps.LatLng(-25.363882,131.044922);
var bounds = new google.maps.LatLngBounds(southWest,northEast);
map.fitBounds(bounds);
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
for (var i = 0; i < 5; i++) {
var location = new google.maps.LatLng(southWest.lat() + latSpan * Math.random(),
southWest.lng() + lngSpan * Math.random());
var marker = new google.maps.Marker({
position: location,
map: map
});
var j = i + 1;
marker.setTitle(j.toString());
attachSecretMessage(marker, i);
}
}
// The five markers show a secret message when clicked
// but that message is not within the marker's instance data.
function attachSecretMessage(marker, number) {
var message = ["This","is","the","secret","message"];
var infowindow = new google.maps.InfoWindow(
{ content: message[number],
size: new google.maps.Size(50,50)
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
}
View example (event-closure.html)
Getting and Setting Properties within Event Handlers
None of the MVC state change events in the Maps API event system pass
arguments when the event is triggered. (User events do
pass arguments which can be inspected.) If you need to inspect a property
on an MVC state change, you should explicitly call the appropriate
getProperty() method on that object. This
inspection will always retrieve the current state of the MVC
object, which may not be the state when the event was first fired.
Note: Explicitly setting a property within an event handler which responds to a state change of that particular property may produce unpredictable and/or unwanted behavior. Setting such a property will trigger a new event, for example, and if you always set a property within this event handler, you may end up creating an infinite loop.
In the example below, we set up an event handler to respond to zoom events by bringing up an info window displaying that level.
function initialize() {
var myLatLng = new google.maps.LatLng(-25.363882, 131.044922);
var mapOptions = {
zoom: 4,
center: myLatLng
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var infowindow = new google.maps.InfoWindow({
content: 'Change the zoom level',
position: myLatLng
});
infowindow.open(map);
google.maps.event.addListener(map, 'zoom_changed', function() {
var zoomLevel = map.getZoom();
map.setCenter(myLatLng);
infowindow.setContent('Zoom: ' + zoomLevel);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
View example (event-properties.html)
Listening to DOM Events
The Google Maps JavaScript API event model creates and manages its own
custom events. However, the DOM (Document Object Model) within the browser
also creates and dispatches its own events, according to the particular
browser event model in use. If you wish to capture and respond to these
events, the Maps API provides the addDomListener() static method
to listen to and bind to DOM events.
This convenience method has a signature as shown below:
addDomListener(instance:Object, eventName:string, handler:Function)
where instance may be any DOM element supported by the browser,
including:
- Hierarchical members of the DOM such as
windowordocument.body.myform - Named elements such as
document.getElementById("foo")
Note that addDomListener() simply passes the indicated event
to the browser, which handles it according to the browser's DOM event model;
however, almost all modern browsers at least support DOM Level 2. (For more
information on DOM level events, see the
Mozilla DOM Levels
reference.)
If you've been reading the documentation this far, you're probably already
familiar with one DOM event: the window.onload event, which
we've handled within the <body> tag. We use this event to
trigger the initial JavaScript code once an HTML page is fully loaded, as
shown below:
<script>
function initialize() {
// Map initialization
}
</script>
<body onload="initialize()">
<div id="map-canvas"></div>
</body>
Although this event is attached to the <body> element
here, this event is really a window event indicating that the
DOM hierarchy below the window element has been fully built out
and rendered.
Although easy to understand, having an onload event within a
<body> tag mixes content with behavior. Generally, it is
good practice to separate your content code (HTML) from your behavioral code
(JavaScript) and provide your presentation code (CSS) separately as well. You
can do so by replacing the inline onload event handler with a
DOM listener within your Maps API JavaScript code like so:
<script>
function initialize() {
// Map initialization
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<body>
<div id="map-canvas"></div>
</body>
View example (event-domListener.html)
Although the above code is Maps JavaScript API code, the
addDomListener() method binds to the window object
of the browser and allows the API to communicate with objects outside of the
API's normal domain.
Removing Event Listeners
To remove a specific event listener, it must have been assigned to a
variable. You can then call removeListener(),
passing the variable name to which the listener was assigned.
var listener1 = google.maps.event.addListener(marker, 'click', aFunction); google.maps.event.removeListener(listener1);
To remove all listeners from a particular instance, call
clearInstanceListeners(), passing the instance name.
var listener1 = google.maps.event.addListener(marker, 'click', aFunction); var listener2 = google.maps.event.addListener(marker, 'mouseover', bFunction); // Remove listener1 and listener2 from marker instance. google.maps.event.clearInstanceListeners(marker);
To remove all listeners for a specific event type for a specific instance,
call clearListeners(), passing the instance name and the event
name.
marker.addListener('click', aFunction);
marker.addListener('click', bFunction);
marker.addListener('click', cFunction);
// Remove all click listeners from marker instance.
google.maps.event.clearListeners(marker, 'click');
For more information, refer to the reference documentation for the google.maps.event namespace.