Hexagon Geospatial
MENU

Shared Samples

M.App Portfolio provides a modern, cloud-based platform for creating and delivering diverse geospatial web applications.
Through the M.App Studio, our partners can design, build, and deploy their own Hexagon Smart M.Apps.
Showing results for 
Search instead for 
Do you mean 

BI Application created just with the JS/CSS customization code

by Technical Evangelist ‎07-26-2016 04:30 AM - edited ‎10-11-2016 09:18 AM (1,376 Views)

Description

This application doesn't have any configuration coming from the wizard besides a map that is centered on Poland. It's also very similar to the application created in "Half-customized Half-configurated" article. The difference is that application described below is almost fully created by JavaScript and CSS code. 

It is using GeoMedia WebMap 2016 WFS connection to

https://dev-test-mapp.hexagongeospatial.com/gsdemo/psz_wojewodztwa_wfs/wfservice.aspx 

 

Link to repository containing code snippets for following exercise: BitBucket repository

 

Filters

Geometry request:

https://dev-test-mapp.hexagongeospatial.com/gsdemo/psz_wojewodztwa_wfs/wfservice.aspx?request=getfeature&service=wfs&version=2.0.0&typenames=wojewodztwaFinal&propertyname=geometry,id_woj&outputFormat=application/vnd.geo%2Bjson&filter=%3Cfes:Filter%20xmlns:fes=%22http://www.opengis.net/ogc%22%20xmlns=%22http://www.opengis.net/gml%22%3E%3Cfes:And%3E%3Cfes:BBOX%3E%3CEnvelope%20srsName=%22EPSG:4326%22%3E%3ClowerCorner%3E48.40%2020.49%3C/lowerCorner%3E%3CupperCorner%3E54.82%2024.79%3C/upperCorner%3E%3C/Envelope%3E%3C/fes:BBOX%3E%3Cfes:PropertyIsEqualTo%3E%3Cfes:PropertyName%3EYEAR%3C/fes:PropertyName%3E%3Cfes:Literal%3E2010%3C/fes:Literal%3E%3C/fes:PropertyIsEqualTo%3E%3C/fes:And%3E%3C/fes:Filter%3E

The filter: 

<fes:Filter xmlns:fes="http://www.opengis.net/ogc" xmlns="http://www.opengis.net/gml">
    <fes:And>
        <fes:BBOX>
            <Envelope srsName="EPSG:4326">
                <lowerCorner>48.40 20.49</lowerCorner>
                <upperCorner>54.82 24.79</upperCorner>
            </Envelope>
        </fes:BBOX>
        <fes:PropertyIsEqualTo>
            <fes:PropertyName>YEAR</fes:PropertyName>
            <fes:Literal>2010</fes:Literal>
        </fes:PropertyIsEqualTo>
    </fes:And>
</fes:Filter>

Attributes request:

https://dev-test-mapp.hexagongeospatial.com/gsdemo/psz_wojewodztwa_wfs/wfservice.aspx?request=getfeature&service=wfs&version=2.0.0&typenames=wojewodztwaFinal&outputFormat=text/csv&filter=%3Cfes:Filter%20xmlns:fes=%22http://www.opengis.net/ogc%22%20xmlns=%22http://www.opengis.net/gml%22%3E%3Cfes:And%3E%3Cfes:BBOX%3E%3CEnvelope%20srsName=%22EPSG:4326%22%3E%3ClowerCorner%3E48.40%2020.49%3C/lowerCorner%3E%3CupperCorner%3E54.82%2024.79%3C/upperCorner%3E%3C/Envelope%3E%3C/fes:BBOX%3E%3Cfes:PropertyIsBetween%3E%3Cfes:PropertyName%3EYEAR%3C/fes:PropertyName%3E%3Cfes:LowerBoundary%3E%3Cfes:Literal%3E2005%3C/fes:Literal%3E%3C/fes:LowerBoundary%3E%3Cfes:UpperBoundary%3E%3Cfes:Literal%3E2010%3C/fes:Literal%3E%3C/fes:UpperBoundary%3E%3C/fes:PropertyIsBetween%3E%3C/fes:And%3E%3C/fes:Filter%3E 

