Popups and Modals

amCharts 4 has built-in capabilities to display information as a Popup or a Modal window. This article will explain how you can use those to display information to users.

Popup or Modal?

Before we begin, let's figure out the difference between the two.

A Popup is a small (or not) window that displays some kind of information in it. Usually it is displayed over other content, like chart or map, but in general does not obstruct interactivity with it. E.g. you can still interact with the chart around the Popup.

There can be any number of popups displayed at any given time.

A Modal is much more stricter. If there's a Modal open, you don't get to do anything with the chart until Modal is closed. There can be only one Modal at the same time.

Opening

Opening a Popup

To open a Popup, we'll use chart's openPopup(content, title) method:

chart.openPopup("Hello there!");
chart.openPopup("Hello there!");

This will create and open a new Popup. The function will also return a Popup object, which we can use to configure it, as we'll see later on.

Opening a Modal

Opening a modal works in much the same way, except we'll be using openModal(content, title).

chart.openModal("OK. Now I'm serious.");
chart.openModal("OK. Now I'm serious.");

Since a chart can have only one and only Modal, opening Modal works a bit differently than opening a Popup.

Calling openModal() will still return Modal instance. It will also set chart's property modal, which you can also use to configure or close Modal.

Popup/Modal content

Popup or Modal itself is an HTML element, which means that content can also be full-fledged HTML. You can use images, tables, iframes, and anything else HTML standard offers.

Unless specified otherwise, the modal will try to size itself to fit your content.

You can also set an optional title (second parameter) which will be displayed above content. Title can also be HTML.

Opening Popup on click

More often than not, we will need to open a Popup whenever user clicks or taps on something.

We can use "hit" event for that.

For example, the following code will open a Popup whenever user clicks on a country on a World map:

polygonTemplate.events.on("hit", function(ev) {
  chart.closeAllPopups();
  chart.openPopup("We clicked on <strong>" + ev.target.dataItem.dataContext.name + "</strong>");
});
polygonTemplate.events.on("hit", function(ev) {
  chart.closeAllPopups();
  chart.openPopup("We clicked on <strong>" + ev.target.dataItem.dataContext.name + "</strong>");
});
{
  // ...
  "series": [{
    // ...
    "columns": {
      "events": {
        "hit": function(ev) {
          chart.closeAllPopups();
          chart.openPopup("We clicked on <strong>" + ev.target.dataItem.dataContext.name + "</strong>");
        }
      }
    }
  }]
}

MORE INFO To refresh your knowledge on event listeners, head over to "Event Listeners" article.

See the Pen amCharts 4: Popups/Modals (1) by amCharts (@amcharts) on CodePen.24419

Closing

Closing a Popup

To close a Popup we can call its close() method.

popup.close();
popup.close();

Closing all open Popups

To close all open Popups at once, we can call chart's closeAllPopups() method.

chart.closeAllPopups();
chart.closeAllPopups();

Closing a Modal

Similarly, closing a modal is as simple as calling its close() method.

Since we have a reference for our Modal in chart's object, we don't have to maintain it in a separate variable:

chart.modal.close();
chart.modal.close();

Closing example

This example will show how we can close all open popups/modals on a MapChart when clicking outside of the map area.

See the Pen amCharts 4: Close popups on body click by amCharts team (@amcharts) on CodePen.24419

Configuring Popup/Modal

Appearance via CSS

As we mentioned before, a Popup/Modal is an HTML element. Its appearance is configured using CSS.

By default the chart will load a standard piece of CSS that configures appearance of the Popup/Modal.

Your page's CSS can override the built-in one.

Or, you can completely disable loading of built-in CSS by setting Popup/Modal's defaultStyles = false.

Here's the default CSS for your reference:

.ampopup {
  overflow: visible;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2000
}

.ampopup-curtain {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2001;
  background: #fff;
  opacity: 0.5
}

.ampopup-title {
  font-weight: bold;
  font-size: 120%
}

.ampopup-content {
  padding: 1em 2em;
  background: rgb(255, 255, 255);
  background-color: rgba(255, 255, 255, 0.8);
  display: inline-block;
  position: absolute;
  max-width: 90%;
  max-height: 90%;
  overflow: auto;
  z-index: 2002
}

.ampopup-close {
  display: block;
  position: absolute;
  top: 0.3em;
  right: 0.3em;
  background-color: rgb(100, 100, 100);
  background: rgba(100, 100, 100, 0.1) url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyBoZWlnaHQ9IjUxMiIgdmVyc2lvbj0iMSIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHdpZHRoPSI1MTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTQ0NS4yIDEwOS4ybC00Mi40LTQyLjRMMjU2IDIxMy42IDEwOS4yIDY2LjhsLTQyLjQgNDIuNEwyMTMuNiAyNTYgNjYuOCA0MDIuOGw0Mi40IDQyLjRMMjU2IDI5OC40bDE0Ni44IDE0Ni44IDQyLjQtNDIuNEwyOTguNCAyNTYiLz48L3N2Zz4=) no-repeat center;
  background-size: 80%;
  width: 1.2em;
  height: 1.2em;
  cursor: pointer
}

Class prefixes

The class prefixes are configurable.

The ampopup part is added by the Popup/Modal itself, and can be configured using popup's classPrefix.

NOTE If you would like to set classPrefix for all popups that are opened, without setting it on each of those individually, set it on chart.popups.template.classPrefix.

Positioning

Popup or Modal can be positioned either relatively or absolutely.

There are two sets of properties that control placement of Popup/Modal.

Positioning by setting horizontal and vertical alignment

There are two properties that control horizontal and vertical alignment of the Popup/Module.

