Events

Select platform: Android iOS JavaScript

This page describes the user interface events and error events that you can listen for and handle programmatically.

User Interface Events

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 Maps JavaScript API. These events are separate and distinct from standard DOM events.
  • MVC state change notifications reflect changes in Maps JavaScript API objects and are named using a property_changed convention.

Each Maps JavaScript 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 calling addListener() to register event handlers on the object.

The following sample will show you which events are triggered by the google.maps.Map as you interact with the map.

For a complete list of events, consult the Maps JavaScript API Reference. Events are listed in a separate section for each object which contains events.

UI Events

Some objects within the Maps JavaScript 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.AdvancedMarkerElement object can listen to:

  • 'click'
  • 'drag'
  • 'dragend'
  • 'dragstart'
  • 'gmp-click'

For the full list, see the AdvancedMarkerElement class. These events may look like standard DOM events, but they are actually part of the Maps JavaScript API. Because different browsers implement different DOM event models, the Maps JavaScript 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 Maps JavaScript 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 calling addListener() to register event handlers on the object 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.

Handle Events

To register for event notifications, use the addListener() event handler. That method takes 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:

TypeScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;
  const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;

  const myLatlng = { lat: -25.363, lng: 131.044 };

  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 4,
      center: myLatlng,
      mapId: "DEMO_MAP_ID",
    }
  );

  const marker = new google.maps.marker.AdvancedMarkerElement({
    position: myLatlng,
    map,
    title: "Click to zoom",
  });

  map.addListener("center_changed", () => {
    // 3 seconds after the center of the map has changed, pan back to the
    // marker.
    window.setTimeout(() => {
      map.panTo(marker.position as google.maps.LatLng);
    }, 3000);
  });

  marker.addListener("click", () => {
    map.setZoom(8);
    map.setCenter(marker.position as google.maps.LatLng);
  });
}

initMap();

JavaScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps");
  const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
  const myLatlng = { lat: -25.363, lng: 131.044 };
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: myLatlng,
    mapId: "DEMO_MAP_ID",
  });
  const marker = new google.maps.marker.AdvancedMarkerElement({
    position: myLatlng,
    map,
    title: "Click to zoom",
  });

  map.addListener("center_changed", () => {
    // 3 seconds after the center of the map has changed, pan back to the
    // marker.
    window.setTimeout(() => {
      map.panTo(marker.position);
    }, 3000);
  });
  marker.addListener("click", () => {
    map.setZoom(8);
    map.setCenter(marker.position);
  });
}

initMap();
View example

Try Sample

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 JavaScript 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)

Access Arguments in UI Events

UI events within the Maps JavaScript API 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.

TypeScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;
  const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;

  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 4,
      center: { lat: -25.363882, lng: 131.044922 },
      mapId: "DEMO_MAP_ID",
    }
  );

  map.addListener("click", (e) => {
    placeMarkerAndPanTo(e.latLng, map);
  });
}

function placeMarkerAndPanTo(latLng: google.maps.LatLng, map: google.maps.Map) {
  new google.maps.marker.AdvancedMarkerElement({
    position: latLng,
    map: map,
  });
  map.panTo(latLng);
}

initMap();

JavaScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps");
  const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary(
    "marker",
  );
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: { lat: -25.363882, lng: 131.044922 },
    mapId: "DEMO_MAP_ID",
  });

  map.addListener("click", (e) => {
    placeMarkerAndPanTo(e.latLng, map);
  });
}

function placeMarkerAndPanTo(latLng, map) {
  new google.maps.marker.AdvancedMarkerElement({
    position: latLng,
    map: map,
  });
  map.panTo(latLng);
}

initMap();
View example

Try Sample

Use 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 reveal a portion of the secret message, which is not contained within the marker itself.

TypeScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;
  const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;

  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 4,
      center: { lat: -25.363882, lng: 131.044922 },
      mapId: "DEMO_MAP_ID",
    }
  );

  const bounds: google.maps.LatLngBoundsLiteral = {
    north: -25.363882,
    south: -31.203405,
    east: 131.044922,
    west: 125.244141,
  };

  // Display the area between the location southWest and northEast.
  map.fitBounds(bounds);

  // Add 5 markers to map at random locations.
  // For each of these markers, give them a title with their index, and when
  // they are clicked they should open an infowindow with text from a secret
  // message.
  const secretMessages = ["This", "is", "the", "secret", "message"];
  const lngSpan = bounds.east - bounds.west;
  const latSpan = bounds.north - bounds.south;

  for (let i = 0; i < secretMessages.length; ++i) {
    const marker = new google.maps.marker.AdvancedMarkerElement({
      position: {
        lat: bounds.south + latSpan * Math.random(),
        lng: bounds.west + lngSpan * Math.random(),
      },
      map: map,
    });

    attachSecretMessage(marker, secretMessages[i]);
  }
}