The filter: 

<fes:Filter xmlns:fes="http://www.opengis.net/ogc" xmlns="http://www.opengis.net/gml">
    <fes:And>
        <fes:BBOX>
            <Envelope srsName="EPSG:4326">
                <lowerCorner>48.40 20.49</lowerCorner>
                <upperCorner>54.82 24.79</upperCorner>
            </Envelope>
        </fes:BBOX>
        <fes:PropertyIsBetween>
            <fes:PropertyName>YEAR</fes:PropertyName>
            <fes:LowerBoundary>
                <fes:Literal>2005</fes:Literal>
            </fes:LowerBoundary>
            <fes:UpperBoundary>
                <fes:Literal>2010</fes:Literal>
            </fes:UpperBoundary>
        </fes:PropertyIsBetween>
    </fes:And>
</fes:Filter>

The WFS Server must be published with HTTPS.

 

JavaScript Code

//WFS configuration
var timeStamp = new Date().getTime(),
    baseUrl = "https://dev-test-mapp.hexagongeospatial.com/gsdemo/psz_wojewodztwa_wfs/wfservice.aspx",
    bboxFilterParts = [
        '<fes:BBOX>',
            '<Envelope srsName="EPSG:4326">',
                '<lowerCorner>48.40 20.49</lowerCorner>',
                '<upperCorner>54.82 24.79</upperCorner>',
            '</Envelope>',
        '</fes:BBOX>'
    ],
    filterBeginParts = [
        '<fes:Filter xmlns:fes="http://www.opengis.net/ogc" xmlns="http://www.opengis.net/gml">'
    ],
    filterEndParts = [
        '</fes:Filter>'
    ],
    andBeginParts = [
        '<fes:And>'
    ],
    andEndParts = [
        '</fes:And>'
    ],
    geometryRequest = "?request=getfeature&service=wfs&version=2.0.0&typenames=wojewodztwaFinal&propertyname=geometry,id_woj&outputFormat=application/vnd.geo%2Bjson&filter=",
    geometryFilterParts = filterBeginParts.concat(andBeginParts).concat(bboxFilterParts).concat([
        '<fes:PropertyIsEqualTo>',
            '<fes:PropertyName>',
                'YEAR',
            '</fes:PropertyName>',
            '<fes:Literal>',
                '2010',
            '</fes:Literal>',
        '</fes:PropertyIsEqualTo>'
    ]).concat(andEndParts).concat(filterEndParts),
    geometryFilter = encodeURI(geometryFilterParts.join("")),
    geometryUrl = baseUrl + geometryRequest + geometryFilter,
    attributesRequest = "?request=getfeature&service=wfs&version=2.0.0&typenames=wojewodztwaFinal&outputFormat=text/csv&filter=",
    attributesFilterParts = filterBeginParts.concat(andBeginParts).concat(bboxFilterParts).concat([
        '<fes:PropertyIsBetween>',
            '<fes:PropertyName>',
                'YEAR',
            '</fes:PropertyName>',
            '<fes:LowerBoundary>',
                '<fes:Literal>',
                    '2005',
                '</fes:Literal>',
            '</fes:LowerBoundary>',
            '<fes:UpperBoundary>',
                '<fes:Literal>',
                    '2010',
                '</fes:Literal>',
            '</fes:UpperBoundary>',
        '</fes:PropertyIsBetween>'
    ]).concat(andEndParts).concat(filterEndParts),
    attributesFilter = encodeURI(attributesFilterParts.join("")),
    attributesUrl = baseUrl + attributesRequest + attributesFilter;

//Error handler
function onError(e) {
    console.log("Something went wrong");
    console.log(e);
}

