[SalesForce] Visualforce Gauge with breakpoints

I have a batch job that runs twice a month to calculate a score. I dump the data into a custom object called CA_NPS_Score__c. Each record just contains A few decimal fields, and a formula field that calculates the NPS Score. I have to do this in a batch job because the calculations done to get the decimal fields are too complex to do in a formula field.

I was fairly easily able to plot these scores into line graphs using VF charting to show the changes over time. Now my clients would like to have a simple gauge to show the score. These seem simple enough as well, but I am unable to get the gauge to look similar to the normal dashboard gauge. The gauge I created looks similar to the the gauge in this blog post

http://blogs.developerforce.com/developer-relations/2012/10/animated-visualforce-charts.html

The issue is I would like it to look more like the standard gauge dashboard component, mainly to be able to have 2 breakpoints, so I can show my low, medium, and high ranges graphically within the gauge. I have tried overlaying a second and third gauge on top of the gauge to show the different sections. I tried carrying the values of the breakpoints in the wrapper class, but I don't know how to show them visually on the VF page. There doesn't seem to be a way to show anything but the actual value on the gauge.

Is this possible?? Is there another way to accomplish this? I can't imagine I am the only person that has ever needed to create a gauge with breakpoints using VF. I can't help but thinking I am missing something very obvious and easy. Has anyone accomplished this?

Here is a very simple page and controller below:

VF

<apex:page controller="TestPageController">

<script>
    MyChart1.on('beforeconfig', function(config) {
        config.axes[0].margin=-10;
    });
</script>

   <apex:chart name="MyChart1" height="300" width="450" animate="true" data="{!data}">
       <apex:axis type="Gauge" position="gauge" title="Total NPS Score"  minimum="0" maximum="45" steps="10"/>
       <apex:gaugeSeries dataField="score" donut="50" colorSet="#00F,#0F0" needle="true"/>       
   </apex:chart>   
</apex:page>

Controller

public class TestPageController {   

    public TestPageController(){

    }

    public List<gaugeData> getData() {
        double NPS_score = 0;
        CA_NPS_Score__c score = [Select Id, Name, Total_NPS_Score__c, Most_Current__c  From CA_NPS_Score__c Where Most_Current__c = true];

        List<gaugeData> data = new List<gaugeData>();
        data.add(new gaugeData('NPS', score.Total_NPS_Score__c));
        return data;
    }
    public class gaugeData {
        public String name { get; set; }
        public decimal score { get; set; }
        public decimal lowRange { get; set; }
        public decimal highRange { get; set; }

        public gaugeData(String name, decimal npsScore) {
            this.name = name;
            this.lowRange = 17;
            this.highRange = 30;
            this.score = npsScore;
        }
    }
}

Here are some Visuals of what I am talking about:
enter image description here

enter image description here

Best Answer

I actually had to take Hraefn's advice. I went with jQuery to accomplish this as opposed to visualforce charting. I used a nice jQuery library chartJs, which can be found here

http://chartjs.devexpress.com/

Here is the basic code I used. Someone could easily adjust this to fit there data

VF

