Commits

cleonello  committed 41ebf7b

Fixed ordering of data labels for funnel charts. Added data label example. Added catch error example.

  • Participants
  • Parent commits 841b662

Comments (0)

Files changed (5)

File examples/catchError.html

+<!DOCTYPE html>
+
+<html lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Simple Test</title>
+  <!--[if IE]><script language="javascript" type="text/javascript" src="../src/excanvas.js"></script><![endif]-->
+  
+  <link rel="stylesheet" type="text/css" href="../src/jquery.jqplot.css" />
+  <link rel="stylesheet" type="text/css" href="examples.css" />
+  
+  <!-- BEGIN: load jquery -->
+  <script language="javascript" type="text/javascript" src="../src/jquery-1.4.2.min.js"></script>
+  <!-- END: load jquery -->
+  
+  <!-- BEGIN: load jqplot -->
+  <script language="javascript" type="text/javascript" src="../src/jquery.jqplot.js"></script>
+  <script language="javascript" type="text/javascript" src="../src/plugins/jqplot.barRenderer.js"></script>
+  <!-- END: load jqplot -->
+
+
+<script language="javascript" type="text/javascript">
+$(document).ready(function(){
+
+    // First, turn on error handling
+    $.jqplot.config.catchErrors = true;
+
+   plot1 = $.jqplot('chart1',[],{});
+   
+   // Second plot will use these customizations to error display.
+   $.jqplot.config.errorMessage = 'A Plot Error has Occurred';
+   $.jqplot.config.errorBackground = '#fbeddf';
+   $.jqplot.config.errorBorder = '2px solid #aaaaaa';
+   $.jqplot.config.errorFont = '16pt Courier New';
+   
+   plot2 = $.jqplot('chart2',[],{
+       axes: {
+           xaxis: {
+               renderer: $.jqplot.BarRenderer.js
+           }
+       }
+   });
+   
+   // The third plot will not display any errors, error will be rethrown as normal.
+   $.jqplot.config.catchErrors = false;
+   
+   plot2 = $.jqplot('chart2',[],{
+       axes: {
+           xaxis: {
+               renderer: $.jqplot.BarRenderer.js
+           }
+       }
+   });
+   
+ });
+</script>
+  </head>
+  <body>
+<?php include "nav.inc"; ?>
+<div id="chart1" class="plot" style="width:500px;height:300px;"></div>
+<div id="chart2" class="plot" style="width:500px;height:300px;"></div>
+  </body>
+</html>

File examples/dataLabels.html