//Custom stage model, more informations about it can be found in API documentation
var stageModel = {
    "id": "zbyszek",
    "fields": [{
        "id": "POPULATION_TOTAL_EMPLOYED",
        "name": "POPULATION_TOTAL_EMPLOYED",
        "value": "POPULATION_M_EMPLOYED+POPULATION_F_EMPLOYED"
    }, {
        "id": "ac2016e27b3e84215bd114745d17c2ad6",
        "name": "id_woj",
        "value": "id_woj"
    }, {
        "id": "a836cd3468f8246ca8314bced09e6393a",
        "name": "year_d",
        "value": "$date(YEAR,'%Y')"
    }, {
        "id": "a520f226f8fc14256828c17c95e3d3ac0",
        "name": "NUTS1_NAME",
        "value": "NUTS1_NAME"
    }, {
        "id": "a694945b7789743798d3b27acae05de94",
        "name": "NUTS1",
        "value": "NUTS1"
    }],
    "totals": [],
    "features": [{
        "id": "labour_geom",
        "key": "id_woj",
        "name": "Adminstrative Zones"
    }],
    "colors": {
        "paletteYellow": {
            "range": ["#fff0b3", "#ffeb99", "#ffe066", "#ffd633", "#ffcc00", "#cca300", "#997a00", "#665200", "#4d3d00", "#332900"],
            "domain": ["2500", "5000"],
            "type": "quantize"
        },
        "paletteRed": {
            "range": ["#ffcccc", "#ffb3b3", "#ff9999", "#ff8080", "#ff4d4d", "#ff3333", "#ff0000", "#cc0000", "#990000", "#660000"],
            "domain": ["2500", "5000"],
            "type": "quantize"
        },
        "paletteBlue": {
            "range": ["#ccd9ff", "#b3c6ff", "#809fff", "#668cff", "#3366ff", "#1a53ff", "#0039e6", "#002db3", "#002080", "#00134d"],
            "domain": ["2500", "5000"],
            "type": "quantize"
        }
    },
    "values": [{
        "id": "vCount",
        "name": "Count",
        "value": "$count"
    }, {
        "id": "vYear",
        "name": "year_m",
        "value": "YEAR"
    }, {
        "id": "vAverageWage",
        "name": "Average_wage",
        "value": "$sum(WAGES_TOTAL*POPULATION_TOTAL)/$sum(POPULATION_TOTAL)"
    }, {
        "id": "vAverageWageMale",
        "name": "Average_wage_men",
        "value": "$sum(WAGES_M*POPULATION_M_EMPLOYED)/$sum(POPULATION_M_EMPLOYED)"
    }, {
        "id": "vAverageWageFemale",
        "name": "Average_wage_women",
        "value": "$sum(WAGES_F*POPULATION_F_EMPLOYED)/$sum(POPULATION_F_EMPLOYED)"
    }, {
        "id": "vTotalEmployedPopulation",
        "name": "Total employed population",
        "value": "$sum(POPULATION_TOTAL_EMPLOYED)"
    }, {
        "id": "vAverageWageFemaleReal",
        "name": "Average_wage_women_real",
        "value": "$sum(WAGES_F_REAL*POPULATION_F_EMPLOYED)/$sum(POPULATION_F_EMPLOYED)"
    }, {
        "id": "vAverageWageMaleReal",
        "name": "Average_wage_men_real",
        "value": "$sum(WAGES_M_REAL*POPULATION_M_EMPLOYED)/$sum(POPULATION_M_EMPLOYED)"
    }, {
        "id": "vAverageWageReal",
        "name": "Average_wage_real",
        "value": "$sum(WAGES_TOTAL_REAL*POPULATION_TOTAL_EMPLOYED)/$sum(POPULATION_TOTAL_EMPLOYED)"
    }, {
        "id": "vAverageWageDiff",
        "name": "Average_wage_diff",
        "value": "$sum(WAGES_M_REAL*POPULATION_M_EMPLOYED)/$sum(POPULATION_M_EMPLOYED) - $sum(WAGES_F_REAL*POPULATION_F_EMPLOYED)/$sum(POPULATION_F_EMPLOYED)"
    }, {
        "id": "vPopulationMaleEmployed",
        "name": "POPULATION_M_EMPLOYED",
        "value": "$sum(POPULATION_M_EMPLOYED)"
    }, {
        "id": "vPopulationFemaleEmployed",
        "name": "POPULATION_F_EMPLOYED",
        "value": "$sum(POPULATION_F_EMPLOYED)"
    }, {
        "id": "vWageGapPercentage",
        "name": "Wage_gap_percentage",
        "value": "($sum(WAGES_M_REAL*POPULATION_M_EMPLOYED)/$sum(POPULATION_M_EMPLOYED) - $sum(WAGES_F_REAL*POPULATION_F_EMPLOYED)/$sum(POPULATION_F_EMPLOYED))/($sum(WAGES_M_REAL*POPULATION_M_EMPLOYED)/$sum(POPULATION_M_EMPLOYED))"
    }]
};

