1

In my current code I have two countries that display a popup when clicked and in the popup you can see some links. Links are mapped correctly but my problem is with the links name.

The way I wrote the code so far, is good for displaying the name of link for a country with one link. I'm calling the link name with ev.target.dataItem.dataContext.linkName in the code below:

chart.openPopup("<strong>" + ev.target.dataItem.dataContext.country + "</strong>" + ev.target.dataItem.dataContext.link.map(url => '<br><a href="' + encodeURI(url) + '">' + ev.target.dataItem.dataContext.linkName  + '</a>').join(""));

How can I write ev.target.dataItem.dataContext.linkName in order to display both names for a country with 2 links? I want Name 2 assigned for https://www.example2.com and Name 3 assigned for https://www.example3.com.

If anyone can help me regarding this issue, I would greatly appreciate it.

am4core.ready(function () {

  // Themes begin
  am4core.useTheme(am4themes_animated);
  // Themes end

  // Create map instance
  let chart = am4core.create("map", am4maps.MapChart);

  // Responsiveness enabled
  chart.responsive.enabled = true;

  // Set map definition
  chart.geodata = am4geodata_worldHigh;

  // Set projection
  chart.projection = new am4maps.projections.Miller();

  // Zoom control
  chart.zoomControl = new am4maps.ZoomControl();

  let homeButton = new am4core.Button();
  homeButton.events.on("hit", function () {
    chart.goHome();
  });

  homeButton.icon = new am4core.Sprite();
  homeButton.padding(7, 5, 7, 5);
  homeButton.width = 30;
  homeButton.icon.path = "M16,8 L14,8 L14,16 L10,16 L10,10 L6,10 L6,16 L2,16 L2,8 L0,8 L8,0 L16,8 Z M16,8";
  homeButton.marginBottom = 10;
  homeButton.parent = chart.zoomControl;
  homeButton.insertBefore(chart.zoomControl.plusButton);

  // Center on the groups by default
  chart.homeZoomLevel = 3.5;
  chart.homeGeoPoint = {
    longitude: 10,
    latitude: 54
  };

  let groupData = [{
    "color": chart.colors.getIndex(0),
    "data": [{
      "country": "Germany",
      "id": "DE",
      "link": ["https://www.example1.com"],
      "linkName": ["Name 1"]
    }, {
      "country": "France",
      "id": "FR",
      "link": ["https://www.example2.com", "https://www.example3.com"],
      "linkName": ["Name 2", "Name 3"]
    }]
  }];

  // This array will be populated with country IDs to exclude from the world series
  let excludedCountries = ["AQ"];

  // Create a series for each group, and populate the above array
  groupData.forEach(function (group) {
    let series = chart.series.push(new am4maps.MapPolygonSeries());
    series.name = group.name;
    series.useGeodata = true;
    let includedCountries = [];

    group.data.forEach(function (country) {
      includedCountries.push(country.id);
      excludedCountries.push(country.id);
    });

    let polygonTemplate = series.mapPolygons.template;
      polygonTemplate.tooltipHTML = '<b>{country}</b>';
      polygonTemplate.events.on("hit", function (ev) {
        chart.closeAllPopups();
        // Map countries and link encoding
        // How to write -> ev.target.dataItem.dataContext.linkName <- in order to display Name 2 and Name 3 separately ?
        chart.openPopup("<strong>" + ev.target.dataItem.dataContext.country + "</strong>" + ev.target.dataItem.dataContext.link.map(url => '<br><a href="' + encodeURI(url) + '">' + ev.target.dataItem.dataContext.linkName  + '</a>').join(""));
    });

    series.include = includedCountries;

    series.fill = am4core.color(group.color);
    series.setStateOnChildren = true;
    series.calculateVisualCenter = true;
    series.tooltip.label.interactionsEnabled = false; //disable tooltip click
    series.tooltip.keepTargetHover = true;


    // Country shape properties & behaviors
    let mapPolygonTemplate = series.mapPolygons.template;
    mapPolygonTemplate.fill = am4core.color("#c4a5e8");
    mapPolygonTemplate.fillOpacity = 0.8;
    mapPolygonTemplate.nonScalingStroke = true;
    mapPolygonTemplate.tooltipPosition = "fixed";

    mapPolygonTemplate.events.on("over", function (event) {
      series.mapPolygons.each(function (mapPolygon) {
        mapPolygon.isHover = false;
      })
      event.target.isHover = false;
      event.target.isHover = true;
    })

    mapPolygonTemplate.events.on("out", function (event) {
      series.mapPolygons.each(function (mapPolygon) {
        mapPolygon.isHover = false;
      })

    })

    // States  
    let hoverState = mapPolygonTemplate.states.create("hover");
    hoverState.properties.fill = am4core.color("#FFCC00");

    series.data = JSON.parse(JSON.stringify(group.data));

  });

  // The rest of the world.
  let worldSeries = chart.series.push(new am4maps.MapPolygonSeries());
  let worldSeriesName = "world";
  worldSeries.name = worldSeriesName;
  worldSeries.useGeodata = true;
  worldSeries.exclude = excludedCountries;
  worldSeries.fillOpacity = 0.5;
  worldSeries.hiddenInLegend = true;
  worldSeries.mapPolygons.template.nonScalingStroke = true;


});
  body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  }

  #map {
    width: 100%;
    height: 600px;
    overflow: hidden;
  }

  #map a,
  b {
    cursor: pointer;
    color:  #003399;
    text-align: center;
  }

  #map a:hover {
    color: #023432;
  }

  .ampopup-content {
    /* width: 40%; */
    text-align: center;
  }

  .ampopup-header {
    background-color: #99000d !important;
  }

  .ampopup-close {
    filter: invert(1);
  }

  .ampopup-inside {
    background-color: rgb(255, 255, 255);
  }

  .ampopup-inside a {
    color: #28a86c !important;
  }

  .ampopup-inside a:hover {
    color: #023432 !important;
  }

  .ampopup-curtain {
    display: block !important;
    background-color: rgba(7, 22, 51, 0.7) !important;
  }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Countries popup with links</title>
    <link rel="stylesheet" href="css/style.css">
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-12">
                <div id="map"></div>
            </div>
        </div>
    </div>

    <!-- Scripts for loading AmCharts Map -->
    <script src="https://cdn.amcharts.com/lib/4/core.js"></script>
    <script src="https://cdn.amcharts.com/lib/4/maps.js"></script>
    <script src="https://cdn.amcharts.com/lib/4/geodata/worldHigh.js"></script>
    <script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
    <script src="js/custom2.js"></script>
    
    <!-- Bootstrap -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
</body>
</html>

1 Answer 1

1

You need to use the index provided by the .map to access the nth element in the linkName array.

let polygonTemplate = series.mapPolygons.template;
polygonTemplate.tooltipHTML = '<b>{country}</b>';
polygonTemplate.events.on("hit", function(ev) {
  chart.closeAllPopups();
  const {
    links,
    linkNames,
    country
  } = ev.target.dataItem.dataContext;

  // Map countries and link encoding
  const popupContent = `<strong>${country}</strong><br />
  ${
  links.map((url,urlIndex)=>`<a href="${encodeURI(url)}">${linkNames[urlIndex]}</a>`).join('')
  }`;
  chart.openPopup(popupContent);
});
Sign up to request clarification or add additional context in comments.

4 Comments

is there a way to avoid jQuery code in your example to keep it strictly JavaScript?
@JustMe there is no jquery in my code, the $ is the syntax of the template literals
Sorry, the $ confused me a little
@JustMe added a link in the previous comments talking about template literals. It helps to avoid the string concatanation and messing with the quotes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.