// Attaches an info window to a marker with the provided message. When the
// marker is clicked, the info window will open with the secret message.
function attachSecretMessage(
  marker: google.maps.marker.AdvancedMarkerElement,
  secretMessage: string
) {
  const infowindow = new google.maps.InfoWindow({
    content: secretMessage,
  });

  marker.addListener("click", () => {
    infowindow.open(marker.map, marker);
  });
}

initMap();

JavaScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps");
  const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: { lat: -25.363882, lng: 131.044922 },
    mapId: "DEMO_MAP_ID",
  });
  const bounds = {
    north: -25.363882,
    south: -31.203405,
    east: 131.044922,
    west: 125.244141,
  };

  // Display the area between the location southWest and northEast.
  map.fitBounds(bounds);

  // Add 5 markers to map at random locations.
  // For each of these markers, give them a title with their index, and when
  // they are clicked they should open an infowindow with text from a secret
  // message.
  const secretMessages = ["This", "is", "the", "secret", "message"];
  const lngSpan = bounds.east - bounds.west;
  const latSpan = bounds.north - bounds.south;

  for (let i = 0; i < secretMessages.length; ++i) {
    const marker = new google.maps.marker.AdvancedMarkerElement({
      position: {
        lat: bounds.south + latSpan * Math.random(),
        lng: bounds.west + lngSpan * Math.random(),
      },
      map: map,
    });

    attachSecretMessage(marker, secretMessages[i]);
  }
}

// Attaches an info window to a marker with the provided message. When the
// marker is clicked, the info window will open with the secret message.
function attachSecretMessage(marker, secretMessage) {
  const infowindow = new google.maps.InfoWindow({
    content: secretMessage,
  });

  marker.addListener("click", () => {
    infowindow.open(marker.map, marker);
  });
}

initMap();
View example

Try Sample

Get and Set Properties within Event Handlers

None of the MVC state change events in the Maps JavaScript 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.

TypeScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;

  const originalMapCenter = new google.maps.LatLng(-25.363882, 131.044922);
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 4,
      center: originalMapCenter,
    }
  );

  const infowindow = new google.maps.InfoWindow({
    content: "Change the zoom level",
    position: originalMapCenter,
  });

  infowindow.open(map);

  map.addListener("zoom_changed", () => {
    infowindow.setContent("Zoom: " + map.getZoom()!);
  });
}

initMap();

JavaScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps");
  const originalMapCenter = new google.maps.LatLng(-25.363882, 131.044922);
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: originalMapCenter,
  });
  const infowindow = new google.maps.InfoWindow({
    content: "Change the zoom level",
    position: originalMapCenter,
  });

  infowindow.open(map);
  map.addListener("zoom_changed", () => {
    infowindow.setContent("Zoom: " + map.getZoom());
  });
}

initMap();
View example

Try Sample

Listen to DOM Events

The 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 JavaScript 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 window or document.body.myform
  • Named elements such as document.getElementById("foo")

Note that addDomListener() 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.)

TypeScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;

  const mapDiv = document.getElementById("map") as HTMLElement;
  const map = new google.maps.Map(mapDiv, {
    zoom: 8,
    center: new google.maps.LatLng(-34.397, 150.644),
  });

  // We add a DOM event here to show an alert if the DIV containing the
  // map is clicked.
  google.maps.event.addDomListener(mapDiv, "click", () => {
    window.alert("Map was clicked!");
  });
}

initMap();

JavaScript

async function initMap() {
  // Request needed libraries.
  const { Map } = await google.maps.importLibrary("maps");
  const mapDiv = document.getElementById("map");
  const map = new google.maps.Map(mapDiv, {
    zoom: 8,
    center: new google.maps.LatLng(-34.397, 150.644),
  });

  // We add a DOM event here to show an alert if the DIV containing the
  // map is clicked.
  google.maps.event.addDomListener(mapDiv, "click", () => {
    window.alert("Map was clicked!");
  });
}

initMap();

HTML

<html>
  <head>
    <title>Listening to DOM Events</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map"></div>

    <!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "weekly"});</script>
  </body>
</html>
View example

Try Sample

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.

Remove 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 = marker.addListener('click', aFunction);

google.maps.event.removeListener(listener1);

To remove all listeners from a particular instance, call clearInstanceListeners(), passing the instance name.

var listener1 = marker.addListener('click', aFunction);
var listener2 = marker.addListener('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.

Listen for authentication errors

If you want to programmatically detect an authentication failure (for example to automatically send a beacon) you can prepare a callback function. If the following global function is defined it will be called when the authentication fails. function gm_authFailure() { /* Code */ };