//Here charts are configured and assigned to variables

var yearNumberDisplayModel ={
    "id": "amatch0",
    "target": "amatch0",
    "chart": "number",
    "name": "amatch0",
    "values": "vYear",
    "number": {
        "html": {
            "one": "The average gross salary in %number",
            "some": "The average gross salary in %number",
            "none": "The average gross salary in %number",
            "negative": "The average gross salary in %number"
        },
        "format": "0.2f"
    }
};

var averageWageNominalNumberDisplayModel = {
    "id": "amatch1",
    "target": "amatch1",
    "chart": "number",
    "name": "amatch1",
    "values": "vAverageWage",
    "number": {
        "html": {
            "one": " was %number",
            "some": " was %number",
            "none": " was %number",
            "negative": " was %number"
        },
        "format": "0.2f"
    }
};

var averageWageRealNumberDisplayModel = {
    "id": "amatch2",
    "target": "amatch2",
    "chart": "number",
    "name": "amatch2",
    "values": "vAverageWageReal",
    "number": {
        "html": {
            "one": " in nominal ZŁ (=%number in current ZŁ)",
            "some": " in nominal ZŁ (=%number in current ZŁ)",
            "none": " in nominal ZŁ (=%number in current ZŁ)",
            "negative": " in nominal ZŁ (=%number in current ZŁ)"
        },
        "format": "0.2f"
    }
};

var employedPopulationChartModel = {
    "id": "ac303bbaf331945c98950a6219e07d883",
    "name": "EMPLOYED POPULATION BY SEX AND NUTS1 REGION",
    "title": "EMPLOYED POPULATION BY SEX AND NUTS1 REGION",
    "placement": "left",
    "key": ["a694945b7789743798d3b27acae05de94"],
    "values": ["vPopulationMaleEmployed", "vPopulationFemaleEmployed"],
    "tooltips": "{vPopulationMaleEmployed} and {vPopulationFemaleEmployed}",
    "colors": ["#2f69f6", "#ffaea1"],
    "axis": {
        "x": {
            "ticks": 2,
            "rotation": "",
            "units": 70
        },
        "y": {
            "ticks": 2,
            "units": 70
        }
    },
    "chart": "bar",
    "margins": {
        "top": 50,
        "right": 30,
        "bottom": 50,
        "left": 60
    }
};

var averageGrossSalaryChartModel = {
    "id": "ab993d83ce0634681acb1f5984070df98",
    "name": "AVERAGE GROSS SALARY BY NUTS1 REGION IN CURRENT ZŁ",
    "title": "AVERAGE GROSS SALARY BY NUTS1 REGION IN CURRENT ZŁ",
    "placement": "left",
    "key": ["a694945b7789743798d3b27acae05de94"],
    "values": ["vAverageWage"],
    "tooltips": "{vAverageWage}",
    "colors": ["#ffbf00", "#ffbf00", "#ffbf00", "#ffbf00", "#ffbf00"],
    "axis": {
        "x": {
            "ticks": 2,
            "rotation": "",
            "units": 70
        },
        "y": {
            "ticks": 2,
            "units": 70
        }
    },
    "chart": "bar",
    "margins": {
        "top": 50,
        "right": 30,
        "bottom": 50,
        "left": 60
    }
};


