Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
94 views
in Technique[技术] by (71.8m points)

javascript - Prevent popup on empty array

I have a map with 3 countries which when clicked, display a popup with links and their name. I would like to avoid the popup for the country without links to be displayed.

How can I check the empty array and prevent the popup only for the countries that don't have any information either in the "link" or "linkName"?

The popup happens here:

let polygonTemplate = series.mapPolygons.template;
    polygonTemplate.tooltipHTML = '<b>{country}</b>';
    polygonTemplate.events.on("hit", function (ev) {
      chart.closeAllPopups();
      // Map countries and link encoding
      const popupContent = `
        <strong>${ev.target.dataItem.dataContext.country}</strong><br />
        ${ev.target.dataItem.dataContext.link.map((url,urlIndex)=>`
        <a href="${encodeURI(url)}">${ev.target.dataItem.dataContext.linkName[urlIndex]}</a><br>
        `).join('')}
        `;
      chart.openPopup(popupContent);
    });

I tried to write an if condition but something is not working properly. Please check it below:

if (Array.isArray(ev.target.dataItem.dataContext.link) && !ev.target.dataItem.dataContext.link.length) {
      let polygonTemplate = series.mapPolygons.template;
        polygonTemplate.tooltipHTML = '<b>{country}</b>';
        polygonTemplate.events.on("hit", function (ev) {
        chart.closeAllPopups();
        // Map countries and link encoding
        const popupContent = `
        <strong>${ev.target.dataItem.dataContext.country}</strong><br />
        ${ev.target.dataItem.dataContext.link.map((url, urlIndex) => `
        <a href="${encodeURI(url)}">${ev.target.dataItem.dataContext.linkName[urlIndex]}</a><br>
        `).join('')}
        `;
        chart.openPopup(popupContent);
      });
    } else {
        console.log("something is wrong");
      }
    });

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"]
    }, {
      "country": "Belgium",
      "id": "BE",
      "link": [""],
      "linkName": [""]
    }]
  }];

  // 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
      const popupContent = `
        <strong>${ev.target.dataItem.dataContext.country}</strong><br />
        ${ev.target.dataItem.dataContext.link.map((url,urlIndex)=>`
        <a href="${encodeURI(url)}">${ev.target.dataItem.dataContext.linkName[urlIndex]}</a><br>
        `).join('')}
        `;
      chart.openPopup(popupContent);
    });

    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: #003399 !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>
question from:https://stackoverflow.com/questions/66047410/prevent-popup-on-empty-array

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to change these lines:

 const popupContent = `
    <strong>${ev.target.dataItem.dataContext.country}</strong><br />
    ${ev.target.dataItem.dataContext.link.map((url,urlIndex)=>`
    <a href="${encodeURI(url)}">${ev.target.dataItem.dataContext.linkName[urlIndex]}</a><br>
    `).join('')}
    `;

with:

popupContent = ev.target.dataItem.dataContext.link.map((url,urlIndex)=>
    `${(url.length) ? `<a href="${encodeURI(url)}">${ev.target.dataItem.dataContext.linkName[urlIndex]}</a><br>` : ''} `
).join('');
if (popupContent.trim().length != 0) {  // if popup contains something....
    popupContent = `<strong >${ev.target.dataItem.dataContext.country} </strong><br />`+ popupContent;
    chart.openPopup(popupContent);
}

The snippet:

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"]
            }, {
                "country": "Belgium",
                "id": "BE",
                "link": [""],
                "linkName": [""]
            }]
        }];

        // 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
                popupContent = ev.target.dataItem.dataContext.link.map((url,urlIndex)=>
                    `${(url.length) ? `<a href="${encodeURI(url)}">${ev.target.dataItem.dataContext.linkName[urlIndex]}</a><br>` : ''} `
).join('');
                if (popupContent.trim().length != 0) {
                    popupContent = `<strong >${ev.target.dataItem.dataContext.country} </strong><br />`+ popupContent;
                    chart.openPopup(popupContent);
                }
        });

        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: #003399 !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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<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>

<div class="container">
    <div class="row">
        <div class="col-12">
            <div id="map"></div>
        </div>
    </div>
</div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...