+<!DOCTYPE html>
+
+<html lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Simple Test</title>
+  <!--[if IE]><script language="javascript" type="text/javascript" src="../src/excanvas.js"></script><![endif]-->
+  
+  <link rel="stylesheet" type="text/css" href="../src/jquery.jqplot.css" />
+  <link rel="stylesheet" type="text/css" href="examples.css" />
+  
+  <!-- BEGIN: load jquery -->
+  <script language="javascript" type="text/javascript" src="../src/jquery-1.4.2.min.js"></script>
+  <!-- END: load jquery -->
+  
+  <link type="text/css" href="jquery-ui/css/ui-lightness/jquery-ui-1.8.1.custom.css" rel="Stylesheet" />	
+  <script type="text/javascript" src="jquery-ui/js/jquery-ui-1.8.1.custom.min.js"></script>
+
+  
+  
+  <!-- BEGIN: load jqplot -->
+  <script language="javascript" type="text/javascript" src="../src/jquery.jqplot.js"></script>
+  <script language="javascript" type="text/javascript" src="../src/plugins/jqplot.funnelRenderer.js"></script>
+  <script language="javascript" type="text/javascript" src="../src/plugins/jqplot.pieRenderer.js"></script>
+  <!-- END: load jqplot -->
+
+  <style type="text/css">
+    #code {
+        font: 10pt "Andale Mono", Monaco, "Courier New", sans-serif ;
+        white-space: pre;
+    }
+    
+    pre {
+        background: #D8F4DC;
+        border: 1px solid rgb(200, 200, 200);
+        padding-top: 1em;
+        padding-left: 3em;
+        padding-bottom: 1em;
+        margin-top: 1em;
+        margin-bottom: 3em;
+        
+    }
+    
+    p {
+        margin: 2em 0;
+    }
+  </style>
+  
+<script id="example_1" type="text/javascript">$(document).ready(function(){
+    s1 = [['Sony',7], ['Samsumg',13.3], ['LG',14.7], ['Vizio',5.2], ['Insignia', 1.2]];
+        
+    plot1 = $.jqplot('chart1', [s1], {
+        seriesDefaults:{
+            renderer:$.jqplot.PieRenderer,
+            rendererOptions: {
+                showDataLabels: true
+            }
+        },
+        legend: {
+            show: true,
+            placement: 'outside'
+        }
+    }); 
+});
+</script>
+  
+<script id="example_2" type="text/javascript">$(document).ready(function(){
+    s1 = [['Sony',7], ['Samsumg',13.3], ['LG',14.7], ['Vizio',5.2], ['Insignia', 1.2]];
+        
+    plot2 = $.jqplot('chart2', [s1], {
+        seriesDefaults:{
+            renderer:$.jqplot.PieRenderer,
+            rendererOptions: {
+                showDataLabels: true,
+                dataLabelThreshold: 1,
+                dataLabelFormatString: '%.1f%%'
+            }
+        },
+        legend: {
+            show: true,
+            placement: 'outside'
+        }
+    }); 
+});
+</script>
+  
+<script id="example_3" type="text/javascript">$(document).ready(function(){
+    s1 = [['Sony',7], ['Samsumg',13.3], ['LG',14.7], ['Vizio',5.2], ['Insignia', 1.2]];
+        
+    plot3 = $.jqplot('chart3', [s1], {
+        seriesDefaults:{
+            renderer:$.jqplot.FunnelRenderer,
+            rendererOptions: {
+                showDataLabels: true,
+                dataLabels: 'label'
+            }
+        }
+    });
+});
+</script>
+  
+<script id="example_4" type="text/javascript">$(document).ready(function(){
+    s1 = [['Sony',7], ['Samsumg',13.3], ['LG',14.7], ['Vizio',5.2], ['Insignia', 1.2]];
+        
+    plot4 = $.jqplot('chart4', [s1], {
+        seriesDefaults:{
+            renderer:$.jqplot.FunnelRenderer,
+            rendererOptions: {
+                showDataLabels: true,
+                dataLabels: ['47 years', '28 years', '22 years', '14 years', '7 years']
+            }
+        },
+        legend: {
+            show: true,
+            placement: 'outside'
+        }
+    });
+});
+</script>
+
+<script type="text/javascript">
+    $(document).ready(function(){
+        
+        $('#code_1').html($('#example_1').text());
+        $('#code_2').html($('#example_2').text());
+        $('#code_3').html($('#example_3').text());
+        $('#code_4').html($('#example_4').text());
+        $(document).unload(function() {$('*').unbind(); });
+
+    });
+</script> 
+    
+  </head>
+  <body>
+<?php include "nav.inc"; ?>
+<div id="code"></div>
+
+    <p>Data labels can be automatically added to pie chart and donut chart slices as well as funnel chart areas.  what labels are displayed is controlled by the series "dataLabel" option.  There are 4 types of data labels to display:<p>
+    <ul>
+        <li>"label" - label of the point.
+        <li>"value" - value of the point.
+        <li>"percent" - percent of the whole (pie/donut/funnel) of the point.
+        <li>Array - custom array of data point labels, one for each point.
+    </ul>
+        
+    <p>Formatting of labels is controlled through the series "dataLabelsFormatString" option.  By default, the format string will be set based on the label type:
+     <ul>
+        <li>"label" - '%s', raw string.
+        <li>"value" - '%d', integer format.
+        <li>"percent" - '%d%%', integer with % sign appended.
+        <li>Array - '%s', raw string.
+    </ul>       
+  
+    <p>The following examples will clarify usage as well as other options.  By default, data labels are turned off.  They are enabled by setting the "showDataLabels: true" option.  Below is the default configuration for a pie chart:</p>
+               
+    <div id="chart1" style="margin-top:20px; margin-left:20px; width:300px; height:300px;"></div>
+    
+    <pre id="code_1"></pre>
+ 
+    <p>Notice that no data label was shown for "Insignia".  This is because the area of its slice is less than the "dataLabelThreshold" (3% by default).  The threshold is applicable no matter what type of label we used.  We can change the threshold and the format string for the label in the following example:<p>
+
+    <div id="chart2" style="margin-top:20px; margin-left:20px; width:300px; height:300px;"></div>
+    
+    <pre id="code_2"></pre>
+    
+    <p>Data labels function similarly for funnel and donut plots.  Here is a funnel plot with the "dataLabels" option set to display the point label.  Note that the label for "Insignia" is not displayed because Insignia represents less than 3% of the overall chart area, which is below the dataLabelThreshold:<p>
+    
+    <div id="chart3" style="margin-top:20px; margin-left:20px; width:300px; height:300px;"></div>
+    
+    <pre id="code_3"></pre>
+    
+    <p>The last example shows usage of a custom dataLabels array.  Again, labels for small sections will not be displayed unless the "dataLabelThreshold" is reduced (it is set to 3 percent by default).</p>
+    
+    <div id="chart4" style="margin-top:20px; margin-left:20px; width:300px; height:300px;"></div>
+    
+    <pre id="code_4"></pre>
+    
+ 
+  </body>
+</html>