var timelineChartModel = {
    "id": "timeChart",
    "name": "AVERAGE GROSS SALARY IN NOMINAL ZŁ OVER TIME",
    "title": "AVERAGE GROSS SALARY IN NOMINAL ZŁ OVER TIME",
    "placement": "bottom",
    "key": ["a836cd3468f8246ca8314bced09e6393a"],
    "values": ["vAverageWage"],
    "tooltips": "{vAverageWage}",
    "colors": "paletteYellow",
    "axis": {
        "x": {
            "scale": "time",
            "units": 70,
            "padding": 300
        },
        "y": {
            "units": 70
        }
    },
    "chart": "bar",
    "margins": {
        "top": 50,
        "right": 30,
        "bottom": 50,
        "left": 60
    },
    "filter": {
        "exclusive": true
    },
    "bar": {
        "centerBar": true,
        "barPadding": 0,
        "outerPadding": 0.5,
        "gap": 2,
        "alwaysUseRounding": false
    }
};

//Variable containing charts
var charts = [
    timelineChartModel,
    yearNumberDisplayModel,
    averageWageNominalNumberDisplayModel,
    averageWageRealNumberDisplayModel,
    employedPopulationChartModel,
    averageGrossSalaryChartModel
];

// workaround for shapefile shortening of the names
var temp = JSON.stringify(stageModel);
[
    ['POPULATION_M_EMPLOYED', 'POPULATI_3'],
    ['POPULATION_F_EMPLOYED', 'POPULATI_4'],
    ['POPULATION_M', 'POPULATI_1'],
    ['POPULATION_F', 'POPULATI_2'],
    ['POPULATION_TOTAL', 'POPULATION'],
    ['EMPLOYMENT_F', 'EMPLOYME_1'],
    ['EMPLOYMENT_M', 'EMPLOYMENT'],
    ['WAGES_F_REAL', 'WAGES_F_RE'],
    ['WAGES_M_REAL', 'WAGES_M_RE'],
    ['WAGES_TOTAL_REAL', 'WAGES_TO_1'],
    ['WAGES_TOTAL', 'WAGES_TOTA']
].forEach(function(pair){
    temp = temp.split(pair[0]).join(pair[1]);
});
stageModel = JSON.parse(temp);
// workaround end


$GP.bi.config.overwriteConfiguration(function (configuration){
    var ret = configuration || {};
    ret.mapConfig = {
        "tooltipAttributes": ["NAME", "NUTS1_NAME", "TERYT", "AVG_WAGE"],
        "mapLegendPlacement": "map",
        "mapLegendEnabled": true,
        "mapTitleEnabled": true
    };
    return ret;
});

//choropleth map configuration
var choroplethModel1 = {
    chart: "choropleth",
    name: "Average Wage",
    target: "map",
    layer: "labour_geom",
    key: "id_woj",
    values: "vAverageWageReal",
    colors: "paletteYellow",
    id: "wojewodztwaChoropleth"
};

var layer1 = {
    definitionName: "MAppPlatformGeoJson",
    url: geometryUrl,
    name: "Average Wage",
    id: "labour_geom",
    bbox: [0, 0, 0, 0],
    bboxCrs: "EPSG:4326",
    supportedCrses: ["EPSG:4326", "EPSG:3857"],
    style: {
        display: "thematicLayer"
    }
};

var s = $GP.bi.stage;