Property Available values Comment
align "left", "center" (default), "right", "none" Horizontal alignment of Popup.
verticalAlign "top", "middle" (default), "bottom", "none" Vertical alignment of Popup.

By default Popup/Modal is displayed in the center of the chart. (align = "center" and verticalAlign = "middle")

If we wanted our Popup to open in the lower/right corner, we'd use align = "right" and verticalAlign = "bottom" instead.

Positioning using absolute coordinates

If we don't want Popup/Modal aligned, we can set its position manually using these properties:

Property Type Comment
bottom number (pixels) or Percent Distance from the bottom of the chart container.
left number (pixels) or Percent Distance from the left edge of the chart container.
right number (pixels) or Percent Distance from the right edge of the chart container.
top number (pixels) or Percent Distance from the top of the chart container.

NOTE If we use absolute positioning properties such as left or top the alignment settings will be ignored.

Positioning relative to mouse

If rather than specifying fixed position for the popup, we can make it relative to a mouse cursor.

Technically, that will require us to use absolute coordinates. Except, we will extract it from an event that triggered our Popup code.

Building upon our previous example, where we were using "hit" event, we'll extract exact coordinates where that event occurred at.

For the "hit" event, we know that, amount other stuff, it also passes in svgPoint in its parameter object. It's an object that will contain x and y coordinates within chart container, where the event occurred.

We can use that to position Popup using its left and top properties:

polygonTemplate.events.on("hit", function(ev) {
  chart.closeAllPopups();
  let popup = chart.openPopup("We clicked on <strong>" + ev.target.dataItem.dataContext.name + "</strong>");
  popup.left = ev.svgPoint.x + 15;
  popup.top = ev.svgPoint.y + 15;
});
polygonTemplate.events.on("hit", function(ev) {
  chart.closeAllPopups();
  var popup = chart.openPopup("We clicked on <strong>" + ev.target.dataItem.dataContext.name + "</strong>");
  popup.left = ev.svgPoint.x + 15;
  popup.top = ev.svgPoint.y + 15;
});
{
  // ...
  "series": [{
    // ...
    "columns": {
      "events": {
        "hit": function(ev) {
          chart.closeAllPopups();
          var popup = chart.openPopup("We clicked on <strong>" + ev.target.dataItem.dataContext.name + "</strong>");
          popup.left = ev.svgPoint.x + 15;
          popup.top = ev.svgPoint.y + 15;
        }
      }
    }
  }]
}

Curtain

A "curtain" is a semi-transparent shade put over all of the chart, fading it all out, and making the popup content more prominent.

A Modal will display it by default.

A Popup will not. To enable curtain for a Popup (or to disable one for a Modal) use showCurtain property:

popup.showCurtain = true;
popup.showCurtain = true;

Controlling closing

By default a Popup/Modal can be closed in a number of ways: hitting ESC key, clicking Close button or the curtain.

You can disable this functionality using closable property:

popup.closable = false;
popup.closable = false;

A non-closable Popup/Modal can only be closed using its method close().

Accessing Popup/Modal elements

In case you'd like to access actual DOM elements that comprise Popup or Modal - to modify them or completely override them - you can use the elements property, which holds keyed references to each of those elements.

Property Type Default classname Comment
close <a> ampopup-close Close button.
content <div> ampopup-content A container that Popup/Modal contents are placed in, including controls like Close button and Title.
curtain <div> ampopup-curtain A curtain element.
title <div> ampopup-title A title element.
wrapper <div> ampopup A wrapper element that all of the Popup/Modal elements are placed in.

As an example, if we'd want to replace the built-in Close button with some other element, we'd do this:

popup.elements.close = myCustomCloseButton;
popup.elements.close = myCustomCloseButton;

Popup container

Popup/Modal's object holds a reference - container - to the container it is placed in.

This is the same container the chart is placed in. Modify with caution.

It can also be used to place Popups/Modals in a completely separate container outside chart, or to cover the whole page by setting it to document.body:

chart.modal.container = document.body;
chart.modal.container = document.body;
{
  // ...
  "modal": {
    "container": document.body
  }
}

Error Modal

Whenever a critical error occurs in the chart, it opens its Modal to display information about what happened.

You can use chart.modal to access Modal instance to configure it the way you see fit.

Event handlers

Popups (and Modals) can have event handlers attached to them as well.

For now there are two events: "opened" and "closed". Their meaning is self-explanatory.

You can attach an event to a specific Popup object, or to all popups, using popups.template. E.g.:

chart.popups.template.events.on("opened", function(ev) {
  console.log(ev);
});

chart.popups.template.events.on("closed", function(ev) {
  console.log(ev);
});
chart.popups.template.events.on("opened", function(ev) {
  console.log(ev);
});

chart.popups.template.events.on("closed", function(ev) {
  console.log(ev);
});
{
  // ...
  "popups": {
    "events": {
      "opened": function(ev) {
        console.log(ev);
      },
      "closed": function(ev) {
        console.log(ev);
      }
    }
  }
}

Or, if you'd like to have those events on a modal:

chart.modal.events.on("opened", function(ev) {
  console.log(ev);
});

chart.modal.events.on("closed", function(ev) {
  console.log(ev);
});
chart.modal.events.on("opened", function(ev) {
  console.log(ev);
});

chart.modal.events.on("closed", function(ev) {
  console.log(ev);
});
{
  // ...
  "modal": {
    "events": {
      "opened": function(ev) {
        console.log(ev);
      },
      "closed": function(ev) {
        console.log(ev);
      }
    }
  }
}

MORE INFO For more information about how event listeners work in amCharts 4, visit "Event Listeners" article.