File src/plugins/jqplot.donutRenderer.js

         this.dataLabels = 'percent';
         // prop: showDataLabels
         // true to show data labels on slices.
-        this.showDataLabels = true;
+        this.showDataLabels = false;
         // prop: dataLabelFormatString
         // Format string for data labels.  If none, '%s' is used for "label" and for arrays, '%d' for value and '%d%%' for percentage.
         this.dataLabelFormatString = null;
                     label = $.jqplot.sprintf(fstr, gd[i][2]*100);
                 }
                 else if (this.dataLabels.constructor == Array) {
-                    fstr = this.dataLabelFormatString || '%d';
+                    fstr = this.dataLabelFormatString || '%s';
                     label = $.jqplot.sprintf(fstr, this.dataLabels[i]);
                 }
                 

File src/plugins/jqplot.funnelRenderer.js

         // prop: lineWidth
         // width of line if areas are stroked and not filled.
         this.lineWidth = 2;
+        // prop: dataLabels
+        // Either 'label', 'value', 'percent' or an array of labels to place on the pie slices.
+        // Defaults to percentage of each pie slice.
+        this.dataLabels = 'percent';
+        // prop: showDataLabels
+        // true to show data labels on slices.
+        this.showDataLabels = false;
+        // prop: dataLabelFormatString
+        // Format string for data labels.  If none, '%s' is used for "label" and for arrays, '%d' for value and '%d%%' for percentage.
+        this.dataLabelFormatString = null;
+        // prop: dataLabelThreshold
+        // Threshhold in percentage (0 - 100) of pie area, below which no label will be displayed.
+        // This applies to all label types, not just to percentage labels.
+        this.dataLabelThreshold = 3;
         
         this.tickRenderer = $.jqplot.FunnelTickRenderer;
         
         this._lengths = [];
         // angle of the funnel to vertical.
         this._angle;
+        this._dataIndices = [];
         
         // sort data
         this._unorderedData = $.extend(true, [], this.data);
+        var idxs = $.extend(true, [], this.data);
+        for (var i=0; i<idxs.length; i++) {
+            idxs[i].push(i);
+        }
         this.data.sort( function (a, b) { return b[1] - a[1]; } );