//Registering stage model and adding choropleth map
s.registerStageModel({
    stageModel: stageModel
}, function() {
    //debugger;
    s.registerDataTable({
        tableSource: attributesUrl
    }, function() {
        s.addWidgets({
            descriptors: charts.map(function(c){
                return {chartM: c};
            })
        }, function (){
            s.registerChoropleth({
                model: choroplethModel1,
                mapTitleEnabled: true,
                mapLegendEnabled: true,
                mapLegendPlacement: "map"
            }, function() {
                $GP.legend.add(layer1, function() {
                    console.log("Registered layer1");
                    customize();
                }, onError);
            }, onError);
        });
    }, onError);
}, onError);

// Function which customize whole app
function customize() {
    var timeChartId = timelineChartModel.id,
        choroplthId = choroplethModel1.id,
        averageSalaryChartId = averageGrossSalaryChartModel.id,
        maleRealWagesId = "vAverageWageMaleReal",
        maleNominalWagesId = "vAverageWageMale",
        maleColorsId = "paletteBlue",
        femaleRealWagesId = "vAverageWageMaleReal",
        femaleNominalWagesId = "vAverageWageFemale",
        femaleColorsId = "paletteRed",
        realWagesId = "vAverageWageReal",
        nominalWagesId = "vAverageWage",
        totalColorsId = "paletteYellow";
    
    // Here is configuration for numbers showing salary in widget called "Pay Gap in Poland"
    var config = {
        "male": {
            "real": maleRealWagesId,
            "nominal": maleNominalWagesId,
            "colors": maleColorsId,
            "color": "#2f69f6",
            "title": '<span style="color:#2f69f6;">male gross salary</span>'
        },
        "female": {
            "real": femaleRealWagesId,
            "nominal": femaleNominalWagesId,
            "colors": femaleColorsId,
            "color": "#FF8C7A",
            "title": '<span style="color:#FF8C7A;">female gross salary</span>'
        },
        "total": {
            "real": realWagesId,
            "nominal": nominalWagesId,
            "colors": totalColorsId,
            "color": "#ffbf00",
            "title": 'gross salary'
        }
    };
    
    var root = document.createElement("div");
    root.setAttribute("class", "widget dc-chart");
    root.innerHTML = '<span class="widget-caption">Pay Gap in Poland</span>';

    var block = document.createElement("div");
    block.setAttribute("style", "margin-top: 30px;");
    block.setAttribute("class", "paygap-legend");

    root.appendChild(block);

    document.querySelector("#widgets-left").appendChild(root);

    var customMatchElement0 = document.createElement("span");
    block.appendChild(customMatchElement0);
    var customMatchElement1 = document.createElement("span");
    block.appendChild(customMatchElement1);
    var customMatchElement2 = document.createElement("span");
    block.appendChild(customMatchElement2);
    var customMatchElement3 = document.createElement("span");
    block.appendChild(customMatchElement3);
    var customMatchElement4 = document.createElement("span");
    block.appendChild(customMatchElement4);
    
    var legendDiv = document.createElement("div");
    legendDiv.setAttribute("class", "widget dc-chart psz-legend-box");
    legendDiv.innerHTML = '<span class="widget-caption">Legend</span><div class="mft-legend"><div class="male"><i>&nbsp;</i>Male</div><div class="female"><i>&nbsp;</i>Female</div><div class="total"><i>&nbsp;</i>Total</div></div>';
    document.querySelector("#widgets-left").appendChild(legendDiv);
    
    $GP.bi.stage.requireLibraries(function(gvc, dc, d3, cf, _) {
        // fix the year_m value by pulling it from the time chart
        $GP.bi.stage.findWidget({
            descriptor: timeChartId
        }, function(ret1) {
            if (!ret1 || !ret1.chart) return;
            $GP.bi.stage.findWidget({
                descriptor: "amatch0"
            }, function(ret2) {
                if (!ret2 || !ret2.chart) return;
    
                function updateYear() {
                    var year = ret1.chart.dimension().top(1)[0].YEAR;
                    ret2.chart
                        .formatNumber(d3.format(".0f"))
                        .data(year)
                        .redraw();
                }
    
                updateYear();
                ret1.chart.on("filtered", updateYear);
            });
        });
        // fix elasticY in the average salary chart
        $GP.bi.stage.findWidget({
            descriptor: averageSalaryChartId
        }, function(ret1) {
            if (!ret1 || !ret1.chart) return;
            ret1.chart.elasticY(true).redraw();
        });
        //function onClick events - redrawing charts
        function makeOnclickHandler (cfg) {
            return function () {
                $GP.bi.stage.findWidget({
                    descriptor: averageSalaryChartId
                }, function(ret1) {
                    if (!ret1 || !ret1.chart) return;
                    ret1.chart.redrawChart({
                        values: cfg.real,
                        colors: cfg.color
                    });
                    ret1.chart.yAxisLabel(" ").redraw();
                    ret1.chart.elasticY(true).redraw();
                    ret1.chart.render();
                    $GP.bi.stage.findWidget({
                        descriptor: "amatch0"
                    }, function(ret2) {
                        if (!ret2 || !ret2.chart) return;
                        ret2.chart.redrawChart({
                            "number": {
                                "html": {
                                    "one": "The average "+cfg.title+" in %number",
                                    "some": "The average "+cfg.title+" in %number",
                                    "none": "The average "+cfg.title+" in %number",
                                    "negative": "The average "+cfg.title+" in %number"
                                },
                                "format": "0.2f"
                            }
                        });
                        ret2.chart
                            .formatNumber(d3.format(".0f"))
                            .data(ret1.chart.dimension().top(1)[0].YEAR)
                            .redraw();
                    });
                });
                $GP.bi.stage.findWidget({
                    descriptor: choroplthId
                }, function(ret1) {
                    if (!ret1 || !ret1.chart) return;
                    ret1.chart.redrawChart({
                        values: cfg.real,
                        colors: cfg.colors
                    });
                });
                $GP.bi.stage.findWidget({
                    descriptor: "amatch1"
                }, function(ret1) {
                    if (!ret1 || !ret1.chart) return;
                    ret1.chart.redrawChart({
                        values: cfg.nominal,
                        colors: cfg.colors
                    });
                });
                $GP.bi.stage.findWidget({
                    descriptor: "amatch2"
                }, function(ret1) {
                    if (!ret1 || !ret1.chart) return;
                    ret1.chart.redrawChart({
                        values: cfg.real,
                        colors: cfg.colors
                    });
                });
            }
        }
        
        document.querySelector(".male").onclick = makeOnclickHandler(config.male);
        document.querySelector(".female").onclick = makeOnclickHandler(config.female);
        document.querySelector(".total").onclick = makeOnclickHandler(config.total);
    });
    
    //Adding widgets to a map
    $GP.bi.stage.requireLibraries(function(gvc, dc, d3, cf, _) {
        $GP.bi.stage.addWidget({
            descriptor: {
                chartM: {
                    "chart": "number",
                    "id": "customMatch0",
                    "name": "customMatch0",
                    "target": "customMatch0",
                    "values": "vCount",
                    "number": {
                        "format": ".0f",
                        "html": {
                            "negative": "",
                            "none": "",
                            "one": "In selected %number province",
                            "some": "In selected %number provinces"
                        }
                    }
                },
                domElement: customMatchElement0
            }
        });
        $GP.bi.stage.addWidget({
            descriptor: {
                chartM: {
                    "chart": "number",
                    "id": "customMatch1",
                    "name": "customMatch1",
                    "target": "customMatch1",
                    "values": config.male.nominal,
                    "number": {
                        "format": "0.2f",
                        "html": {
                            "negative": " the average male gross salary was <span class=\"bi-blue\"> %number ZŁ </span>",
                            "none": " the average male gross salary was <span class=\"bi-blue\"> %number ZŁ </span>",
                            "one": " the average male gross salary was <span class=\"bi-blue\"> %number ZŁ </span>",
                            "some": " the average male gross salary was <span class=\"bi-blue\"> %number ZŁ </span>"
                        }
                    }
                },
                domElement: customMatchElement1
            }
        });
        $GP.bi.stage.addWidget({
            descriptor: {
                chartM: {
                    "chart": "number",
                    "id": "customMatch2",
                    "name": "customMatch2",
                    "target": "customMatch2",
                    "values": config.female.nominal,
                    "number": {
                        "format": "0.2f",
                        "html": {
                            "negative": "<br>while the average female gross salary was <span class=\"bi-pink\"> %number ZŁ.</span>",
                            "none": "<br>while the average female gross salary was <span class=\"bi-pink\"> %number ZŁ.</span>",
                            "one": "<br>while the average female gross salary was <span class=\"bi-pink\"> %number ZŁ.</span>",
                            "some": "<br>while the average female gross salary was <span class=\"bi-pink\"> %number ZŁ.</span>"
                        }
                    }
                },
                domElement: customMatchElement2
            }
        });
        $GP.bi.stage.addWidget({
            descriptor: {
                chartM: {
                    "chart": "number",
                    "id": "customMatch3",
                    "name": "customMatch3",
                    "target": "customMatch3",
                    "values": "vAverageWageDiff",
                    "number": {
                        "format": "0.2f",
                        "html": {
                            "negative": "<br>The average female salary was <span class=\"bi-diff\"> %number ZŁ </span> lower than the average male salary",
                            "none": "<br>The average female salary was <span class=\"bi-diff\"> %number ZŁ </span> lower than the average male salary",
                            "one": "<br>The average female salary was <span class=\"bi-diff\"> %number ZŁ </span> lower than the average male salary",
                            "some": "<br>The average female salary was <span class=\"bi-diff\"> %number ZŁ </span> lower than the average male salary"
                        }
                    }
                },
                domElement: customMatchElement3
            }
        });
        $GP.bi.stage.addWidget({
            descriptor: {
                chartM: {
                    "chart": "number",
                    "id": "customMatch4",
                    "name": "customMatch4",
                    "target": "customMatch4",
                    "values": "vWageGapPercentage",
                    "number": {
                        "format": "0.2%",
                        "html": {
                            "negative": " (by <span class=\"bi-diff\"> %number </span>).",
                            "none": " (by <span class=\"bi-diff\"> %number </span>).",
                            "one": " (by <span class=\"bi-diff\"> %number </span>).",
                            "some": " (by <span class=\"bi-diff\"> %number </span>).",
                        }
                    }
                },
                domElement: customMatchElement4
            }
        });
    });
}

 

