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,753 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