+        idxs.sort( function (a, b) { return b[1] - a[1]; });
+        for (var i=0; i<idxs.length; i++) {
+            this._dataIndices.push(idxs[i][2]);
+        }
         
         // set highlight colors if none provided
         if (this.highlightColors.length == 0) {
         
     };
     
+    // gridData will be of form [label, percentage of total]
     $.jqplot.FunnelRenderer.prototype.setGridData = function(plot) {
         // set gridData property.  This will hold angle in radians of each data point.
         var sum = 0;
     };
     
     // called with scope of series
-    $.jqplot.FunnelRenderer.prototype.draw = function (ctx, gd, options) {
+    $.jqplot.FunnelRenderer.prototype.draw = function (ctx, gd, options, plot) {
         var i;
         var opts = (options != undefined) ? options : {};
         // offset and direction of offset due to legend placement
             
         }
         for (var i=0; i<gd.length; i++) {
-            this.renderer.drawSection.call (this, ctx, this._vertices[i], this.seriesColors[i]);
+            var v = this._vertices[i];
+            this.renderer.drawSection.call (this, ctx, v, this.seriesColors[i]);
+            
+            if (this.showDataLabels && gd[i][1]*100 >= this.dataLabelThreshold) {
+                var fstr, label;
+                
+                if (this.dataLabels == 'label') {
+                    fstr = this.dataLabelFormatString || '%s';
+                    label = $.jqplot.sprintf(fstr, gd[i][0]);
+                }
+                else if (this.dataLabels == 'value') {
+                    fstr = this.dataLabelFormatString || '%d';
+                    label = $.jqplot.sprintf(fstr, this.data[i][1]);
+                }
+                else if (this.dataLabels == 'percent') {
+                    fstr = this.dataLabelFormatString || '%d%%';
+                    label = $.jqplot.sprintf(fstr, gd[i][1]*100);
+                }
+                else if (this.dataLabels.constructor == Array) {
+                    fstr = this.dataLabelFormatString || '%s';
+                    label = $.jqplot.sprintf(fstr, this.dataLabels[this._dataIndices[i]]);
+                }
+                
+                var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge;
+                
+                var x = (v[0][0] + v[1][0])/2 + this.canvas._offsets.left;
+                var y = (v[1][1] + v[2][1])/2 + this.canvas._offsets.top;
+                
+                var labelelem = $('<span class="jqplot-funnel-series jqplot-data-label" style="position:absolute;">' + label + '</span>').insertBefore(plot.eventCanvas._elem);
+                x -= labelelem.width()/2;
+                y -= labelelem.height()/2;
+                x = Math.round(x);
+                y = Math.round(y);
+                labelelem.css({left: x, top: y});
+            }
+            
         }
                
     };
         this.plugins.funnelRenderer = {};
         this.plugins.funnelRenderer.highlightCanvas = new $.jqplot.GenericCanvas();
         
-        this.eventCanvas._elem.before(this.plugins.funnelRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-funnelRenderer-highlight-canvas', this._plotDimensions));
+        // do we have any data labels?  if so, put highlight canvas before those
+        var labels = this.target.find('.jqplot-data-label:first');
+        if (labels.length) {
+            labels.before(this.plugins.funnelRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-funnelRenderer-highlight-canvas', this._plotDimensions));
+        }
+        // else put highlight canvas before event canvas.
+        else {
+            this.eventCanvas._elem.before(this.plugins.funnelRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-funnelRenderer-highlight-canvas', this._plotDimensions));
+        }
         var hctx = this.plugins.funnelRenderer.highlightCanvas.setContext();
     }
     

File src/plugins/jqplot.pieRenderer.js

                     label = $.jqplot.sprintf(fstr, gd[i][2]*100);
                 }
                 else if (this.dataLabels.constructor == Array) {
-                    fstr = this.dataLabelFormatString || '%d';
+                    fstr = this.dataLabelFormatString || '%s';
                     label = $.jqplot.sprintf(fstr, this.dataLabels[i]);
                 }