CSS code

.bi-pink, .bi-blue, .bi-diff {
    font-weight: bold;
    font-size: larger;
    margin-left: 4px;
}

.bi-pink {
    color: #FF8C7A;
}

.bi-blue {
    color: #2f69f6;
}

.bi-diff {
    color: black;
}

.em {
    color: black;
    font-weight: bold;
}

.male, .female, .total {
    display: inline-block;
    margin: 10px;
    cursor: pointer;
}

.male >i, .female>i, .total>i {
    width: 16px;
    height: 16px;
    display: inline-block;
    margin-right: 5px;
}

.male > i{
    background-color: #2f69f6;
}

.female > i{
    background-color: #FF8C7A;
}

.total > i{
    background-color: #ffbf00;
}

.paygap-legend {
    margin-top: 20px;
}

.paygap-legend {
    padding: 10px;
    text-align: left;
    line-height: 2;
}

.widget-caption {
    font-weight: 600 !important;
    color: #555555 !important;
}

.mft-legend {
    margin-top: 25px;
}

.psz-legend-box {
    height: 90px !important;
}

 

 

Comments
by
on ‎03-02-2018 03:01 AM

Hi developers of this nice and probably very helpful sample code,

 

might it be possible that the service which provides the data for this sample doesn't exist anymore?

That would be a pitty because understanding this example would help me a lot for my project.

I would be very greatful if you could fix this.

 

Thanks

Marisa