Data classes and popup

author(s): Torstein Hønsi

HTML

<script src="https://code.highcharts.com/maps/highmaps.js"></script>
<script src="https://code.highcharts.com/modules/annotations.js"></script>
<script src="https://code.highcharts.com/maps/modules/data.js"></script>
<script src="https://code.highcharts.com/maps/modules/exporting.js"></script>
<script src="https://code.highcharts.com/maps/modules/offline-exporting.js"></script>
<script src="https://code.highcharts.com/maps/modules/accessibility.js"></script>

<div id="container">
    <div class="loading">
        <i class="icon-spinner icon-spin icon-large"></i>
        Loading data from Google Spreadsheets...
    </div>
</div>

CSS

body {
    background: var(--highcharts-background-color);
    color: var(--highcharts-neutral-color-100);
}

#container {
    height: 500px;
    min-width: 310px;
    max-width: 600px;
    margin: 0 auto;
}

.loading {
    margin-top: 10em;
    text-align: center;
    color: #808080;
}

#popup-pie {
    width: 280px;
    height: 230px;
    padding: 0.5em 1em;
    cursor: default;
}

#annotation-header {
    display: flex;
    justify-content: space-between;
    width: 280px;
    align-items: center;
    color: #333;
    font-size: 1.45em;
    font-weight: bold;
    background: #e9e9e9;
    padding: 0.4em 1em;
    cursor: move;
    border: 1px solid #ddd;
    border-radius: 3px;
}

#annotation-close-btn {
    width: 20px;
    height: 20px;
    padding: 1px;
    color: #777;
    text-align: center;
    font-size: 0.7em;
    font-weight: 700;
    border: 1px solid #c5c5c5;
    border-radius: 3px;
    background: #f6f6f6;
    cursor: pointer;
    z-index: 999;
}

JavaScript

(async () => {

    const mapData = await fetch(
        'https://code.highcharts.com/mapdata/countries/us/us-all.topo.json'
    ).then(response => response.json());

    // Custom template helper
    Highcharts.Templating.helpers.abs = value => Math.abs(value);

    // Load the data from a Google Spreadsheet
    Highcharts.data({
        googleAPIKey: 'AIzaSyCQ0Jh8OFRShXam8adBbBcctlbeeA-qJOk',
        googleSpreadsheetKey: '1uj1Gzv3fpH-b0w2tYpuKNp3TrGr43I9XAAqmgVE_jMs',

        // Custom handler for columns
        parsed: function (columns) {

            /**
             * Event handler for clicking points.
             */
            function pointClick() {
                const row = this.options.row,
                    chart = this.series.chart;

                // Remove existing annotation if present
                chart.removeAnnotation('election-popup');

                // Add new annotation with a pie chart
                chart.addAnnotation({
                    id: 'election-popup',
                    labelOptions: {
                        useHTML: true,
                        backgroundColor: '#fff'
                    },
                    labels: [{
                        point: {
                            x: chart.plotWidth / 2,
                            y: chart.plotHeight / 10
                        },
                        text: `
                            <div id="annotation-header">
                                <span>${this.name}</span>
                                <button id="annotation-close-btn">
                                X
                                </button>
                            </div>
                            <div id="popup-pie"></div>
                        `,
                        shape: 'rect'
                    }],
                    zIndex: 10
                });

                // Create the pie chart inside the annotation
                const pieChart =...