<apex:page controller="NPSScoreController">

    <apex:includeScript value="{!URLFOR($Resource.jquery, 'jquery-ui-1.10.2.custom/js/jquery-1.9.1.js')}" />    
    <apex:includeScript value="{!URLFOR($Resource.jquery, 'jquery-ui-1.10.2.custom/js/jquery-ui-1.10.2.custom.min.js')}" />
    <apex:includeScript value="{!URLFOR($Resource.jquery, 'jquery-ui-1.10.2.custom/js/d3.v3.js')}" />
    <apex:styleSheet value="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/smoothness/jquery-ui.css" />
    <apex:includeScript value="{!URLFOR($Resource.ChartJs, 'Lib/js/knockout-2.2.1.js')}" />
    <apex:includeScript value="{!URLFOR($Resource.ChartJs, 'Lib/js/globalize.min.js')}" />
    <apex:includeScript value="{!URLFOR($Resource.ChartJs, 'Lib/js/dx.chartjs.js')}" />



    <script>
    var j$ = jQuery.noConflict();

    //On Page load
    j$(function() {

        createBullet('OverallContainer', 'Total NPS Score', '{!score.Total_NPS_Score__c}');
        createBullet('EpicContainer', 'Epic Score', '{!score.Epic_NPS_Score__c}');
        createBullet('CernerContainer', 'Cerner Score', '{!score.Cerner_NPS_Score__c}');
        createBullet('RemContainer', 'Remediation Score', '{!score.Remediation_NPS_Score__c}');
        createBullet('DeployedContainer', 'Deployed Score', '{!score.Deployed_NPS_Score__c}');
        createBullet('LargestContainer', 'Largest Score', '{!score.Largest_NPS_Score__c}');
        createBullet('TierBContainer', 'Tier B Score', '{!score.TIER_B_NPS_Score__c}');
        createBullet('NewTierBContainer', '2013 New Tier B Score', '{!score.New_Tier_B_NPS_Score__c}');
        createBullet('NewTierAContainer', '2013 New Tier A Score', '{!score.New_Tier_A_NPS_Score__c}');
        createBullet('EMEARemediationContainer', 'EMEA Remediation Score', '{!score.EMEA_Remediation_NPS_Score__c}');
        createBullet('EMEADeploymentContainer', 'EMEA Deployment Score', '{!score.EMEA_Deployment_NPS_Score__c}');

    });

    function createBullet(divId, title, nps){
        j$("#" + divId).dxLinearGauge({
            scale: {
                startValue: -20,
                endValue: 50,
                label: {
                    indentFromTick: 7
                },
                majorTick: {
                    showCalculatedTicks: false,
                    customTickValues: [0, 17, 30, 50],
                    color: "#000"           
                }
            },

            title: {
                text: title,
                font: {
                    color:'#000',
                    weight:900,
                    size: 20
                }
            },

            rangeContainer: {
                backgroundColor: "none",
                ranges: [
                    {
                        startValue: -20,
                        endValue: 17,
                        color: "red"
                    },
                    {
                        startValue: 17,
                        endValue: 30,
                        color: "orange"
                    },
                    {
                        startValue: 30,
                        endValue: 50,
                        color: "green"
                    }
                ]
            },

            //needles: [{ value: nps, color: "#000"}],      
            markers: [{ value: nps, color: "#000"}],        

        });
    }

    </script> 
        <div class="Page-Wrap">
            <div class="First-Line">
                <div id="OverallContainer" class="Container"></div> 
            </div>
            <div class="Lower-Line">
                <div class="Lower-Left">
                    <div class="Container-Wrapper">
                        <div id="EpicContainer" class="Container"></div> 
                    </div>
                    <div class="Container-Wrapper">
                        <div id="CernerContainer" class="Container"></div> 
                    </div>
                    <div class="Container-Wrapper">
                        <div id="RemContainer" class="Container"></div>
                    </div>
                    <div class="Container-Wrapper">
                        <div id="NewTierAContainer" class="Container"></div>
                    </div>  
                    <div class="Container-Wrapper">
                        <div id="NewTierBContainer" class="Container"></div>
                    </div>
                </div>  

                <div class="Lower-Right">
                    <div class="Container-Wrapper">
                        <div id="DeployedContainer" class="Container"></div>
                    </div>
                    <div class="Container-Wrapper">
                        <div id="LargestContainer" class="Container"></div>
                    </div>  
                    <div class="Container-Wrapper">
                        <div id="TierBContainer" class="Container"></div>
                    </div>
                    <div class="Container-Wrapper">
                        <div id="EMEARemediationContainer" class="Container"></div>
                    </div>
                    <div class="Container-Wrapper">
                        <div id="EMEADeploymentContainer" class="Container"></div>
                    </div>      
                </div>      
            </div>   
        </div>

    </apex:page>

Controller

public class NPSScoreController {

    public CA_NPS_Score__c score                        {get;set;}

    public NPSScoreController(){
        score = getScore();
    }

    public List<Schema.FieldSetMember> getFields() {
        return SObjectType.CA_NPS_Score__c.FieldSets.Dashboard_Fields.getFields();
    }

    private CA_NPS_Score__c getScore() {
        String query = 'SELECT ';
        for(Schema.FieldSetMember f : SObjectType.CA_NPS_Score__c.FieldSets.Dashboard_Fields.getFields()) {
            query += f.getFieldPath() + ', ';
        }
        query += 'Name FROM CA_NPS_Score__c Where Most_Current__c = true';
        return Database.query(query);
    }
}

And this is what it came out looking like...

enter image description here

Related Topic